📄 flash.c
字号:
//==========================================================================
//
// 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 functions
local_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]"
#endif
local_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 functions
local_cmd_entry("erase",
"Erase FLASH contents",
"-f <flash_addr> -l <length>",
fis_erase,
FIS_cmds
);
#ifdef CYGHWR_IO_FLASH_BLOCK_LOCKING
local_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
);
#endif
local_cmd_entry("write",
"Write raw data directly to FLASH",
"-f <flash_addr> -b <mem_base> -l <image_length>",
fis_write,
FIS_cmds
);
// Define table boundaries
CYG_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 function
static 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 routines
void *flash_start, *flash_end;
int flash_block_size, flash_num_blocks;
#ifdef CYGOPT_REDBOOT_FIS
void *fis_work_block;
void *fis_addr;
int fisdir_size; // Size of FIS directory.
#endif
#ifdef CYGSEM_REDBOOT_FLASH_CONFIG
extern void *cfg_base; // Location in Flash of config data
extern int cfg_size; // Length of config data - rounded to Flash block size
extern struct _config *config;
#endif
static void
fis_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_FIS
struct 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;
}
void
fis_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 void
fis_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 + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -