This is the mail archive of the ecos-patches@sourceware.org mailing list for the eCos project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: [flashv2 merge] RedBoot


Jonathan Larmour wrote:
> With many eCosCentric updates. Attached.

Let's try again.... forgive me, it's late :).

Jifl
-- 
eCosCentric Limited      http://www.eCosCentric.com/     The eCos experts
Barnwell House, Barnwell Drive, Cambridge, UK.       Tel: +44 1223 245571
Registered in England and Wales: Reg No 4422071.
------["Si fractum non sit, noli id reficere"]------       Opinions==mine
Index: packages/redboot/current/ChangeLog
===================================================================
RCS file: /cvs/ecos/ecos/packages/redboot/current/ChangeLog,v
retrieving revision 1.259
retrieving revision 1.260
diff -u -5 -p -r1.259 -r1.260
--- packages/redboot/current/ChangeLog	11 Nov 2008 17:08:17 -0000	1.259
+++ packages/redboot/current/ChangeLog	18 Nov 2008 01:02:43 -0000	1.260
@@ -1,5 +1,25 @@
+2008-11-16  Jonathan Larmour  <jifl@eCosCentric.com>
+
+	* cdl/redboot.cdl, src/flash.c, src/fconfig.c:
+	Flash-related eCosCentric changes to these files (including a
+	merge of the flashv2 work) have been merged. Changes have been
+	directly interleaved below on the correct dates.
+
+2008-11-14  Jonathan Larmour  <jifl@eCosCentric.com>
+
+	* src/flash.c (fis_lock): Revert patch of 2005-10-05 which disabled
+	locking entirely if FIS was disabled. Was better fixed by patch of
+	2006-02-17.
+	(fis_list): Revert patch of 2007-04-03 to avoid skipping entries
+	at 0x0. Replaced by anoncvs patch of 2007-06-02 for consistency.
+
+2008-09-11  Nick Garnett  <nickg@ecoscentric.com>
+
+	* src/flash.c (fis_create, fis_write, fis_erase): Change alignment
+	test to cope with flash blocks that are not a power of 2 in size.
+
 2008-06-18  Bart Veer  <bartv@ecoscentric.com>
 
 	* src/fconfig.c, src/flash.c, src/io.c, src/load.c, src/main.c,
   	src/xyzModem.c, include/redboot.h: more signed vs. unsigned char
 	issues. 
@@ -20,10 +40,15 @@
 	* src/io.c: Ditto.
 	* src/xyzModem.c: Ditto.
 	* src/load.c: Ditto.
 	* src/flash.c: Ditto.
 
+2007-11-21  Jonathan Larmour  <jifl@eCosCentric.com>
+
+	* src/flash.c (fis_create): Allow length to be inferred if same
+	mem address given as prior load address.
+
 2007-08-28  Gary Thomas  <gary@mlbassoc.com>
 
 	* src/flash.c (do_flash_init): Memory allocation was slightly
 	incorrect - 'workspace_end' should always be used to find 
 	the end of available memory.
@@ -56,15 +81,32 @@
 	* src/fs/fileio.c: Temporary kludge to treat flash correctly if either
 	flash v1 or flash v2 used with this file.
 	(do_mount): silence warning. Include accidentally omitted printf arg.
 	(do_list): silence warning.
 
+2007-04-03  Bart Veer  <bartv@ecoscentric.com>
+
+	* src/flash.c (fis_list): don't skip entries at location 0x0
+
 2007-01-22  Peter Korsgaard  <peter.korsgaard@barco.com>
 
 	* src/load.c (do_load): Reset entry address before load so
 	go/exec commands will fail after an incomplete upload.
 
+2006-12-18  John Dallaway  <jld@ecoscentric.com>
+
+	* src/flash.c, src/fconfig.c: Eliminate some compiler warnings.
+
+2006-12-06  Jonathan Larmour  <jifl@eCosCentric.com>
+
+	* src/flash.c (find_free): When eliminating collapsed free chunks,
+	don't decrement num_chunks as a side effect every loop!
+
+2006-12-04  Bart Veer  <bartv@ecoscentric.com>
+
+	* src/flash.c, src/main.c: eliminate some compiler warnings.
+
 2006-11-28  David Fernandez  <dfernandez@cct.co.uk>
 
 	* cdl/redboot.cdl: Modified to change the option
 	CYGDAT_REDBOOT_DEFAULT_NETWORK_DEVICE to make it independent of
 	CYGSEM_REDBOOT_FLASH_CONFIG, changes in net_io.c will allow to
@@ -82,10 +124,20 @@
 2006-11-19  Andrew Lunn  <lunn@laptop.lunn.ch>
 
 	* src/load.c: Only call valid_address() if
 	CYGSEM_REDBOOT_VALIDATE_USER_RAM_LOADS is enabled.
 
+2006-11-01  Jonathan Larmour  <jifl@eCosCentric.com>
+
+	* src/flash.c (fis_create): Ensure flash_addr is always inferred
+	to come from unused space if not set.
+
+2006-10-19  Jonathan Larmour  <jifl@eCosCentric.com>
+
+	* src/flash.c (fis_create): If not copying, no reason to insist
+	on a flash address being set.
+
 2006-09-06  Andrew Lunn  <andrew.lunn@ascom.ch>
 
 	* cdl/redboot.cdl: Fix description of CYGSEM_REDBOOT_DISK_IDE.
 	Error pointed out by Wang Cui
 
@@ -96,10 +148,23 @@
 2006-07-21  David Ho <davidkwho@gmail.com>
 
 	* src/flash.c (fis_start_update_directory): Fix build error when
 	redundant FIS selected and locking is not enabled/supported.
 
+2006-06-16  Nick Garnett  <nickg@ecoscentric.com>
+
+	* src/flash.c (flash_reserved): Value for the macro used when this
+	feature is disabled should be false not true.
+
+2006-06-09  Nick Garnett  <nickg@ecoscentric.com>
+
+	* cdl/redboot.cdl:
+	* src/flash.c (flash_reserved): Added config option,
+	CYGNUM_REDBOOT_FLASH_RESERVED_DEVICES, and code to check for a
+	list of reserved flash devices that should not be used for FIS
+	file allocation.
+
 2006-05-24  Gary Thomas  <gary@mlbassoc.com>
 
 	* src/net/net_io.c (do_ip_addr): Bail out if no networking.
 
 2006-05-23  Gary Thomas  <gary@mlbassoc.com>
@@ -127,10 +192,28 @@
 2006-03-27  Gary Thomas  <gary@mlbassoc.com>
 
 	* src/net/tcp.c (__tcp_write_block): Fix calculation of actual
 	total number of bytes sent (from Wolfgang Koebler)
 
+2006-03-21  Jonathan Larmour  <jifl@eCosCentric.com>
+
+	* src/flash.c (find_free): Fix typo in last change.
+
+2006-03-16  Jonathan Larmour  <jifl@eCosCentric.com>
+
+	* src/flash.c (find_free): Fix indentation.
+	Trivial optimisation when free chunk collapsed.
+	When splitting chunks, be sure to insert not overwrite - there may be
+	a subsequent free chunk.
+	Even if out of free chunks when splitting, be sure to mark end of this
+	chunk as used, to avoid it inappropriately being reported as free.
+
+2006-03-10  Bart Veer  <bartv@ecoscentric.com>
+
+	* src/flash.c (find_free): fix boundary condition when an fis img
+	is right at the end of memory.
+
 2006-02-25  Oliver Munz  <munz@speag.ch>
 	    Andrew Lunn  <andrew.lunn@ascom.ch>
 	
 	* src/xyzModem.c (xyzModem_stream_open): Fix compiler warnings.
 	* src/flash_load.c (NEW): Implements access to flash
@@ -151,18 +234,62 @@
 	* src/flash.c (fis_lock & fis_unlock): Allow compilation without
 	FIS being enabled.
 	* src/flash.c (fis_update_directory): When reading/writing flash
 	use the full size of the fis directory, not just one block.
 
+2006-01-26  John Dallaway  <jld@ecoscentric.com>
+
+	* src/flash.c (_flash_info): Tidy presentation of flash block info.
+
+2006-01-17  Jonathan Larmour  <jifl@eCosCentric.com>
+
+	* src/flash.c (fis_init): Default data_length = FIS partition
+	size for special partitions.
+
+2005-12-22  Jonathan Larmour  <jifl@eCosCentric.com>
+
+	* src/flash.c (find_free): adjust base only for appropriate device.
+	(fis_free): Fix up case for !CYGDAT_REDBOOT_FIS_MAX_FREE_CHUNKS
+	to correctly scan for blank regions.
+	Remove obsolete version of same.	
+	(fis_find_free): Adapt fis_free changes for this.
+
+2005-12-12  Jonathan Larmour  <jifl@eCosCentric.com>
+
+	* src/flash.c (fis_free): Rewrite to improve support
+	for multiple flash devices. Still not really right - needs
+	wider changes.
+	(fis_find_free): Better support multiple flash devices.
+	Far from perfect yet though. Minor improvement on what
+	was there before though.
+
 2005-11-23  Peter Korsgaard  <peter.korsgaard@barco.com>
 
 	* src/gunzip.c (do_gunzip): Fixed diag_printf format string warnings.
 
 2005-10-17  Gary Thomas  <gary@mlbassoc.com>
 
 	* src/iomem.c (do_iopeek): Correct number of options.
 
+2005-10-05  Nick Garnett  <nickg@ecoscentric.com>
+
+	* src/flash.c: Changes to various ifdefs to allow FCONFIG to be
+	used independently of FIS. It was always intended that this be
+	possible, but over time it suffered a little bitrot.
+
+2005-09-30  Nick Garnett  <nickg@ecoscentric.com>
+
+	* cdl/redboot.cdl: Move CYGNUM_REDBOOT_FLASH_BASE out of
+	CYGPKG_REDBOOT_FLASH component so that it can be used from RBL
+	when CYGPKG_REDBOOT_FLASH is disabled.
+
+2005-09-26  Bart Veer  <bartv@ecoscentric.com>
+
+	* src/flash.c: put flag into .bss rather than .data, avoids
+	problems if soft reset involves branching to the entry point and
+	.data does not get reinitialized.
+
 2005-09-13  Jonathan Larmour  <jifl@eCosCentric.com>
 
 	* src/parse.c (redboot_exec): Conditionalise use of 
 	__mem_fault_handler to only be when stubs are included.
 	(error_handler): Ditto for this function.
@@ -309,25 +436,39 @@
 
 	* src/alias.c (lookup_alias): Fix compiler warnings about formats
 	* src/cksum.c (do_cksum): Ditto
 	* src/dump.c  (do_dump): Ditto	
 
-2005-04-07  Peter Korsgaard  <jacmet@sunsite.dk>
-
-	* cdl/redboot.cdl, doc/redboot_cmds.sgml, src/gunzip.c: Added
-	gunzip command to uncompress GZIP compressed data.	
-
 2005-04-11  Peter Korsgaard  <jacmet@sunsite.dk>
 
 	* src/flash.c (find_free): Correctly split chunks in two when
 	not final chunk.
 
+2005-04-07  Peter Korsgaard  <jacmet@sunsite.dk>
+
+	* cdl/redboot.cdl, doc/redboot_cmds.sgml, src/gunzip.c: Added
+	gunzip command to uncompress GZIP compressed data.	
+
 2005-03-07 Alexander Neundorf <alexander.neundorf@jenoptik.com>
 
         * src/net/arp.c: use correct sizeof(rt->enet_addr) in
 	__arp_lookup()
 	
+2005-02-17 Â?Bart Veer Â?<bartv@ecoscentric.com>
+
+	* src/flash.c (fis_create): if -r is not specified, set the ram
+	base address in the fis directory to the current load address.
+	This assumes the data is currently in the right place, as should
+	be the case after e.g. loading an elf executable.
+
+2005-02-11  Jonathan Larmour  <jifl@eCosCentric.com>
+
+	* src/flash.c (find_free): Correct fis free calculations to account
+	for chunk regions ending 1 byte before fis fis regions.
+	(fis_find_free): Allow for difference of end from start being one
+	less than size of region.
+
 2005-01-26  Nick Garnett  <nickg@ecoscentric.com>
 
 	* src/fs/fileio.c (do_mkdir, do_deldir, do_del, do_write): Added
 	some extra argument checking to these functions.
 
@@ -380,10 +521,60 @@
 	commands.
 
 	* src/fs/fileio.c (do_write): Added O_TRUNC to the open call to
 	ensure that the file is resized to fit the new data.
 
+2004-11-24  Bart Veer  <bartv@ecoscentric.com>
+
+	* Merge from flash V2 branch
+	
+  2004-11-21  Bart Veer  <bartv@ecoscentric.com>
+
+	* src/flash.c (check_code_overlaps): cyg_flash_code_overlaps() has
+	been removed, so use a RedBoot-specific function instead
+
+  2004-11-20  Bart Veer  <bartv@ecoscentric.com>
+
+	* src/flash.c (do_flash_init): info.end already holds the last
+	flash byte, no need to adjust.
+
+  2004-10-07  Andrew Lunn  <andrew.lunn@ascom.ch>
+
+	* src/flash.c (do_flash_init): Fix compiler warning about an
+	unused variable.
+
+  2004-10-06  Andrew Lunn  <andrew.lunn@ascom.ch>
+
+	* src/flash.c (do_flash_init): We need info independent of
+	CYGNUM_REDBOOT_FLASH_BASE being set or not.
+	
+  2004-09-14  Andrew Lunn  <andrew.lunn@ascom.ch>
+
+	* cdl/redboot.cdl: Change CYGNUM_REDBOOT_FLASH_BASE to a booldata
+	so we don't always look at address 0 for the flash!
+
+  2004-08-21  Andrew Lunn  <andrew.lunn@ascom.ch>
+
+	* src/flash.c (do_flash_init): cyg_flash_get_limits has been removed.
+	Reimplement this functionality using other calls.
+
+  2004-08-13  Andrew Lunn  <andrew.lunn@ascom.ch>
+
+	* cdl/redboot.cdl: Fixed the type of CYGNUM_REDBOOT_FLASH_BASE
+	* src/flash.c (fis_[un]lock): Fix compiler warnings
+
+  2004-08-06  Andrew Lunn  <andrew.lunn@ascom.ch>
+
+	* src/flash.c (do_flash_init): Removed the MIPS br0ken condition
+	which i wrongly added. My problem was actually a / 0. This roundup
+	is needed otherwise the workspace goes off the end of the RAM.
+
+  2004-08-05  Andrew Lunn  <andrew.lunn@ascom.ch>
+
+	* src/flash.c:
+	* src/fconfig.c: Make use of the new flash API.
+
 2004-11-24  Nick Garnett  <nickg@ecoscentric.com>
 
 	* src/fs/fileio.c: Significantly reorganized to present an
 	interface similar to the fis commands. Added a variety of command
 	to manipulate files and directories in a filesystem.
@@ -402,10 +593,15 @@
 	* src/net/net_io.c: Changed init priority to RedBoot_INIT_NET.
 	
 	* include/redboot.h: Added some extra initialization
 	priorities. Added prototypes for redboot_exec() and err_printf().
 
+2004-11-11  Bart Veer  <bartv@ecoscentric.com>
+
+	* src/flash.c (find_free): allow for flash blocks larger than the
+	RedBoot MIN_IMAGE_SIZE
+
 2004-11-09  Ian Campbell  <icampbell@arcom.com>
 
 	* cdl/redboot.cdl, doc/redboot_cmds.sgml, src/iomem.c: Add support
 	for iopeek and iopoke commands to allow access to the I/O regions.
 
@@ -416,10 +612,18 @@
 
 	* src/flash.c (find_free, fis_free, fis_find_free): Don't ignore
         an extra CYGBLD_REDBOOT_MIN_IMAGE_SIZE amount from the start.
         This fixes the case where nothing uses the start of flash.
 
+2004-11-05  John Dallaway  <jld@ecoscentric.com>
+
+	* src/flash.c (fis_create): Eliminate MIPS compiler workaround
+	which causes problems with multiple use of flash blocks and appears
+	to be unnecessary with GCC 3.2.1.
+
+	* src/flash.c (fis_write): Eliminate MIPS compiler workaround.
+
 2004-11-04  Peter Korsgaard  <jacmet@sunsite.dk>
 
 	* src/fconfig.c (flash_write_config): Removed compiler warning
 	when building redboot with combined FIS and config.
 
@@ -524,10 +728,15 @@
 
 	* src/flash.c (find_free): fix endless loop when removing a
 	collapsed chunk from chunk table. Found by Laurent Gonzalez
 	(fis_load): Fixed a compiler warning.
 
+2004-06-11  Nick Garnett  <nickg@ecoscentric.com>
+
+	* src/flash.c (fis_create): Made unlock/lock operations dependent
+	on CYGHWR_IO_FLASH_BLOCK_LOCKING.
+
 2004-05-31  Jani Monoses <jani@iv.ro>
 
 	* src/main.c:
 	* include/redboot.h: Get rid of unused workspace_size.
 	
@@ -539,10 +748,17 @@
 
 2004-05-21  Ian Campbell  <icampbell@arcom.com>
 	 
 	* src/main.c: Make it build without CYGSEM_REDBOOT_FLASH_ALIASES.
 	
+2004-05-07  Nick Garnett  <nickg@ecoscentric.com>
+
+	* src/flash.c (fis_create): Added unlock and lock operations
+	around programming of flash region. Some flash parts power up with
+	all locks on, so we have to unlock, and we might as well play safe
+	and keep everything locked.
+
 2004-05-05  Gary Thomas  <gary@mlbassoc.com>
 
 	* src/flash.c (fis_load): CRC check on load was broken (the CDL
 	option changed names)
 
@@ -3918,10 +4134,11 @@
 //===========================================================================
 //####ECOSGPLCOPYRIGHTBEGIN####
 // -------------------------------------------
 // This file is part of eCos, the Embedded Configurable Operating System.
 // Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc.
+// Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008 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.
 //
@@ -3941,11 +4158,8 @@
 // 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####
 //===========================================================================
Index: packages/redboot/current/cdl/redboot.cdl
===================================================================
RCS file: /cvs/ecos/ecos/packages/redboot/current/cdl/redboot.cdl,v
retrieving revision 1.80
retrieving revision 1.81
diff -u -5 -p -r1.80 -r1.81
--- packages/redboot/current/cdl/redboot.cdl	11 Nov 2008 04:32:10 -0000	1.80
+++ packages/redboot/current/cdl/redboot.cdl	18 Nov 2008 01:02:44 -0000	1.81
@@ -6,10 +6,11 @@
 #
 # ====================================================================
 #####ECOSGPLCOPYRIGHTBEGIN####
 ## -------------------------------------------
 ## This file is part of eCos, the Embedded Configurable Operating System.
+## Copyright (C) 2005, 2006, 2008 eCosCentric Limited
 ## Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc.
 ## Copyright (C) 2002, 2003, 2004, 2005 Gary Thomas
 ##
 ## 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
@@ -674,10 +675,20 @@ cdl_package CYGPKG_REDBOOT {
               for a safer environment, but this check may not be valid
               on all platforms, thus the ability to disable it.  
               ** Disable this only with great care **"
         }
     
+        cdl_option CYGNUM_REDBOOT_FLASH_BASE {
+            display       "Base address of flash device redboot should use"
+            flavor        booldata
+            description   "
+                This option controls how redboot finds the flash
+                device. Setting this option to an address will
+                cause redboot to use that address as the base of the 
+                flash device."
+        }
+
         cdl_component CYGPKG_REDBOOT_FLASH {
             display       "Allow RedBoot to support FLASH programming"
             flavor        bool
             default_value 1
             active_if     CYGHWR_IO_FLASH_DEVICE
@@ -893,10 +904,22 @@ cdl_package CYGPKG_REDBOOT {
                       FLASH where RedBoot will never interfere; it is
                       expected that this area contains
                       (non-RedBoot-based) POST code or some other boot
                       monitor that executes before RedBoot."
                 }
+
+                cdl_option CYGNUM_REDBOOT_FLASH_RESERVED_DEVICES {
+                    display         "List of Flash devices that are reserved"
+                    flavor          booldata
+                    default_value   0
+                    description     "This option lists the base addresses of any Flash
+                                     devices that should not be managed by the flash
+                                     image system. In particular, this means that these
+                                     devices will not be considered when looking for free
+                                     space in which to create new files. It should consist
+                                     of a comma-separated list of (virtual) addresses."
+                }
             }
     
             cdl_option CYGSEM_REDBOOT_FLASH_LOCK_SPECIAL {
                 display       "Keep all RedBoot FLASH data blocks locked."
                 flavor        bool
Index: packages/redboot/current/src/fconfig.c
===================================================================
RCS file: /cvs/ecos/ecos/packages/redboot/current/src/fconfig.c,v
retrieving revision 1.14
retrieving revision 1.15
diff -u -5 -p -r1.14 -r1.15
--- packages/redboot/current/src/fconfig.c	11 Nov 2008 04:32:10 -0000	1.14
+++ packages/redboot/current/src/fconfig.c	18 Nov 2008 01:28:12 -0000	1.15
@@ -75,11 +75,11 @@ externC void read_eeprom(void *buf, int 
 externC bool cyg_plf_redboot_esa_validate(unsigned char *val);
 #endif
 
 #ifdef CYGHWR_REDBOOT_FLASH_CONFIG_MEDIA_FLASH
 externC int do_flash_init(void);
-externC int flash_read(void *flash_base, void *ram_base, int len, void **err_address);
+#include <cyg/io/flash.h>
 #endif
 
 // Round a quantity up
 #define _rup(n,s) ((((n)+(s-1))/s)*s)
 
@@ -89,23 +89,24 @@ externC int flash_read(void *flash_base,
 // normal "configuration" data items.
 struct _config *config, *backup_config;
 
 // Local data used by these routines
 #ifdef CYGHWR_REDBOOT_FLASH_CONFIG_MEDIA_FLASH
-extern void *flash_start, *flash_end;
-extern int flash_block_size, flash_num_blocks;
+extern cyg_flashaddr_t flash_start, flash_end;
+extern size_t flash_block_size;
+extern cyg_uint32 flash_num_blocks;
 extern int __flash_init;
 #ifdef CYGOPT_REDBOOT_FIS
 extern void *fis_work_block;
-extern void *fis_addr;
+extern cyg_flashaddr_t fis_addr;
 extern int fisdir_size;  // Size of FIS directory.
 #endif
 #ifdef CYGSEM_REDBOOT_FLASH_CONFIG_READONLY_FALLBACK
 static struct _config  *readonly_config;
 #endif
-void *cfg_base;   // Location in Flash of config data
-int   cfg_size;   // Length of config data - rounded to Flash block size
+cyg_flashaddr_t cfg_base;    // Location in Flash of config data
+size_t  cfg_size;            // Length of config data - rounded to Flash block size
 #endif // FLASH MEDIA
 
 // Prototypes for local functions
 static char *flash_lookup_config(char *key);
 
@@ -773,17 +774,13 @@ flash_crc(struct _config *conf)
 // Write the in-memory copy of the configuration data to the flash device.
 //
 void
 flash_write_config(bool prompt)
 {
-#if defined(CYGHWR_REDBOOT_FLASH_CONFIG_MEDIA_FLASH) && !defined(CYGSEM_REDBOOT_FLASH_COMBINED_FIS_AND_CONFIG)
-# ifdef CYG_FLASH_ERR_OK // crude temporary hack to see if we're being used with flashv2
-    cyg_flashaddr_t err_addr;
-# else
-    void *err_addr;
-# endif
+#if defined(CYGHWR_REDBOOT_FLASH_CONFIG_MEDIA_FLASH)
 #if !defined(CYGSEM_REDBOOT_FLASH_COMBINED_FIS_AND_CONFIG)
+    cyg_flashaddr_t err_addr;
     int stat;
 #endif
 #endif
 
     config->len = sizeof(struct _config);
@@ -796,25 +793,27 @@ flash_write_config(bool prompt)
         fis_read_directory();
         fis_update_directory();
 #else 
 #ifdef CYGSEM_REDBOOT_FLASH_LOCK_SPECIAL
         // Insure [quietly] that the config page is unlocked before trying to update
-        flash_unlock((void *)cfg_base, cfg_size, (void **)&err_addr);
+        cyg_flash_unlock(cfg_base, cfg_size, &err_addr);
 #endif
-        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));
+        if ((stat = cyg_flash_erase(cfg_base, cfg_size, &err_addr)) != 0) {
+            diag_printf("   initialization failed at %p: %s\n", (void*)err_addr, 
+                        cyg_flash_errmsg(stat));
         } else {
             conf_endian_fixup(config);
-            if ((stat = FLASH_PROGRAM(cfg_base, config, sizeof(struct _config), (void **)&err_addr)) != 0) {
+            if ((stat = cyg_flash_program(cfg_base, (void *)config, sizeof(struct _config), 
+                                      &err_addr)) != 0) {
                 diag_printf("Error writing config data at %p: %s\n", 
-                            err_addr, flash_errmsg(stat));
+                            (void*)err_addr, cyg_flash_errmsg(stat));
             }
             conf_endian_fixup(config);
         }
 #ifdef CYGSEM_REDBOOT_FLASH_LOCK_SPECIAL
         // Insure [quietly] that the config data is locked after the update
-        flash_lock((void *)cfg_base, cfg_size, (void **)&err_addr);
+        cyg_flash_lock(cfg_base, cfg_size, &err_addr);
 #endif
 #endif // CYGSEM_REDBOOT_FLASH_COMBINED_FIS_AND_CONFIG
 #else  // CYGHWR_REDBOOT_FLASH_CONFIG_MEDIA_FLASH
         write_eeprom(config, sizeof(struct _config));  // into 'config'
 #endif
@@ -1125,11 +1124,11 @@ static void
 load_flash_config(void)
 {
     bool use_boot_script;
     unsigned char *cfg_temp = (unsigned char *)workspace_end;
 #ifdef CYGHWR_REDBOOT_FLASH_CONFIG_MEDIA_FLASH
-    void *err_addr;
+    cyg_flashaddr_t err_addr;
 #endif
 
     config_ok = false;
     script = NULL;
     cfg_temp -= sizeof(struct _config);  // Space for primary config data
@@ -1149,25 +1148,25 @@ load_flash_config(void)
                                   CYGNUM_REDBOOT_FIS_DIRECTORY_ENTRY_SIZE)) {
         // Too bad this can't be checked at compile/build time
         diag_printf("Sorry, FLASH config exceeds available space in FIS directory\n");
         return;
     }
-    cfg_base = (void *)(((CYG_ADDRESS)fis_addr + fisdir_size) - cfg_size);
+    cfg_base = (((CYG_ADDRESS)fis_addr + fisdir_size) - cfg_size);
     fisdir_size -= cfg_size;
 #else
     cfg_size = (flash_block_size > sizeof(struct _config)) ? 
         sizeof(struct _config) : 
         _rup(sizeof(struct _config), flash_block_size);
     if (CYGNUM_REDBOOT_FLASH_CONFIG_BLOCK < 0) {
-        cfg_base = (void *)((CYG_ADDRESS)flash_end + 1 -
+        cfg_base = ((CYG_ADDRESS)flash_end + 1 -
            _rup(_rup((-CYGNUM_REDBOOT_FLASH_CONFIG_BLOCK*flash_block_size), cfg_size), flash_block_size));
     } else {
-        cfg_base = (void *)((CYG_ADDRESS)flash_start + 
+        cfg_base = ((CYG_ADDRESS)flash_start + 
            _rup(_rup((CYGNUM_REDBOOT_FLASH_CONFIG_BLOCK*flash_block_size), cfg_size), flash_block_size));
     }
 #endif
-    FLASH_READ(cfg_base, config, sizeof(struct _config), &err_addr);
+    cyg_flash_read(cfg_base, (void *)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
@@ -1179,10 +1178,11 @@ load_flash_config(void)
         diag_printf("Use 'fconfig -i' to [re]initialize database\n");
         config_init();
         return;
     }
     config_ok = true;
+    
     flash_get_config("boot_script", &use_boot_script, CONFIG_BOOL);
     if (use_boot_script) {
         flash_get_config("boot_script_data", &script, CONFIG_SCRIPT);
         flash_get_config("boot_script_timeout", &script_timeout, CONFIG_INT);
     }
Index: packages/redboot/current/src/flash.c
===================================================================
RCS file: /cvs/ecos/ecos/packages/redboot/current/src/flash.c,v
retrieving revision 1.84
retrieving revision 1.85
diff -u -5 -p -r1.84 -r1.85
--- packages/redboot/current/src/flash.c	28 Aug 2007 10:59:52 -0000	1.84
+++ packages/redboot/current/src/flash.c	18 Nov 2008 01:28:12 -0000	1.85
@@ -6,10 +6,11 @@
 //
 //==========================================================================
 //####ECOSGPLCOPYRIGHTBEGIN####
 // -------------------------------------------
 // This file is part of eCos, the Embedded Configurable Operating System.
+// Copyright (C) 2004, 2005, 2006, 2007, 2008 eCosCentric Limited
 // 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
 // the terms of the GNU General Public License as published by the Free
@@ -31,13 +32,10 @@
 // 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####
 //
@@ -162,23 +160,24 @@ RedBoot_nested_cmd("fis", 
             do_fis,
             __FIS_cmds_TAB__, &__FIS_cmds_TAB_END__
     );
 
 // Local data used by these routines
-void *flash_start, *flash_end;
-int flash_block_size, flash_num_blocks;
+cyg_flashaddr_t flash_start, flash_end;
+size_t flash_block_size;
+cyg_uint32 flash_num_blocks;
 #ifdef CYGOPT_REDBOOT_FIS
 void *fis_work_block;
-void *fis_addr;
+cyg_flashaddr_t 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
-extern void *cfg_base;   // Location in Flash of config data
-extern int   cfg_size;   // Length of config data - rounded to Flash block size
+extern cyg_flashaddr_t cfg_base;   // Location in Flash of config data
+extern size_t cfg_size;            // Length of config data - rounded to Flash block size
 extern struct _config *config;
 #endif
 
 static void
 fis_usage(char *why)
@@ -188,12 +187,41 @@ fis_usage(char *why)
 }
 
 static void        
 _show_invalid_flash_address(CYG_ADDRESS flash_addr, int stat)
 {
-    diag_printf("Invalid FLASH address %p: %s\n", (void *)flash_addr, flash_errmsg(stat));
-    diag_printf("   valid range is %p-%p\n", (void *)flash_start, (void *)flash_end);
+    cyg_uint32 i=0;
+    cyg_flash_info_t info;
+    int ret;
+    
+    diag_printf("Invalid FLASH address %p: %s\n", (void *)flash_addr, 
+                cyg_flash_errmsg(stat));
+    do {
+      ret = cyg_flash_get_info(i, &info);
+      if (ret == CYG_FLASH_ERR_OK) {
+          diag_printf("   valid range is %p - %p\n", (void*)info.start, (void*)info.end);
+      }
+      i++;
+    } while (ret != CYG_FLASH_ERR_INVALID);
+}
+
+// Avoid overwriting the current executable. This is not a complete
+// implementation, there may be code outside the text region, but it
+// is generally good enough. If either the start of the text region or
+// the end of the text region is within the specified range then at
+// least some of the code is in the area of flash about to be erased
+// or programmed.
+static cyg_bool
+check_code_overlaps(cyg_flashaddr_t start, cyg_flashaddr_t end)
+{
+  extern char _stext[], _etext[];
+  
+  return ((((unsigned long)&_stext >= (unsigned long)start) &&
+           ((unsigned long)&_stext < (unsigned long)end))
+          ||
+          (((unsigned long)&_etext >= (unsigned long)start) &&
+           ((unsigned long)&_etext < (unsigned long)end)));
 }
 
 #ifdef CYGOPT_REDBOOT_FIS
 
 // fis_endian_fixup() is used to swap endianess if required.
@@ -218,13 +246,13 @@ static inline void fis_endian_fixup(void
 }
 
 void
 fis_read_directory(void)
 {
-    void *err_addr;
+    cyg_flashaddr_t err_addr;
 
-    FLASH_READ(fis_addr, fis_work_block, fisdir_size, (void **)&err_addr);
+    cyg_flash_read(fis_addr, fis_work_block, fisdir_size, &err_addr);
     fis_endian_fixup(fis_work_block);
 }
 
 struct fis_image_desc *
 fis_lookup(char *name, int *num)
@@ -234,11 +262,11 @@ fis_lookup(char *name, int *num)
 
     fis_read_directory();
 
     img = (struct fis_image_desc *)fis_work_block;
     for (i = 0;  i < fisdir_size/sizeof(*img);  i++, img++) {
-        if ((img->u.name[0] != (unsigned char)0xFF) &&
+        if ((img->u.name[0] != '\xFF') &&
             (strcasecmp(name, img->u.name) == 0)) {
             if (num) *num = i;
             return img;
         }
     }
@@ -256,12 +284,13 @@ int fis_start_update_directory(int autol
    int do_autolock=autolock;
 #endif
 #endif
 
    struct fis_image_desc* img=NULL;
-   void* err_addr=NULL;
-   void* tmp_fis_addr=NULL;
+   cyg_flashaddr_t err_addr=NULL;
+   cyg_flashaddr_t tmp_fis_addr=NULL;
+   int stat;
 
    /*exchange old and new valid fis tables*/
    tmp_fis_addr=fis_addr;
    fis_addr=redundant_fis_addr;
    redundant_fis_addr=tmp_fis_addr;
@@ -275,17 +304,24 @@ int fis_start_update_directory(int autol
    img->u.valid_info.version_count=img->u.valid_info.version_count+1;
 
    //ready to go....
 #ifdef CYGHWR_IO_FLASH_BLOCK_LOCKING
    if (do_autolock)
-      flash_unlock((void *)fis_addr, fisdir_size, (void **)&err_addr);
+      cyg_flash_unlock(fis_addr, fisdir_size, &err_addr);
 #endif
 
-   flash_erase(fis_addr, fisdir_size, (void **)&err_addr);
+   if ((stat = cyg_flash_erase(fis_addr, fisdir_size, &err_addr)) != 0) {
+       diag_printf("Error erasing FIS directory at %p: %s\n", err_addr, cyg_flash_errmsg(stat));
+       return 1;
+   }
    //now magic is 0xffffffff
    fis_endian_fixup(fis_work_block);
-   flash_program(fis_addr, fis_work_block, flash_block_size, (void **)&err_addr);
+   if ((stat = cyg_flash_program(fis_addr, fis_work_block, flash_block_size, &err_addr)) != 0) {
+       diag_printf("Error writing FIS directory at %p: %s\n",
+                   err_addr, cyg_flash_errmsg(stat));
+       return 1;
+   }
    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 */
@@ -295,11 +331,12 @@ int fis_start_update_directory(int autol
 }
 
 int
 fis_update_directory(int autolock, int error)
 {
-   void* err_addr=0;
+   cyg_flashaddr_t err_addr;
+   int stat;
 
 #ifdef CYGHWR_IO_FLASH_BLOCK_LOCKING
 #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;
@@ -332,45 +369,48 @@ fis_update_directory(int autolock, int e
       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);
+      if ((stat = cyg_flash_program(tmp_fis_addr, img->u.valid_info.valid_flag,
+                                    sizeof(img->u.valid_info.valid_flag), &err_addr)) != 0) {
+          diag_printf("Error writing FIS directory at %p: %s\n", 
+                      err_addr, cyg_flash_errmsg(stat));
+      }
    }
 #ifdef CYGHWR_IO_FLASH_BLOCK_LOCKING
    if (do_autolock)
       flash_lock((void *)fis_addr, fisdir_size, (void **)&err_addr);
 #endif
 
 #else // CYGOPT_REDBOOT_REDUNDANT_FIS
     int blk_size = fisdir_size;
-    int stat;
 
     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);
     blk_size += cfg_size;
 #endif
 #ifdef CYGHWR_IO_FLASH_BLOCK_LOCKING
     if (do_autolock)
-        flash_unlock((void *)fis_addr, blk_size, (void **)&err_addr);
+        cyg_flash_unlock(fis_addr, blk_size, &err_addr);
 #endif
 
-    if ((stat = flash_erase(fis_addr, blk_size, (void **)&err_addr)) != 0) {
-        diag_printf("Error erasing FIS directory at %p: %s\n", err_addr, flash_errmsg(stat));
+    if ((stat = cyg_flash_erase(fis_addr, blk_size, &err_addr)) != 0) {
+        diag_printf("Error erasing FIS directory at %p: %s\n", (void*)err_addr, cyg_flash_errmsg(stat));
     } else {
-        if ((stat = FLASH_PROGRAM(fis_addr, fis_work_block,
-                                  blk_size, (void **)&err_addr)) != 0) {
+        if ((stat = cyg_flash_program(fis_addr, fis_work_block, blk_size,
+                                      &err_addr)) != 0) {
             diag_printf("Error writing FIS directory at %p: %s\n", 
-                        err_addr, flash_errmsg(stat));
+                        (void*)err_addr, cyg_flash_errmsg(stat));
         }
     }
     fis_endian_fixup(fis_work_block);
 #ifdef CYGHWR_IO_FLASH_BLOCK_LOCKING
     if (do_autolock)
-       flash_lock((void *)fis_addr, blk_size, (void **)&err_addr);
+        cyg_flash_lock(fis_addr, blk_size, &err_addr);
 #endif
 
 #endif // CYGOPT_REDBOOT_REDUNDANT_FIS
 
     return 0;
@@ -426,31 +466,31 @@ fis_erase_redundant_directory(void)
     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, fisdir_size,
-                 (void **)&err_addr);
+    cyg_flash_unlock(redundant_fis_addr, fisdir_size,
+                     &err_addr);
 #endif
-    if ((stat = flash_erase(redundant_fis_addr, fisdir_size,
-                            (void **)&err_addr)) != 0) {
+    if ((stat = cyg_flash_erase(redundant_fis_addr, fisdir_size,
+                                &err_addr)) != 0) {
          diag_printf("Error erasing FIS directory at %p: %s\n",
-                     err_addr, flash_errmsg(stat));
+                     err_addr, cyg_flash_errmsg(stat));
     }
 #ifdef CYGSEM_REDBOOT_FLASH_LOCK_SPECIAL
     // Ensure [quietly] that the directory is locked after the update
-    flash_lock((void *)redundant_fis_addr, fisdir_size, (void **)&err_addr);
+    cyg_flash_lock(redundant_fis_addr, fisdir_size, &err_addr);
 #endif
 }
 #endif
 
 static void
 fis_init(int argc, char *argv[])
 {
     int stat;
     struct fis_image_desc *img;
-    void *err_addr;
+    cyg_flashaddr_t err_addr;
     bool full_init = false;
     struct option_info opts[1];
     CYG_ADDRESS redboot_flash_start;
     unsigned long redboot_image_size;
 
@@ -470,11 +510,11 @@ fis_init(int argc, char *argv[])
 #define MIN_REDBOOT_IMAGE_SIZE CYGBLD_REDBOOT_MIN_IMAGE_SIZE
     redboot_image_size = flash_block_size > MIN_REDBOOT_IMAGE_SIZE ? 
                          flash_block_size : MIN_REDBOOT_IMAGE_SIZE;
 
     img = (struct fis_image_desc *)fis_work_block;
-    memset(img, 0xFF, fisdir_size);  // Start with erased data
+    memset(img, '\xFF', 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);
@@ -489,19 +529,21 @@ fis_init(int argc, char *argv[])
     memset(img, 0, sizeof(*img));
     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;
+    img->data_length = img->size;
     img++;
 #endif
     redboot_flash_start = (CYG_ADDRESS)flash_start + CYGBLD_REDBOOT_FLASH_BOOT_OFFSET;
 #ifdef CYGOPT_REDBOOT_FIS_REDBOOT
     memset(img, 0, sizeof(*img));
     strcpy(img->u.name, "RedBoot");
     img->flash_base = redboot_flash_start;
     img->mem_base = redboot_flash_start;
     img->size = redboot_image_size;
+    img->data_length = img->size;
     img++;
     redboot_flash_start += redboot_image_size;
 #endif
 #ifdef CYGOPT_REDBOOT_FIS_REDBOOT_POST
 #ifdef CYGNUM_REDBOOT_FIS_REDBOOT_POST_OFFSET
@@ -511,38 +553,42 @@ fis_init(int argc, char *argv[])
     memset(img, 0, sizeof(*img));
     strcpy(img->u.name, "RedBoot[post]");
     img->flash_base = redboot_flash_start;
     img->mem_base = redboot_flash_start;
     img->size = redboot_image_size;
+    img->data_length = img->size;
     img++;
     redboot_flash_start += redboot_image_size;
 #endif
 #ifdef CYGOPT_REDBOOT_FIS_REDBOOT_BACKUP
     // And a backup image
     memset(img, 0, sizeof(*img));
     strcpy(img->u.name, "RedBoot[backup]");
     img->flash_base = redboot_flash_start;
     img->mem_base = redboot_flash_start;
     img->size = redboot_image_size;
+    img->data_length = img->size;
     img++;
     redboot_flash_start += redboot_image_size;
 #endif
 #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->u.name, "RedBoot config");
     img->flash_base = (CYG_ADDRESS)cfg_base;
     img->mem_base = (CYG_ADDRESS)cfg_base;
     img->size = cfg_size;
+    img->data_length = img->size;
     img++;
 #endif
     // And a descriptor for the descriptor table itself
     memset(img, 0, sizeof(*img));
     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->data_length = img->size;
     img++;
 
     //create the entry for the redundant fis table
 #ifdef CYGOPT_REDBOOT_REDUNDANT_FIS
     memset(img, 0, sizeof(*img));
@@ -601,14 +647,14 @@ fis_init(int argc, char *argv[])
 #if (CYGBLD_REDBOOT_FLASH_BOOT_OFFSET > CYGNUM_REDBOOT_FLASH_RESERVED_BASE)
         erase_start = (CYG_ADDRESS)flash_start + CYGNUM_REDBOOT_FLASH_RESERVED_BASE;
         erase_size =  (CYG_ADDRESS)flash_start + CYGBLD_REDBOOT_FLASH_BOOT_OFFSET;
         if ( erase_size > erase_start ) {
             erase_size -= erase_start;
-            if ((stat = flash_erase((void *)erase_start, erase_size,
-                                    (void **)&err_addr)) != 0) {
+            if ((stat = cyg_flash_erase((void *)erase_start, erase_size,
+                                        &err_addr)) != 0) {
                 diag_printf("   initialization failed at %p: %s\n",
-                            err_addr, flash_errmsg(stat));
+                            err_addr, cyg_flash_errmsg(stat));
             }
         }
 #endif
         // second deal with the larger part in the main:
         erase_start = redboot_flash_start; // high water of created images
@@ -620,44 +666,40 @@ fis_init(int argc, char *argv[])
         if (fis_addr > cfg_base) {
           erase_size = (CYG_ADDRESS)cfg_base - erase_start; // the gap between HWM and config data
         } else {
           erase_size = (CYG_ADDRESS)fis_addr - erase_start; // the gap between HWM and fis data
         }
-        if ((stat = flash_erase((void *)erase_start, erase_size,
-                                (void **)&err_addr)) != 0) {
+        if ((stat = cyg_flash_erase(erase_start, erase_size,&err_addr)) != 0) {
           diag_printf("   initialization failed %p: %s\n",
-                 err_addr, flash_errmsg(stat));
+                 err_addr, cyg_flash_errmsg(stat));
         }
         erase_start += (erase_size + flash_block_size);
         if (fis_addr > cfg_base) {
           erase_size = (CYG_ADDRESS)fis_addr - erase_start; // the gap between config and fis data
         } else {
           erase_size = (CYG_ADDRESS)cfg_base - erase_start; // the gap between fis and config data
         }
-        if ((stat = flash_erase((void *)erase_start, erase_size,
-                                (void **)&err_addr)) != 0) {
+        if ((stat = cyg_flash_erase(erase_start, erase_size,&err_addr)) != 0) {
           diag_printf("   initialization failed %p: %s\n",
-                 err_addr, flash_errmsg(stat));
+                 err_addr, cyg_flash_errmsg(stat));
         }
         erase_start += (erase_size + flash_block_size);
 #else  // !CYGSEM_REDBOOT_FLASH_CONFIG        
         erase_size = (CYG_ADDRESS)fis_addr - erase_start; // the gap between HWM and fis data
-        if ((stat = flash_erase((void *)erase_start, erase_size,
-                                (void **)&err_addr)) != 0) {
+        if ((stat = cyg_flash_erase(erase_start, erase_size,&err_addr)) != 0) {
           diag_printf("   initialization failed %p: %s\n",
-                 err_addr, flash_errmsg(stat));
+                      (void*)err_addr, cyg_flash_errmsg(stat));
         }
         erase_start += (erase_size + flash_block_size);          
 #endif
-        // Lastly, anything at the end, if there is any
-        if ( erase_start < (((CYG_ADDRESS)flash_end)+1) ) {
-            erase_size = ((CYG_ADDRESS)flash_end - erase_start) + 1;
-            if ((stat = flash_erase((void *)erase_start, erase_size,
-                                    (void **)&err_addr)) != 0) {
-                diag_printf("   initialization failed at %p: %s\n",
-                            err_addr, flash_errmsg(stat));
-            }
+        // Lastly, anything at the end
+        erase_size = ((CYG_ADDRESS)flash_end - erase_start) + 1;
+        if ((erase_size > 0) &&
+            ((stat = cyg_flash_erase(erase_start, erase_size,
+                                     &err_addr))) != 0) {
+            diag_printf("   initialization failed at %p: %s\n",
+                        (void*)err_addr, cyg_flash_errmsg(stat));
         }
 #ifndef CYGDAT_REDBOOT_FIS_MAX_FREE_CHUNKS
     // In this case, 'fis free' works by scanning for erased blocks.  Since the
     // "-f" option was not supplied, there may be areas which are not used but
     // don't appear to be free since they are not erased - thus the warning
@@ -716,11 +758,11 @@ fis_list(int argc, char *argv[])
     do {
         image_found = false;
         lowest_addr = 0xFFFFFFFF;
         img = (struct fis_image_desc *) fis_work_block;
         for (i = 0;  i < fisdir_size/sizeof(*img);  i++, img++) {
-            if (img->u.name[0] != (unsigned char)0xFF) {
+            if (img->u.name[0] != '\xFF') {
                 if ((img->flash_base >= last_addr) && (img->flash_base < lowest_addr)) {
                     lowest_addr = img->flash_base;
                     image_found = true;
                     image_indx = i;
                 }
@@ -742,64 +784,106 @@ fis_list(int argc, char *argv[])
         }
         last_addr = lowest_addr + 1;
     } while (image_found == true);
 }
 
+#ifdef CYGNUM_REDBOOT_FLASH_RESERVED_DEVICES
+static CYG_ADDRESS flash_reserved_devices[] = { CYGNUM_REDBOOT_FLASH_RESERVED_DEVICES, 0xFFFFFFFF };
+
+static cyg_bool flash_reserved( CYG_ADDRESS start )
+{
+    int i;
+    for( i = 0; flash_reserved_devices[i] != 0xFFFFFFFF; i++ )
+        if( start == flash_reserved_devices[i] )
+            return true;
+    return false;
+}
+#else
+#define flash_reserved(__start) false
+#endif
+
 #ifdef CYGDAT_REDBOOT_FIS_MAX_FREE_CHUNKS
 struct free_chunk {
     CYG_ADDRESS start, end;
 };
 
 static int
 find_free(struct free_chunk *chunks)
 {
-    CYG_ADDRESS *fis_ptr, *fis_end;
+    cyg_flash_info_t info;
     struct fis_image_desc *img;
-    int i, idx;
-    int num_chunks = 1;
+    int i=0, idx;
+    int num_chunks = 0;
+    int ret;
+    
+    do {
+        // get info for each flash device
+        ret = cyg_flash_get_info(i, &info);
 
-    // Do not search the area reserved for pre-RedBoot systems:
-    fis_ptr = (CYG_ADDRESS *)((CYG_ADDRESS)flash_start + 
-                              CYGNUM_REDBOOT_FLASH_RESERVED_BASE);
-    fis_end = (CYG_ADDRESS *)flash_end;
-    chunks[num_chunks-1].start = (CYG_ADDRESS)fis_ptr;
-    chunks[num_chunks-1].end = (CYG_ADDRESS)fis_end;
+        if (ret == CYG_FLASH_ERR_OK && !flash_reserved( info.start )) {
+            
+#ifdef CYGNUM_REDBOOT_FLASH_BASE
+            if ( CYGNUM_REDBOOT_FLASH_BASE == info.start )
+#else
+            if (i == 0 )
+#endif
+            {
+                // Do not search the area reserved for pre-RedBoot systems:
+                chunks[num_chunks].start = (info.start + 
+                                            CYGNUM_REDBOOT_FLASH_RESERVED_BASE);
+                chunks[num_chunks].end = info.end;
+                num_chunks++;
+            } else {   // Contiguous flash? If so collapse the chunks together.
+                if (chunks[num_chunks-1].end == (info.start -1)) {
+                    chunks[num_chunks-1].end = info.end;
+                } else {
+                    chunks[num_chunks].start = info.start;
+                    chunks[num_chunks].end = info.end;
+                    num_chunks++;
+                }
+            }
+        }
+        i++;
+    } while (ret != CYG_FLASH_ERR_INVALID);
+    
     fis_read_directory();
     img = (struct fis_image_desc *) fis_work_block;
     for (i = 0;  i < fisdir_size/sizeof(*img);  i++, img++) {
-        if (img->u.name[0] != (unsigned char)0xFF) {
+        if (img->u.name[0] != '\xFF') {
             // Figure out which chunk this is in and split it
             for (idx = 0;  idx < num_chunks;  idx++) {
                 if ((img->flash_base >= chunks[idx].start) && 
                     (img->flash_base <= chunks[idx].end)) {
                     if (img->flash_base == chunks[idx].start) {
                         chunks[idx].start += img->size;
                         if (chunks[idx].start >= chunks[idx].end) {
                             // This free chunk has collapsed
-                            while (idx < (num_chunks-1)) {
+                            num_chunks--;
+                            while (idx < num_chunks) {
                                 chunks[idx] = chunks[idx+1];
                                 idx++;
                             }
-                            num_chunks--;
                         }
-                    } else if ((img->flash_base+img->size) == chunks[idx].end) {
-                        chunks[idx].end = img->flash_base;
+                    } else if ((img->flash_base+img->size-1) >= chunks[idx].end) {
+                        chunks[idx].end = img->flash_base - 1;
                     } 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;
-                            }
+                        int idxtmp;
+                        
+                        // shift chunks along one so we insert the new one
+                        for (idxtmp=num_chunks; idxtmp > (idx+1); idxtmp--)
+                        {
+                            chunks[idxtmp] = chunks[idxtmp-1];
+                        }
+                        
+                        chunks[idx+1].start = img->flash_base + img->size;
+                        chunks[idx+1].end = chunks[idx].end;
+                        chunks[idx].end = img->flash_base - 1;
+                        if (++num_chunks == CYGDAT_REDBOOT_FIS_MAX_FREE_CHUNKS) {
+                          diag_printf("Warning: too many free chunks\n");
+                          return num_chunks;
                         }
-                        chunks[idx].end = img->flash_base;
                     }
                     break;
                 }
             }
         }
@@ -809,46 +893,112 @@ find_free(struct free_chunk *chunks)
 #endif // CYGDAT_REDBOOT_FIS_MAX_FREE_CHUNKS
 
 static void
 fis_free(int argc, char *argv[])
 {
-#ifndef CYGDAT_REDBOOT_FIS_MAX_FREE_CHUNKS
-    unsigned long *fis_ptr, *fis_end, flash_data;
-    unsigned long *area_start;
-    void *err_addr;
+#if !defined(CYGDAT_REDBOOT_FIS_MAX_FREE_CHUNKS)
+    cyg_uint32 flash_data;
+    cyg_flashaddr_t area_start;
+    cyg_flashaddr_t err_addr;
+    cyg_uint32 flash_dev_no;
+    int flash_err;
+    cyg_flash_info_t flash_info;
+    cyg_uint32 curr_block, curr_block_info;
+    cyg_flashaddr_t curr_flash_addr, next_flash_addr;
 
-    // Do not search the area reserved for pre-RedBoot systems:
-    fis_ptr = (unsigned long *)((CYG_ADDRESS)flash_start + 
-                                CYGNUM_REDBOOT_FLASH_RESERVED_BASE);
-    fis_end = (unsigned long *)(CYG_ADDRESS)flash_end;
-    area_start = fis_ptr;
-    while (fis_ptr < fis_end) {
-        flash_read(fis_ptr, &flash_data, sizeof(unsigned long), (void **)&err_addr);
-        if (flash_data != (unsigned long)0xFFFFFFFF) {
-            if (area_start != fis_ptr) {
-                // Assume that this is something
-                diag_printf("  0x%08lX .. 0x%08lX\n",
-                            (CYG_ADDRESS)area_start, (CYG_ADDRESS)fis_ptr);
-            }
-            // Find next blank block
-            area_start = fis_ptr;
-            while (area_start < fis_end) {
-                flash_read(area_start, &flash_data, sizeof(unsigned long), (void **)&err_addr);
-                if (flash_data == (unsigned long)0xFFFFFFFF) {
-                    break;
+    // For each flash device
+    for (flash_dev_no=0;; flash_dev_no++)
+    {
+        flash_err = cyg_flash_get_info( flash_dev_no, &flash_info );
+        if ( CYG_FLASH_ERR_OK != flash_err )  // assume all done
+            break;
+
+        if( flash_reserved( flash_info.start ) ) // Ignore reserved devices
+            continue;
+        
+        // Once more, from the top...
+        curr_flash_addr = area_start = flash_info.start;
+
+        // We must not search the area reserved for pre-RedBoot systems,
+        // but this is only the case for the first flash device, or
+        // the one corresponding to CYGNUM_REDBOOT_FLASH_BASE.
+        // FIXME: this is insufficiently generic by design - can only
+        // reserve on one flash.
+#ifdef CYGNUM_REDBOOT_FLASH_BASE
+        if ( CYGNUM_REDBOOT_FLASH_BASE == area_start )
+#else
+        if ( 0 == flash_dev_no )
+#endif
+        {
+            //cyg_flashaddr_t asold = area_start;
+            area_start += CYGNUM_REDBOOT_FLASH_RESERVED_BASE;
+            //diag_printf("area_start was %08x now %08x\n", asold, area_start );
+        }
+        // For each region of blocks
+        for ( curr_block_info = 0;
+              curr_block_info < flash_info.num_block_infos;
+              curr_block_info++ )
+        {
+            // For each individual block
+            for ( curr_block = 0;
+                  curr_block < flash_info.block_info[curr_block_info].blocks;
+                  curr_flash_addr = next_flash_addr, curr_block++ )
+            {
+                cyg_ucount32 i;
+                cyg_bool is_blank = true; // until proved otherwise
+                size_t amount_to_check;
+
+                // determine this now to avoid recalculating it later in this block, so we know the
+                // end of this block
+                next_flash_addr = curr_flash_addr + flash_info.block_info[curr_block_info].block_size;
+
+                // If area_start got adjusted further up, skip until we reach it
+                if ( curr_flash_addr < area_start )
+                    continue;
+                
+                //diag_printf("block region %d, block %d, flashaddr %08x\n",curr_block_info,curr_block,curr_flash_addr);
+                
+                // check 32 bytes at most. Reading it all will take too long on many devices.
+                // Perhaps this should be a config option.
+                amount_to_check = 32; 
+                if ( amount_to_check > flash_info.block_info[curr_block_info].block_size ) // paranoia
+                    amount_to_check = flash_info.block_info[curr_block_info].block_size;
+
+                for ( i=0; i<amount_to_check; i += sizeof(cyg_uint32) )
+                {
+                    flash_err = cyg_flash_read(curr_flash_addr+i, &flash_data, sizeof(cyg_uint32), &err_addr);
+                    if ( (CYG_FLASH_ERR_OK != flash_err) || (flash_data != 0xffffffff) )
+                    {
+                        is_blank = false;
+                        break; // no point continuing
+                    }
+                } // for
+                
+                if (!is_blank)
+                {
+                    /* If not blank, output the preceding region if any */
+                    if ( curr_flash_addr != area_start )
+                    {
+                        diag_printf("  0x%08lX .. 0x%08lX\n",
+                                    area_start,
+                                    next_flash_addr-1 );
+                    }
+                    area_start = next_flash_addr;
                 }
-                area_start += flash_block_size / sizeof(CYG_ADDRESS);
-            }
-            fis_ptr = area_start;
-        } else {
-            fis_ptr += flash_block_size / sizeof(CYG_ADDRESS);
+            } // for block
+        } // for block region
+
+        /* If the blank region extended to the very end of the device, we need to do one
+         * final check at the end of the device.
+         */
+        if ( curr_flash_addr != area_start )
+        {
+            diag_printf("  0x%08lX .. 0x%08lX\n",
+                        area_start,
+                        next_flash_addr-1 );
         }
-    }
-    if (area_start != fis_ptr) {
-        diag_printf("  0x%08lX .. 0x%08lX\n", 
-                    (CYG_ADDRESS)area_start, (CYG_ADDRESS)fis_ptr);
-    }
+    } // for flash device
 #else
     struct free_chunk chunks[CYGDAT_REDBOOT_FIS_MAX_FREE_CHUNKS];
     int idx, num_chunks;
 
     num_chunks = find_free(chunks);
@@ -863,85 +1013,151 @@ fis_free(int argc, char *argv[])
 // Find the first unused area of flash which is long enough
 static bool
 fis_find_free(CYG_ADDRESS *addr, unsigned long length)
 {
 #ifndef CYGDAT_REDBOOT_FIS_MAX_FREE_CHUNKS
-    unsigned long *fis_ptr, *fis_end, flash_data;
-    unsigned long *area_start;
-    void *err_addr;
+    cyg_uint32 flash_data;
+    cyg_flashaddr_t area_start;
+    cyg_flashaddr_t err_addr;
+    cyg_uint32 flash_dev_no;
+    int flash_err;
+    cyg_flash_info_t flash_info;
+    cyg_uint32 curr_block, curr_block_info;
+    cyg_flashaddr_t curr_flash_addr, next_flash_addr;
 
-    // Do not search the area reserved for pre-RedBoot systems:
-    fis_ptr = (unsigned long *)((CYG_ADDRESS)flash_start + 
-                                CYGNUM_REDBOOT_FLASH_RESERVED_BASE);
-    fis_end = (unsigned long *)(CYG_ADDRESS)flash_end;
-    area_start = fis_ptr;
-    while (fis_ptr < fis_end) {
-        flash_read(fis_ptr, &flash_data, sizeof(unsigned long), (void **)&err_addr);
-        if (flash_data != (unsigned long)0xFFFFFFFF) {
-            if (area_start != fis_ptr) {
-                // Assume that this is something
-                if ((fis_ptr-area_start) >= (length/sizeof(unsigned))) {
-                    *addr = (CYG_ADDRESS)area_start;
-                    return true;
-                }
-            }
-            // Find next blank block
-            area_start = fis_ptr;
-            while (area_start < fis_end) {
-                flash_read(area_start, &flash_data, sizeof(unsigned long), (void **)&err_addr);
-                if (flash_data == (unsigned long)0xFFFFFFFF) {
-                    break;
+    // For each flash device
+    for (flash_dev_no=0;; flash_dev_no++)
+    {
+        flash_err = cyg_flash_get_info( flash_dev_no, &flash_info );
+        if ( CYG_FLASH_ERR_OK != flash_err )  // assume all done
+            break;
+
+        if( flash_reserved( flash_info.start ) ) // Ignore reserved devices
+            continue;
+        
+        // Once more, from the top...
+        curr_flash_addr = area_start = flash_info.start;
+
+        // We must not search the area reserved for pre-RedBoot systems,
+        // but this is only the case for the first flash device, or
+        // the one corresponding to CYGNUM_REDBOOT_FLASH_BASE.
+        // FIXME: this is insufficiently generic by design - can only
+        // reserve on one flash.
+#ifdef CYGNUM_REDBOOT_FLASH_BASE
+        if ( CYGNUM_REDBOOT_FLASH_BASE == area_start )
+#else
+        if ( 0 == flash_dev_no )
+#endif
+        {
+            //cyg_flashaddr_t asold = area_start;
+            area_start += CYGNUM_REDBOOT_FLASH_RESERVED_BASE;
+            //diag_printf("area_start was %08x now %08x\n", asold, area_start );
+        }
+        // For each region of blocks
+        for ( curr_block_info = 0;
+              curr_block_info < flash_info.num_block_infos;
+              curr_block_info++ )
+        {
+            // For each individual block
+            for ( curr_block = 0;
+                  curr_block < flash_info.block_info[curr_block_info].blocks;
+                  curr_flash_addr = next_flash_addr, curr_block++ )
+            {
+                cyg_ucount32 i;
+                cyg_bool is_blank = true; // until proved otherwise
+                size_t amount_to_check;
+
+                // determine this now to avoid recalculating it later in this block, so we know the
+                // end of this block
+                next_flash_addr = curr_flash_addr + flash_info.block_info[curr_block_info].block_size;
+
+                // If area_start got adjusted further up, skip until we reach it
+                if ( curr_flash_addr < area_start )
+                    continue;
+                
+                //diag_printf("block region %d, block %d, flashaddr %08x\n",curr_block_info,curr_block,curr_flash_addr);
+                
+                // check 32 bytes at most. Reading it all will take too long on many devices.
+                // Perhaps this should be a config option.
+                amount_to_check = 32; 
+                if ( amount_to_check > flash_info.block_info[curr_block_info].block_size ) // paranoia
+                    amount_to_check = flash_info.block_info[curr_block_info].block_size;
+
+                for ( i=0; i<amount_to_check; i += sizeof(cyg_uint32) )
+                {
+                    flash_err = cyg_flash_read(curr_flash_addr+i, &flash_data, sizeof(cyg_uint32), &err_addr);
+                    if ( (CYG_FLASH_ERR_OK != flash_err) || (flash_data != 0xffffffff) )
+                    {
+                        is_blank = false;
+                        break; // no point continuing
+                    }
+                } // for
+                
+                if (!is_blank)
+                {
+                    /* If not blank, output the preceding region if any */
+                    if ( curr_flash_addr != area_start )
+                    {
+                        if ( length <= (next_flash_addr - area_start) )
+                        {
+                            *addr = (CYG_ADDRESS)area_start;
+                            return true;
+                        }    
+                    }
+                    area_start = next_flash_addr;
                 }
-                area_start += flash_block_size / sizeof(CYG_ADDRESS);
-            }
-            fis_ptr = area_start;
-        } else {
-            fis_ptr += flash_block_size / sizeof(CYG_ADDRESS);
-        }
-    }
-    if (area_start != fis_ptr) {
-        if ((fis_ptr-area_start) >= (length/sizeof(unsigned))) {
-            *addr = (CYG_ADDRESS)area_start;
-            return true;
+            } // for block
+        } // for block region
+
+        /* If the blank region extended to the very end of the device, we need to do one
+         * final check at the end of the device.
+         */
+        if ( curr_flash_addr != area_start )
+        {
+            if ( length <= (next_flash_addr - area_start) )
+            {
+                *addr = (CYG_ADDRESS)area_start;
+                return true;
+            }    
         }
-    }
-    return false;
+    } // for flash device
 #else
     struct free_chunk chunks[CYGDAT_REDBOOT_FIS_MAX_FREE_CHUNKS];
     int idx, num_chunks;
 
     num_chunks = find_free(chunks);
     for (idx = 0;  idx < num_chunks;  idx++) {
-        if ((chunks[idx].end - chunks[idx].start) >= length) {
+        if ((chunks[idx].end - chunks[idx].start + 1) >= length) {
             *addr = (CYG_ADDRESS)chunks[idx].start;
             return true;
         }
     }
-    return false;
 #endif
+    return false;
 }
 
 static void
 fis_create(int argc, char *argv[])
 {
     int i, stat;
     unsigned long length, img_size;
-    CYG_ADDRESS mem_addr, exec_addr, flash_addr, entry_addr;
+    CYG_ADDRESS mem_addr, exec_addr, flash_addr, entry_addr, flash_offset;
     char *name;
     bool mem_addr_set = false;
     bool exec_addr_set = false;
     bool entry_addr_set = false;
     bool flash_addr_set = false;
     bool length_set = false;
     bool img_size_set = false;
     bool no_copy = false;
-    void *err_addr;
+    cyg_flashaddr_t err_addr;
     struct fis_image_desc *img = NULL;
     bool defaults_assumed;
     struct option_info opts[7];
     bool prog_ok = true;
-
+    size_t block_size;
+    
     init_opts(&opts[0], 'b', true, OPTION_ARG_TYPE_NUM, 
               (void *)&mem_addr, (bool *)&mem_addr_set, "memory base address");
     init_opts(&opts[1], 'r', true, OPTION_ARG_TYPE_NUM, 
               (void *)&exec_addr, (bool *)&exec_addr_set, "ram base address");
     init_opts(&opts[2], 'e', true, OPTION_ARG_TYPE_NUM, 
@@ -972,18 +1188,20 @@ fis_create(int argc, char *argv[])
                 length = img->size;
                 defaults_assumed = true;
             }
         }
     }
-    if (!mem_addr_set && (load_address >= (CYG_ADDRESS)ram_start) &&
+    if ((!mem_addr_set || mem_addr == load_address) && !no_copy && (load_address >= (CYG_ADDRESS)ram_start) &&
 	(load_address_end) < (CYG_ADDRESS)ram_end) {
 	mem_addr = load_address;
 	mem_addr_set = true;
         defaults_assumed = true;
         // Get entry address from loader, unless overridden
-        if (!entry_addr_set)
+        if (!entry_addr_set) {
             entry_addr = entry_address;
+            entry_addr_set = true;
+        }
 	if (!length_set) {
 	    length = load_address_end - load_address;
 	    length_set = true;
 	} else if (defaults_assumed && !img_size_set) {
 	    /* We got length from the FIS table, so the size of the
@@ -1004,56 +1222,69 @@ fis_create(int argc, char *argv[])
             flash_addr = img->flash_base;
             defaults_assumed = true;
         }
     }
 
-    if ((!no_copy && !mem_addr_set) || (no_copy && !flash_addr_set) ||
+    if ((!no_copy && !mem_addr_set) ||
         !length_set || !name) {
         fis_usage("required parameter missing");
         return;
     }
     if (!img_size_set) {
         img_size = length;
     }
-    // 'length' is size of FLASH image, 'img_size' is actual data size
-    // Round up length to FLASH block size
-#ifndef CYGPKG_HAL_MIPS // FIXME: compiler is b0rken
-    length = ((length + flash_block_size - 1) / flash_block_size) * flash_block_size;
     if (length < img_size) {
         diag_printf("Invalid FLASH image size/length combination\n");
         return;
     }
-#endif
+
+    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 (flash_addr_set &&
         ((stat = flash_verify_addr((void *)flash_addr)) ||
          (stat = flash_verify_addr((void *)(flash_addr+length-1))))) {
         _show_invalid_flash_address(flash_addr, stat);
         return;
     }
-    if (flash_addr_set && ((flash_addr & (flash_block_size-1)) != 0)) {
-        diag_printf("Invalid FLASH address: %p\n", (void *)flash_addr);
-        diag_printf("   must be 0x%x aligned\n", flash_block_size);
-        return;
-    }
-    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) {
         if ((mem_addr < (CYG_ADDRESS)ram_start) ||
             ((mem_addr+img_size) >= (CYG_ADDRESS)ram_end)) {
             diag_printf("** WARNING: RAM address: %p may be invalid\n", (void *)mem_addr);
             diag_printf("   valid range is %p-%p\n", (void *)ram_start, (void *)ram_end);
         }
-        if (!flash_addr_set && !fis_find_free(&flash_addr, length)) {
-            diag_printf("Can't locate %lx(%ld) bytes free in FLASH\n", length, length);
-            return;
-        }
     }
+    if (!flash_addr_set && !fis_find_free(&flash_addr, length)) {
+        diag_printf("Can't locate %lx(%ld) bytes free in FLASH\n", length, length);
+        return;
+    }
+    flash_addr_set = true;
+
+    block_size = cyg_flash_block_size(flash_addr + length);
+    length = ((length + block_size - 1) / block_size) * block_size;
+    if (length < img_size) {
+        diag_printf("Invalid FLASH image size/length combination\n");
+        return;
+    }
+    if ((stat = cyg_flash_verify_addr(flash_addr)) ||
+        (stat = cyg_flash_verify_addr((flash_addr+length-1)))) {
+        _show_invalid_flash_address(flash_addr, stat);
+        return;
+    }
+    block_size = cyg_flash_block_size(flash_addr);
+    flash_offset = (flash_addr-flash_start)/block_size;
+    if( flash_start + (flash_offset * block_size) != flash_addr ) {
+        diag_printf("Invalid FLASH address: %p\n", (void *)flash_addr);
+        diag_printf("   must be 0x%x aligned\n", (unsigned int)flash_block_size);
+        return;
+    }
+    
     // First, see if the image by this name has agreable properties
     if (img) {
-        if (flash_addr_set && (img->flash_base != flash_addr)) {
+        if (img->flash_base != flash_addr) {
             diag_printf("Image found, but flash address (%p)\n"
                         "             is incorrect (present image location %p)\n",
                         (void*)flash_addr, (void*)img->flash_base);
             
             return;
@@ -1077,17 +1308,18 @@ fis_create(int argc, char *argv[])
             }
         }
     } else {
 #ifdef CYGDAT_REDBOOT_FIS_MAX_FREE_CHUNKS
         // Make sure that any FLASH address specified directly is truly free
-        if (flash_addr_set && !no_copy) {
+        if (!no_copy) {
             struct free_chunk chunks[CYGDAT_REDBOOT_FIS_MAX_FREE_CHUNKS];
             int idx, num_chunks;
             bool is_free = false;
 
             num_chunks = find_free(chunks);
             for (idx = 0;  idx < num_chunks;  idx++) {
+                //diag_printf("addr %08x, length %d chunk start %08x, end %08x\n",flash_addr, length, chunks[idx].start, chunks[idx].end);
                 if ((flash_addr >= chunks[idx].start) && 
                     ((flash_addr+length-1) <= chunks[idx].end)) {
                     is_free = true;
                 }
             }
@@ -1095,42 +1327,62 @@ fis_create(int argc, char *argv[])
                 diag_printf("Invalid FLASH address - not free!\n");
                 return;
             }
         }
 #endif
-        // If not image by that name, try and find an empty slot
+        // If no 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->u.name[0] == (unsigned char)0xFF) {
+            if (img->u.name[0] == '\xFF') {
                 break;
             }
         }
 	if (i >= fisdir_size/sizeof(*img)) {
 	    diag_printf("Can't find an empty slot in FIS directory!\n");
 	    return;
 	}
     }
     if (!no_copy) {
         // Safety check - make sure the address range is not within the code we're running
-        if (flash_code_overlaps((void *)flash_addr, (void *)(flash_addr+img_size-1))) {
+        if (check_code_overlaps(flash_addr, (flash_addr+img_size-1))) {
             diag_printf("Can't program this region - contains code in use!\n");
             return;
         }
+#ifdef CYGHWR_IO_FLASH_BLOCK_LOCKING            
+        if (prog_ok) {
+            // Unlock area to be programmed
+            if ((stat = cyg_flash_unlock((cyg_flashaddr_t)flash_addr, length, &err_addr)) != 0) {
+                diag_printf("Can't unlock region at %p: %s\n", (void*)err_addr, flash_errmsg(stat));
+                prog_ok = false;
+            }
+        }
+#endif
         if (prog_ok) {
             // Erase area to be programmed
-            if ((stat = flash_erase((void *)flash_addr, length, (void **)&err_addr)) != 0) {
-                diag_printf("Can't erase region at %p: %s\n", err_addr, flash_errmsg(stat));
+            if ((stat = cyg_flash_erase(flash_addr, length, &err_addr)) != 0) {
+                diag_printf("Can't erase region at %p: %s\n", (void*)err_addr, cyg_flash_errmsg(stat));
                 prog_ok = false;
             }
         }
         if (prog_ok) {
             // Now program it
-            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));
+            if ((stat = cyg_flash_program(flash_addr, (void *)mem_addr, img_size, 
+                                          &err_addr)) != 0) {
+                diag_printf("Can't program region at %p: %s\n", (void*)err_addr, 
+                            cyg_flash_errmsg(stat));
+                prog_ok = false;
+            }
+        }
+#ifdef CYGHWR_IO_FLASH_BLOCK_LOCKING            
+        if (prog_ok) {
+            // Lock area programmed
+            if ((stat = cyg_flash_lock((cyg_flashaddr_t)flash_addr, length, &err_addr)) != 0) {
+                diag_printf("Can't lock region at %p: %s\n", (void*)err_addr, flash_errmsg(stat));
                 prog_ok = false;
             }
         }
+#endif
     }
     if (prog_ok) {
         // Update directory
         memset(img, 0, sizeof(*img));
         strcpy(img->u.name, name);
@@ -1156,11 +1408,11 @@ extern void arm_fis_delete(char *);
 static void
 fis_delete(int argc, char *argv[])
 {
     char *name;
     int num_reserved, i, stat;
-    void *err_addr;
+    cyg_flashaddr_t err_addr;
     struct fis_image_desc *img;
 
     if (!scan_opts(argc, argv, 2, 0, 0, (void *)&name, OPTION_ARG_TYPE_STR, "image name"))
     {
         fis_usage("invalid arguments");
@@ -1204,14 +1456,14 @@ fis_delete(int argc, char *argv[])
     } else {
         diag_printf("No image '%s' found\n", name);
         return;
     }
     // Erase Data blocks (free space)
-    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));
+    if ((stat = cyg_flash_erase(img->flash_base, img->size, &err_addr)) != 0) {
+        diag_printf("Error erasing at %p: %s\n", (void*)err_addr, cyg_flash_errmsg(stat));
     } else {
-        img->u.name[0] = (unsigned char)0xFF;    
+        img->u.name[0] = '\xFF';    
         fis_start_update_directory(0);
         fis_update_directory(0, 0);
     }
 }
 
@@ -1229,11 +1481,11 @@ fis_load(int argc, char *argv[])
 #endif
     int num_options;
 #if defined(CYGPRI_REDBOOT_ZLIB_FLASH) ||  defined(CYGSEM_REDBOOT_FIS_CRC_CHECK)
     bool decompress = false;
 #endif
-    void *err_addr;
+    cyg_flashaddr_t err_addr;
 
     init_opts(&opts[0], 'b', true, OPTION_ARG_TYPE_NUM, 
               (void *)&mem_addr, (bool *)&mem_addr_set, "memory [load] base address");
     init_opts(&opts[1], 'c', false, OPTION_ARG_TYPE_FLG, 
               (void *)&show_cksum, (bool *)0, "display checksum");
@@ -1297,11 +1549,12 @@ fis_load(int argc, char *argv[])
         // Reload fis directory
         fis_read_directory();
     } else // dangling block
 #endif
     {
-        flash_read((void *)img->flash_base, (void *)mem_addr, img->data_length, (void **)&err_addr);
+        cyg_flash_read(img->flash_base, (void *)mem_addr, img->data_length, 
+                       &err_addr);
 
         // Set load address/top
         load_address = mem_addr;
         load_address_end = mem_addr + img->data_length;
     }
@@ -1327,18 +1580,19 @@ fis_load(int argc, char *argv[])
 static void
 fis_write(int argc, char *argv[])
 {
     int stat;
     unsigned long length;
-    CYG_ADDRESS mem_addr, flash_addr;
+    CYG_ADDRESS mem_addr, flash_addr, flash_offset;
     bool mem_addr_set = false;
     bool flash_addr_set = false;
     bool length_set = false;
-    void *err_addr;
+    cyg_flashaddr_t err_addr;
     struct option_info opts[3];
     bool prog_ok;
-
+    size_t block_size;
+    
     init_opts(&opts[0], 'b', true, OPTION_ARG_TYPE_NUM, 
               (void *)&mem_addr, (bool *)&mem_addr_set, "memory base address");
     init_opts(&opts[1], 'f', true, OPTION_ARG_TYPE_NUM, 
               (void *)&flash_addr, (bool *)&flash_addr_set, "FLASH memory base address");
     init_opts(&opts[2], 'l', true, OPTION_ARG_TYPE_NUM, 
@@ -1353,31 +1607,32 @@ fis_write(int argc, char *argv[])
         fis_usage("required parameter missing");
         return;
     }
 
     // Round up length to FLASH block size
-#ifndef CYGPKG_HAL_MIPS // FIXME: compiler is b0rken
-    length = ((length + flash_block_size - 1) / flash_block_size) * flash_block_size;
-#endif
-    if (flash_addr_set &&
-        ((stat = flash_verify_addr((void *)flash_addr)) ||
-         (stat = flash_verify_addr((void *)(flash_addr+length-1))))) {
+    block_size = cyg_flash_block_size(flash_addr + length);
+    length = ((length + block_size - 1) / block_size) * block_size;
+    if ((stat = cyg_flash_verify_addr(flash_addr)) ||
+         (stat = cyg_flash_verify_addr((flash_addr+length-1)))) {
         _show_invalid_flash_address(flash_addr, stat);
         return;
     }
-    if (flash_addr_set && flash_addr & (flash_block_size-1)) {
+
+    block_size = cyg_flash_block_size(flash_addr);
+    flash_offset = (flash_addr-flash_start)/block_size;
+    if( flash_start + (flash_offset * block_size) != flash_addr ) {
         diag_printf("Invalid FLASH address: %p\n", (void *)flash_addr);
-        diag_printf("   must be 0x%x aligned\n", flash_block_size);
+        diag_printf("   must be 0x%x aligned\n", (unsigned int)block_size);
         return;
     }
     if ((mem_addr < (CYG_ADDRESS)ram_start) ||
         ((mem_addr+length) >= (CYG_ADDRESS)ram_end)) {
         diag_printf("** WARNING: RAM address: %p may be invalid\n", (void *)mem_addr);
         diag_printf("   valid range is %p-%p\n", (void *)ram_start, (void *)ram_end);
     }
     // Safety check - make sure the address range is not within the code we're running
-    if (flash_code_overlaps((void *)flash_addr, (void *)(flash_addr+length-1))) {
+    if (check_code_overlaps(flash_addr, (flash_addr+length-1))) {
         diag_printf("Can't program this region - contains code in use!\n");
         return;
     }
     if (!verify_action("* CAUTION * about to program FLASH\n            at %p..%p from %p", 
                        (void *)flash_addr, (void *)(flash_addr+length-1),
@@ -1385,34 +1640,39 @@ fis_write(int argc, char *argv[])
         return;  // The guy gave up
     }
     prog_ok = true;
     if (prog_ok) {
         // Erase area to be programmed
-        if ((stat = flash_erase((void *)flash_addr, length, (void **)&err_addr)) != 0) {
-            diag_printf("Can't erase region at %p: %s\n", err_addr, flash_errmsg(stat));
+        if ((stat = cyg_flash_erase(flash_addr, length, &err_addr)) != 0) {
+            diag_printf("Can't erase region at %p: %s\n", (void*)err_addr, 
+                        cyg_flash_errmsg(stat));
             prog_ok = false;
         }
     }
     if (prog_ok) {
         // Now program it
-        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));
+        if ((stat = cyg_flash_program(flash_addr, (void *)mem_addr, length, 
+                                      &err_addr)) != 0) {
+            diag_printf("Can't program region at %p: %s\n", (void*)err_addr, 
+                        cyg_flash_errmsg(stat));
             prog_ok = false;
         }
     }
 }
 
 static void
 fis_erase(int argc, char *argv[])
 {
     int stat;
     unsigned long length;
-    CYG_ADDRESS flash_addr;
+    CYG_ADDRESS flash_addr, flash_offset;
     bool flash_addr_set = false;
     bool length_set = false;
-    void *err_addr;
+    cyg_flashaddr_t err_addr;
     struct option_info opts[2];
+    size_t block_size;
+    
 
     init_opts(&opts[0], 'f', true, OPTION_ARG_TYPE_NUM, 
               (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");
@@ -1425,27 +1685,29 @@ fis_erase(int argc, char *argv[])
     if (!flash_addr_set || !length_set) {
         fis_usage("missing argument");
         return;
     }
     if (flash_addr_set &&
-        ((stat = flash_verify_addr((void *)flash_addr)) ||
-         (stat = flash_verify_addr((void *)(flash_addr+length-1))))) {
+        ((stat = cyg_flash_verify_addr(flash_addr)) ||
+         (stat = cyg_flash_verify_addr((flash_addr+length-1))))) {
         _show_invalid_flash_address(flash_addr, stat);
         return;
     }
-    if (flash_addr_set && flash_addr & (flash_block_size-1)) {
+    block_size = cyg_flash_block_size(flash_addr);
+    flash_offset = (flash_addr-flash_start)/block_size;
+    if( flash_addr_set && (flash_start + (flash_offset * block_size) != flash_addr) ) {
         diag_printf("Invalid FLASH address: %p\n", (void *)flash_addr);
-        diag_printf("   must be 0x%x aligned\n", flash_block_size);
+        diag_printf("   must be 0x%x aligned\n", (unsigned int)flash_block_size);
         return;
     }
     // Safety check - make sure the address range is not within the code we're running
-    if (flash_code_overlaps((void *)flash_addr, (void *)(flash_addr+length-1))) {
+    if (check_code_overlaps(flash_addr, (flash_addr+length-1))) {
         diag_printf("Can't erase this region - contains code in use!\n");
         return;
     }
-    if ((stat = flash_erase((void *)flash_addr, length, (void **)&err_addr)) != 0) {
-        diag_printf("Error erasing at %p: %s\n", err_addr, flash_errmsg(stat));
+    if ((stat = cyg_flash_erase(flash_addr, length, &err_addr)) != 0) {
+        diag_printf("Error erasing at %p: %s\n", (void*)err_addr, cyg_flash_errmsg(stat));
     }
 }
 
 #ifdef CYGHWR_IO_FLASH_BLOCK_LOCKING
 
@@ -1456,11 +1718,11 @@ fis_lock(int argc, char *argv[])
     int stat;
     unsigned long length;
     CYG_ADDRESS flash_addr;
     bool flash_addr_set = false;
     bool length_set = false;
-    void *err_addr;
+    cyg_flashaddr_t err_addr;
     struct option_info opts[2];
 
     init_opts(&opts[0], 'f', true, OPTION_ARG_TYPE_NUM, 
               (void *)&flash_addr, (bool *)&flash_addr_set, "FLASH memory base address");
     init_opts(&opts[1], 'l', true, OPTION_ARG_TYPE_NUM, 
@@ -1486,17 +1748,17 @@ fis_lock(int argc, char *argv[])
       if (!flash_addr_set || !length_set) {
         fis_usage("missing argument");
         return;
     }
     if (flash_addr_set &&
-        ((stat = flash_verify_addr((void *)flash_addr)) ||
-         (stat = flash_verify_addr((void *)(flash_addr+length-1))))) {
+        ((stat = cyg_flash_verify_addr(flash_addr)) ||
+         (stat = cyg_flash_verify_addr((flash_addr+length-1))))) {
         _show_invalid_flash_address(flash_addr, stat);
         return;
     }
-    if ((stat = flash_lock((void *)flash_addr, length, (void **)&err_addr)) != 0) {
-        diag_printf("Error locking at %p: %s\n", err_addr, flash_errmsg(stat));
+    if ((stat = cyg_flash_lock(flash_addr, length, &err_addr)) != 0) {
+        diag_printf("Error locking at %p: %s\n", (void*)err_addr, cyg_flash_errmsg(stat));
     }
 }
 
 static void
 fis_unlock(int argc, char *argv[])
@@ -1505,11 +1767,11 @@ fis_unlock(int argc, char *argv[])
     int stat;
     unsigned long length;
     CYG_ADDRESS flash_addr;
     bool flash_addr_set = false;
     bool length_set = false;
-    void *err_addr;
+    cyg_flashaddr_t err_addr;
     struct option_info opts[2];
 
     init_opts(&opts[0], 'f', true, OPTION_ARG_TYPE_NUM, 
               (void *)&flash_addr, (bool *)&flash_addr_set, "FLASH memory base address");
     init_opts(&opts[1], 'l', true, OPTION_ARG_TYPE_NUM, 
@@ -1534,45 +1796,62 @@ fis_unlock(int argc, char *argv[])
       if (!flash_addr_set || !length_set) {
         fis_usage("missing argument");
         return;
     }
     if (flash_addr_set &&
-        ((stat = flash_verify_addr((void *)flash_addr)) ||
-         (stat = flash_verify_addr((void *)(flash_addr+length-1))))) {
+        ((stat = cyg_flash_verify_addr(flash_addr)) ||
+         (stat = cyg_flash_verify_addr((flash_addr+length-1))))) {
         _show_invalid_flash_address(flash_addr, stat);
         return;
     }
 
-    if ((stat = flash_unlock((void *)flash_addr, length, (void **)&err_addr)) != 0) {
-        diag_printf("Error unlocking at %p: %s\n", err_addr, flash_errmsg(stat));
+    if ((stat = cyg_flash_unlock(flash_addr, length, &err_addr)) != 0) {
+        diag_printf("Error unlocking at %p: %s\n", (void*)err_addr, cyg_flash_errmsg(stat));
     }
 }
 #endif
 
 // This is set non-zero if the FLASH subsystem has successfully been initialized
-int __flash_init = 0;
+int __flash_init;
 
 void
 _flash_info(void)
-{
+{   
+    cyg_uint32 i=0,j;
+    cyg_flash_info_t info;
+    int ret;
+    
     if (!__flash_init) return;
-    diag_printf("FLASH: %p - 0x%x, %d blocks of %p bytes each.\n", 
-           flash_start, (CYG_ADDRWORD)flash_end + 1, flash_num_blocks, (void *)flash_block_size);
+
+    do {
+      ret = cyg_flash_get_info(i, &info);
+      if (ret == CYG_FLASH_ERR_OK) {
+          diag_printf("FLASH: %p-%p", (void*)info.start, (void*)info.end);
+        for (j=0;j < info.num_block_infos; j++) {
+          diag_printf(", %d x 0x%x blocks",
+                      info.block_info[j].blocks,
+                      (unsigned int)info.block_info[j].block_size);
+        }
+        diag_printf("\n");
+      }
+      i++;
+    } while (ret != CYG_FLASH_ERR_INVALID);
 }
 
 /* Returns -1 on failure, 0 on success, 1 if it was successfull
  but a failed fis update was detected  */
 int
 do_flash_init(void)
 {
-    int stat;
+    int stat, i;
+    cyg_flash_info_t info;
 
 #ifdef CYGOPT_REDBOOT_REDUNDANT_FIS
     struct fis_image_desc img0;
     struct fis_image_desc img1;
     int fis_update_was_interrupted=0;
-    void *err_addr;
+    cyg_flashaddr_t err_addr;
 
     //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");
@@ -1580,18 +1859,43 @@ do_flash_init(void)
 
 
 
     if (!__flash_init) {
         __flash_init = 1;
-        if ((stat = flash_init(diag_printf)) != 0) {
-            diag_printf("FLASH: driver init failed: %s\n", flash_errmsg(stat));
+        
+        if ((stat = cyg_flash_init(diag_printf)) != 0) {
+            diag_printf("FLASH: driver init failed: %s\n", cyg_flash_errmsg(stat));
             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
-        flash_end = (void *)((CYG_ADDRESS)flash_end - 1);
-        flash_get_block_info(&flash_block_size, &flash_num_blocks);
+
+#ifdef CYGNUM_REDBOOT_FLASH_BASE
+        stat = cyg_flash_get_info_addr(CYGNUM_REDBOOT_FLASH_BASE, &info);
+#else
+        stat = cyg_flash_get_info(0, &info);
+#endif
+        if (stat != CYG_FLASH_ERR_OK) {
+             diag_printf("FLASH: driver init failed: %s\n", 
+                         cyg_flash_errmsg(stat));
+             return false;
+        }
+        flash_start = info.start;
+        flash_end = info.end;
+
+        // No bootblock support yet, so we merge any bootblocks we might
+        // find into full size blocks
+        for (i=0; i < info.num_block_infos; i++) {
+          if (info.block_info[i].block_size > flash_block_size) {
+            flash_block_size = info.block_info[i].block_size;
+          }
+        }
+        flash_num_blocks = 0;
+        for (i=0; i < info.num_block_infos; i++) {
+          flash_num_blocks += (info.block_info[i].block_size *
+                               info.block_info[i].blocks) /
+            flash_block_size;
+        }
+        
 #ifdef CYGOPT_REDBOOT_FIS
         fisdir_size = CYGNUM_REDBOOT_FIS_DIRECTORY_ENTRY_COUNT * CYGNUM_REDBOOT_FIS_DIRECTORY_ENTRY_SIZE;
         fisdir_size = ((fisdir_size + flash_block_size - 1) / flash_block_size) * flash_block_size;
 # if defined(CYGPRI_REDBOOT_ZLIB_FLASH) && defined(CYGOPT_REDBOOT_FIS_ZLIB_COMMON_BUFFER)
 	fis_work_block = fis_zlib_common_buffer;
@@ -1601,16 +1905,17 @@ do_flash_init(void)
 	}
 # else
         workspace_end = (unsigned char *)(workspace_end-fisdir_size);
         fis_work_block = workspace_end;
 # endif
+
         if (CYGNUM_REDBOOT_FIS_DIRECTORY_BLOCK < 0) {
-            fis_addr = (void *)((CYG_ADDRESS)flash_end + 1 +
-                                (CYGNUM_REDBOOT_FIS_DIRECTORY_BLOCK*flash_block_size));
+            fis_addr = ((CYG_ADDRESS)flash_end + 1 +
+                        (CYGNUM_REDBOOT_FIS_DIRECTORY_BLOCK*flash_block_size));
         } else {
-            fis_addr = (void *)((CYG_ADDRESS)flash_start + 
-                                (CYGNUM_REDBOOT_FIS_DIRECTORY_BLOCK*flash_block_size));
+            fis_addr = ((CYG_ADDRESS)flash_start + 
+                        (CYGNUM_REDBOOT_FIS_DIRECTORY_BLOCK*flash_block_size));
         }
         
         if (((CYG_ADDRESS)fis_addr + fisdir_size - 1) > (CYG_ADDRESS)flash_end) {
             diag_printf("FIS directory doesn't fit\n");
             return -1;
@@ -1627,12 +1932,12 @@ do_flash_init(void)
 
         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);
+        cyg_flash_read(fis_addr, &img0, sizeof(img0), &err_addr);
+        cyg_flash_read(redundant_fis_addr, &img1, sizeof(img1), &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));
         }

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]