diff packages/redboot/current/src/flash.c @ 132:0ae0bc38e387 ecos-sw-2000-10-31

Merge from eCos master repository on 2000-10-31-00:30:36-GMT
author jlarmour
date Tue, 31 Oct 2000 20:53:09 +0000
parents eb9fd8c04db3
children 289bf90c6a9b
line wrap: on
line diff
--- a/packages/redboot/current/src/flash.c
+++ b/packages/redboot/current/src/flash.c
@@ -70,7 +70,7 @@ local_cmd_entry("init",
     );
 local_cmd_entry("list",
                 "Display contents of FLASH Image System [FIS]",
-                "",
+                "[-c]",
                 fis_list,
                 FIS_cmds
     );
@@ -108,7 +108,7 @@ local_cmd_entry("delete",
     );
 local_cmd_entry("load",
                 "Load image from FLASH Image System [FIS] into RAM",
-                "name",
+                "[-b <memory_load_address>] [-c] name",
                 fis_load,
                 FIS_cmds
     );
@@ -130,6 +130,38 @@ static void *flash_start, *flash_end;
 static int block_size, blocks;
 static void *fis_work_block;
 
+// Simple XOR style checksum
+static unsigned long
+_cksum(unsigned long *buf, int len)
+{
+    unsigned long cksum = 0;
+
+    // Round 'len' up to multiple of longwords
+    len = (len + (sizeof(unsigned long)-1)) / sizeof(unsigned long);   
+    while (len-- > 0) {
+        cksum ^= *buf++;
+    }
+    return cksum;
+}
+
+struct fis_image_desc *
+fis_lookup(char *name)
+{
+    int i;
+    void *fis_addr;
+    struct fis_image_desc *img;
+
+    fis_addr = (void *)((unsigned long)flash_end - block_size);
+    memcpy(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)) {
+            return img;
+        }
+    }
+    return (struct fis_image_desc *)0;
+}
+
 static void
 fis_usage(char *why)
 {
@@ -205,6 +237,10 @@ fis_init(int argc, char *argv[])
     img->mem_base = (unsigned long)fis_base;
     img->size = block_size;
     img++;  img_count++;
+#ifdef CYGSEM_REDBOOT_FLASH_LOCK_SPECIAL
+    // Insure [quietly] that the directory is unlocked before trying to update
+    flash_unlock((void *)fis_base, block_size, (void **)&err_addr);
+#endif
     if ((stat = flash_erase(fis_base, block_size, (void **)&err_addr)) != 0) {
             printf("   initialization failed %p: %x(%s)\n", err_addr, stat, flash_errmsg(stat));
     } else {
@@ -214,6 +250,10 @@ fis_init(int argc, char *argv[])
                    err_addr, stat, flash_errmsg(stat));
         }
     }
+#ifdef CYGSEM_REDBOOT_FLASH_LOCK_SPECIAL
+    // Insure [quietly] that the directory is locked after the update
+    flash_lock((void *)fis_base, block_size, (void **)&err_addr);
+#endif
 }
 
 static void
@@ -221,13 +261,25 @@ fis_list(int argc, char *argv[])
 {
     struct fis_image_desc *img;
     int i;
+    bool show_cksums = false;
+    struct option_info opts[1];
+
+    init_opts(&opts[0], 'c', false, OPTION_ARG_TYPE_FLG, 
+              (void **)&show_cksums, (bool *)0, "display checksums");
+    if (!scan_opts(argc, argv, 2, opts, 1, 0, 0, ""))
+    {
+        return;
+    }
 
     img = (struct fis_image_desc *)((unsigned long)flash_end - block_size);    
-    printf("Name              FLASH addr   Mem addr    Length    Entry point\n");
+    printf("Name              FLASH addr   %s    Length      Entry point\n",
+           show_cksums ? "Checksum" : "Mem addr");
     for (i = 0;  i < block_size/sizeof(*img);  i++, img++) {
         if (img->name[0] != (unsigned char)0xFF) {
-            printf("%-16s  0x%08lX   0x%08lX  0x%06lX  0x%08lX\n", img->name, 
-                   img->flash_base, img->mem_base, img->size, img->entry_point);
+            printf("%-16s  0x%08lX   0x%08lX  0x%08lX  0x%08lX\n", img->name, 
+                   img->flash_base, 
+                   show_cksums ? img->file_cksum : img->mem_base, 
+                   img->size, img->entry_point);
         }
     }
 }
@@ -440,6 +492,12 @@ fis_create(int argc, char *argv[])
     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;
+    img->file_cksum = _cksum((unsigned long *)mem_addr, img_size);
+#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: %x(%s)\n", err_addr, stat, flash_errmsg(stat));
         // Don't try to program if the erase failed
@@ -449,6 +507,10 @@ fis_create(int argc, char *argv[])
             printf("Error programming at %p: %x(%s)\n", err_addr, stat, 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
@@ -605,6 +667,10 @@ fis_delete(int argc, char *argv[])
     if ((stat = flash_erase((void *)img->flash_base, img->size, (void **)&err_addr)) != 0) {
         printf("Error erasing at %p: %x(%s)\n", err_addr, stat, 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) {
@@ -616,45 +682,56 @@ fis_delete(int argc, char *argv[])
             printf("Error programming at %p: %x(%s)\n", err_addr, stat, 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;
-    int i;
-    void *fis_addr;
     struct fis_image_desc *img;
-    bool slot_found;
+    unsigned long mem_addr;
+    bool mem_addr_set = false;
+    bool show_cksum = false;
+    struct option_info opts[2];
 
-    if (!scan_opts(argc, argv, 2, 0, 0, (void **)&name, OPTION_ARG_TYPE_STR, "image name"))
+    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");
+    if (!scan_opts(argc, argv, 2, opts, 2, (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);
-    memcpy(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)) {
-            slot_found = true;
-            break;
-        }
-    }
-    if (!slot_found) {
+    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 ((img->mem_base < (unsigned long)ram_start) ||
-        ((img->mem_base+img->size) >= (unsigned long)ram_end)) {
+    if ((mem_addr < (unsigned long)ram_start) ||
+        ((mem_addr+img->size) >= (unsigned long)ram_end)) {
         printf("Not a loadable image\n");
         return;
     }
-    memcpy((void *)img->mem_base, (void *)img->flash_base, img->size);
+    memcpy((void *)mem_addr, (void *)img->flash_base, img->size);
     entry_address = (unsigned long *)img->entry_point;
+    if (img->file_cksum) {
+        unsigned long cksum = _cksum((unsigned long *)mem_addr, img->data_length);
+        if (cksum != img->file_cksum) {
+            printf("** Warning - checksum failure.  stored: %08lx, computed: %08lx\n",
+                   img->file_cksum, cksum);
+        }
+        if (show_cksum) {
+            printf("Checksum: %08lx\n", cksum);
+        }
+    }
 }
 
 static bool
@@ -672,7 +749,7 @@ do_flash_init(void)
         }
         flash_get_limits((void *)0, (void **)&flash_start, (void **)&flash_end);
         flash_get_block_info(&block_size, &blocks);
-        printf("FLASH: %p - %p, %d blocks of %p bytes ea.\n", 
+        printf("FLASH: %p - %p, %d blocks of %p bytes each.\n", 
                flash_start, flash_end, blocks, (void *)block_size);
         fis_work_block = (unsigned char *)(ram_end-FLASH_MIN_WORKSPACE-block_size);
     }
@@ -904,7 +981,7 @@ get_config(struct config_option *opt, in
 // over time.
 
 static unsigned long
-_cksum(unsigned long *buf, int len)
+_fconfig_cksum(unsigned long *buf, int len)
 {
     unsigned long cksum = 0;
     int shift = 0;
@@ -993,9 +1070,13 @@ do_flash_config(int argc, char *argv[])
  done:
     if (!need_update) return;
     config.key1 = CONFIG_KEY1;  config.key2 = CONFIG_KEY2;
-    config.cksum = _cksum((unsigned long *)&config, sizeof(config)-sizeof(config.cksum));
+    config.cksum = _fconfig_cksum((unsigned long *)&config, sizeof(config)-sizeof(config.cksum));
     cfg_base = (void *)((unsigned long)flash_end - (2*block_size));
     if (verify_action("Update RedBoot non-volatile configuration")) {
+#ifdef CYGSEM_REDBOOT_FLASH_LOCK_SPECIAL
+        // Insure [quietly] that the config page is unlocked before trying to update
+        flash_unlock((void *)cfg_base, block_size, (void **)&err_addr);
+#endif
         if ((stat = flash_erase(cfg_base, block_size, (void **)&err_addr)) != 0) {
             printf("   initialization failed %p: %x(%s)\n", err_addr, stat, flash_errmsg(stat));
         } else {
@@ -1005,6 +1086,10 @@ do_flash_config(int argc, char *argv[])
                        err_addr, stat, flash_errmsg(stat));
             }
         }
+#ifdef CYGSEM_REDBOOT_FLASH_LOCK_SPECIAL
+        // Insure [quietly] that the config data is locked after the update
+        flash_lock((void *)cfg_base, block_size, (void **)&err_addr);
+#endif
     }
 }
 
@@ -1072,7 +1157,7 @@ load_flash_config(void)
     if (!do_flash_init()) return;
     cfg_base = (void *)((unsigned long)flash_end - (2*block_size));
     memcpy(&config, cfg_base, sizeof(config));
-    if ((_cksum((unsigned long *)&config, sizeof(config)-sizeof(config.cksum)) != config.cksum) ||
+    if ((_fconfig_cksum((unsigned long *)&config, sizeof(config)-sizeof(config.cksum)) != config.cksum) ||
         (config.key1 != CONFIG_KEY1)|| (config.key2 != CONFIG_KEY2)) {
         printf("FLASH configuration checksum error or invalid key\n");
         memset(&config, 0, sizeof(config));