📄 flash.c
字号:
} else {
// Now program it
if ((stat = flash_program((void *)fis_addr, (void *)fis_work_block, block_size, (void **)&err_addr)) != 0) {
printf("Error programming at %p: %s\n", err_addr, flash_errmsg(stat));
}
}
#ifdef CYGSEM_REDBOOT_FLASH_LOCK_SPECIAL
// Insure [quietly] that the directory is locked after the update
flash_lock((void *)fis_addr, block_size, (void **)&err_addr);
#endif
}
static void
fis_load(int argc, char *argv[])
{
char *name;
struct fis_image_desc *img;
unsigned long mem_addr;
bool mem_addr_set = false;
bool show_cksum = false;
bool word_mode = false;
struct option_info opts[4];
#ifdef CYGPKG_REDBOOT_FIS_CRC_CHECK
unsigned long cksum;
#endif
int num_options;
#ifdef CYGPKG_COMPRESS_ZLIB
bool decompress = false;
#endif
init_opts(&opts[0], 'b', true, OPTION_ARG_TYPE_NUM,
(void **)&mem_addr, (bool *)&mem_addr_set, "memory [load] base address");
init_opts(&opts[1], 'c', false, OPTION_ARG_TYPE_FLG,
(void **)&show_cksum, (bool *)0, "display checksum");
init_opts(&opts[2], 'w', false, OPTION_ARG_TYPE_FLG,
(void **)&word_mode, (bool *)0, "read flash in 32-bit mode");
num_options = 3;
#ifdef CYGPKG_COMPRESS_ZLIB
init_opts(&opts[3], 'd', false, OPTION_ARG_TYPE_FLG,
(void **)&decompress, 0, "decompress");
num_options++;
#endif
if (!scan_opts(argc, argv, 2, opts, num_options, (void **)&name, OPTION_ARG_TYPE_STR, "image name"))
{
fis_usage("invalid arguments");
return;
}
if ((img = fis_lookup(name)) == (struct fis_image_desc *)0) {
printf("No image '%s' found\n", name);
return;
}
if (!mem_addr_set) {
mem_addr = img->mem_base;
}
// Load image from FLASH into RAM
if (((mem_addr < (unsigned long)user_ram_start) || ((mem_addr+img->size) >= (unsigned long)user_ram_end))
&& ((mem_addr < SRAM_BASE) || ((mem_addr+img->size) >= (SRAM_BASE + qdr_ch_sz_array[0])))
&& ((mem_addr < (SRAM_BASE + 0x10000000)) || ((mem_addr+img->size) >= ((SRAM_BASE + 0x10000000) + qdr_ch_sz_array[1])))) {
printf("Not a loadable image\n");
return;
}
#ifdef CYGPKG_COMPRESS_ZLIB
if (decompress) {
int err;
_pipe_t fis_load_pipe;
_pipe_t* p = &fis_load_pipe;
p->out_buf = (unsigned char*) mem_addr;
p->out_size = -1;
p->in_buf = (unsigned char*) img->flash_base;
p->in_avail = img->data_length;
err = (*_dc_init)(p);
if (0 == err)
err = (*_dc_inflate)(p);
// Free used resources, do final translation of
// error value.
err = (*_dc_close)(p, err);
if (0 != err && p->msg) {
printf("decompression error: %s\n", p->msg);
} else {
printf("Image loaded from %p-%p\n", (unsigned char *)mem_addr, p->out_buf);
}
} else // dangling block
#endif
{
if(word_mode)
{
*(SP_FRM_REG) = USE_32_BIT_DATA;
memcpy((void *)mem_addr, (void *)img->flash_base, img->data_length);
*(SP_FRM_REG) = USE_8_BIT_DATA;
}
else
{
charcpy((void *)mem_addr, (void *)img->flash_base, img->data_length);
}
}
entry_address = (unsigned long *)img->entry_point;
flash_entry_address = (unsigned long *)img->flash_base;
#ifdef CYGPKG_REDBOOT_FIS_CRC_CHECK
cksum = crc32((unsigned char *)mem_addr, img->data_length);
if (show_cksum) {
printf("Checksum: 0x%08lx\n", cksum);
}
// When decompressing, leave CRC checking to decompressor
if (!decompress && img->file_cksum) {
if (cksum != img->file_cksum) {
printf("** Warning - checksum failure. stored: 0x%08lx, computed: 0x%08lx\n",
img->file_cksum, cksum);
}
}
#endif
}
#endif // CYGOPT_REDBOOT_FIS
static void
fis_write(int argc, char *argv[])
{
int stat;
unsigned long mem_addr, flash_addr, length;
bool mem_addr_set = false;
bool flash_addr_set = false;
bool length_set = false;
void *err_addr;
struct option_info opts[3];
bool prog_ok;
bool overlap = false;
init_opts(&opts[0], 'b', true, OPTION_ARG_TYPE_NUM,
(void **)&mem_addr, (bool *)&mem_addr_set, "memory base address");
init_opts(&opts[1], 'f', true, OPTION_ARG_TYPE_NUM,
(void **)&flash_addr, (bool *)&flash_addr_set, "FLASH memory base address");
init_opts(&opts[2], 'l', true, OPTION_ARG_TYPE_NUM,
(void **)&length, (bool *)&length_set, "image length [in FLASH]");
if (!scan_opts(argc, argv, 2, opts, 3, 0, 0, 0))
{
fis_usage("invalid arguments");
return;
}
if (!mem_addr_set || !flash_addr_set || !length_set) {
fis_usage("required parameter missing");
return;
}
// Round up length to FLASH block size
#ifndef CYGPKG_HAL_MIPS // FIXME: compiler is b0rken
length = ((length + block_size - 1) / block_size) * block_size;
#endif
if (flash_addr_set &&
((stat = flash_verify_addr((void *)flash_addr)) ||
(stat = flash_verify_addr((void *)(flash_addr+length-1))))) {
printf("Invalid FLASH address %p: (%s)\n", (void *)flash_addr, flash_errmsg(stat));
printf(" valid range is %p-%p\n", (void *)flash_start, (void *)flash_end);
return;
}
if (flash_addr_set && flash_addr & (block_size-1)) {
printf("Invalid FLASH address: %p\n", (void *)flash_addr);
printf(" must be 0x%x aligned\n", block_size);
return;
}
if ((mem_addr < (unsigned long)ram_start) ||
((mem_addr+length) >= (unsigned long)ram_end)) {
printf("** WARNING: RAM address: %p may be invalid\n", (void *)mem_addr);
printf(" valid range is %p-%p\n", (void *)ram_start, (void *)ram_end);
}
// Safety check - make sure the address range is not within the code we're running
if (flash_code_overlaps((void *)flash_addr, (void *)(flash_addr+length-1), &overlap)) {
return;
}
if (!verify_action("* CAUTION * about to program FLASH\n at %p..%p from %p",
(void *)flash_addr, (void *)(flash_addr+length-1),
(void *)mem_addr)) {
return; // The guy gave up
}
if(overlap)
{
flash_unlock((void *)flash_addr, length, (void **)&err_addr);
}
prog_ok = true;
if (prog_ok) {
// Erase area to be programmed
if ((stat = flash_erase((void *)flash_addr, length, (void **)&err_addr)) != 0) {
printf("Can't erase region at %p: %s\n", err_addr, flash_errmsg(stat));
prog_ok = false;
}
}
if (prog_ok) {
// Now program it
if ((stat = flash_program((void *)flash_addr, (void *)mem_addr, length, (void **)&err_addr)) != 0) {
printf("Can't program region at %p: %s\n", err_addr, flash_errmsg(stat));
prog_ok = false;
}
}
if(overlap)
{
flash_lock((void *)flash_addr, length, (void **)&err_addr);
}
}
static void
fis_erase(int argc, char *argv[])
{
int stat;
unsigned long flash_addr, length;
bool flash_addr_set = false;
bool length_set = false;
void *err_addr;
struct option_info opts[2];
bool overlap = false;
init_opts(&opts[0], 'f', true, OPTION_ARG_TYPE_NUM,
(void **)&flash_addr, (bool *)&flash_addr_set, "FLASH memory base address");
init_opts(&opts[1], 'l', true, OPTION_ARG_TYPE_NUM,
(void **)&length, (bool *)&length_set, "length");
if (!scan_opts(argc, argv, 2, opts, 2, (void **)0, 0, ""))
{
fis_usage("invalid arguments");
return;
}
if (!flash_addr_set || !length_set) {
fis_usage("missing argument");
return;
}
if (flash_addr_set &&
((stat = flash_verify_addr((void *)flash_addr)) ||
(stat = flash_verify_addr((void *)(flash_addr+length-1))))) {
printf("Invalid FLASH address %p: %s\n", (void *)flash_addr, flash_errmsg(stat));
printf(" valid range is %p-%p\n", (void *)flash_start, (void *)flash_end);
return;
}
if (flash_addr_set && flash_addr & (block_size-1)) {
printf("Invalid FLASH address: %p\n", (void *)flash_addr);
printf(" must be 0x%x aligned\n", block_size);
return;
}
// Safety check - make sure the address range is not within the code we're running
if (flash_code_overlaps((void *)flash_addr, (void *)(flash_addr+length-1), &overlap)) {
return;
}
if(overlap)
{
flash_unlock((void *)flash_addr, length, (void **)&err_addr);
}
if ((stat = flash_erase((void *)flash_addr, length, (void **)&err_addr)) != 0) {
printf("Error erasing at %p: %s\n", err_addr, flash_errmsg(stat));
}
if(overlap)
{
flash_lock((void *)flash_addr, length, (void **)&err_addr);
}
}
#ifdef CYGHWR_IO_FLASH_BLOCK_LOCKING
static void
fis_lock(int argc, char *argv[])
{
int stat;
unsigned long flash_addr, length;
bool flash_addr_set = false;
bool length_set = false;
void *err_addr;
struct option_info opts[2];
init_opts(&opts[0], 'f', true, OPTION_ARG_TYPE_NUM,
(void **)&flash_addr, (bool *)&flash_addr_set, "FLASH memory base address");
init_opts(&opts[1], 'l', true, OPTION_ARG_TYPE_NUM,
(void **)&length, (bool *)&length_set, "length");
if (!scan_opts(argc, argv, 2, opts, 2, (void **)0, 0, ""))
{
fis_usage("invalid arguments");
return;
}
if (!flash_addr_set || !length_set) {
fis_usage("missing argument");
return;
}
if (flash_addr_set &&
((stat = flash_verify_addr((void *)flash_addr)) ||
(stat = flash_verify_addr((void *)(flash_addr+length-1))))) {
printf("Invalid FLASH address %p: %s\n", (void *)flash_addr, flash_errmsg(stat));
printf(" valid range is %p-%p\n", (void *)flash_start, (void *)flash_end);
return;
}
if ((stat = flash_lock((void *)flash_addr, length, (void **)&err_addr)) != 0) {
printf("Error locking at %p: %s\n", err_addr, flash_errmsg(stat));
}
}
static void
fis_unlock(int argc, char *argv[])
{
int stat;
unsigned long flash_addr, length;
bool flash_addr_set = false;
bool length_set = false;
void *err_addr;
struct option_info opts[2];
init_opts(&opts[0], 'f', true, OPTION_ARG_TYPE_NUM,
(void **)&flash_addr, (bool *)&flash_addr_set, "FLASH memory base address");
init_opts(&opts[1], 'l', true, OPTION_ARG_TYPE_NUM,
(void **)&length, (bool *)&length_set, "length");
if (!scan_opts(argc, argv, 2, opts, 2, (void **)0, 0, ""))
{
fis_usage("invalid arguments");
return;
}
if (!flash_addr_set || !length_set) {
fis_usage("missing argument");
return;
}
if (flash_addr_set &&
((stat = flash_verify_addr((void *)flash_addr)) ||
(stat = flash_verify_addr((void *)(flash_addr+length-1))))) {
printf("Invalid FLASH address %p: %s\n", (void *)flash_addr, flash_errmsg(stat));
printf(" valid range is %p-%p\n", (void *)flash_start, (void *)flash_end);
return;
}
if ((stat = flash_unlock((void *)flash_addr, length, (void **)&err_addr)) != 0) {
printf("Error unlocking at %p: %s\n", err_addr, flash_errmsg(stat));
}
}
#endif
static int __flash_init = 0;
void
_flash_info(void)
{
if (!__flash_init) return;
printf("FLASH(%dM): %p - %p, %d blocks of %p bytes each.\n", (((int)flash_end - (int)flash_start) / (1024 * 1024)),
flash_start, flash_end, (int)blocks, (void *)block_size);
}
static bool
do_flash_init(void)
{
int stat;
if (!__flash_init) {
*(SP_FRM_REG) = USE_8_BIT_DATA;
if ((stat = flash_init((void *)(workspace_end-FLASH_MIN_WORKSPACE),
FLASH_MIN_WORKSPACE, printf)) != 0) {
printf("FLASH: driver init failed: %s\n", flash_errmsg(stat));
return false;
}
__flash_init = 1;
flash_get_limits((void *)0, (void **)&flash_start, (void **)&flash_end);
flash_get_block_info(&block_size, &blocks);
fis_work_block = (unsigned char *)(workspace_end-FLASH_MIN_WORKSPACE-block_size);
workspace_end = fis_work_block;
fisdir_size = block_size;
}
return true;
}
#ifndef CYGOPT_REDBOOT_FLASH_CONFIG
RedBoot_init(do_flash_init, RedBoot_INIT_FIRST);
#endif
static void
do_fis(int argc, char *argv[])
{
struct cmd *cmd;
if (argc < 2) {
fis_usage("too few arguments");
return;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -