diff -rbup ecos-orig/packages/redboot/current/ChangeLog ecos-mod/packages/redboot/current/ChangeLog
--- ecos-orig/packages/redboot/current/ChangeLog	2005-10-17 22:59:01.000000000 +0200
+++ ecos-mod/packages/redboot/current/ChangeLog	2006-01-12 14:41:02.000000000 +0100
@@ -1,3 +1,8 @@
+2006-01-12  Alexander Neundorf <alexander.neundorf@jenoptik.com>
+        * include/fis.h, src/fconfig.c, src/flash.c, src/main.c: added
+        support for redundant FIS tables, in order to enable a failsafe
+        update of FIS images from eCos applications
+
 2005-10-17  Gary Thomas  <gary@mlbassoc.com>
 
 	* src/iomem.c (do_iopeek): Correct number of options.
diff -rbup ecos-orig/packages/redboot/current/cdl/redboot.cdl ecos-mod/packages/redboot/current/cdl/redboot.cdl
--- ecos-orig/packages/redboot/current/cdl/redboot.cdl	2005-09-08 14:14:29.000000000 +0200
+++ ecos-mod/packages/redboot/current/cdl/redboot.cdl	2005-09-23 14:51:27.000000000 +0200
@@ -684,6 +684,32 @@ cdl_package CYGPKG_REDBOOT {
                       means the last but one block."
                 }
     
+			       cdl_component CYGOPT_REDBOOT_REDUNDANT_FIS {
+                    display         "Redundant Flash Image System Directory Support"
+                    default_value   0
+                    requires { 0 == CYGSEM_REDBOOT_FLASH_COMBINED_FIS_AND_CONFIG }
+                    description "
+                              This option enables the use of a redundant FIS
+                              directory within RedBoot.  If enabled a flash block
+                              will be reserved for a second copy of the fis
+                              directory. Doing this allow for power failure safe
+                              updates of the directory by the application."
+      
+                    cdl_option CYGNUM_REDBOOT_FIS_REDUNDANT_DIRECTORY_BLOCK {
+                        display         "Flash block containing the backup Directory"
+                        flavor          data
+                        default_value   (-3)
+                        requires { CYGNUM_REDBOOT_FIS_REDUNDANT_DIRECTORY_BLOCK !=
+                                   CYGNUM_REDBOOT_FIS_DIRECTORY_BLOCK }
+                        description "
+                                 Which block of flash should hold the redundant
+                                 directory information. Positive numbers are
+                                 absolute block numbers. Negative block numbers
+                                 count backwards from the last block. eg 2 means
+                                 block 2, -2 means the last but one block."
+                    }
+                }
+    
                 cdl_option CYGOPT_REDBOOT_FIS_RESERVED_BASE {
                     display         "Pseudo-file to describe reserved area"
                     active_if       { 0 != CYGNUM_REDBOOT_FLASH_RESERVED_BASE }
diff -rbup ecos-orig/packages/redboot/current/include/fis.h ecos-mod/packages/redboot/current/include/fis.h
--- ecos-orig/packages/redboot/current/include/fis.h	2002-08-24 13:20:55.000000000 +0200
+++ ecos-mod/packages/redboot/current/include/fis.h	2005-06-10 14:23:24.000000000 +0200
@@ -58,11 +58,38 @@
 #ifdef CYGOPT_REDBOOT_FIS
 #include <cyg/infra/cyg_type.h>
 
+//the version can be tested via the VV calls to check for compatibility
+#define CYG_REDBOOT_FIS_VERSION      (1)
+
+// These will need to move somewhere else when the fisfs needs to use
+// the following definitions.
+#ifdef CYGOPT_REDBOOT_REDUNDANT_FIS
+#define CYG_REDBOOT_RFIS_VALID_MAGIC_LENGTH 10
+#define CYG_REDBOOT_RFIS_VALID_MAGIC ".FisValid"  //exactly 10 bytes
+
+#define CYG_REDBOOT_RFIS_VALID       (0xa5)
+#define CYG_REDBOOT_RFIS_IN_PROGRESS (0xfd)
+#define CYG_REDBOOT_RFIS_EMPTY       (0xff)
+
+struct fis_valid_info
+{
+   char magic_name[CYG_REDBOOT_RFIS_VALID_MAGIC_LENGTH];
+   unsigned char valid_flag[2]; //this should be safe for all alignment issues
+   unsigned long version_count;
+};
+#endif // CYGOPT_REDBOOT_REDUNDANT_FIS
+
 #define FIS_IMAGE_DESC_SIZE_UNPADDED \
   (16 + 4 * sizeof(unsigned long) + 3 * sizeof(CYG_ADDRESS))
 
 struct fis_image_desc {
+    union
+    {
     unsigned char name[16];      // Null terminated name
+#ifdef CYGOPT_REDBOOT_REDUNDANT_FIS
+       struct fis_valid_info valid_info;
+#endif
+    } u;
     CYG_ADDRESS   flash_base;    // Address within FLASH of image
     CYG_ADDRESS   mem_base;      // Address in memory where it executes
     unsigned long size;          // Length of image
diff -rbup ecos-orig/packages/redboot/current/include/redboot.h ecos-mod/packages/redboot/current/include/redboot.h
--- ecos-orig/packages/redboot/current/include/redboot.h	2005-09-08 14:14:31.000000000 +0200
+++ ecos-mod/packages/redboot/current/include/redboot.h	2006-01-12 10:53:38.000000000 +0100
@@ -89,7 +89,7 @@ EXTERN struct _mem_segment {
 #define NO_MEMORY (unsigned char *)0xFFFFFFFF
 EXTERN bool valid_address(unsigned char *addr);
 EXTERN void cyg_plf_memory_segment(int seg, unsigned char **start, unsigned char **end);
-EXTERN unsigned char *workspace_start, *workspace_end;
+EXTERN unsigned char *workspace_start, *workspace_end, *workspace_end_init;
 
 // Data squirreled away after a load operation
 EXTERN unsigned long entry_address;
diff -rbup ecos-orig/packages/redboot/current/src/fconfig.c ecos-mod/packages/redboot/current/src/fconfig.c
--- ecos-orig/packages/redboot/current/src/fconfig.c	2005-07-06 20:41:21.000000000 +0200
+++ ecos-mod/packages/redboot/current/src/fconfig.c	2005-09-23 13:22:47.000000000 +0200
@@ -75,7 +75,7 @@ externC bool cyg_plf_redboot_esa_validat
 #endif
 
 #ifdef CYGHWR_REDBOOT_FLASH_CONFIG_MEDIA_FLASH
-externC bool do_flash_init(void);
+externC int do_flash_init(void);
 externC int flash_read(void *flash_base, void *ram_base, int len, void **err_address);
 #endif
 
@@ -1137,7 +1137,7 @@ load_flash_config(void)
 #endif
     workspace_end = cfg_temp;
 #ifdef CYGHWR_REDBOOT_FLASH_CONFIG_MEDIA_FLASH
-    if (!do_flash_init()) return;
+    if (do_flash_init()<0) return;
 #ifdef CYGSEM_REDBOOT_FLASH_COMBINED_FIS_AND_CONFIG
     cfg_size = _rup(sizeof(struct _config), sizeof(struct fis_image_desc));
     if ((fisdir_size-cfg_size) < (CYGNUM_REDBOOT_FIS_DIRECTORY_ENTRY_COUNT *
diff -rbup ecos-orig/packages/redboot/current/src/flash.c ecos-mod/packages/redboot/current/src/flash.c
--- ecos-orig/packages/redboot/current/src/flash.c	2005-09-08 14:14:33.000000000 +0200
+++ ecos-mod/packages/redboot/current/src/flash.c	2006-01-12 11:04:43.000000000 +0100
@@ -169,6 +169,9 @@ int flash_block_size, flash_num_blocks;
 #ifdef CYGOPT_REDBOOT_FIS
 void *fis_work_block;
 void *fis_addr;
+#ifdef CYGOPT_REDBOOT_REDUNDANT_FIS
+void *redundant_fis_addr;
+#endif
 int fisdir_size;  // Size of FIS directory.
 #endif
 #ifdef CYGSEM_REDBOOT_FLASH_CONFIG
@@ -233,8 +236,8 @@ fis_lookup(char *name, int *num)
 
     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) && 
-            (strcasecmp(name, img->name) == 0)) {
+        if ((img->u.name[0] != (unsigned char)0xFF) &&
+            (strcasecmp(name, img->u.name) == 0)) {
             if (num) *num = i;
             return img;
         }
@@ -242,21 +245,104 @@ fis_lookup(char *name, int *num)
     return (struct fis_image_desc *)0;
 }
 
-void
-fis_update_directory(void)
+int fis_start_update_directory(int autolock)
 {
+#ifdef CYGSEM_REDBOOT_FLASH_LOCK_SPECIAL
+   // Ensure [quietly] that the directory is unlocked before trying to update and locked again afterwards
+   int do_autolock=1;
+#else
+   int do_autolock=autolock;
+#endif
+
+#ifdef CYGOPT_REDBOOT_REDUNDANT_FIS
+   struct fis_image_desc* img=NULL;
+   void* err_addr=NULL;
+   void* tmp_fis_addr=NULL;
+
+   /*exchange old and new valid fis tables*/
+   tmp_fis_addr=fis_addr;
+   fis_addr=redundant_fis_addr;
+   redundant_fis_addr=tmp_fis_addr;
+
+   //adjust the contents of the new fis table
+   img=(struct fis_image_desc*)fis_work_block;
+
+   memcpy(img->u.valid_info.magic_name, CYG_REDBOOT_RFIS_VALID_MAGIC, CYG_REDBOOT_RFIS_VALID_MAGIC_LENGTH);
+   img->u.valid_info.valid_flag[0]=CYG_REDBOOT_RFIS_IN_PROGRESS;
+   img->u.valid_info.valid_flag[1]=CYG_REDBOOT_RFIS_IN_PROGRESS;
+   img->u.valid_info.version_count=img->u.valid_info.version_count+1;
+
+   //ready to go....
+   if (do_autolock)
+      flash_unlock((void *)fis_addr, flash_block_size, (void **)&err_addr);
+
+   flash_erase(fis_addr, flash_block_size, (void **)&err_addr);
+   //now magic is 0xffffffff
+   fis_endian_fixup(fis_work_block);
+   flash_program(fis_addr, fis_work_block, flash_block_size, (void **)&err_addr);
+   fis_endian_fixup(fis_work_block);
+   //now magic is 0xff1234ff, valid is IN_PROGRESS, version_count is the old one +1
+
+#else
+   /* nothing to do here without redundant fis */
+#endif
+   return 0;
+
+}
+
+int
+fis_update_directory(int autolock, int error)
+{
+   void* err_addr=0;
+
+#ifdef CYGSEM_REDBOOT_FLASH_LOCK_SPECIAL
+   // Ensure [quietly] that the directory is unlocked before trying to update and locked again afterwards
+   int do_autolock=1;
+#else
+   int do_autolock=autolock;
+#endif
+
+
+#ifdef CYGOPT_REDBOOT_REDUNDANT_FIS
+
+   struct fis_image_desc* img=(struct fis_image_desc*)fis_work_block;
+
+   // called from invalid state
+   if (img->u.valid_info.valid_flag[0]!=CYG_REDBOOT_RFIS_IN_PROGRESS)
+      return -1;
+
+   //if it failed, reset is0Valid to the state before startUpdateDirectory()
+   //g_data.fisTable hasn't been changed yet, so it doesn't have to be reset now
+   //then reread the contents from flash
+   //setting the valid flag of the failed table to "INVALID" might also be not too bad
+   //but IN_PROGRESS is also good enough I think
+   if (error!=0)
+   {
+      void* swap_fis_addr=fis_addr;
+      fis_addr=redundant_fis_addr;
+      redundant_fis_addr=swap_fis_addr;
+   }
+   else //success
+   {
+      void* tmp_fis_addr=(void *)((CYG_ADDRESS)fis_addr+CYG_REDBOOT_RFIS_VALID_MAGIC_LENGTH);
+
+      img->u.valid_info.valid_flag[0]=CYG_REDBOOT_RFIS_VALID;
+      img->u.valid_info.valid_flag[1]=CYG_REDBOOT_RFIS_VALID;
+
+      flash_program(tmp_fis_addr, img->u.valid_info.valid_flag, sizeof(img->u.valid_info.valid_flag), (void **)&err_addr);
+   }
+
+#else // CYGOPT_REDBOOT_REDUNDANT_FIS
     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
+    if (do_autolock)
     flash_unlock((void *)fis_addr, flash_block_size, (void **)&err_addr);
-#endif
+
     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 {
@@ -266,13 +352,85 @@ fis_update_directory(void)
                         err_addr, flash_errmsg(stat));
         }
     }
+    fis_endian_fixup(fis_work_block);
+
+
+#endif // CYGOPT_REDBOOT_REDUNDANT_FIS
+    if (do_autolock)
+       flash_lock((void *)fis_addr, flash_block_size, (void **)&err_addr);
+
+    return 0;
+}
+
+#ifdef CYGOPT_REDBOOT_REDUNDANT_FIS
+
+int
+fis_get_valid_buf(struct fis_image_desc* img0, struct fis_image_desc* img1, int* update_was_interrupted)
+{
+   *update_was_interrupted=0;
+   if (strncmp(img1->u.valid_info.magic_name, CYG_REDBOOT_RFIS_VALID_MAGIC, CYG_REDBOOT_RFIS_VALID_MAGIC_LENGTH)!=0)  //buf0 must be valid
+   {
+      if (img0->u.valid_info.version_count>0)
+      {
+         *update_was_interrupted=1;
+      }
+      return 0;
+   }
+   else if (strncmp(img0->u.valid_info.magic_name, CYG_REDBOOT_RFIS_VALID_MAGIC, CYG_REDBOOT_RFIS_VALID_MAGIC_LENGTH)!=0)  //buf1 must be valid
+   {
+      if (img1->u.valid_info.version_count>0)
+      {
+         *update_was_interrupted=1;
+      }
+      return 1;
+   }
+   //magic is ok for both, now check the valid flag
+   if ((img1->u.valid_info.valid_flag[0]!=CYG_REDBOOT_RFIS_VALID)
+       || (img1->u.valid_info.valid_flag[1]!=CYG_REDBOOT_RFIS_VALID)) //buf0 must be valid
+   {
+      *update_was_interrupted=1;
+      return 0;
+   }
+   else if ((img0->u.valid_info.valid_flag[0]!=CYG_REDBOOT_RFIS_VALID)
+            || (img0->u.valid_info.valid_flag[1]!=CYG_REDBOOT_RFIS_VALID)) //buf1 must be valid
+   {
+      *update_was_interrupted=1;
+      return 1;
+   }
+
+   //now check the version
+   if (img1->u.valid_info.version_count == (img0->u.valid_info.version_count+1)) //buf1 must be valid
+      return 1;
+
+   return 0;
+}
+
+void
+fis_erase_redundant_directory(void)
+{
+    int stat;
+    void *err_addr;
+
+#ifdef CYGSEM_REDBOOT_FLASH_LOCK_SPECIAL
+    // Ensure [quietly] that the directory is unlocked before trying
+    // to update
+    flash_unlock((void *)redundant_fis_addr, flash_block_size,
+                 (void **)&err_addr);
+#endif
+    if ((stat = flash_erase(redundant_fis_addr, flash_block_size,
+                            (void **)&err_addr)) != 0) {
+         diag_printf("Error erasing FIS directory at %p: %s\n",
+                     err_addr, flash_errmsg(stat));
+    }
 #ifdef CYGSEM_REDBOOT_FLASH_LOCK_SPECIAL
     // Ensure [quietly] that the directory is locked after the update
-    flash_lock((void *)fis_addr, flash_block_size, (void **)&err_addr);
+    flash_lock((void *)redundant_fis_addr, flash_block_size, (void **)&err_addr);
 #endif
-    fis_endian_fixup(fis_work_block);
 }
 
+#endif
+
+
 static void
 fis_init(int argc, char *argv[])
 {
@@ -301,12 +459,23 @@ fis_init(int argc, char *argv[])
     redboot_image_size = flash_block_size > MIN_REDBOOT_IMAGE_SIZE ? 
                          flash_block_size : MIN_REDBOOT_IMAGE_SIZE;
 
-    // Create a pseudo image for RedBoot
     img = (struct fis_image_desc *)fis_work_block;
     memset(img, 0xFF, fisdir_size);  // Start with erased data
+
+#ifdef CYGOPT_REDBOOT_REDUNDANT_FIS
+    //create the valid flag entry
+    memset(img, 0, sizeof(struct fis_image_desc));
+    strcpy(img->u.valid_info.magic_name, CYG_REDBOOT_RFIS_VALID_MAGIC);
+    img->u.valid_info.valid_flag[0]=CYG_REDBOOT_RFIS_VALID;
+    img->u.valid_info.valid_flag[1]=CYG_REDBOOT_RFIS_VALID;
+    img->u.valid_info.version_count=0;
+    img++;
+#endif
+
+    // Create a pseudo image for RedBoot
 #ifdef CYGOPT_REDBOOT_FIS_RESERVED_BASE
     memset(img, 0, sizeof(*img));
-    strcpy(img->name, "(reserved)");
+    strcpy(img->u.name, "(reserved)");
     img->flash_base = (CYG_ADDRESS)flash_start;
     img->mem_base = (CYG_ADDRESS)flash_start;
     img->size = CYGNUM_REDBOOT_FLASH_RESERVED_BASE;
@@ -315,7 +484,7 @@ fis_init(int argc, char *argv[])
     redboot_flash_start = (CYG_ADDRESS)flash_start + CYGBLD_REDBOOT_FLASH_BOOT_OFFSET;
 #ifdef CYGOPT_REDBOOT_FIS_REDBOOT
     memset(img, 0, sizeof(*img));
-    strcpy(img->name, "RedBoot");
+    strcpy(img->u.name, "RedBoot");
     img->flash_base = redboot_flash_start;
     img->mem_base = redboot_flash_start;
     img->size = redboot_image_size;
@@ -328,7 +497,7 @@ fis_init(int argc, char *argv[])
     redboot_flash_start = (CYG_ADDRESS)flash_start + CYGNUM_REDBOOT_FIS_REDBOOT_POST_OFFSET;
 #endif
     memset(img, 0, sizeof(*img));
-    strcpy(img->name, "RedBoot[post]");
+    strcpy(img->u.name, "RedBoot[post]");
     img->flash_base = redboot_flash_start;
     img->mem_base = redboot_flash_start;
     img->size = redboot_image_size;
@@ -338,7 +507,7 @@ fis_init(int argc, char *argv[])
 #ifdef CYGOPT_REDBOOT_FIS_REDBOOT_BACKUP
     // And a backup image
     memset(img, 0, sizeof(*img));
-    strcpy(img->name, "RedBoot[backup]");
+    strcpy(img->u.name, "RedBoot[backup]");
     img->flash_base = redboot_flash_start;
     img->mem_base = redboot_flash_start;
     img->size = redboot_image_size;
@@ -348,7 +517,7 @@ fis_init(int argc, char *argv[])
 #if defined(CYGSEM_REDBOOT_FLASH_CONFIG) && defined(CYGHWR_REDBOOT_FLASH_CONFIG_MEDIA_FLASH)
     // And a descriptor for the configuration data
     memset(img, 0, sizeof(*img));
-    strcpy(img->name, "RedBoot config");
+    strcpy(img->u.name, "RedBoot config");
     img->flash_base = (CYG_ADDRESS)cfg_base;
     img->mem_base = (CYG_ADDRESS)cfg_base;
     img->size = cfg_size;
@@ -356,12 +525,22 @@ fis_init(int argc, char *argv[])
 #endif
     // And a descriptor for the descriptor table itself
     memset(img, 0, sizeof(*img));
-    strcpy(img->name, "FIS directory");
+    strcpy(img->u.name, "FIS directory");
     img->flash_base = (CYG_ADDRESS)fis_addr;
     img->mem_base = (CYG_ADDRESS)fis_addr;
     img->size = fisdir_size;
     img++;
 
+    //create the entry for the redundant fis table
+#ifdef CYGOPT_REDBOOT_REDUNDANT_FIS
+    memset(img, 0, sizeof(*img));
+    strcpy(img->u.name, "Redundant FIS");
+    img->flash_base = (CYG_ADDRESS)redundant_fis_addr;
+    img->mem_base = (CYG_ADDRESS)redundant_fis_addr;
+    img->size = fisdir_size;
+    img++;
+#endif
+
 #ifdef CYGOPT_REDBOOT_FIS_DIRECTORY_ARM_SIB_ID
     // FIS gets the size of a full block - note, this should be changed
     // if support is added for multi-block FIS structures.
@@ -474,7 +653,11 @@ fis_init(int argc, char *argv[])
         diag_printf("    Warning: device contents not erased, some blocks may not be usable\n");
 #endif
     }
-    fis_update_directory();
+    fis_start_update_directory(0);
+    fis_update_directory(0, 0);
+#ifdef CYGOPT_REDBOOT_REDUNDANT_FIS
+    fis_erase_redundant_directory();
+#endif
 }
 
 static void
@@ -523,7 +706,7 @@ fis_list(int argc, char *argv[])
         lowest_addr = 0xFFFFFFFF;
         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) {
+            if (img->u.name[0] != (unsigned char)0xFF) {
                 if ((img->flash_base > last_addr) && (img->flash_base < lowest_addr)) {
                     lowest_addr = img->flash_base;
                     image_found = true;
@@ -534,7 +717,7 @@ fis_list(int argc, char *argv[])
         if (image_found) {
             img = (struct fis_image_desc *) fis_work_block;
             img += image_indx;
-            diag_printf("%-16s  0x%08lX  0x%08lX  0x%08lX  0x%08lX\n", img->name, 
+            diag_printf("%-16s  0x%08lX  0x%08lX  0x%08lX  0x%08lX\n", img->u.name,
                         (unsigned long)img->flash_base, 
 #ifdef CYGSEM_REDBOOT_FIS_CRC_CHECK
                         show_cksums ? img->file_cksum : img->mem_base, 
@@ -571,7 +754,7 @@ find_free(struct free_chunk *chunks)
     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) {
+       if (img->u.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) && 
@@ -591,12 +774,14 @@ find_free(struct free_chunk *chunks)
                     } else {
                         // Split chunk into two parts
                         if ((img->flash_base+img->size) < (CYG_ADDRESS)fis_end) {
+
                             int j;
                             // make room for new chunk
                             for (j = num_chunks; j > (idx+1); j--)
                                 chunks[j] = chunks[j-1];
                             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;
@@ -839,8 +1024,8 @@ fis_create(int argc, char *argv[])
         diag_printf("   must be 0x%x aligned\n", flash_block_size);
         return;
     }
-    if (strlen(name) >= sizeof(img->name)) {
-        diag_printf("Name is too long, must be less than %d chars\n", (int)sizeof(img->name));
+    if (strlen(name) >= sizeof(img->u.name)) {
+        diag_printf("Name is too long, must be less than %d chars\n", (int)sizeof(img->u.name));
         return;
     }
     if (!no_copy) {
@@ -905,7 +1090,7 @@ fis_create(int argc, char *argv[])
         // If not image by that name, try and find an empty slot
         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) {
+            if (img->u.name[0] == (unsigned char)0xFF) {
                 break;
             }
         }
@@ -938,7 +1123,7 @@ fis_create(int argc, char *argv[])
     if (prog_ok) {
         // Update directory
         memset(img, 0, sizeof(*img));
-        strcpy(img->name, name);
+        strcpy(img->u.name, name);
         img->flash_base = flash_addr;
         img->mem_base = exec_addr_set ? exec_addr : (mem_addr_set ? mem_addr : flash_addr);
         img->entry_point = entry_addr_set ? entry_addr : (CYG_ADDRESS)entry_address;  // Hope it's been set
@@ -952,7 +1137,8 @@ fis_create(int argc, char *argv[])
             img->file_cksum = 0;
         }
 #endif
-        fis_update_directory();
+        fis_start_update_directory(0);
+        fis_update_directory(0, 0);
     }
 }
 
@@ -999,7 +1185,7 @@ fis_delete(int argc, char *argv[])
     img = fis_lookup(name, &i);
     if (img) {
         if (i < num_reserved) {
-            diag_printf("Sorry, '%s' is a reserved image and cannot be deleted\n", img->name);
+            diag_printf("Sorry, '%s' is a reserved image and cannot be deleted\n", img->u.name);
             return;
         }
         if (!verify_action("Delete image '%s'", name)) {
@@ -1013,8 +1199,9 @@ fis_delete(int argc, char *argv[])
     if ((stat = flash_erase((void *)img->flash_base, img->size, (void **)&err_addr)) != 0) {
         diag_printf("Error erasing at %p: %s\n", err_addr, flash_errmsg(stat));
     } else {
-        img->name[0] = (unsigned char)0xFF;    
-        fis_update_directory();
+        img->u.name[0] = (unsigned char)0xFF;
+        fis_start_update_directory(0);
+        fis_update_directory(0, 0);
     }
 }
 
@@ -1358,16 +1545,32 @@ _flash_info(void)
            flash_start, (CYG_ADDRWORD)flash_end + 1, flash_num_blocks, (void *)flash_block_size);
 }
 
-bool
+/* Returns -1 on failure, 0 on success, 1 if it was successfull
+ but an failed fis update was detected  */
+int
 do_flash_init(void)
 {
     int stat;
 
+    void *err_addr;
+#ifdef CYGOPT_REDBOOT_REDUNDANT_FIS
+    struct fis_image_desc img0;
+    struct fis_image_desc img1;
+    int fis_update_was_interrupted=0;
+
+    //check the size of fis_valid_info
+    CYG_ASSERT((sizeof(struct fis_valid_info)<=sizeof(img0.u.name)), "fis_valid_info size mismatch");
+    //try to check the alignment of version_count
+    CYG_ASSERT((((unsigned long)&img0.u.valid_info.version_count - (unsigned long)&img0) % sizeof(unsigned long) == 0), "alignment problem");
+#endif
+
+
+
     if (!__flash_init) {
         __flash_init = 1;
         if ((stat = flash_init(diag_printf)) != 0) {
             diag_printf("FLASH: driver init failed: %s\n", flash_errmsg(stat));
-            return false;
+            return -1;
         }
         flash_get_limits((void *)0, (void **)&flash_start, (void **)&flash_end);
         // Keep 'end' address as last valid location, to avoid wrap around problems
@@ -1380,10 +1583,10 @@ do_flash_init(void)
 	fis_work_block = fis_zlib_common_buffer;
 	if(CYGNUM_REDBOOT_FIS_ZLIB_COMMON_BUFFER_SIZE < fisdir_size) {
             diag_printf("FLASH: common buffer too small\n");
-            return false;
+            return -1;
 	}
 # else
-        workspace_end = (unsigned char *)(workspace_end-fisdir_size);
+        workspace_end = (unsigned char *)(workspace_end_init-fisdir_size);
         fis_work_block = workspace_end;
 # endif
         if (CYGNUM_REDBOOT_FIS_DIRECTORY_BLOCK < 0) {
@@ -1395,12 +1598,60 @@ do_flash_init(void)
         }
         if (((CYG_ADDRESS)fis_addr + fisdir_size - 1) > (CYG_ADDRESS)flash_end) {
             diag_printf("FIS directory doesn't fit\n");
-            return false;
+            return -1;
+        }
+#ifdef CYGOPT_REDBOOT_REDUNDANT_FIS
+
+        if (CYGNUM_REDBOOT_FIS_REDUNDANT_DIRECTORY_BLOCK < 0) {
+            redundant_fis_addr = (void *)((CYG_ADDRESS)flash_end + 1 +
+                                          (CYGNUM_REDBOOT_FIS_REDUNDANT_DIRECTORY_BLOCK*flash_block_size));
+        } else {
+            redundant_fis_addr = (void *)((CYG_ADDRESS)flash_start +
+                                (CYGNUM_REDBOOT_FIS_REDUNDANT_DIRECTORY_BLOCK*flash_block_size));
+        }
+
+        if (((CYG_ADDRESS)redundant_fis_addr + fisdir_size - 1) > (CYG_ADDRESS)flash_end) {
+            diag_printf("Redundant FIS directory doesn't fit\n");
+            return -1;
         }
+        FLASH_READ(fis_addr, &img0, sizeof(img0), (void **)&err_addr);
+        FLASH_READ(redundant_fis_addr, &img1, sizeof(img1), (void **)&err_addr);
+
+        if (strncmp(img0.u.valid_info.magic_name, CYG_REDBOOT_RFIS_VALID_MAGIC, CYG_REDBOOT_RFIS_VALID_MAGIC_LENGTH)!=0)
+        {
+           memset(&img0, 0, sizeof(img0));
+        }
+
+        if (strncmp(img1.u.valid_info.magic_name, CYG_REDBOOT_RFIS_VALID_MAGIC, CYG_REDBOOT_RFIS_VALID_MAGIC_LENGTH)!=0)
+        {
+           memset(&img1, 0, sizeof(img0));
+        }
+
+#ifdef REDBOOT_FLASH_REVERSE_BYTEORDER
+        img0.u.valid_info.version_count = CYG_SWAP32(img0.u.valid_info.version_count);
+        img1.u.valid_info.version_count = CYG_SWAP32(img1.u.valid_info.version_count);
+#endif
+
+        if (fis_get_valid_buf(&img0, &img1, &fis_update_was_interrupted)==1)
+        {
+           // Valid, so swap primary and secondary
+           void * tmp;
+           tmp = fis_addr;
+           fis_addr = redundant_fis_addr;
+           redundant_fis_addr = tmp;
+        }
+#endif
         fis_read_directory();
 #endif
     }
-    return true;
+#ifdef CYGOPT_REDBOOT_REDUNDANT_FIS
+    if (fis_update_was_interrupted)
+       return 1;
+    else
+       return 0;
+#else
+    return 0;
+#endif
 }
 
 // Wrapper to avoid compiler warnings
@@ -1424,7 +1675,7 @@ do_fis(int argc, char *argv[])
         fis_usage("too few arguments");
         return;
     }
-    if (!do_flash_init()) {
+    if (do_flash_init()<0) {
         diag_printf("Sorry, no FLASH memory is available\n");
         return;
     }
diff -rbup ecos-orig/packages/redboot/current/src/main.c ecos-mod/packages/redboot/current/src/main.c
--- ecos-orig/packages/redboot/current/src/main.c	2005-06-07 20:55:52.000000000 +0200
+++ ecos-mod/packages/redboot/current/src/main.c	2006-01-12 11:04:43.000000000 +0100
@@ -297,6 +297,7 @@ cyg_start(void)
         // but the heap1 region remains greater...
         workspace_end = ram_end;
     }
+    workspace_end_init=workspace_end;
 
     // Nothing has ever been loaded into memory
     entry_address = (unsigned long)NO_MEMORY;
