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 + -
显示快捷键?