flash.c

来自「eCos操作系统源码」· C语言 代码 · 共 1,397 行 · 第 1/4 页

C
1,397
字号
//==========================================================================////      flash.c////      RedBoot - FLASH memory support////==========================================================================//####ECOSGPLCOPYRIGHTBEGIN####// -------------------------------------------// This file is part of eCos, the Embedded Configurable Operating System.// Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003 Red Hat, Inc.// Copyright (C) 2003, 2004 Gary Thomas//// eCos is free software; you can redistribute it and/or modify it under// the terms of the GNU General Public License as published by the Free// Software Foundation; either version 2 or (at your option) any later version.//// eCos is distributed in the hope that it will be useful, but WITHOUT ANY// WARRANTY; without even the implied warranty of MERCHANTABILITY or// FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License// for more details.//// You should have received a copy of the GNU General Public License along// with eCos; if not, write to the Free Software Foundation, Inc.,// 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.//// As a special exception, if other files instantiate templates or use macros// or inline functions from this file, or you compile this file and link it// with other works to produce a work based on this file, this file does not// by itself cause the resulting work to be covered by the GNU General Public// License. However the source code for this file must still be made available// in accordance with section (3) of the GNU General Public License.//// This exception does not invalidate any other reasons why a work based on// this file might be covered by the GNU General Public License.//// Alternative licenses for eCos may be arranged by contacting Red Hat, Inc.// at http://sources.redhat.com/ecos/ecos-license/// -------------------------------------------//####ECOSGPLCOPYRIGHTEND####//==========================================================================//#####DESCRIPTIONBEGIN####//// Author(s):    gthomas// Contributors: gthomas, tkoeller// Date:         2000-07-28// Purpose:      // Description:  //              // This code is part of RedBoot (tm).////####DESCRIPTIONEND####////==========================================================================#include <redboot.h>#include <cyg/io/flash.h>#include <fis.h>#include <sib.h>#include <cyg/infra/cyg_ass.h>         // assertion macros#ifdef CYGSEM_REDBOOT_FLASH_COMBINED_FIS_AND_CONFIG// Note horrid intertwining of functions, to save precious FLASH#endif// Round a quantity up#define _rup(n,s) ((((n)+(s-1))/s)*s)#ifdef CYGOPT_REDBOOT_FIS// Image management functionslocal_cmd_entry("init",                "Initialize FLASH Image System [FIS]",                "[-f]",                fis_init,                FIS_cmds    );#ifdef CYGSEM_REDBOOT_FIS_CRC_CHECK# define FIS_LIST_OPTS "[-c] [-d]"#else# define FIS_LIST_OPTS "[-d]"#endiflocal_cmd_entry("list",                "Display contents of FLASH Image System [FIS]",                FIS_LIST_OPTS,                fis_list,                FIS_cmds    );local_cmd_entry("free",                "Display free [available] locations within FLASH Image System [FIS]",                "",                fis_free,                FIS_cmds    );local_cmd_entry("delete",                "Delete an image from FLASH Image System [FIS]",                "name",                fis_delete,                FIS_cmds    );static char fis_load_usage[] = #ifdef CYGPRI_REDBOOT_ZLIB_FLASH                      "[-d] "#endif                      "[-b <memory_load_address>] [-c] name";local_cmd_entry("load",                "Load image from FLASH Image System [FIS] into RAM",                fis_load_usage,                fis_load,                FIS_cmds    );local_cmd_entry("create",                "Create an image",                "-b <mem_base> -l <image_length> [-s <data_length>]\n"                "      [-f <flash_addr>] [-e <entry_point>] [-r <ram_addr>] [-n] <name>",                fis_create,                FIS_cmds    );#endif// Raw flash access functionslocal_cmd_entry("erase",                "Erase FLASH contents",                "-f <flash_addr> -l <length>",                fis_erase,                FIS_cmds    );#ifdef CYGHWR_IO_FLASH_BLOCK_LOCKINGlocal_cmd_entry("lock",                "LOCK FLASH contents",                "[-f <flash_addr> -l <length>] [name]",                fis_lock,                FIS_cmds    );local_cmd_entry("unlock",                "UNLOCK FLASH contents",                "[-f <flash_addr> -l <length>] [name]",                fis_unlock,                FIS_cmds    );#endiflocal_cmd_entry("write",                "Write raw data directly to FLASH",                "-f <flash_addr> -b <mem_base> -l <image_length>",                fis_write,                FIS_cmds    );// Define table boundariesCYG_HAL_TABLE_BEGIN( __FIS_cmds_TAB__, FIS_cmds);CYG_HAL_TABLE_END( __FIS_cmds_TAB_END__, FIS_cmds);extern struct cmd __FIS_cmds_TAB__[], __FIS_cmds_TAB_END__;// CLI functionstatic cmd_fun do_fis;RedBoot_nested_cmd("fis",             "Manage FLASH images",             "{cmds}",            do_fis,            __FIS_cmds_TAB__, &__FIS_cmds_TAB_END__    );// Local data used by these routinesvoid *flash_start, *flash_end;int flash_block_size, flash_num_blocks;#ifdef CYGOPT_REDBOOT_FISvoid *fis_work_block;void *fis_addr;int fisdir_size;  // Size of FIS directory.#endif#ifdef CYGSEM_REDBOOT_FLASH_CONFIGextern void *cfg_base;   // Location in Flash of config dataextern int   cfg_size;   // Length of config data - rounded to Flash block sizeextern struct _config *config;#endifstatic voidfis_usage(char *why){    diag_printf("*** invalid 'fis' command: %s\n", why);    cmd_usage(__FIS_cmds_TAB__, &__FIS_cmds_TAB_END__, "fis ");}static void        _show_invalid_flash_address(CYG_ADDRESS flash_addr, int stat){    diag_printf("Invalid FLASH address %p: %s\n", (void *)flash_addr, flash_errmsg(stat));    diag_printf("   valid range is %p-%p\n", (void *)flash_start, (void *)flash_end);}#ifdef CYGOPT_REDBOOT_FISstruct fis_image_desc *fis_lookup(char *name, int *num){    int i;    struct fis_image_desc *img;    void *err_addr;    flash_read(fis_addr, fis_work_block, fisdir_size, (void **)&err_addr);    img = (struct fis_image_desc *)fis_work_block;    for (i = 0;  i < fisdir_size/sizeof(*img);  i++, img++) {        if ((img->name[0] != (unsigned char)0xFF) &&             (strcasecmp(name, img->name) == 0)) {            if (num) *num = i;            return img;        }    }    return (struct fis_image_desc *)0;}voidfis_update_directory(void){    int stat;    void *err_addr;#ifdef CYGSEM_REDBOOT_FLASH_COMBINED_FIS_AND_CONFIG    memcpy((char *)fis_work_block+fisdir_size, config, cfg_size);#endif#ifdef CYGSEM_REDBOOT_FLASH_LOCK_SPECIAL    // Ensure [quietly] that the directory is unlocked before trying to update    flash_unlock((void *)fis_addr, flash_block_size, (void **)&err_addr);#endif    if ((stat = flash_erase(fis_addr, flash_block_size, (void **)&err_addr)) != 0) {        diag_printf("Error erasing FIS directory at %p: %s\n", err_addr, flash_errmsg(stat));    } else {        if ((stat = flash_program(fis_addr, fis_work_block, flash_block_size,                                  (void **)&err_addr)) != 0) {            diag_printf("Error writing FIS directory at %p: %s\n",                         err_addr, flash_errmsg(stat));        }    }#ifdef CYGSEM_REDBOOT_FLASH_LOCK_SPECIAL    // Ensure [quietly] that the directory is locked after the update    flash_lock((void *)fis_addr, flash_block_size, (void **)&err_addr);#endif}static voidfis_init(int argc, char *argv[]){    int stat;    struct fis_image_desc *img;    void *err_addr;    bool full_init = false;    struct option_info opts[1];    CYG_ADDRESS redboot_flash_start;    unsigned long redboot_image_size;    init_opts(&opts[0], 'f', false, OPTION_ARG_TYPE_FLG,               (void *)&full_init, (bool *)0, "full initialization, erases all of flash");    if (!scan_opts(argc, argv, 2, opts, 1, 0, 0, ""))    {        return;    }    if (!verify_action("About to initialize [format] FLASH image system")) {        diag_printf("** Aborted\n");        return;    }    diag_printf("*** Initialize FLASH Image System\n");#define MIN_REDBOOT_IMAGE_SIZE CYGBLD_REDBOOT_MIN_IMAGE_SIZE    redboot_image_size = flash_block_size > MIN_REDBOOT_IMAGE_SIZE ?                          flash_block_size : MIN_REDBOOT_IMAGE_SIZE;    // Create a pseudo image for RedBoot    img = (struct fis_image_desc *)fis_work_block;    memset(img, 0xFF, fisdir_size);  // Start with erased data#ifdef CYGOPT_REDBOOT_FIS_RESERVED_BASE    memset(img, 0, sizeof(*img));    strcpy(img->name, "(reserved)");    img->flash_base = (CYG_ADDRESS)flash_start;    img->mem_base = (CYG_ADDRESS)flash_start;    img->size = CYGNUM_REDBOOT_FLASH_RESERVED_BASE;    img++;#endif    redboot_flash_start = (CYG_ADDRESS)flash_start + CYGBLD_REDBOOT_FLASH_BOOT_OFFSET;#ifdef CYGOPT_REDBOOT_FIS_REDBOOT    memset(img, 0, sizeof(*img));    strcpy(img->name, "RedBoot");    img->flash_base = redboot_flash_start;    img->mem_base = redboot_flash_start;    img->size = redboot_image_size;    img++;    redboot_flash_start += redboot_image_size;#endif#ifdef CYGOPT_REDBOOT_FIS_REDBOOT_POST#ifdef CYGNUM_REDBOOT_FIS_REDBOOT_POST_OFFSET    // Take care to place the POST entry at the right offset:    redboot_flash_start = (CYG_ADDRESS)flash_start + CYGNUM_REDBOOT_FIS_REDBOOT_POST_OFFSET;#endif    memset(img, 0, sizeof(*img));    strcpy(img->name, "RedBoot[post]");    img->flash_base = redboot_flash_start;    img->mem_base = redboot_flash_start;    img->size = redboot_image_size;    img++;    redboot_flash_start += redboot_image_size;#endif#ifdef CYGOPT_REDBOOT_FIS_REDBOOT_BACKUP    // And a backup image    memset(img, 0, sizeof(*img));    strcpy(img->name, "RedBoot[backup]");    img->flash_base = redboot_flash_start;    img->mem_base = redboot_flash_start;    img->size = redboot_image_size;    img++;    redboot_flash_start += redboot_image_size;#endif#if defined(CYGSEM_REDBOOT_FLASH_CONFIG) && defined(CYGHWR_REDBOOT_FLASH_CONFIG_MEDIA_FLASH)    // And a descriptor for the configuration data    memset(img, 0, sizeof(*img));    strcpy(img->name, "RedBoot config");    img->flash_base = (CYG_ADDRESS)cfg_base;    img->mem_base = (CYG_ADDRESS)cfg_base;    img->size = cfg_size;    img++;#endif    // And a descriptor for the descriptor table itself    memset(img, 0, sizeof(*img));    strcpy(img->name, "FIS directory");    img->flash_base = (CYG_ADDRESS)fis_addr;    img->mem_base = (CYG_ADDRESS)fis_addr;    img->size = fisdir_size;    img++;#ifdef CYGOPT_REDBOOT_FIS_DIRECTORY_ARM_SIB_ID    // FIS gets the size of a full block - note, this should be changed    // if support is added for multi-block FIS structures.    img = (struct fis_image_desc *)((CYG_ADDRESS)fis_work_block + fisdir_size);    // Add a footer so the FIS will be recognized by the ARM Boot    // Monitor as a reserved area.    {        tFooter* footer_p = (tFooter*)((CYG_ADDRESS)img - sizeof(tFooter));        cyg_uint32 check = 0;        cyg_uint32 *check_ptr = (cyg_uint32 *)footer_p;        cyg_int32 count = (sizeof(tFooter) - 4) >> 2;        // Prepare footer. Try to protect all but the reserved space        // and the first RedBoot image (which is expected to be        // bootable), but fall back to just protecting the FIS if it's        // not at the default position in the flash.#if defined(CYGOPT_REDBOOT_FIS_RESERVED_BASE) && (-1 == CYGNUM_REDBOOT_FIS_DIRECTORY_BLOCK)        footer_p->blockBase = (char*)_ADDR_REDBOOT_TO_ARM(flash_start);        footer_p->blockBase += CYGNUM_REDBOOT_FLASH_RESERVED_BASE + redboot_image_size;#else        footer_p->blockBase = (char*)_ADDR_REDBOOT_TO_ARM(fis_work_block);

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?