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-03 16:39:01.000000000 +0100 @@ -0,0 +1,76 @@ +# ==================================================================== +# +# 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 +# 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 + + compile -library=libextras.a fisupdate.c + + cdl_option CYGDBG_FS_FIS_DEBUG_OUTPUT { + display "Enable debug output" + default_value 1 + } + + 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 + + * 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-03 14:08:26.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 +#include +#include + +/* 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 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 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 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-03 16:40:04.000000000 +0100 @@ -0,0 +1,526 @@ +//========================================================================== +// +// 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 +#include +#include +#include + +#include // base kernel types +#include +#include // tracing macros +#include // assertion macros +#include +#include +#include + +#include +#include + +// how many entries can the FIS contain at most ? initialized in fis_init() +int 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 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; + } + + 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 fis_find_entry(const char* name, struct fis_table_entry* entry) +{ + unsigned int i=0; + + for (i=0; isize) + { + 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 +#endif + +int 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 (fis_max_entries==-1) + { + result=fis_init(); + if ((result!=ENOERR) && (result!=EXDEV)) + { + return result; + } + } + + index=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(); + flash_unlock((void *)oldEntry.flash_base, oldEntry.size, (void **)&err_addr); + result=flash_erase((void *)oldEntry.flash_base, oldEntry.size, (void **)&err_addr); + flash_lock((void *)oldEntry.flash_base, oldEntry.size, (void **)&err_addr); + cyg_interrupt_enable(); + + // make sure everything is initialized correctly again + if (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 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 (fis_max_entries==-1) + { + result=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=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=fis_find_entry(backupName, &previousBackupTableEntry); // find eventually existing previous backup image, will be removed/overwritten later + } + + // find a free entry + for (i=0; i= 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); + 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); + + cyg_interrupt_disable(); + flash_unlock((void *)newTableEntry.flash_base, newTableEntry.size, (void **)&err_addr); + cyg_interrupt_enable(); + + fis_program_data((void *)newTableEntry.flash_base, buf, newTableEntry.size, newTableEntry.data_length); + + CYG_TRACE1(DEBUG_FIS, "locking %p", newTableEntry.flash_base); + + cyg_interrupt_disable(); + flash_lock((void *)newTableEntry.flash_base, newTableEntry.size, (void **)&err_addr); + cyg_interrupt_enable(); + +#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 (fis_init()!=0) + { + return ENOSUPP; + } + + return 0; +} + +#endif // CYGFUN_FS_FIS_UPDATE + +// EOF fisupdate.c