📄 flash.c
字号:
//==========================================================================
//
// flash.c
//
// RedBoot - FLASH memory support
//
//==========================================================================
//####COPYRIGHTBEGIN####
//
// -------------------------------------------
// The contents of this file are subject to the Red Hat eCos Public License
// Version 1.1 (the "License"); you may not use this file except in
// compliance with the License. You may obtain a copy of the License at
// http://www.redhat.com/
//
// Software distributed under the License is distributed on an "AS IS"
// basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the
// License for the specific language governing rights and limitations under
// the License.
//
// The Original Code is eCos - Embedded Configurable Operating System,
// released September 30, 1998.
//
// The Initial Developer of the Original Code is Red Hat.
// Portions created by Red Hat are
// Copyright (C) 1998, 1999, 2000, 2001 Red Hat, Inc.
// All Rights Reserved.
// -------------------------------------------
//
//####COPYRIGHTEND####
//==========================================================================
//#####DESCRIPTIONBEGIN####
//
// Author(s): gthomas
// Contributors: gthomas
// 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 <cyg/hal/hal_ixdp2400.h> // Hardware definitions
#include <cyg/hal/hal_platform_ints.h>
externC int qdr_ch_sz_array[MAX_QDR_CHANNEL];
// CLI function
static cmd_fun do_fis;
RedBoot_cmd("fis",
"Manage FLASH images",
"{cmds}",
do_fis
);
#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",
"Display 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] [-w] 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>",
fis_lock,
FIS_cmds
);
local_cmd_entry("unlock",
"UNLOCK FLASH contents",
"-f <flash_addr> -l <length>",
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__;
// Local data used by these routines
static void *flash_start, *flash_end;
static int block_size, blocks;
static void *fis_work_block;
static int fisdir_size; // Size of FIS directory. Note: zero if FIS not enabled
#ifdef CYGSEM_REDBOOT_FLASH_CONFIG
static void *cfg_base; // Location in Flash of config data
static int cfg_size; // Length of config data - rounded to Flash block size
#endif
static void charcpy(unsigned char *dest, unsigned char *src, int len)
{
int i;
for(i = 0; i < len; i++)
dest[i] = src[i];
return;
}
static void
fis_usage(char *why)
{
printf("*** invalid 'fis' command: %s\n", why);
cmd_usage(__FIS_cmds_TAB__, &__FIS_cmds_TAB_END__, "fis ");
}
#ifdef CYGOPT_REDBOOT_FIS
struct fis_image_desc *
fis_lookup(char *name)
{
int i;
void *fis_addr;
struct fis_image_desc *img;
fis_addr = (void *)((unsigned long)flash_end - block_size);
charcpy(fis_work_block, fis_addr, block_size);
img = (struct fis_image_desc *)fis_work_block;
for (i = 0; i < block_size/sizeof(*img); i++, img++) {
if ((img->name[0] != (unsigned char)0xFF) && (strcmp(name, img->name) == 0)) {
return img;
}
}
return (struct fis_image_desc *)0;
}
static void
fis_init(int argc, char *argv[])
{
int stat;
struct fis_image_desc *img;
void *fis_base, *err_addr, *syslog_base;
bool full_init = false;
struct option_info opts[1];
unsigned long redboot_image_size, redboot_flash_start;
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")) {
printf("** Aborted\n");
return;
}
printf("*** Initialize FLASH Image System\n");
#define MIN_REDBOOT_IMAGE_SIZE CYGBLD_REDBOOT_MIN_IMAGE_SIZE
redboot_image_size = block_size > MIN_REDBOOT_IMAGE_SIZE ? block_size : MIN_REDBOOT_IMAGE_SIZE;
// Create a pseudo image for RedBoot
img = (struct fis_image_desc *)fis_work_block;
#ifdef CYGOPT_REDBOOT_FIS_RESERVED_BASE
memset(img, 0, sizeof(*img));
strcpy(img->name, "(reserved)");
img->flash_base = (unsigned long)flash_start;
img->mem_base = (unsigned long)flash_start;
img->size = CYGNUM_REDBOOT_FLASH_RESERVED_BASE;
img++;
#endif
redboot_flash_start = (unsigned long)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->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 = (unsigned long)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
// a descriptor for system logs
memset(img, 0, sizeof(*img));
strcpy(img->name, "System Log");
syslog_base = (void *)((unsigned long)flash_end - (3 * block_size));
img->flash_base = (unsigned long)syslog_base;
img->mem_base = (unsigned long)syslog_base;
img->size = block_size;
img++;
#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 = (unsigned long)cfg_base;
img->mem_base = (unsigned long)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");
fis_base = (void *)((unsigned long)flash_end - block_size);
img->flash_base = (unsigned long)fis_base;
img->mem_base = (unsigned long)fis_base;
img->size = block_size;
img++;
// Do this after creating the initialized table because that inherently
// calculates where the high water mark of default RedBoot images is.
if (full_init) {
unsigned long erase_start, erase_size;
// Erase everything except default RedBoot images, fis block, and config block.
// FIXME! This still assumes that fis and config blocks can use top of FLASH.
// first deal with the possible first part, before RedBoot images:
erase_start = (unsigned long)flash_start + CYGNUM_REDBOOT_FLASH_RESERVED_BASE;
erase_size = (unsigned long)flash_start + CYGBLD_REDBOOT_FLASH_BOOT_OFFSET;
if ( erase_size > erase_start ) {
erase_size -= erase_start;
if ((stat = flash_erase((void *)erase_start, erase_size,
(void **)&err_addr)) != 0) {
printf(" initialization failed at %p: %s\n",
err_addr, flash_errmsg(stat));
}
}
// second deal with the larger part in the main:
erase_start = redboot_flash_start; // high water of created images
#ifdef CYGSEM_REDBOOT_FLASH_CONFIG
erase_size = (unsigned long)cfg_base - erase_start; // the gap between HWM and config data
#else
erase_size = (unsigned long)fis_base - erase_start; // the gap between HWM and fis data
#endif
if ((stat = flash_erase((void *)erase_start, erase_size,
(void **)&err_addr)) != 0) {
printf(" initialization failed at %p: %s\n",
err_addr, flash_errmsg(stat));
}
} else {
printf(" Warning: device contents not erased, some blocks may not be usable\n");
}
#ifdef CYGSEM_REDBOOT_FLASH_LOCK_SPECIAL
// Ensure [quietly] that the directory is unlocked before trying to update
flash_unlock((void *)fis_base, block_size, (void **)&err_addr);
#endif
if ((stat = flash_erase(fis_base, block_size, (void **)&err_addr)) != 0) {
printf(" initialization failed at %p: %s\n", err_addr, flash_errmsg(stat));
} else {
if ((stat = flash_program(fis_base, fis_work_block,
(unsigned long)img - (unsigned long)fis_work_block,
(void **)&err_addr)) != 0) {
printf("Error writing image descriptors 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_base, block_size, (void **)&err_addr);
// lock BM blocks also
flash_lock((void *)flash_start, MIN_REDBOOT_IMAGE_SIZE, (void **)&err_addr);
#endif
}
static void
fis_list(int argc, char *argv[])
{
struct fis_image_desc *img;
int i;
bool show_cksums = false;
bool show_datalen = false;
struct option_info opts[2];
init_opts(&opts[0], 'd', false, OPTION_ARG_TYPE_FLG,
(void **)&show_datalen, (bool *)0, "display data length");
#ifdef CYGSEM_REDBOOT_FIS_CRC_CHECK
init_opts(&opts[1], 'c', false, OPTION_ARG_TYPE_FLG,
(void **)&show_cksums, (bool *)0, "display checksums");
i = 2;
#else
i = 1;
#endif
if (!scan_opts(argc, argv, 2, opts, i, 0, 0, ""))
{
return;
}
img = (struct fis_image_desc *)((unsigned long)flash_end - block_size);
// Let printf do the formatting in both cases, rather than cnouting
// cols by hand....
printf("%-16s %-10s %-10s %-10s %-s\n",
"Name","FLASH addr",
show_cksums ? "Checksum" : "Mem addr",
show_datalen ? "Datalen" : "Length",
"Entry point" );
for (i = 0; i < block_size/sizeof(*img); i++, img++) {
struct fis_image_desc temp;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -