📄 flash.c
字号:
charcpy((unsigned char *)&temp, (unsigned char *)img, sizeof(temp));
if (temp.name[0] != (unsigned char)0xFF) {
printf("%-16s 0x%08lX 0x%08lX 0x%08lX 0x%08lX\n", temp.name,
temp.flash_base,
#ifdef CYGSEM_REDBOOT_FIS_CRC_CHECK
show_cksums ? temp.file_cksum : temp.mem_base,
show_datalen ? temp.data_length : temp.size,
#else
temp.mem_base,
temp.size,
#endif
temp.entry_point);
}
}
}
static void
fis_free(int argc, char *argv[])
{
unsigned long *fis_ptr, *fis_end;
unsigned long *area_start;
// Do not search the area reserved for pre-RedBoot systems:
fis_ptr = (unsigned long *)((unsigned long)flash_start + CYGNUM_REDBOOT_FLASH_RESERVED_BASE);
fis_end = (unsigned long *)(unsigned long)flash_end;
area_start = fis_ptr;
while (fis_ptr < fis_end) {
if (*fis_ptr != (unsigned long)0xFFFFFFFF) {
if (area_start != fis_ptr) {
// Assume that this is something
printf(" 0x%08lX .. 0x%08lX\n",
(unsigned long)area_start, (unsigned long)fis_ptr);
}
// Find next blank block
area_start = fis_ptr;
while (area_start < fis_end) {
if (*area_start == (unsigned long)0xFFFFFFFF) {
break;
}
area_start += block_size / sizeof(unsigned long);
}
fis_ptr = area_start;
} else {
fis_ptr += block_size / sizeof(unsigned long);
}
}
if (area_start != fis_ptr) {
printf(" 0x%08lX .. 0x%08lX\n",
(unsigned long)area_start, (unsigned long)fis_ptr);
}
}
// Find the first unused area of flash which is long enough
static bool
fis_find_free(unsigned long *addr, unsigned long length)
{
unsigned long *fis_ptr, *fis_end;
unsigned long *area_start;
// Do not search the area reserved for pre-RedBoot systems:
fis_ptr = (unsigned long *)((unsigned long)flash_start + CYGNUM_REDBOOT_FLASH_RESERVED_BASE);
fis_end = (unsigned long *)(unsigned long)flash_end;
area_start = fis_ptr;
while (fis_ptr < fis_end) {
if (*fis_ptr != (unsigned long)0xFFFFFFFF) {
if (area_start != fis_ptr) {
// Assume that this is something
if ((fis_ptr-area_start) >= (length/sizeof(unsigned long))) {
*addr = (unsigned long)area_start;
return true;
}
}
// Find next blank block
area_start = fis_ptr;
while (area_start < fis_end) {
if (*area_start == (unsigned long)0xFFFFFFFF) {
break;
}
area_start += block_size / sizeof(unsigned long);
}
fis_ptr = area_start;
} else {
fis_ptr += block_size / sizeof(unsigned long);
}
}
if (area_start != fis_ptr) {
if ((fis_ptr-area_start) >= (length/sizeof(unsigned long))) {
*addr = (unsigned long)area_start;
return true;
}
}
return false;
}
static void
fis_create(int argc, char *argv[])
{
int i, stat;
unsigned long mem_addr, exec_addr, flash_addr, entry_addr, length, img_size;
char *name;
bool mem_addr_set = false;
bool exec_addr_set = false;
bool entry_addr_set = false;
bool flash_addr_set = false;
bool length_set = false;
bool img_size_set = false;
bool no_copy = false;
void *fis_addr, *err_addr;
struct fis_image_desc *img;
bool slot_found, defaults_assumed;
struct option_info opts[7];
bool prog_ok = false;
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], 'r', true, OPTION_ARG_TYPE_NUM,
(void **)&exec_addr, (bool *)&exec_addr_set, "ram base address");
init_opts(&opts[2], 'e', true, OPTION_ARG_TYPE_NUM,
(void **)&entry_addr, (bool *)&entry_addr_set, "entry point address");
init_opts(&opts[3], 'f', true, OPTION_ARG_TYPE_NUM,
(void **)&flash_addr, (bool *)&flash_addr_set, "FLASH memory base address");
init_opts(&opts[4], 'l', true, OPTION_ARG_TYPE_NUM,
(void **)&length, (bool *)&length_set, "image length [in FLASH]");
init_opts(&opts[5], 's', true, OPTION_ARG_TYPE_NUM,
(void **)&img_size, (bool *)&img_size_set, "image size [actual data]");
init_opts(&opts[6], 'n', false, OPTION_ARG_TYPE_FLG,
(void **)&no_copy, (bool *)0, "don't copy from RAM to FLASH, just update directory");
if (!scan_opts(argc, argv, 2, opts, 7, (void *)&name, OPTION_ARG_TYPE_STR, "file name"))
{
fis_usage("invalid arguments");
return;
}
defaults_assumed = false;
if (name) {
// Search existing files to acquire defaults for params not specified:
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)) {
// Found it, so get any unset but necessary params from there:
if (!length_set) {
length_set = true;
length = img->size;
defaults_assumed = true;
}
if (!exec_addr_set) {
// Preserve "normal" behaviour
exec_addr_set = true;
exec_addr = flash_addr_set ? flash_addr : mem_addr;
}
if (!flash_addr_set) {
flash_addr_set = true;
flash_addr = img->flash_base;
defaults_assumed = true;
}
break;
}
}
}
if ((!no_copy && !mem_addr_set) || (no_copy && !flash_addr_set) ||
!length_set || !name) {
fis_usage("required parameter missing");
return;
}
if (!img_size_set) {
img_size = length;
}
// 'length' is size of FLASH image, 'img_size' is actual data size
// Round up length to FLASH block size
#ifndef CYGPKG_HAL_MIPS // FIXME: compiler is b0rken
length = ((length + block_size - 1) / block_size) * block_size;
if (length < img_size) {
printf("Invalid FLASH image size/length combination\n");
return;
}
#endif
if (flash_addr_set &&
((stat = flash_verify_addr((void *)flash_addr)) ||
(stat = flash_verify_addr((void *)(flash_addr+img_size-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 (strlen(name) >= sizeof(img->name)) {
printf("Name is too long, must be less than %d chars\n", (int)sizeof(img->name));
return;
}
if (!no_copy) {
if ((mem_addr < (unsigned long)ram_start) ||
((mem_addr+img_size) >= (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);
}
if (!flash_addr_set && !fis_find_free(&flash_addr, length)) {
printf("Can't locate %ld bytes free in FLASH\n", length);
return;
}
}
// Find a slot in the directory for this entry
// First, see if an image by this name is already present
slot_found = false;
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)) {
if (flash_addr_set && (img->flash_base != flash_addr)) {
printf("Image found, but FLASH address incorrect\n");
return;
}
if (img->size != length) {
printf("Image found, but LENGTH is incorrect (0x%lx != 0x%lx)\n", img->size, length);
return;
}
if (!verify_action("An image named '%s' exists", name)) {
return;
} else {
slot_found = true;
if (defaults_assumed) {
if (!verify_action("* CAUTION * about to program '%s'\n at %p..%p from %p",
name, (void *)flash_addr, (void *)(flash_addr+img_size-1),
(void *)mem_addr)) {
return; // The guy gave up
}
}
break;
}
}
}
// If not found, try and find an empty slot
if (!slot_found) {
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) {
slot_found = true;
break;
}
}
}
if (!no_copy) {
// 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+img_size-1), &overlap)) {
return;
}
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, img_size, (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);
}
}
if (prog_ok) {
// Update directory
memset(img, 0, sizeof(*img));
strcpy(img->name, name);
img->flash_base = flash_addr;
img->mem_base = exec_addr_set ? exec_addr : (flash_addr_set ? flash_addr : mem_addr);
img->entry_point = entry_addr_set ? entry_addr : (unsigned long)entry_address; // Hope it's been set
img->size = length;
img->data_length = img_size;
#ifdef CYGSEM_REDBOOT_FIS_CRC_CHECK
img->file_cksum = crc32((unsigned char *)flash_addr, img_size);
#endif
#ifdef CYGSEM_REDBOOT_FLASH_LOCK_SPECIAL
// Insure [quietly] that the directory is unlocked before trying to update
flash_unlock((void *)fis_addr, block_size, (void **)&err_addr);
#endif
if ((stat = flash_erase((void *)fis_addr, block_size, (void **)&err_addr)) != 0) {
printf("Error erasing at %p: %s\n", err_addr, flash_errmsg(stat));
// Don't try to program if the erase failed
} 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_delete(int argc, char *argv[])
{
char *name;
int i, stat;
void *fis_addr, *err_addr;
struct fis_image_desc *img;
bool slot_found;
if (!scan_opts(argc, argv, 2, 0, 0, (void **)&name, OPTION_ARG_TYPE_STR, "image name"))
{
fis_usage("invalid arguments");
return;
}
slot_found = false;
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;
i = 0;
#ifdef CYGOPT_REDBOOT_FIS_RESERVED_BASE
i++;
#endif
#ifdef CYGOPT_REDBOOT_FIS_REDBOOT
i++;
#endif
#ifdef CYGOPT_REDBOOT_FIS_REDBOOT_BACKUP
i++;
#endif
#ifdef CYGOPT_REDBOOT_FIS_REDBOOT_POST
i++;
#endif
#ifdef CYGSEM_REDBOOT_FLASH_CONFIG
i++;
#endif
#if 1 // And the descriptor for the descriptor table itself
i++;
#endif
img += i; // Skip reserved files
for ( /* i, img */; i < block_size/sizeof(*img); i++, img++) {
if ((img->name[0] != (unsigned char)0xFF) && (strcmp(name, img->name) == 0)) {
if (!verify_action("Delete image '%s'", name)) {
return;
} else {
slot_found = true;
break;
}
}
}
if (!slot_found) {
printf("No image '%s' found\n", name);
return;
}
// Erase Data blocks (free space)
if ((stat = flash_erase((void *)img->flash_base, img->size, (void **)&err_addr)) != 0) {
printf("Error erasing at %p: %s\n", err_addr, flash_errmsg(stat));
}
#ifdef CYGSEM_REDBOOT_FLASH_LOCK_SPECIAL
// Insure [quietly] that the directory is unlocked before trying to update
flash_unlock((void *)fis_addr, block_size, (void **)&err_addr);
#endif
// Update directory
memset(img, 0xFF, sizeof(*img));
if ((stat = flash_erase((void *)fis_addr, block_size, (void **)&err_addr)) != 0) {
printf("Error erasing at %p: %s\n", err_addr, flash_errmsg(stat));
// Don't try to program if the erase failed
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -