Mercurial > flash_v2
changeset 1297:4212c82ebff6
Make 'fis free' use the FIS directory to determine what's free
| author | gthomas |
|---|---|
| date | Sat, 11 Oct 2003 21:22:32 +0000 |
| parents | 498ac6b4af79 |
| children | 3487ed83fe0c |
| files | packages/redboot/current/ChangeLog packages/redboot/current/cdl/redboot.cdl packages/redboot/current/src/flash.c |
| diffstat | 3 files changed, 107 insertions(+), 0 deletions(-) [+] |
line wrap: on
line diff
--- a/packages/redboot/current/ChangeLog +++ b/packages/redboot/current/ChangeLog @@ -1,3 +1,11 @@ +2003-10-11 Gary Thomas <gary@mlbassoc.com> + + * src/flash.c: + * cdl/redboot.cdl: Change 'fis free' to use the directory structure + to determine what space is free in the FLASH. This is controlled + by the CDL option CYGDAT_REDBOOT_FIS_MAX_FREE_CHUNKS so the old + behaviour can still be defined if desired. + 2003-10-09 Gary Thomas <gary@mlbassoc.com> * src/flash.c (fis_create): Check whole length of image, not just
--- a/packages/redboot/current/cdl/redboot.cdl +++ b/packages/redboot/current/cdl/redboot.cdl @@ -545,6 +545,20 @@ cdl_package CYGPKG_REDBOOT { FLASH manipulation, but do not have the need or space for complete image management." } + + cdl_option CYGDAT_REDBOOT_FIS_MAX_FREE_CHUNKS { + display "Max number of chunks of free space to manage" + flavor booldata + default_value 32 + description " + If this option is defined then \"fis free\" will rely on the + FIS directory to determine what space is free within the FLASH. + This option controls the maximum number of free segment which + can be handled (typically this number is small). If this option + is not enabled, the the archaic behaviour of actually scanning + the FLASH for erased sectors (unreliable) will be used to + determine what's free and what's not." + } cdl_component CYGPKG_REDBOOT_FIS_CONTENTS { display "Flash Image System default directory contents"
--- a/packages/redboot/current/src/flash.c +++ b/packages/redboot/current/src/flash.c @@ -508,9 +508,71 @@ fis_list(int argc, char *argv[]) } while (image_found == true); } +#ifdef CYGDAT_REDBOOT_FIS_MAX_FREE_CHUNKS +struct free_chunk { + CYG_ADDRESS start, end; +}; + +static int +find_free(struct free_chunk *chunks) +{ + CYG_ADDRESS *fis_ptr, *fis_end; + void *err_addr; + struct fis_image_desc *img; + int i, idx; + int num_chunks = 1; + + // Do not search the area reserved for pre-RedBoot systems: + fis_ptr = (CYG_ADDRESS *)((CYG_ADDRESS)flash_start + + CYGNUM_REDBOOT_FLASH_RESERVED_BASE + + CYGBLD_REDBOOT_MIN_IMAGE_SIZE); + fis_end = (CYG_ADDRESS *)(CYG_ADDRESS)flash_end; + chunks[num_chunks-1].start = (CYG_ADDRESS)fis_ptr; + chunks[num_chunks-1].end = (CYG_ADDRESS)fis_end; + 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) { + // Figure out which chunk this is in and split it + for (idx = 0; idx < num_chunks; idx++) { + if ((img->flash_base >= chunks[idx].start) && + (img->flash_base <= chunks[idx].end)) { + if (img->flash_base == chunks[idx].start) { + chunks[idx].start += img->size; + if (chunks[idx].start == chunks[idx].end) { + // This free chunk has collapsed + while (idx < (num_chunks-1)) { + chunks[idx] = chunks[idx+1]; + } + num_chunks--; + } + } else if ((img->flash_base+img->size) == chunks[idx].end) { + chunks[idx].end = img->flash_base; + } else { + // Split chunk into two parts + if ((img->flash_base+img->size) < (CYG_ADDRESS)fis_end) { + chunks[idx+1].start = img->flash_base + img->size; + chunks[idx+1].end = chunks[idx].end; + if (++num_chunks == CYGDAT_REDBOOT_FIS_MAX_FREE_CHUNKS) { + diag_printf("Warning: too many free chunks\n"); + return num_chunks; + } + } + chunks[idx].end = img->flash_base; + } + break; + } + } + } + } + return num_chunks; +} +#endif // CYGDAT_REDBOOT_FIS_MAX_FREE_CHUNKS + static void fis_free(int argc, char *argv[]) { +#ifndef CYGDAT_REDBOOT_FIS_MAX_FREE_CHUNKS unsigned long *fis_ptr, *fis_end, flash_data; unsigned long *area_start; void *err_addr; @@ -547,12 +609,22 @@ fis_free(int argc, char *argv[]) diag_printf(" 0x%08lX .. 0x%08lX\n", (CYG_ADDRESS)area_start, (CYG_ADDRESS)fis_ptr); } +#else + struct free_chunk chunks[CYGDAT_REDBOOT_FIS_MAX_FREE_CHUNKS]; + int idx, num_chunks; + + num_chunks = find_free(chunks); + for (idx = 0; idx < num_chunks; idx++) { + diag_printf(" 0x%08lX .. 0x%08lX\n", chunks[idx].start, chunks[idx].end); + } +#endif } // Find the first unused area of flash which is long enough static bool fis_find_free(CYG_ADDRESS *addr, unsigned long length) { +#ifndef CYGDAT_REDBOOT_FIS_MAX_FREE_CHUNKS unsigned long *fis_ptr, *fis_end, flash_data; unsigned long *area_start; void *err_addr; @@ -594,6 +666,19 @@ fis_find_free(CYG_ADDRESS *addr, unsigne } } return false; +#else + struct free_chunk chunks[CYGDAT_REDBOOT_FIS_MAX_FREE_CHUNKS]; + int idx, num_chunks; + + num_chunks = find_free(chunks); + for (idx = 0; idx < num_chunks; idx++) { + if ((chunks[idx].end - chunks[idx].start) >= length) { + *addr = (CYG_ADDRESS)chunks[idx].start; + return true; + } + } + return false; +#endif } static void
