flash.c

来自「ecos实时嵌入式操作系统」· C语言 代码 · 共 1,912 行 · 第 1/5 页

C
1,912
字号
//==========================================================================////      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 Red Hat, Inc.//// 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>#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 CYGSEM_REDBOOT_FLASH_CONFIG#include <flash_config.h>// Configuration data, saved in FLASH, used to set/update RedBoot// normal "configuration" data items.static struct _config {    unsigned long len;    unsigned long key1;    unsigned char config_data[MAX_CONFIG_DATA-(4*4)];    unsigned long key2;    unsigned long cksum;} *config, *backup_config;#ifdef CYGSEM_REDBOOT_FLASH_CONFIG_READONLY_FALLBACKstatic struct _config  *readonly_config;#endif#endif#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 CYGPKG_COMPRESS_ZLIB                      "[-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 routinesstatic void *flash_start, *flash_end;static int flash_block_size, flash_num_blocks;#ifdef CYGOPT_REDBOOT_FISstatic void *fis_work_block;static void *fis_addr;static int fisdir_size;  // Size of FIS directory.#endif#ifdef CYGSEM_REDBOOT_FLASH_CONFIGstatic void *cfg_base;   // Location in Flash of config datastatic int   cfg_size;   // Length of config data - rounded to Flash block size// Prototypes for local functionsstatic unsigned char *flash_lookup_config(char *key);#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;    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;}static 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#ifdef CYGSEM_REDBOOT_FLASH_CONFIG    // 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);#endif        footer_p->infoBase = NULL;        footer_p->signature = FLASH_FOOTER_SIGNATURE;        footer_p->type = TYPE_REDHAT_REDBOOT;        // and compute its checksum        for ( ; count > 0; count--) {            if (*check_ptr > ~check)                check++;            check += *check_ptr++;        }        footer_p->checksum = ~check;    }#endif    // Do this after creating the initialized table because that inherently    // calculates where the high water mark of default RedBoot images is.    if (full_init) {

⌨️ 快捷键说明

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