This is the mail archive of the
ecos-patches@sources.redhat.com
mailing list for the eCos project.
RedBoot - FIS free relies on directory
- From: Gary Thomas <gary at mlbassoc dot com>
- To: eCos patches <ecos-patches at ecos dot sourceware dot org>
- Date: 11 Oct 2003 15:23:59 -0600
- Subject: RedBoot - FIS free relies on directory
- Organization: MLB Associates
'fis free' used to just scan the FLASH to decide what was free.
This was unreliable, and sometimes even dangerous. This new
behaviour will rely on the FIS directory contents to get it
right.
--
Gary Thomas <gary@mlbassoc.com>
MLB Associates
Index: redboot/current/ChangeLog
===================================================================
RCS file: /misc/cvsfiles/ecos/packages/redboot/current/ChangeLog,v
retrieving revision 1.149
diff -u -5 -p -r1.149 ChangeLog
--- redboot/current/ChangeLog 9 Oct 2003 21:34:03 -0000 1.149
+++ redboot/current/ChangeLog 11 Oct 2003 21:20:23 -0000
@@ -1,5 +1,13 @@
+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
effective size, when validating addresses.
Index: redboot/current/cdl/redboot.cdl
===================================================================
RCS file: /misc/cvsfiles/ecos/packages/redboot/current/cdl/redboot.cdl,v
retrieving revision 1.56
diff -u -5 -p -r1.56 redboot.cdl
--- redboot/current/cdl/redboot.cdl 2 Oct 2003 20:13:29 -0000 1.56
+++ redboot/current/cdl/redboot.cdl 11 Oct 2003 21:17:05 -0000
@@ -543,10 +543,24 @@ cdl_package CYGPKG_REDBOOT {
access commands such as \"fis write\" will still exist.
This option would be disabled for targets that need simple
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"
active_if CYGOPT_REDBOOT_FIS
calculated 1
Index: redboot/current/src/flash.c
===================================================================
RCS file: /misc/cvsfiles/ecos/packages/redboot/current/src/flash.c,v
retrieving revision 1.55
diff -u -5 -p -r1.55 flash.c
--- redboot/current/src/flash.c 9 Oct 2003 21:34:04 -0000 1.55
+++ redboot/current/src/flash.c 11 Oct 2003 21:17:03 -0000
@@ -506,13 +506,75 @@ fis_list(int argc, char *argv[])
}
last_addr = lowest_addr;
} 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;
// Do not search the area reserved for pre-RedBoot systems:
@@ -545,16 +607,26 @@ fis_free(int argc, char *argv[])
}
if (area_start != fis_ptr) {
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;
// Do not search the area reserved for pre-RedBoot systems:
@@ -592,10 +664,23 @@ fis_find_free(CYG_ADDRESS *addr, unsigne
*addr = (CYG_ADDRESS)area_start;
return true;
}
}
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
fis_create(int argc, char *argv[])
{