This is the mail archive of the ecos-patches@sources.redhat.com mailing list for the eCos project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

RedBoot - FIS free relies on directory


'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[])
 {

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]