changeset 1740:0031b615f51c

Add support for reverse endianess of fis and config data
author msalter
date Wed, 01 Sep 2004 21:21:30 +0000
parents 5ee8bd19b4f5
children 3480e423c3a2
files packages/redboot/current/ChangeLog packages/redboot/current/cdl/redboot.cdl packages/redboot/current/include/redboot.h packages/redboot/current/src/fconfig.c packages/redboot/current/src/flash.c packages/redboot/current/src/main.c
diffstat 6 files changed, 188 insertions(+), 33 deletions(-) [+]
line wrap: on
line diff
--- a/packages/redboot/current/ChangeLog
+++ b/packages/redboot/current/ChangeLog
@@ -1,3 +1,14 @@
+2004-09-01  Mark Salter  <msalter@redhat.com>
+
+	* cdl/redboot.cdl (CYGOPT_REDBOOT_FLASH_BYTEORDER): New option.
+	* include/redboot.h: Define FLASH_{READ,PROGRAM} macros.
+	Define REDBOOT_FLASH_REVERSE_BYTEORDER if appropriate.
+	* src/flash.c: Add support for CYGOPT_REDBOOT_FLASH_BYTEORDER.
+	Use FLASH_{READ,PROGRAM} macros instead of flash driver api.
+	* src/fconfig.c: Ditto.
+
+	* src/main.c (do_version): Update copyright message.
+
 2004-08-31  Jonathan Larmour  <jifl@eCosCentric.com>
 
 	* src/flash.c (fis_init): Avoid potentially unnecessary erase
--- a/packages/redboot/current/cdl/redboot.cdl
+++ b/packages/redboot/current/cdl/redboot.cdl
@@ -574,6 +574,16 @@ cdl_package CYGPKG_REDBOOT {
               into memory for execution or executed in place."
             compile -library=libextras.a flash.c
     
+            cdl_option CYGOPT_REDBOOT_FLASH_BYTEORDER {
+                display         "Byte order used to store info in flash."
+                flavor          data
+                default_value   { "NATURAL" }
+                legal_values    {"NATURAL" "MSBFIRST" "LSBFIRST" }
+                description "
+                    This option controls the byte ordering used to store
+                    the FIS directory info and flash config info."
+            }
+    
             cdl_option CYGOPT_REDBOOT_FIS {
                 display         "RedBoot Flash Image System support"
                 default_value   1
--- a/packages/redboot/current/include/redboot.h
+++ b/packages/redboot/current/include/redboot.h
@@ -8,7 +8,7 @@
 //####ECOSGPLCOPYRIGHTBEGIN####
 // -------------------------------------------
 // This file is part of eCos, the Embedded Configurable Operating System.
-// Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc.
+// Copyright (C) 1998, 1999, 2000, 2001, 2002, 2004 Red Hat, Inc.
 // Copyright (C) 2002, 2003, 2004 Gary Thomas
 //
 // eCos is free software; you can redistribute it and/or modify it under
@@ -60,6 +60,7 @@
 #include <pkgconf/hal.h>
 #include <cyg/hal/hal_if.h>
 #include <cyg/hal/hal_tables.h>
+#include <cyg/hal/hal_endian.h>
 #include <cyg/infra/diag.h>
 #include <cyg/crc/crc.h>
 #include <string.h>
@@ -481,4 +482,27 @@ isalnum(int c)
 
 #endif // CYGSEM_REDBOOT_BSP_SYSCALLS
 
+
+//----------------------------------------------------------------------------
+// Allow HAL to override RedBoot flash read/program operations.
+#ifdef HAL_FLASH_READ
+#define FLASH_READ(f, r, l, e) HAL_FLASH_READ((f),(r),(l),(e))
+#else
+#define FLASH_READ(f, r, l, e) flash_read((f), (r), (l), (e))
+#endif
+
+#ifdef HAL_FLASH_PROGRAM
+#define FLASH_PROGRAM(f, r, l, e) HAL_FLASH_PROGRAM((f),(r),(l),(e))
+#else
+#define FLASH_PROGRAM(f, r, l, e) flash_program((f), (r), (l), (e))
+#endif
+
+
+// Define REDBOOT_FLASH_REVERSE_BYTEORDER if config and fis info is stored in flash
+// with byte ordering opposite from CYG_BYTEORDER. 
+#if (defined(CYGOPT_REDBOOT_FLASH_BYTEORDER_MSBFIRST) && (CYG_BYTEORDER != CYG_MSBFIRST)) || \
+    (defined(CYGOPT_REDBOOT_FLASH_BYTEORDER_LSBFIRST) && (CYG_BYTEORDER != CYG_LSBFIRST))
+#define REDBOOT_FLASH_REVERSE_BYTEORDER
+#endif
+
 #endif // _REDBOOT_H_
--- a/packages/redboot/current/src/fconfig.c
+++ b/packages/redboot/current/src/fconfig.c
@@ -8,7 +8,7 @@
 //####ECOSGPLCOPYRIGHTBEGIN####
 // -------------------------------------------
 // This file is part of eCos, the Embedded Configurable Operating System.
-// Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003 Red Hat, Inc.
+// Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004 Red Hat, Inc.
 // Copyright (C) 2003 Gary Thomas
 //
 // eCos is free software; you can redistribute it and/or modify it under
@@ -54,12 +54,14 @@
 //==========================================================================
 
 #include <redboot.h>
+#include <cyg/io/flash.h>
 #ifdef CYGOPT_REDBOOT_FIS
 #include <fis.h>
 #endif
 
 #ifdef CYGSEM_REDBOOT_FLASH_COMBINED_FIS_AND_CONFIG
 // Note horrid intertwining of functions, to save precious FLASH
+externC void fis_read_directory(void);
 externC void fis_update_directory(void);
 #endif
 
@@ -191,6 +193,60 @@ extern struct config_option __CONFIG_opt
 #define LIST_OPT_DUMBTERM  (8)
 
 static void config_init(void);
+static int  config_length(int type);
+
+// Change endianness of config data
+void
+conf_endian_fixup(void *ptr)
+{
+#ifdef REDBOOT_FLASH_REVERSE_BYTEORDER
+    struct _config *p = (struct _config *)ptr;
+    unsigned char *dp = p->config_data;
+    void *val_ptr;
+    int len;
+    cyg_uint16 u16;
+    cyg_uint32 u32;
+
+    p->len = CYG_SWAP32(p->len);
+    p->key1 = CYG_SWAP32(p->key1);
+    p->key2 = CYG_SWAP32(p->key2);
+    p->cksum = CYG_SWAP32(p->cksum);
+
+    while (dp < &p->config_data[sizeof(config->config_data)]) {
+        len = 4 + CONFIG_OBJECT_KEYLEN(dp) + CONFIG_OBJECT_ENABLE_KEYLEN(dp) +
+            config_length(CONFIG_OBJECT_TYPE(dp));
+        val_ptr = (void *)CONFIG_OBJECT_VALUE(dp);
+
+        switch (CONFIG_OBJECT_TYPE(dp)) {
+            // Note: the data may be unaligned in the configuration data
+        case CONFIG_BOOL:
+            if (sizeof(bool) == 2) {
+                memcpy(&u16, val_ptr, 2);
+                u16 = CYG_SWAP16(u16);
+                memcpy(val_ptr, &u16, 2);
+            } else if (sizeof(bool) == 4) {
+                memcpy(&u32, val_ptr, 4);
+                u32 = CYG_SWAP32(u32);
+                memcpy(val_ptr, &u32, 4);
+            }
+            break;
+        case CONFIG_INT:
+            if (sizeof(unsigned long) == 2) {
+                memcpy(&u16, val_ptr, 2);
+                u16 = CYG_SWAP16(u16);
+                memcpy(val_ptr, &u16, 2);
+            } else if (sizeof(unsigned long) == 4) {
+                memcpy(&u32, val_ptr, 4);
+                u32 = CYG_SWAP32(u32);
+                memcpy(val_ptr, &u32, 4);
+            }
+            break;
+        }
+
+        dp += len;
+    }
+#endif
+}
 
 static int
 get_config(unsigned char *dp, char *title, int list_opt, char *newvalue )
@@ -683,6 +739,28 @@ flash_lookup_alias(char *alias, char *al
 
 #endif //  CYGSEM_REDBOOT_FLASH_ALIASES
 
+cyg_uint32
+flash_crc(struct _config *conf)
+{
+    cyg_uint32 crc;
+#ifdef REDBOOT_FLASH_REVERSE_BYTEORDER
+    int        swabbed = 0;
+
+    if (conf->key1 == CONFIG_KEY1 && conf->key2 == CONFIG_KEY2) {
+        swabbed = 1;
+        conf_endian_fixup(conf);
+    }
+#endif
+ 
+    crc = cyg_crc32((unsigned char *)conf, sizeof(*conf)-sizeof(conf->cksum));
+
+#ifdef REDBOOT_FLASH_REVERSE_BYTEORDER
+    if (swabbed)
+        conf_endian_fixup(conf);
+#endif
+    return crc;
+}
+
 //
 // Write the in-memory copy of the configuration data to the flash device.
 //
@@ -699,11 +777,11 @@ flash_write_config(bool prompt)
     config->len = sizeof(struct _config);
     config->key1 = CONFIG_KEY1;  
     config->key2 = CONFIG_KEY2;
-    config->cksum = cyg_crc32((unsigned char *)config, sizeof(struct _config)-sizeof(config->cksum));
+    config->cksum = flash_crc(config);
     if (!prompt || verify_action("Update RedBoot non-volatile configuration")) {
 #ifdef CYGHWR_REDBOOT_FLASH_CONFIG_MEDIA_FLASH
 #ifdef CYGSEM_REDBOOT_FLASH_COMBINED_FIS_AND_CONFIG
-        flash_read(fis_addr, fis_work_block, fisdir_size, (void **)&err_addr);
+        fis_read_directory();
         fis_update_directory();
 #else 
 #ifdef CYGSEM_REDBOOT_FLASH_LOCK_SPECIAL
@@ -713,11 +791,12 @@ flash_write_config(bool prompt)
         if ((stat = flash_erase(cfg_base, cfg_size, (void **)&err_addr)) != 0) {
             diag_printf("   initialization failed at %p: %s\n", err_addr, flash_errmsg(stat));
         } else {
-            if ((stat = flash_program(cfg_base, (void *)config, sizeof(struct _config), 
-                                      (void **)&err_addr)) != 0) {
+            conf_endian_fixup(config);
+            if ((stat = FLASH_PROGRAM(cfg_base, config, sizeof(struct _config), (void **)&err_addr)) != 0) {
                 diag_printf("Error writing config data at %p: %s\n", 
                             err_addr, flash_errmsg(stat));
             }
+            conf_endian_fixup(config);
         }
 #ifdef CYGSEM_REDBOOT_FLASH_LOCK_SPECIAL
         // Insure [quietly] that the config data is locked after the update
@@ -828,13 +907,11 @@ flash_get_config(char *key, void *val, i
     // Check to see if the config data is valid, if not, revert to 
     // readonly mode, by setting config to readonly_config.  We
     // will set it back before we leave this function.
-    if ( (config != readonly_config) && ((cyg_crc32((unsigned char *)config, 
-               sizeof(struct _config)-sizeof(config->cksum)) != config->cksum) ||
+    if ( (config != readonly_config) && ((flash_crc(config) != config->cksum) ||
         (config->key1 != CONFIG_KEY1)|| (config->key2 != CONFIG_KEY2))) {
         save_config = config;
         config = readonly_config;
-        if ((cyg_crc32((unsigned char *)config, 
-                       sizeof(struct _config)-sizeof(config->cksum)) != config->cksum) ||
+        if ((flash_crc(config) != config->cksum) ||
             (config->key1 != CONFIG_KEY1)|| (config->key2 != CONFIG_KEY2)) {
             diag_printf("FLASH configuration checksum error or invalid key\n");
             config = save_config;
@@ -1076,15 +1153,15 @@ load_flash_config(void)
            _rup(_rup((CYGNUM_REDBOOT_FLASH_CONFIG_BLOCK*flash_block_size), cfg_size), flash_block_size));
     }
 #endif
-    flash_read((void *)cfg_base, (void *)config, sizeof(struct _config), (void **)&err_addr);
+    FLASH_READ(cfg_base, config, sizeof(struct _config), &err_addr);
+    conf_endian_fixup(config);
 #else
     read_eeprom(config, sizeof(struct _config));  // into 'config'
 #endif
 #ifdef CYGSEM_REDBOOT_FLASH_CONFIG_READONLY_FALLBACK
     memcpy(readonly_config, config, sizeof(struct _config));
 #endif
-    if ((cyg_crc32((unsigned char *)config, 
-                   sizeof(struct _config)-sizeof(config->cksum)) != config->cksum) ||
+    if ((flash_crc(config) != config->cksum) ||
         (config->key1 != CONFIG_KEY1)|| (config->key2 != CONFIG_KEY2)) {
         diag_printf("**Warning** FLASH configuration checksum error or invalid key\n");
         diag_printf("Use 'fconfig -i' to [re]initialize database\n");
--- a/packages/redboot/current/src/flash.c
+++ b/packages/redboot/current/src/flash.c
@@ -8,7 +8,7 @@
 //####ECOSGPLCOPYRIGHTBEGIN####
 // -------------------------------------------
 // This file is part of eCos, the Embedded Configurable Operating System.
-// Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003 Red Hat, Inc.
+// Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004 Red Hat, Inc.
 // Copyright (C) 2003, 2004 Gary Thomas
 //
 // eCos is free software; you can redistribute it and/or modify it under
@@ -61,6 +61,7 @@
 
 #ifdef CYGSEM_REDBOOT_FLASH_COMBINED_FIS_AND_CONFIG
 // Note horrid intertwining of functions, to save precious FLASH
+extern void conf_endian_fixup(void *p);
 #endif
 
 // Round a quantity up
@@ -191,14 +192,45 @@ static void
 }
 
 #ifdef CYGOPT_REDBOOT_FIS
+
+// fis_endian_fixup() is used to swap endianess if required.
+//
+static inline void fis_endian_fixup(void *addr)
+{
+#ifdef REDBOOT_FLASH_REVERSE_BYTEORDER
+    struct fis_image_desc *p = addr;
+    int cnt = fisdir_size / sizeof(struct fis_image_desc);
+
+    while (cnt-- > 0) {
+        p->flash_base = CYG_SWAP32(p->flash_base);
+        p->mem_base = CYG_SWAP32(p->mem_base);
+        p->size = CYG_SWAP32(p->size);
+        p->entry_point = CYG_SWAP32(p->entry_point);
+        p->data_length = CYG_SWAP32(p->data_length);
+        p->desc_cksum = CYG_SWAP32(p->desc_cksum);
+        p->file_cksum = CYG_SWAP32(p->file_cksum);
+        p++;
+    }
+#endif
+}
+
+void
+fis_read_directory(void)
+{
+    void *err_addr;
+
+    FLASH_READ(fis_addr, fis_work_block, fisdir_size, (void **)&err_addr);
+    fis_endian_fixup(fis_work_block);
+}
+
 struct fis_image_desc *
 fis_lookup(char *name, int *num)
 {
     int i;
     struct fis_image_desc *img;
-    void *err_addr;
 
-    flash_read(fis_addr, fis_work_block, fisdir_size, (void **)&err_addr);
+    fis_read_directory();
+
     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) && 
@@ -216,8 +248,10 @@ fis_update_directory(void)
     int stat;
     void *err_addr;
 
+    fis_endian_fixup(fis_work_block);
 #ifdef CYGSEM_REDBOOT_FLASH_COMBINED_FIS_AND_CONFIG
     memcpy((char *)fis_work_block+fisdir_size, config, cfg_size);
+    conf_endian_fixup((char *)fis_work_block+fisdir_size);
 #endif
 #ifdef CYGSEM_REDBOOT_FLASH_LOCK_SPECIAL
     // Ensure [quietly] that the directory is unlocked before trying to update
@@ -226,8 +260,8 @@ fis_update_directory(void)
     if ((stat = flash_erase(fis_addr, flash_block_size, (void **)&err_addr)) != 0) {
         diag_printf("Error erasing FIS directory at %p: %s\n", err_addr, flash_errmsg(stat));
     } else {
-        if ((stat = flash_program(fis_addr, fis_work_block, flash_block_size,
-                                  (void **)&err_addr)) != 0) {
+        if ((stat = FLASH_PROGRAM(fis_addr, fis_work_block,
+                                  flash_block_size, (void **)&err_addr)) != 0) {
             diag_printf("Error writing FIS directory at %p: %s\n", 
                         err_addr, flash_errmsg(stat));
         }
@@ -236,6 +270,7 @@ fis_update_directory(void)
     // Ensure [quietly] that the directory is locked after the update
     flash_lock((void *)fis_addr, flash_block_size, (void **)&err_addr);
 #endif
+    fis_endian_fixup(fis_work_block);
 }
 
 static void
@@ -450,7 +485,6 @@ fis_list(int argc, char *argv[])
     bool show_cksums = false;
     bool show_datalen = false;
     struct option_info opts[2];
-    void *err_addr;
     unsigned long last_addr, lowest_addr;
     bool image_found;
 
@@ -473,7 +507,8 @@ fis_list(int argc, char *argv[])
     if (!scan_opts(argc, argv, 2, opts, i, 0, 0, "")) {
         return;
     }
-    flash_read(fis_addr, fis_work_block, fisdir_size, (void **)&err_addr);
+    fis_read_directory();
+
     // Let diag_printf do the formatting in both cases, rather than counting
     // cols by hand....
     diag_printf("%-16s  %-10s  %-10s  %-10s  %-s\n",
@@ -523,7 +558,6 @@ 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;
@@ -535,7 +569,7 @@ find_free(struct free_chunk *chunks)
     fis_end = (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);
+    fis_read_directory();
     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) {
@@ -728,7 +762,7 @@ fis_create(int argc, char *argv[])
         return;
     }
 
-    flash_read(fis_addr, fis_work_block, fisdir_size, (void **)&err_addr);
+    fis_read_directory();
     defaults_assumed = false;
     if (name) {
         // Search existing files to acquire defaults for params not specified:
@@ -888,7 +922,7 @@ fis_create(int argc, char *argv[])
         }
         if (prog_ok) {
             // Now program it
-            if ((stat = flash_program((void *)flash_addr, (void *)mem_addr, img_size, (void **)&err_addr)) != 0) {
+            if ((stat = FLASH_PROGRAM((void *)flash_addr, (void *)mem_addr, img_size, (void **)&err_addr)) != 0) {
                 diag_printf("Can't program region at %p: %s\n", err_addr, flash_errmsg(stat));
                 prog_ok = false;
             }
@@ -1056,8 +1090,8 @@ fis_load(int argc, char *argv[])
         load_address = mem_addr;
         load_address_end = (unsigned long)p->out_buf;
 
-    	// Reload fis directory
-        flash_read(fis_addr, fis_work_block, fisdir_size, (void **)&err_addr);
+        // Reload fis directory
+        fis_read_directory();
     } else // dangling block
 #endif
     {
@@ -1156,7 +1190,7 @@ fis_write(int argc, char *argv[])
     }
     if (prog_ok) {
         // Now program it
-        if ((stat = flash_program((void *)flash_addr, (void *)mem_addr, length, (void **)&err_addr)) != 0) {
+        if ((stat = FLASH_PROGRAM((void *)flash_addr, (void *)mem_addr, length, (void **)&err_addr)) != 0) {
             diag_printf("Can't program region at %p: %s\n", err_addr, flash_errmsg(stat));
             prog_ok = false;
         }
@@ -1227,7 +1261,7 @@ fis_lock(int argc, char *argv[])
               (void *)&flash_addr, (bool *)&flash_addr_set, "FLASH memory base address");
     init_opts(&opts[1], 'l', true, OPTION_ARG_TYPE_NUM, 
               (void *)&length, (bool *)&length_set, "length");
-    if (!scan_opts(argc, argv, 2, opts, 2, (void **)&name, OPTION_ARG_TYPE_STR, "image name"))
+    if (!scan_opts(argc, argv, 2, opts, 2, &name, OPTION_ARG_TYPE_STR, "image name"))
     {
         fis_usage("invalid arguments");
         return;
@@ -1274,7 +1308,7 @@ fis_unlock(int argc, char *argv[])
               (void *)&flash_addr, (bool *)&flash_addr_set, "FLASH memory base address");
     init_opts(&opts[1], 'l', true, OPTION_ARG_TYPE_NUM, 
               (void *)&length, (bool *)&length_set, "length");
-    if (!scan_opts(argc, argv, 2, opts, 2, (void **)&name, OPTION_ARG_TYPE_STR, "image name"))
+    if (!scan_opts(argc, argv, 2, opts, 2, &name, OPTION_ARG_TYPE_STR, "image name"))
     {
         fis_usage("invalid arguments");
         return;
@@ -1321,7 +1355,6 @@ bool
 do_flash_init(void)
 {
     int stat;
-    void *err_addr;
 
     if (!__flash_init) {
         __flash_init = 1;
@@ -1357,7 +1390,7 @@ do_flash_init(void)
             diag_printf("FIS directory doesn't fit\n");
             return false;
         }
-        flash_read(fis_addr, fis_work_block, fisdir_size, (void **)&err_addr);
+        fis_read_directory();
 #endif
     }
     return true;
--- a/packages/redboot/current/src/main.c
+++ b/packages/redboot/current/src/main.c
@@ -8,7 +8,7 @@
 //####ECOSGPLCOPYRIGHTBEGIN####
 // -------------------------------------------
 // This file is part of eCos, the Embedded Configurable Operating System.
-// Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003 Red Hat, Inc.
+// Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004 Red Hat, Inc.
 // Copyright (C) 2002, 2003, 2004 Gary Thomas
 //
 // eCos is free software; you can redistribute it and/or modify it under
@@ -178,7 +178,7 @@ do_version(int argc, char *argv[])
 #ifdef HAL_PLATFORM_CPU
     diag_printf("Platform: %s (%s) %s\n", HAL_PLATFORM_BOARD, HAL_PLATFORM_CPU, HAL_PLATFORM_EXTRA);
 #endif
-    diag_printf("Copyright (C) 2000, 2001, 2002, Red Hat, Inc.\n\n");
+    diag_printf("Copyright (C) 2000, 2001, 2002, 2003, 2004 Red Hat, Inc.\n\n");
     diag_printf("RAM: %p-%p, ", (void*)ram_start, (void*)ram_end);
     diag_printf("[%p-%p]", mem_segments[0].start, mem_segments[0].end);
     diag_printf(" available\n");