diff -rbupN ecos/packages/ecos.db ecos-fisfs-util/packages/ecos.db
--- ecos/packages/ecos.db	2007-01-03 16:36:32.000000000 +0100
+++ ecos-fisfs-util/packages/ecos.db	2007-01-03 16:37:39.000000000 +0100
@@ -6296,6 +6296,13 @@ package CYGPKG_FS_FAT {
         This package contains a FAT filesystem implementation."
 }
 
+package CYGPKG_FS_FIS {
+    alias       { "FIS Filesystem" fisfs fis_fs fs_fis }
+    directory   fs/fisfs
+    script      fisfs.cdl
+    description "
+        This package contains a filesystem implementation for FIS."
+}
 
 # --------------------------------------------------------------------------
 
diff -rbupN ecos/packages/fs/fisfs/current/cdl/fisfs.cdl ecos-fisfs-util/packages/fs/fisfs/current/cdl/fisfs.cdl
--- ecos/packages/fs/fisfs/current/cdl/fisfs.cdl	1970-01-01 01:00:00.000000000 +0100
+++ ecos-fisfs-util/packages/fs/fisfs/current/cdl/fisfs.cdl	2007-01-08 08:52:24.000000000 +0100
@@ -0,0 +1,77 @@
+# ====================================================================
+#
+#      fisfs.cdl
+#
+#      FIS Filesystem configuration data
+#
+# ====================================================================
+#####ECOSGPLCOPYRIGHTBEGIN####
+## -------------------------------------------
+## This file is part of eCos, the Embedded Configurable Operating System.
+## Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004 Red Hat, Inc.
+## Copyright (C) 2004 eCosCentric Limited
+##
+## eCos is free software; you can redistribute it and/or modify it under
+## the terms of the GNU General Public License as published by the Free
+## Software Foundation; either version 2 or (at your option) any later version.
+##
+## eCos is distributed in the hope that it will be useful, but WITHOUT ANY
+## WARRANTY; without even the implied warranty of MERCHANTABILITY or
+## FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+## for more details.
+##
+## You should have received a copy of the GNU General Public License along
+## with eCos; if not, write to the Free Software Foundation, Inc.,
+## 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+##
+## As a special exception, if other files instantiate templates or use macros
+## or inline functions from this file, or you compile this file and link it
+## with other works to produce a work based on this file, this file does not
+## by itself cause the resulting work to be covered by the GNU General Public
+## License. However the source code for this file must still be made available
+## in accordance with section (3) of the GNU General Public License.
+##
+## This exception does not invalidate any other reasons why a work based on
+## this file might be covered by the GNU General Public License.
+##
+## -------------------------------------------
+#####ECOSGPLCOPYRIGHTEND####
+# ====================================================================
+######DESCRIPTIONBEGIN####
+#
+# Author(s):      Alexander Neundorf <alexander.neundorf@jenoptik.com>
+# Contributors:
+# Date:           2005-09-22
+#
+#####DESCRIPTIONEND####
+#
+# ====================================================================
+
+cdl_package CYGPKG_FS_FIS {
+    display         "FIS update and filesystem"
+    include_dir     cyg/fs
+
+    requires        CYGPKG_ISOINFRA
+    requires        CYGINT_ISO_ERRNO
+    requires        CYGINT_ISO_ERRNO_CODES
+    requires        CYGPKG_LIBC_STRING
+    requires        CYGPKG_IO_FLASH
+
+    compile         fisupdate.c
+
+    cdl_option CYGDBG_FS_FIS_DEBUG_OUTPUT {
+       display "Enable debug output"
+       default_value 0
+    }
+
+    cdl_option CYGFUN_FS_FIS_UPDATE {
+       requires        CYGPKG_CRC
+       display "Build FIS update support"
+       default_value 0
+       description "This enables some special functions which can be
+       used to update the contents of the Redboot FIS."
+    }
+}
+
+# ====================================================================
+# End of fisfs.cdl
diff -rbupN ecos/packages/fs/fisfs/current/ChangeLog ecos-fisfs-util/packages/fs/fisfs/current/ChangeLog
--- ecos/packages/fs/fisfs/current/ChangeLog	1970-01-01 01:00:00.000000000 +0100
+++ ecos-fisfs-util/packages/fs/fisfs/current/ChangeLog	2007-01-03 14:37:49.000000000 +0100
@@ -0,0 +1,4 @@
+2007-01-02 Alexander Neundorf <alexander.neundorf@jenoptik.com>
+
+        * initial import of the FIS update and utility functions
+        
diff -rbupN ecos/packages/fs/fisfs/current/doc/redundant_fis.txt ecos-fisfs-util/packages/fs/fisfs/current/doc/redundant_fis.txt
--- ecos/packages/fs/fisfs/current/doc/redundant_fis.txt	1970-01-01 01:00:00.000000000 +0100
+++ ecos-fisfs-util/packages/fs/fisfs/current/doc/redundant_fis.txt	2005-07-12 15:13:55.000000000 +0200
@@ -0,0 +1,134 @@
+A safe update mechanism for fis
+
+The fis table consists of entries of the type fis_image_desc.
+If an image is created or removed, the table has to be rewritten.
+Rewriting this table on flash means it is first deleted and then written
+again. If something bad happens between the deletion and the end of the
+write process the fis table can be lost. If the fis table is destroyed,
+redboot can't load the application image anymore and so the device won't
+boot.
+
+In order to achieve a safe update, there has to be a redundant copy of the
+fis table which can never be destroyed. So instead of one fis table there
+are now always two fis tables on the flash and redboot has to decide which
+one of both is valid.
+For this the new struct fis_valid_info has been introduced. It is mapped via
+a union over the fis_image_desc.name. It creates a special entry in the fis
+table with the name ".FisValid" and all sizes and addresses set to 0.
+Additionally to the name fis_valid_info features a version count and a
+"valid flag". With each update the version count is increased by one. If the
+table is deleted the valid_flag is set to 0xffff, if the table is written
+preliminary it is set to 0xfdfd, and only if everything has finished
+successfully it is set to 0xa5a5.
+So if redboot looks at both fis tables, it checks
+-that the name is ".FisValid"
+-that valid_flag is 0xa5a5
+-and then decides for the one with the bigger version_count
+
+So if one image is modified/created/removed, at most this one image can be
+lost, all the other images will still be accessible.
+
+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;
+};
+
+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
+    CYG_ADDRESS   entry_point;   // Execution entry point
+    unsigned long data_length;   // Length of actual data
+    unsigned char
+_pad[CYGNUM_REDBOOT_FIS_DIRECTORY_ENTRY_SIZE-FIS_IMAGE_DESC_SIZE_UNPADDED];
+    unsigned long desc_cksum;    // Checksum over image descriptor
+    unsigned long file_cksum;    // Checksum over image data
+};
+
+The procedure for creating/removing an image is as follows:
+
+-erase the not currently valid table : valid flag= 0xffff
+-write this table with the new contents, but valid flag = 0xfdfd (in progress)
+-write/erase the image data on flash
+-set the valid flag to 0xa5a5 -> now this fis table is the valid one
+
+There are some virtual vector functions implemented to provide this
+functionality:
+
+CYGACC_CALL_IF_FLASH_FIS_OP2(CYGNUM_CALL_IF_FLASH_FIS_GET_VERSION, 0, NULL)
+
+returns the version number of the fis implementation, you should only
+proceed if it matches your expected version number
+
+CYGACC_CALL_IF_FLASH_FIS_OP2(CYGNUM_CALL_IF_FLASH_FIS_INIT, 0, NULL)
+
+initialize fis, read the fis table, determine the valid one
+
+CYGACC_CALL_IF_FLASH_FIS_OP2(CYGNUM_CALL_IF_FLASH_FIS_GET_ENTRY_COUNT, 0, NULL)
+
+return the maximum number of entries the fis table could possibly have
+
+CYGACC_CALL_IF_FLASH_FIS_OP2(CYGNUM_CALL_IF_FLASH_FIS_GET_ENTRY, int index, struct fis_table_entry* entry)
+
+fill entry with the contents of the entry at position index from the valid
+fis table
+
+
+CYGACC_CALL_IF_FLASH_FIS_OP2(CYGNUM_CALL_IF_FLASH_FIS_START_UPDATE, 0, NULL)
+
+write the new fis table to flash but mark it as IN_PROGRESS (does nothing
+without redundant fis)
+
+CYGACC_CALL_IF_FLASH_FIS_OP2(CYGNUM_CALL_IF_FLASH_FIS_FINISH_UPDATE, int error, NULL)
+
+mark the IN_PROGRESS fis table as valid (without redundant fis: erase the
+fis table and write it again)
+
+CYGACC_CALL_IF_FLASH_FIS_OP2(CYGNUM_CALL_IF_FLASH_FIS_MODIFY_ENTRY, int index, struct fis_table_entry* entry)
+
+-modify the entry at position index with the contents given in entry. This
+fis table(s) on flash are not yet modified
+
+
+Using these functions a read-only fis file system is implemented as a
+regular ecos file system.
+Additionally there are three special function for modifying the fis:
+
+int fis_get_entry(const char* name, struct fis_table_entry* entry);
+
+returns 0 if an entry with the given name exists and fills entry with its
+contents, otherwise returns an errorcode
+
+int fis_remove_image(const char* name);
+
+removes image with the given name from the fis, returns 0 on success
+
+int fis_create_image(const char* name, char* buf, CYG_ADDRESS flash_base, 
+             CYG_ADDRESS mem_base, unsigned long size,
+             CYG_ADDRESS entry_point, unsigned long data_length, int backup);
+
+-create an image with the given name and the given parameters.
+If (backup==0) and an image with the name already exists, an error is
+returned.
+If (backup!=0) and an image with the given name already exists, a "~" will
+be appended to the name of the existing image and the new image will be
+created.
+
+This way the following redboot boot script can be used:
+
+fis load app; go; fis load app~; go
+
+So after an update the new application image will be named "app", and the
+previous one will have been renamed to "app~".
+
+
diff -rbupN ecos/packages/fs/fisfs/current/include/fisupdate.h ecos-fisfs-util/packages/fs/fisfs/current/include/fisupdate.h
--- ecos/packages/fs/fisfs/current/include/fisupdate.h	1970-01-01 01:00:00.000000000 +0100
+++ ecos-fisfs-util/packages/fs/fisfs/current/include/fisupdate.h	2007-01-08 12:52:34.000000000 +0100
@@ -0,0 +1,90 @@
+//==========================================================================
+//
+//      fisupdate.h
+//
+//      Functions for updating the FIS from eCos applications
+//
+//==========================================================================
+//####ECOSGPLCOPYRIGHTBEGIN####
+// -------------------------------------------
+// This file is part of eCos, the Embedded Configurable Operating System.
+// Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc.
+//
+// eCos is free software; you can redistribute it and/or modify it under
+// the terms of the GNU General Public License as published by the Free
+// Software Foundation; either version 2 or (at your option) any later version.
+//
+// eCos is distributed in the hope that it will be useful, but WITHOUT ANY
+// WARRANTY; without even the implied warranty of MERCHANTABILITY or
+// FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+// for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with eCos; if not, write to the Free Software Foundation, Inc.,
+// 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+//
+// As a special exception, if other files instantiate templates or use macros
+// or inline functions from this file, or you compile this file and link it
+// with other works to produce a work based on this file, this file does not
+// by itself cause the resulting work to be covered by the GNU General Public
+// License. However the source code for this file must still be made available
+// in accordance with section (3) of the GNU General Public License.
+//
+// This exception does not invalidate any other reasons why a work based on
+// this file might be covered by the GNU General Public License.
+//
+// Alternative licenses for eCos may be arranged by contacting Red Hat, Inc.
+// at http://sources.redhat.com/ecos/ecos-license/
+// -------------------------------------------
+//####ECOSGPLCOPYRIGHTEND####
+//==========================================================================
+//#####DESCRIPTIONBEGIN####
+//
+// Author(s):           alexander.neundorf@jenoptik.com
+// Date:                2007-01-02
+// Purpose:             Functions for updating the FIS from eCos applications
+// Description:         This file provides functions to update the contents
+//                      of the flash image system from eCos applications.
+//
+//
+//####DESCRIPTIONEND####
+//
+
+#ifndef FISUPDATE_H
+#define FISUPDATE_H
+
+#ifdef __cplusplus
+   extern "C" {
+#endif
+
+#include <pkgconf/fs_fis.h>
+#include <pkgconf/hal.h>
+#include <cyg/hal/hal_if.h>
+
+/* Get the fis_table_entry for the image with the given name, the index
+ of the image is returned, -1 if no such image exists.
+ If a NULL pointer is used for entry, only the index is returned. */
+int cyg_fis_get_entry(const char* name, struct fis_table_entry* entry);
+
+#ifdef CYGFUN_FS_FIS_UPDATE
+
+/* Remove the image with the given name from the FIS */
+int cyg_fis_remove_image(const char* name);
+
+/* Create a new image with the specified name.
+If backup is false, it fails if an image with the given name already exists.
+If backup is true and an image with the given name already exists,
+a "~" is appended to its name and a new image with the name is created.
+With this mechanism it is possible to do failsafe image updates.
+The other arguments are the same ones as known from the fis create RedBoot command.*/
+int cyg_fis_create_image(const char* name, char* buf,
+                CYG_ADDRESS flash_base, CYG_ADDRESS mem_base, unsigned long size,
+                CYG_ADDRESS entry_point, unsigned long data_length, int backup);
+
+#endif /* CYGFUN_FS_FIS_UPDATE */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff -rbupN ecos/packages/fs/fisfs/current/src/fisupdate.c ecos-fisfs-util/packages/fs/fisfs/current/src/fisupdate.c
--- ecos/packages/fs/fisfs/current/src/fisupdate.c	1970-01-01 01:00:00.000000000 +0100
+++ ecos-fisfs-util/packages/fs/fisfs/current/src/fisupdate.c	2007-01-08 12:55:13.000000000 +0100
@@ -0,0 +1,535 @@
+//==========================================================================
+//
+//      fisupdate.c
+//
+//      FIS utility and update functions
+//
+//==========================================================================
+//####ECOSGPLCOPYRIGHTBEGIN####
+// -------------------------------------------
+// This file is part of eCos, the Embedded Configurable Operating System.
+// Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc.
+//
+// eCos is free software; you can redistribute it and/or modify it under
+// the terms of the GNU General Public License as published by the Free
+// Software Foundation; either version 2 or (at your option) any later version.
+//
+// eCos is distributed in the hope that it will be useful, but WITHOUT ANY
+// WARRANTY; without even the implied warranty of MERCHANTABILITY or
+// FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+// for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with eCos; if not, write to the Free Software Foundation, Inc.,
+// 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+//
+// As a special exception, if other files instantiate templates or use macros
+// or inline functions from this file, or you compile this file and link it
+// with other works to produce a work based on this file, this file does not
+// by itself cause the resulting work to be covered by the GNU General Public
+// License. However the source code for this file must still be made available
+// in accordance with section (3) of the GNU General Public License.
+//
+// This exception does not invalidate any other reasons why a work based on
+// this file might be covered by the GNU General Public License.
+//
+// Alternative licenses for eCos may be arranged by contacting Red Hat, Inc.
+// at http://sources.redhat.com/ecos/ecos-license/
+// -------------------------------------------
+//####ECOSGPLCOPYRIGHTEND####
+//==========================================================================
+//#####DESCRIPTIONBEGIN####
+//
+// Author(s):           alexander.neundorf@jenoptik.com
+// Date:                2007-01-02
+// Purpose:             FIS acess and modification
+// Description:         Utility function for accessing the FIS from within eCos
+//                      applications. Additionally it provides some functions for modifying
+//                      the FIS. They can be used e.g. for updating the firmware
+//                      or other images. They don't feature wear levelling or
+//                      automatic space allocation.
+//
+//####DESCRIPTIONEND####
+//
+
+#include <pkgconf/system.h>
+#include <pkgconf/hal.h>
+#include <pkgconf/kernel.h>
+#include <pkgconf/fs_fis.h>
+#include <pkgconf/io_flash.h>
+
+#include <cyg/kernel/ktypes.h>         // base kernel types
+#include <cyg/kernel/kapi.h>
+#include <cyg/infra/cyg_trac.h>        // tracing macros
+#include <cyg/infra/cyg_ass.h>         // assertion macros
+#include <cyg/hal/hal_if.h>
+#include <cyg/infra/diag.h>
+#include <cyg/io/flash.h>
+
+#include <string.h>
+#include <errno.h>
+
+// how many entries can the FIS contain at most ? initialized in cyg_fis_init()
+int cyg_fis_max_entries=-1;
+
+// enable debug from CYG_TRACE
+#ifdef CYGDBG_FS_FIS_DEBUG_OUTPUT
+#define DEBUG_FIS 1
+#else
+#define DEBUG_FIS 0
+#endif
+
+#define SUPPORTED_FIS_VERSION (1)
+
+/* Initialize the FIS support.
+ It ensures that the version number of the Redboot FIS VV interface is compatible to the
+ VV interface expected here by checking the version numbers. The FLASH_FIS_INIT call
+ basically "mounts" the filesystem: the FIS table contents are read and the valid
+ table is detected. All files are marked as closed.*/
+int cyg_fis_init(void)
+{
+   int result=0;
+   if ( SUPPORTED_FIS_VERSION != CYGACC_CALL_IF_FLASH_FIS_OP2(CYGNUM_CALL_IF_FLASH_FIS_GET_VERSION, 0, NULL))
+   {
+      return ENOSUPP;
+   }
+
+   // 0: success, -1: failure, 1: success, but failed update detected
+   result=CYGACC_CALL_IF_FLASH_FIS_OP2(CYGNUM_CALL_IF_FLASH_FIS_INIT, 0, NULL);
+
+   if (result<0)
+   {
+      return ENOSUPP;
+   }
+
+   if (flash_init(diag_printf)!=0)
+   {
+      return EIO;
+   }
+
+   cyg_fis_max_entries=CYGACC_CALL_IF_FLASH_FIS_OP2(CYGNUM_CALL_IF_FLASH_FIS_GET_ENTRY_COUNT, 0, NULL);
+
+   // During FLASH_FIS_INIT a failed update was detected
+   if (result==1)
+   {
+      return EXDEV;
+   }
+
+   return ENOERR;
+}
+
+/* If an image with the given name exists its index is returned and
+ entry is filled appropriatly. Using a NULL-pointer for entry is also
+ ok, then only the index will be returned. If no such image exists, it returns -1.*/
+int cyg_fis_find_entry(const char* name, struct fis_table_entry* entry)
+{
+   unsigned int i=0;
+
+   for (i=0; i<cyg_fis_max_entries; i++)
+   {
+      struct fis_table_entry tmpEntry;
+      CYGACC_CALL_IF_FLASH_FIS_OP2(CYGNUM_CALL_IF_FLASH_FIS_GET_ENTRY, i, &tmpEntry);
+      if (tmpEntry.name[0]==0xff)  // empty
+      {
+         continue;
+      }
+
+      if (strcmp((const char*)tmpEntry.name, name)==0)
+      {
+         if (entry!=NULL)
+         {
+            memcpy(entry, &tmpEntry, sizeof(struct fis_table_entry));
+         }
+         return i;
+      }
+   }
+   return -1;
+}
+
+/* "Exported" function for more direct access to the FIS. Returns 0 on success. */
+int cyg_fis_get_entry(const char* name, struct fis_table_entry* entry)
+{
+   CYG_TRACE1(DEBUG_FIS, "get_entry name: -%s-", name);
+   if (cyg_fis_max_entries==-1)
+   {
+      int result=cyg_fis_init();
+      if ((result!=ENOERR) && (result!=EXDEV))
+      {
+         return result;
+      }
+   }
+
+   if (cyg_fis_find_entry(name, entry)<0)
+   {
+      return ENOENT;
+   }
+
+   return ENOERR;
+}
+
+#ifdef CYGFUN_FS_FIS_UPDATE
+
+/* This function programs the data from buf into the flash starting
+ at membase.
+ It first erases the flash and then programs the data.
+ This is done block by block, and during each block erase/program step
+ interrupts are disabled, otherwise the process can crash.
+*/
+static int cyg_fis_program_data(const void* membase, const char* buf, unsigned long size, unsigned long data_length)
+{
+   void* err_addr=0;
+   const char* current_flash_addr=membase;
+   const char* current_buf=buf;
+   int flash_block_size=0;
+   int flash_num_blocks=0;
+   unsigned long bytes_to_erase=size;
+   unsigned long bytes_to_write=data_length;
+
+   if (data_length>size)
+   {
+      return EINVAL;
+   }
+
+   flash_get_block_info(&flash_block_size, &flash_num_blocks);
+   CYG_TRACE2(DEBUG_FIS, "block_size: %d block_num: %d", flash_block_size, flash_num_blocks);
+
+   while ((bytes_to_erase>0) || (bytes_to_write>0))
+   {
+      int result=0;
+      if (bytes_to_erase>0)
+      {
+         CYG_TRACE2(DEBUG_FIS, "erasing %p bytes_to_erase: %d", current_flash_addr, bytes_to_erase);
+
+         cyg_interrupt_disable();
+         result=flash_erase(current_flash_addr, flash_block_size, (void **)&err_addr);
+         cyg_interrupt_enable();
+
+         bytes_to_erase= (bytes_to_erase>flash_block_size)?(bytes_to_erase-flash_block_size):0;
+         if (result!=0)
+         {
+            return EIO;
+         }
+      }
+
+      if (bytes_to_write>0)
+      {
+         unsigned long write_now = (bytes_to_write>flash_block_size)?flash_block_size:bytes_to_write;
+         CYG_TRACE3(DEBUG_FIS, "programming %p, size: %d bytes_to_write: %d", current_flash_addr, write_now, bytes_to_write);
+
+         cyg_interrupt_disable();
+         result=flash_program(current_flash_addr, (void*)current_buf, write_now, (void **)&err_addr);
+         cyg_interrupt_enable();
+
+         current_buf+=write_now;
+         bytes_to_write-=write_now;
+
+         if (result!=0)
+         {
+            return EIO;
+         }
+      }
+
+      current_flash_addr+=flash_block_size;
+   }
+
+   return 0;
+}
+
+#ifdef CYGPKG_CRC
+#include <cyg/crc/crc.h>
+#endif
+
+int cyg_fis_remove_image(const char* name)
+{
+   struct fis_table_entry oldEntry;
+   struct fis_table_entry entry;
+   int index=0;
+   int result=0;
+   void *err_addr=0;
+
+   // ensure that everything is initialized
+   if (cyg_fis_max_entries==-1)
+   {
+      result=cyg_fis_init();
+      if ((result!=ENOERR) && (result!=EXDEV))
+      {
+         return result;
+      }
+   }
+
+   index=cyg_fis_find_entry(name, &oldEntry);
+   if (index<0)
+   {
+      CYG_TRACE1(DEBUG_FIS, "no such image %s", name);
+      return ENOENT;
+   }
+
+   if ((strcmp(name, "FIS directory")==0)
+       || (strcmp(name, "RedBoot config")==0))
+   {
+      CYG_TRACE1(DEBUG_FIS, "deleting %s not permitted", name);
+      return EPERM;
+   }
+
+   CYG_TRACE3(DEBUG_FIS, "erasing -%s- addr: %x size: %d", name, oldEntry.flash_base, oldEntry.size);
+   // modify the directory so that it reflects the changes in RAM
+   memset(&entry, 0xff, sizeof(struct fis_table_entry));
+
+   CYGACC_CALL_IF_FLASH_FIS_OP2(CYGNUM_CALL_IF_FLASH_FIS_MODIFY_ENTRY, index, &entry);
+
+   // write them for now into the flash
+   CYGACC_CALL_IF_FLASH_FIS_OP2(CYGNUM_CALL_IF_FLASH_FIS_START_UPDATE, 0, NULL);
+   // and make the new written directory now valid, because once the erasing has started the data is corrupt
+   CYGACC_CALL_IF_FLASH_FIS_OP2(CYGNUM_CALL_IF_FLASH_FIS_FINISH_UPDATE, 0, NULL);
+
+   // erase it
+   cyg_interrupt_disable();
+#ifdef CYGHWR_IO_FLASH_BLOCK_LOCKING
+   flash_unlock((void *)oldEntry.flash_base, oldEntry.size, (void **)&err_addr);
+#endif
+   result=flash_erase((void *)oldEntry.flash_base, oldEntry.size, (void **)&err_addr);
+#ifdef CYGHWR_IO_FLASH_BLOCK_LOCKING
+   flash_lock((void *)oldEntry.flash_base, oldEntry.size, (void **)&err_addr);
+#endif
+   cyg_interrupt_enable();
+
+   // make sure everything is initialized correctly again
+   if (cyg_fis_init()!=0)
+   {
+      return ENOSUPP;
+   }
+
+   if (result!=0)
+   {
+      return EIO;
+   }
+
+   return 0;
+}
+
+/* Create a new image.
+If backup is false, it fails if an image with the given name
+already exists.
+If backup is true and an image with the given name already exists,
+a "~" is appended to its name and a new image with the name is created.
+With this mechanism it is possible to do failsafe image updates. */
+int cyg_fis_create_image(const char* name, char* buf,
+                CYG_ADDRESS flash_base, CYG_ADDRESS mem_base, unsigned long size,
+                CYG_ADDRESS entry_point, unsigned long data_length, int backup)
+{
+   int result=0;
+
+   int existingImgIndex=-1;
+   struct fis_table_entry existingImgTableEntry;
+
+   int previousBackupIndex=-1;
+   struct fis_table_entry previousBackupTableEntry;
+
+   int newIndex=-1;
+   struct fis_table_entry newTableEntry;
+
+   int i=0; //for iterations
+   unsigned long cksum=0;
+
+   void *err_addr=0;
+
+   unsigned int nameLength=0;
+
+   char backupName[16];
+   backupName[0]='\0';
+
+   // ensure that everything is initialized
+   if (cyg_fis_max_entries==-1)
+   {
+      result=cyg_fis_init();
+      if ((result!=ENOERR) && (result!=EXDEV))
+      {
+         return result;
+      }
+   }
+
+   // check parameters
+   if (size==0)
+   {
+      CYG_TRACE1(DEBUG_FIS, "invalid size: %d", size);
+      return EINVAL;
+   }
+
+
+   if ((flash_verify_addr((void*)flash_base)!=0)
+       || (flash_verify_addr((void*)(flash_base+size-1))!=0))
+   {
+      CYG_TRACE2(DEBUG_FIS, "invalid addresses %p %p", flash_base, flash_base+size-1);
+      return EINVAL;
+   }
+
+   nameLength=strlen(name);
+   if (nameLength>15)   // the name can be up to 16 characters including the terminating 0
+   {
+      return EINVAL;
+   }
+
+   existingImgIndex=cyg_fis_find_entry(name, &existingImgTableEntry);
+
+   if ((!backup) && (existingImgIndex>=0))  // if creating a new image without backup, it may not exist yet
+   {
+      CYG_TRACE1(DEBUG_FIS, "image already exists: %s", name);
+      return EEXIST;
+   }
+
+   if (backup)
+   {
+      // a ~ will be appended to the original name
+      if (nameLength>14)
+      {
+         return EINVAL;
+      }
+      strcpy(backupName, name);
+      backupName[nameLength]='~';
+      backupName[nameLength+1]='\0';
+      previousBackupIndex=cyg_fis_find_entry(backupName, &previousBackupTableEntry); // find eventually existing previous backup image, will be removed/overwritten later
+   }
+
+   // find a free entry
+   for (i=0; i<cyg_fis_max_entries; i++)
+   {
+      struct fis_table_entry tmpEntry;
+      CYGACC_CALL_IF_FLASH_FIS_OP2(CYGNUM_CALL_IF_FLASH_FIS_GET_ENTRY, i, &tmpEntry);
+      CYG_TRACE2(DEBUG_FIS, "i: %d c[0]: 0x%x", i, (unsigned int )(tmpEntry.name[0] & 0xff));
+      if ((tmpEntry.name[0]==0xff)      // empty
+          || (i==previousBackupIndex))  // this one will be removed later, so it can be considered empty
+      {
+         newIndex=i;
+         break;
+      }
+   }
+
+   // no free slot found :-(
+   if (newIndex==-1)
+   {
+      CYG_TRACE0(DEBUG_FIS, "no free slot left");
+      return EMFILE;
+   }
+
+   // check for overlapping
+   for (i=0; i<cyg_fis_max_entries; i++)
+   {
+      struct fis_table_entry tmpEntry;
+      CYGACC_CALL_IF_FLASH_FIS_OP2(CYGNUM_CALL_IF_FLASH_FIS_GET_ENTRY, i, &tmpEntry);
+
+      if (i==previousBackupIndex)  // will be removed later on, so can be ignored here
+      {
+         continue;
+      }
+
+      if (tmpEntry.name[0]==0xff)  // empty entry
+      {
+         continue;
+      }
+
+      if ((tmpEntry.flash_base >= flash_base+size)
+           || ((tmpEntry.flash_base+tmpEntry.size)<= flash_base) )  // doesn't overlap
+      {
+         continue;
+      }
+
+      // error case, overlapping
+      CYG_TRACE5(DEBUG_FIS, "overlap: name: %s base: 0x%x size: 0x%x (b: 0x%x s: 0x%x)\n", tmpEntry.name, tmpEntry.flash_base, tmpEntry.size, flash_base, size);
+      return ENOMEM;
+   }
+
+   // if a backup is desired, ...
+   if (backup)
+   {
+      if (previousBackupIndex>=0)  //...erase the old backup entry...
+      {
+         memset(&previousBackupTableEntry, 0xff, sizeof(struct fis_table_entry));
+         CYGACC_CALL_IF_FLASH_FIS_OP2(CYGNUM_CALL_IF_FLASH_FIS_MODIFY_ENTRY, previousBackupIndex, &previousBackupTableEntry);
+      }
+
+      if (existingImgIndex>=0) //... and make the current image the new backup image
+      {
+         strcpy((char*)existingImgTableEntry.name, backupName);
+         CYGACC_CALL_IF_FLASH_FIS_OP2(CYGNUM_CALL_IF_FLASH_FIS_MODIFY_ENTRY, existingImgIndex, &existingImgTableEntry);
+      }
+   }
+
+   // create the new directory entry
+   memset(&newTableEntry, 0xff, sizeof(struct fis_table_entry));
+   strcpy((char*)newTableEntry.name, name);
+   newTableEntry.flash_base=flash_base;
+   newTableEntry.mem_base=mem_base;
+   newTableEntry.size=size;
+   newTableEntry.entry_point=entry_point;
+   newTableEntry.data_length=data_length;
+#ifdef CYGPKG_CRC
+   newTableEntry.file_cksum=cyg_crc32((unsigned char*)buf, data_length);
+#else
+   newTableEntry.file_cksum=0;
+#endif
+
+   cyg_interrupt_disable();
+   CYGACC_CALL_IF_FLASH_FIS_OP2(CYGNUM_CALL_IF_FLASH_FIS_MODIFY_ENTRY, newIndex, &newTableEntry);
+   cyg_interrupt_enable();
+
+   // write them for now into the flash
+   cyg_interrupt_disable();
+   result=CYGACC_CALL_IF_FLASH_FIS_OP2(CYGNUM_CALL_IF_FLASH_FIS_START_UPDATE, 0, NULL);
+   cyg_interrupt_enable();
+
+   if (result!=0)
+   {
+      // restore copy in ram...
+      CYG_TRACE1(DEBUG_FIS, "start update failed: 0x%x", result);
+      cyg_fis_init();
+      return EIO;
+   }
+
+   // unlock, erase, program and lock  it, error checking is done using the CRC
+   CYG_TRACE1(DEBUG_FIS, "unlocking %p", newTableEntry.flash_base);
+
+#ifdef CYGHWR_IO_FLASH_BLOCK_LOCKING
+   cyg_interrupt_disable();
+   flash_unlock((void *)newTableEntry.flash_base, newTableEntry.size, (void **)&err_addr);
+   cyg_interrupt_enable();
+#endif
+
+   cyg_fis_program_data((void *)newTableEntry.flash_base, buf, newTableEntry.size, newTableEntry.data_length);
+
+   CYG_TRACE1(DEBUG_FIS, "locking %p", newTableEntry.flash_base);
+
+#ifdef CYGHWR_IO_FLASH_BLOCK_LOCKING
+   cyg_interrupt_disable();
+   flash_lock((void *)newTableEntry.flash_base, newTableEntry.size, (void **)&err_addr);
+   cyg_interrupt_enable();
+#endif
+
+#ifdef CYGPKG_CRC
+   // read back and check the crc
+   flash_read((void *)newTableEntry.flash_base, buf, newTableEntry.data_length, (void **)&err_addr);
+   cksum=cyg_crc32((unsigned char*)buf, data_length);
+   if (newTableEntry.file_cksum!=cksum)
+   {
+      CYG_TRACE2(DEBUG_FIS, "crc error: read: 0x%x expected: 0x%x", cksum, newTableEntry.file_cksum);
+      CYGACC_CALL_IF_FLASH_FIS_OP2(CYGNUM_CALL_IF_FLASH_FIS_FINISH_UPDATE, 1, NULL);
+      return EIO;
+   }
+#endif
+
+   //and make the new written directory valid
+   cyg_interrupt_disable();
+   CYGACC_CALL_IF_FLASH_FIS_OP2(CYGNUM_CALL_IF_FLASH_FIS_FINISH_UPDATE, 0, NULL);
+   cyg_interrupt_enable();
+
+   //make sure everything is initialized correctly again
+   if (cyg_fis_init()!=0)
+   {
+      return ENOSUPP;
+   }
+
+   return 0;
+}
+
+#endif //  CYGFUN_FS_FIS_UPDATE
+
+// EOF fisupdate.c
