Mercurial > ecos
changeset 2631:13376f3cfc60 jifl-post-flashv2-merge-20081118
Merge flashv2 branch to trunk, with eCosCentric additions
line wrap: on
line diff
--- a/doc/ChangeLog +++ b/doc/ChangeLog @@ -1,3 +1,8 @@ +2008-11-17 Jonathan Larmour <jifl@eCosCentric.com> + + * sgml/doclist: Add AMD AM29XXXXX and Intel StrataFlash v2 flash + driver documentation. + 2008-10-08 Bart Veer <bartv@ecoscentric.com> * sgml/doclist: added generic framebuffer and synthetic target
--- a/doc/sgml/doclist +++ b/doc/sgml/doclist @@ -48,3 +48,5 @@ devs/watchdog/synth/current/doc/synth_wa devs/wallclock/dallas/ds1307/current/doc/ds1307.sgml devs/disk/generic/mmc/current/doc/disk_mmc.sgml devs/framebuf/synth/current/doc/synth_framebuf.sgml +devs/flash/amd/am29xxxxxv2/current/doc/am29xxxxx.sgml +devs/flash/intel/stratav2/current/doc/strata.sgml
--- a/packages/ChangeLog +++ b/packages/ChangeLog @@ -1,3 +1,24 @@ +2008-11-16 Jonathan Larmour <jifl@eCosCentric.com> + + * ecos.db: Use v2 drivers for adder/adderII and IXDP425. + +2008-11-16 Jonathan Larmour <jifl@eCosCentric.com> + + * ecos.db: Merge flash_v2 branch to trunk including these changes: + + 2004-11-20 Bart Veer <bartv@ecoscentric.com> + + * ecos.db: Add new AM29xxxxxx driver which supports the V2 API + + 2004-08-06 Andrew Lunn <andrew.lunn@ascom.ch> + + * ecos.db: Added the new strata driver which uses the V2 API. + + 2004-08-05 Andrew Lunn <andrew.lunn@ascom.ch> + + * ecos.db: Added the new synthetic target flash device which uses + the new API and has some extra goodies like boot blocks. + 2008-11-11 Nick Garnett <nickg@ecoscentric.com> * ecos.db: Add STM32 wallclock driver.
--- a/packages/NEWS +++ b/packages/NEWS @@ -1,3 +1,5 @@ +* Intel Strataflash v2 flash driver contributed by eCosCentric Ltd. +* New Flash API with lots of new goodies. * ADC device driver for EA2468 OEM board * ADC device driver for LP24XXX devices. * Cortex-M Architecture HAL contributed by eCosCentric Ltd.
--- a/packages/ecos.db +++ b/packages/ecos.db @@ -209,7 +209,7 @@ package CYGPKG_DEVS_FLASH_ARM_AAED2000 { } package CYGPKG_DEVS_FLASH_AMD_AM29XXXXX { - alias { "Support for AMD AM29xxxxx flash memory" flash_amd_am29xxxxx } + alias { "Support for AMD AM29xxxxx flash memory (deprecated)" flash_amd_am29xxxxx } directory devs/flash/amd/am29xxxxx script flash_amd_am29xxxxx.cdl hardware @@ -218,6 +218,16 @@ package CYGPKG_DEVS_FLASH_AMD_AM29XXXXX flash memory devices." } +package CYGPKG_DEVS_FLASH_AMD_AM29XXXXX_V2 { + alias { "Support for AMD AM29xxxxx flash memory" flash_amd_am29xxxxx_v2 } + directory devs/flash/amd/am29xxxxxv2 + script flash_am29xxxxx_v2.cdl + hardware + description " + This package contains hardware support for AMD AM29xxxxx + flash memory devices." +} + package CYGPKG_DEVS_FLASH_ATMEL_AT29CXXXX { alias { "Support for Atmel AT29Cxxxx flash memory" flash_atmel_at29cxxxx } directory devs/flash/atmel/at29cxxxx @@ -589,7 +599,7 @@ package CYGPKG_DEVS_FLASH_NANO { } package CYGPKG_DEVS_FLASH_STRATA { - alias { "Generic FLASH memory support for Intel StrataFLASH" strata } + alias { "Generic FLASH memory support for Intel StrataFLASH (deprecated)" strata } directory devs/flash/intel/strata script flash_strata.cdl hardware @@ -598,6 +608,16 @@ package CYGPKG_DEVS_FLASH_STRATA { StrataFLASH memory devices." } +package CYGPKG_DEVS_FLASH_STRATA_V2 { + alias { "Generic FLASH memory support for Intel StrataFLASH" strata_v2 } + directory devs/flash/intel/stratav2 + script flash_strata_v2.cdl + hardware + description " + This package contains generic hardware support for Intel + StrataFLASH memory devices using the V2 device API." +} + package CYGPKG_DEVS_FLASH_SST_39VFXXX { alias { "Support for SST 39VFXXX flash memory" flash_sst_39vfXXX } directory devs/flash/sst/39vfxxx @@ -799,7 +819,7 @@ package CYGPKG_DEVS_FLASH_ATLAS { on the MIPS Atlas platform." } package CYGPKG_DEVS_FLASH_SYNTH { - alias { "Synthetic FLASH memory support" synth_flash flash_synth } + alias { "Synthetic FLASH memory support (legacy)" synth_flash flash_synth } directory devs/flash/synth script flash_synth.cdl hardware @@ -807,6 +827,15 @@ package CYGPKG_DEVS_FLASH_SYNTH { FLASH memory device support for Synthetic target" } +package CYGPKG_DEVS_FLASH_SYNTH_V2 { + alias { "Synthetic FLASH memory support" synth_flashv2 flash_synthv2 } + directory devs/flash/synthv2 + script flash_synth.cdl + hardware + description " + FLASH memory device support for Synthetic target using the new API" +} + package CYGPKG_DEVS_FLASH_TOSHIBA_TC58XXX { alias { "Support for Toshiba TC58xxx flash memory" flash_toshiba_tc58xxx } directory devs/flash/toshiba/tc58xxx @@ -4702,6 +4731,7 @@ target eb55 { CYGPKG_HAL_ARM_AT91_EB55 CYGPKG_DEVS_FLASH_EB55 CYGPKG_DEVS_FLASH_ATMEL_AT49XXXX + CYGPKG_DEVS_FLASH_ATMEL_DATAFLASH CYGPKG_IO_SERIAL_ARM_AT91 CYGPKG_DEVS_SPI_ARM_EB55 CYGPKG_DEVS_SPI_ARM_AT91 @@ -5137,8 +5167,7 @@ target ixdp425 { CYGPKG_IO_PCI CYGPKG_DEVS_ETH_INTEL_I82559 CYGPKG_DEVS_ETH_ARM_IXDP425_I82559 - CYGPKG_DEVS_FLASH_STRATA - CYGPKG_DEVS_FLASH_IXDP425 + CYGPKG_DEVS_FLASH_STRATA_V2 } description " The ixdp425 target provides the packages needed to run @@ -6330,8 +6359,7 @@ target adder { CYGPKG_HAL_POWERPC_MPC8xx CYGPKG_HAL_POWERPC_ADDER CYGPKG_HAL_QUICC - CYGPKG_DEVS_FLASH_POWERPC_ADDER - CYGPKG_DEVS_FLASH_AMD_AM29XXXXX + CYGPKG_DEVS_FLASH_AMD_AM29XXXXX_V2 CYGPKG_DEVS_ETH_POWERPC_QUICC CYGPKG_DEVS_ETH_POWERPC_ADDER CYGPKG_IO_SERIAL_POWERPC_QUICC_SMC @@ -6348,8 +6376,7 @@ target adderII { CYGPKG_HAL_POWERPC_MPC8xx CYGPKG_HAL_POWERPC_ADDER CYGPKG_HAL_QUICC - CYGPKG_DEVS_FLASH_POWERPC_ADDER - CYGPKG_DEVS_FLASH_AMD_AM29XXXXX + CYGPKG_DEVS_FLASH_AMD_AM29XXXXX_V2 CYGPKG_DEVS_ETH_POWERPC_FEC CYGPKG_DEVS_ETH_POWERPC_ADDERII CYGPKG_IO_SERIAL_POWERPC_QUICC_SMC
--- a/packages/fs/jffs2/current/ChangeLog +++ b/packages/fs/jffs2/current/ChangeLog @@ -1,3 +1,21 @@ +2008-11-18 Jonathan Larmour <jifl@eCosCentric.com> + + * tests/jffs2_1.c, tests/jffs2_2.c, tests/jffs2_3.c: + Select device name to use according to configury, including flash + API in use. + +2008-06-09 Jonathan Larmour <jifl@eCosCentric.com> + + * cdl/jffs2.cdl (CYGPKG_FS_JFFS2_CFLAGS_ADD): Conditionalise use of + workaround for building with native linux tools so that it only + applies when using synth target. Otherwise it can cause problems + with some other third-party builds of the toolchain. + +2004-07-14 Andrew Lunn <andrew.lunn@ascom.ch> + + * tests/fileio1.c (main): If we have two filesystem configured + mount the second one on /mnt and list the root of it. + 2008-04-02 Xinghua Yang <yxinghua@sunnorth.com.cn> Taiyun Wang <taiyun@sunnorth.com.cn> Andrew Lunn <andrew.lunn@ascom.ch> @@ -94,6 +112,11 @@ 2004-08-12 Andrew Lunn <andrew.lunn@asc * Merge from public MTD. +2004-07-10 Andrew Lunn <andrew.lunn@ascom.ch> + + * src/flashio.c (jffs2_flash_erase): Minor update for new + flash API. + 2004-04-19 Oyvind Harboe <oyvind.harboe@zylin.com> * src/build.c: JFFS2 can now be used as a write-once, read many mode
--- a/packages/fs/jffs2/current/cdl/jffs2.cdl +++ b/packages/fs/jffs2/current/cdl/jffs2.cdl @@ -234,7 +234,8 @@ cdl_package CYGPKG_FS_JFFS2 { # We add '-D__ECOS' to trigger eCos-specific code in places. # We add '-nostdinc -iwithprefix include' to avoid picking up # native <linux/*.h> include files when building on Linux. - default_value { "-D__ECOS -nostdinc -iwithprefix include" } + default_value { "-D__ECOS " . \ + (CYGPKG_HAL_SYNTH ? " -nostdinc -iwithprefix include" : "") } description " This option modifies the set of compiler flags for building the JFFS2 package.
--- a/packages/fs/jffs2/current/src/flashio.c +++ b/packages/fs/jffs2/current/src/flashio.c @@ -144,7 +144,7 @@ cyg_bool jffs2_flash_erase(struct jffs2_ struct jffs2_eraseblock * jeb) { cyg_io_flash_getconfig_erase_t e; - void *err_addr; + cyg_flashaddr_t err_addr; Cyg_ErrNo err; cyg_uint32 len = sizeof (e); struct super_block *sb = OFNI_BS_2SFFJ(c);
--- a/packages/fs/jffs2/current/tests/jffs2_1.c +++ b/packages/fs/jffs2/current/tests/jffs2_1.c @@ -61,6 +61,7 @@ #include <pkgconf/hal.h> #include <pkgconf/kernel.h> #include <pkgconf/io_fileio.h> +#include <pkgconf/io_flash.h> #include <cyg/kernel/ktypes.h> // base kernel types #include <cyg/infra/cyg_trac.h> // tracing macros @@ -74,6 +75,7 @@ #include <string.h> #include <dirent.h> #include <stdio.h> +#include <stdlib.h> #include <cyg/fileio/fileio.h> @@ -83,6 +85,22 @@ #include <pkgconf/fs_jffs2.h> // Address of JFFS2 //========================================================================== +// Mount details + +#define stringify2(_x_) #_x_ +#define stringify(_x_) stringify2(_x_) + +#if defined(CYGDAT_IO_FLASH_BLOCK_DEVICE_NAME_1) +# define JFFS2_TEST_DEV CYGDAT_IO_FLASH_BLOCK_DEVICE_NAME_1 +#elif defined(CYGFUN_IO_FLASH_BLOCK_FROM_FIS) +# define JFFS2_TEST_DEV "/dev/flash/fis/jffs2test" +#else +// fall back to using a user set area in the first device (only) +# define JFFS2_TEST_DEV "/dev/flash/0/" stringify(CYGNUM_FS_JFFS2_TEST_OFFSET) "," stringify(CYGNUM_FS_JFFS2_TEST_LENGTH) +#endif + +// we could use an mtab but we don't in order to get better diagnostics +// by calling mount() directly. #if 0 MTAB_ENTRY( jffs2_mte1, @@ -428,11 +446,17 @@ int main( int argc, char **argv ) //int i; int existingdirents=-1; + struct mallinfo info; + + info = mallinfo(); + diag_printf("arenasize %d, freeblocks %d, totalallocated %d, totalfree %d, maxfree %d\n", + info.arena, info.ordblks, info.uordblks, info.fordblks, info.maxfree); + CYG_TEST_INIT(); // -------------------------------------------------------------- - err = mount( CYGDAT_IO_FLASH_BLOCK_DEVICE_NAME_1, "/", "jffs2" ); + err = mount( JFFS2_TEST_DEV, "/", "jffs2" ); if( err < 0 ) SHOW_RESULT( mount, err ); err = chdir( "/" ); @@ -523,7 +547,7 @@ int main( int argc, char **argv ) // -------------------------------------------------------------- diag_printf("<INFO>: mount /jffs2 \n"); - err = mount( CYGDAT_IO_FLASH_BLOCK_DEVICE_NAME_1, "/jffs2", "jffs2" ); + err = mount( JFFS2_TEST_DEV, "/jffs2", "jffs2" ); if( err < 0 ) SHOW_RESULT( mount, err ); createfile( "/jffs2/tinky", 456 ); @@ -670,6 +694,29 @@ int main( int argc, char **argv ) err = umount( "/jffs2" ); if( err < 0 ) SHOW_RESULT( umount, err ); +#ifdef CYGDAT_IO_FLASH_BLOCK_DEVICE_NAME_2 + diag_printf("<INFO>: mounting second JFFS2 filesystem on /mnt\n"); + + err = mount( CYGDAT_IO_FLASH_BLOCK_DEVICE_NAME_2, "/mnt", "jffs2" ); + if( err < 0 ) SHOW_RESULT( mount, err ); + + err = chdir( "/" ); + if( err < 0 ) SHOW_RESULT( chdir, err ); + + checkcwd( "/" ); + + listdir( "/", true, -1, &existingdirents ); + if ( existingdirents < 2 ) + CYG_TEST_FAIL("Not enough dir entries\n"); + + listdir( "/mnt", true, -1, &existingdirents ); + if ( existingdirents < 2 ) + CYG_TEST_FAIL("Not enough dir entries\n"); + + diag_printf("<INFO>: umount /mnt\n"); + err = umount( "/mnt" ); +#endif + diag_printf("<INFO>: umount /\n"); err = umount( "/" ); if( err < 0 ) SHOW_RESULT( umount, err );
--- a/packages/fs/jffs2/current/tests/jffs2_2.c +++ b/packages/fs/jffs2/current/tests/jffs2_2.c @@ -57,6 +57,8 @@ //####DESCRIPTIONEND#### // //========================================================================== + +#include <pkgconf/io_flash.h> #include <stdio.h> #include <unistd.h> #include <fcntl.h> @@ -68,6 +70,24 @@ #include <cyg/infra/testcase.h> #include <cyg/infra/diag.h> // HAL polled output + +#include <pkgconf/fs_jffs2.h> // Address of JFFS2 + +//========================================================================== +// Mount details + +#define stringify2(_x_) #_x_ +#define stringify(_x_) stringify2(_x_) + +#if defined(CYGDAT_IO_FLASH_BLOCK_DEVICE_NAME_1) +# define JFFS2_TEST_DEV CYGDAT_IO_FLASH_BLOCK_DEVICE_NAME_1 +#elif defined(CYGFUN_IO_FLASH_BLOCK_FROM_FIS) +# define JFFS2_TEST_DEV "/dev/flash/fis/jffs2test" +#else +// fall back to using a user set area in the first device (only) +# define JFFS2_TEST_DEV "/dev/flash/0/" stringify(CYGNUM_FS_JFFS2_TEST_OFFSET) "," stringify(CYGNUM_FS_JFFS2_TEST_LENGTH) +#endif + //========================================================================== #define SHOW_RESULT( _fn, _res ) \ @@ -94,7 +114,7 @@ int main( int argc, char **argv ) // -------------------------------------------------------------- CYG_TEST_INFO("mount /"); - err = mount( CYGDAT_IO_FLASH_BLOCK_DEVICE_NAME_1, "/", "jffs2" ); + err = mount( JFFS2_TEST_DEV, "/", "jffs2" ); if( err < 0 ) SHOW_RESULT( mount, err );
--- a/packages/fs/jffs2/current/tests/jffs2_3.c +++ b/packages/fs/jffs2/current/tests/jffs2_3.c @@ -48,6 +48,8 @@ //####DESCRIPTIONEND#### // //========================================================================== + +#include <pkgconf/io_flash.h> #include <stdio.h> #include <unistd.h> #include <fcntl.h> @@ -62,6 +64,22 @@ #include <cyg/infra/testcase.h> #include <cyg/infra/diag.h> // HAL polled output +#include <pkgconf/fs_jffs2.h> // Address of JFFS2 + +//========================================================================== + +#define stringify2(_x_) #_x_ +#define stringify(_x_) stringify2(_x_) + +#if defined(CYGDAT_IO_FLASH_BLOCK_DEVICE_NAME_1) +# define JFFS2_TEST_DEV CYGDAT_IO_FLASH_BLOCK_DEVICE_NAME_1 +#elif defined(CYGFUN_IO_FLASH_BLOCK_FROM_FIS) +# define JFFS2_TEST_DEV "/dev/flash/fis/jffs2test" +#else +// fall back to using a user set area in the first device (only) +# define JFFS2_TEST_DEV "/dev/flash/0/" stringify(CYGNUM_FS_JFFS2_TEST_OFFSET) "," stringify(CYGNUM_FS_JFFS2_TEST_LENGTH) +#endif + //========================================================================== #define ITERATIONS 1000000 @@ -151,7 +169,7 @@ int main( int argc, char **argv ) // -------------------------------------------------------------- CYG_TEST_INFO("mount /"); - err = mount( CYGDAT_IO_FLASH_BLOCK_DEVICE_NAME_1, "/", "jffs2" ); + err = mount( JFFS2_TEST_DEV, "/", "jffs2" ); if( err < 0 ) SHOW_RESULT( mount, err ); chdir ("/");
--- a/packages/hal/arm/xscale/ixdp425/current/ChangeLog +++ b/packages/hal/arm/xscale/ixdp425/current/ChangeLog @@ -1,7 +1,24 @@ +2006-08-02 Jonathan Larmour <jifl@eCosCentric.com> + + * src/ixdp425_strataflash.c: In CYG_FLASH_FUNS, replace query + function with generic nop version. + Remove hwr_map_error: it no longer exists for CYG_FLASH_FUNS. + 2006-03-01 Mark Salter <msalter@sadr.localdomain> * include/hal_platform_setup.h: Fix DELAY macro. +2006-01-31 Jonathan Larmour <jifl@eCosCentric.com> + + * cdl/hal_arm_xscale_ixdp425.cdl + (CYGHWR_HAL_ARM_XSCALE_IXDP425_FLASH): New option to support + v2 Flash driver. + * src/ixdp425_strataflash.c: New v2 flash driver. + * include/hal_platform_setup.h: Add uncached Flash mapping. + * include/ixdp425.h: Add uncached flash mappings. + * include/plf_io.h: Provide CYGARC_UNCACHED_ADDRESS. + * misc/redboot*.ecm: Use Strata V2 Flash driver. + 2004-09-27 Mark Salter <msalter@redhat.com> * misc/redboot_ROMRAM.ecm: Remove CYGHWR_HAL_IXP425_PCI_NP_WORKAROUND.
--- a/packages/hal/arm/xscale/ixdp425/current/cdl/hal_arm_xscale_ixdp425.cdl +++ b/packages/hal/arm/xscale/ixdp425/current/cdl/hal_arm_xscale_ixdp425.cdl @@ -91,6 +91,21 @@ cdl_package CYGPKG_HAL_ARM_XSCALE_IXDP42 into ROM, but execute from RAM." } + cdl_option CYGHWR_HAL_ARM_XSCALE_IXDP425_FLASH { + display "External Intel StrataFLASH memory support" + parent CYGPKG_IO_FLASH + active_if CYGPKG_IO_FLASH + flavor bool + default_value 1 + no_define + implements CYGHWR_IO_FLASH_BLOCK_LOCKING + compile -library=libextras.a ixdp425_strataflash.c + description " + The IXDP425 development board is fitted with an external Intel + StrataFLASH 28F128J3 FLASH memory device. This option enables + support for the StrataFlash." + } + cdl_component CYGBLD_GLOBAL_OPTIONS { display "Global build options" flavor none
--- a/packages/hal/arm/xscale/ixdp425/current/include/hal_platform_setup.h +++ b/packages/hal/arm/xscale/ixdp425/current/include/hal_platform_setup.h @@ -305,6 +305,7 @@ 30: IXP_MAP_EXP 5, (1 << 20), 0, 0, 0, 0 // NPE use IXP_MAP_EXP_V 0, IXDP_FLASH_DC_BASE, IXDP_FLASH_SIZE, 1, 0, 0, 1 // data coherent flash + IXP_MAP_EXP_V 0, IXDP_FLASH_UNCACHED_BASE, IXDP_FLASH_SIZE, 0, 0, 0, 0 // uncached flash IXP_MAP_IO IXP425_PCI_WINDOW_BASE, IXP425_PCI_WINDOW_SIZE IXP_MAP_IO IXP425_QMGR_BASE, IXP425_QMGR_SIZE
--- a/packages/hal/arm/xscale/ixdp425/current/include/ixdp425.h +++ b/packages/hal/arm/xscale/ixdp425/current/include/ixdp425.h @@ -74,6 +74,7 @@ #define IXDP_FLASH_BASE 0x50000000 #define IXDP_FLASH_SIZE 0x01000000 #define IXDP_FLASH_DC_BASE 0xA0000000 +#define IXDP_FLASH_UNCACHED_BASE 0xB0000000 // CS0 (flash optimum timing) #define IXP425_EXP_CS0_INIT \
--- a/packages/hal/arm/xscale/ixdp425/current/include/plf_io.h +++ b/packages/hal/arm/xscale/ixdp425/current/include/plf_io.h @@ -55,10 +55,18 @@ //============================================================================= #include <pkgconf/hal.h> -#include <cyg/hal/hal_io.h> // IO macros #include <cyg/hal/ixdp425.h> #include CYGBLD_HAL_PLF_INTS_H +// Override IXP425 variant CYGARC_UNCACHED_ADDRESS definition +#define CYGARC_UNCACHED_ADDRESS(x) \ + ((((cyg_uint32)(x)) < 0x10000000) ? (((cyg_uint32)(x))+0x20000000) : \ + ((((cyg_uint32)(x)) >= IXDP_FLASH_BASE) && (((cyg_uint32)(x)) < (IXDP_FLASH_BASE+IXDP_FLASH_SIZE))) ? \ + ((x)+(IXDP_FLASH_UNCACHED_BASE-IXDP_FLASH_BASE)) : \ + (x)) + +#include <cyg/hal/hal_io.h> // IO macros + //----------------------------------------------------------------------------- // end of plf_io.h #endif // CYGONCE_PLF_IO_H
--- a/packages/hal/arm/xscale/ixdp425/current/misc/redboot_RAM.ecm +++ b/packages/hal/arm/xscale/ixdp425/current/misc/redboot_RAM.ecm @@ -15,8 +15,7 @@ cdl_configuration eCos { package -hardware CYGPKG_HAL_ARM_XSCALE_CORE current ; package -hardware CYGPKG_HAL_ARM_XSCALE_IXP425 current ; package -hardware CYGPKG_HAL_ARM_XSCALE_IXDP425 current ; - package -hardware CYGPKG_DEVS_FLASH_STRATA current ; - package -hardware CYGPKG_DEVS_FLASH_IXDP425 current ; + package -hardware CYGPKG_DEVS_FLASH_STRATA_V2 current ; package -hardware CYGPKG_DEVS_ETH_INTEL_I82559 current ; package -hardware CYGPKG_DEVS_ETH_ARM_IXDP425_I82559 current ; package -template CYGPKG_HAL current ;
--- a/packages/hal/arm/xscale/ixdp425/current/misc/redboot_RAMLE.ecm +++ b/packages/hal/arm/xscale/ixdp425/current/misc/redboot_RAMLE.ecm @@ -15,8 +15,7 @@ cdl_configuration eCos { package -hardware CYGPKG_HAL_ARM_XSCALE_CORE current ; package -hardware CYGPKG_HAL_ARM_XSCALE_IXP425 current ; package -hardware CYGPKG_HAL_ARM_XSCALE_IXDP425 current ; - package -hardware CYGPKG_DEVS_FLASH_STRATA current ; - package -hardware CYGPKG_DEVS_FLASH_IXDP425 current ; + package -hardware CYGPKG_DEVS_FLASH_STRATA_V2 current ; package -hardware CYGPKG_DEVS_ETH_INTEL_I82559 current ; package -hardware CYGPKG_DEVS_ETH_ARM_IXDP425_I82559 current ; package -template CYGPKG_HAL current ;
--- a/packages/hal/arm/xscale/ixdp425/current/misc/redboot_ROM.ecm +++ b/packages/hal/arm/xscale/ixdp425/current/misc/redboot_ROM.ecm @@ -15,8 +15,7 @@ cdl_configuration eCos { package -hardware CYGPKG_HAL_ARM_XSCALE_CORE current ; package -hardware CYGPKG_HAL_ARM_XSCALE_IXP425 current ; package -hardware CYGPKG_HAL_ARM_XSCALE_IXDP425 current ; - package -hardware CYGPKG_DEVS_FLASH_STRATA current ; - package -hardware CYGPKG_DEVS_FLASH_IXDP425 current ; + package -hardware CYGPKG_DEVS_FLASH_STRATA_V2 current ; package -hardware CYGPKG_DEVS_ETH_INTEL_I82559 current ; package -hardware CYGPKG_DEVS_ETH_ARM_IXDP425_I82559 current ; package -template CYGPKG_HAL current ;
--- a/packages/hal/arm/xscale/ixdp425/current/misc/redboot_ROMLE.ecm +++ b/packages/hal/arm/xscale/ixdp425/current/misc/redboot_ROMLE.ecm @@ -15,8 +15,7 @@ cdl_configuration eCos { package -hardware CYGPKG_HAL_ARM_XSCALE_CORE current ; package -hardware CYGPKG_HAL_ARM_XSCALE_IXP425 current ; package -hardware CYGPKG_HAL_ARM_XSCALE_IXDP425 current ; - package -hardware CYGPKG_DEVS_FLASH_STRATA current ; - package -hardware CYGPKG_DEVS_FLASH_IXDP425 current ; + package -hardware CYGPKG_DEVS_FLASH_STRATA_V2 current ; package -hardware CYGPKG_DEVS_ETH_INTEL_I82559 current ; package -hardware CYGPKG_DEVS_ETH_ARM_IXDP425_I82559 current ; package -template CYGPKG_HAL current ;
--- a/packages/hal/arm/xscale/ixdp425/current/misc/redboot_ROMRAM.ecm +++ b/packages/hal/arm/xscale/ixdp425/current/misc/redboot_ROMRAM.ecm @@ -15,8 +15,7 @@ cdl_configuration eCos { package -hardware CYGPKG_HAL_ARM_XSCALE_CORE current ; package -hardware CYGPKG_HAL_ARM_XSCALE_IXP425 current ; package -hardware CYGPKG_HAL_ARM_XSCALE_IXDP425 current ; - package -hardware CYGPKG_DEVS_FLASH_STRATA current ; - package -hardware CYGPKG_DEVS_FLASH_IXDP425 current ; + package -hardware CYGPKG_DEVS_FLASH_STRATA_V2 current ; package -hardware CYGPKG_DEVS_ETH_INTEL_I82559 current ; package -hardware CYGPKG_DEVS_ETH_ARM_IXDP425_I82559 current ; package -template CYGPKG_HAL current ;
--- a/packages/hal/arm/xscale/ixdp425/current/misc/redboot_ROMRAMLE.ecm +++ b/packages/hal/arm/xscale/ixdp425/current/misc/redboot_ROMRAMLE.ecm @@ -15,8 +15,7 @@ cdl_configuration eCos { package -hardware CYGPKG_HAL_ARM_XSCALE_CORE current ; package -hardware CYGPKG_HAL_ARM_XSCALE_IXP425 current ; package -hardware CYGPKG_HAL_ARM_XSCALE_IXDP425 current ; - package -hardware CYGPKG_DEVS_FLASH_STRATA current ; - package -hardware CYGPKG_DEVS_FLASH_IXDP425 current ; + package -hardware CYGPKG_DEVS_FLASH_STRATA_V2 current ; package -hardware CYGPKG_DEVS_ETH_INTEL_I82559 current ; package -hardware CYGPKG_DEVS_ETH_ARM_IXDP425_I82559 current ; package -template CYGPKG_HAL current ;
new file mode 100644 --- /dev/null +++ b/packages/hal/arm/xscale/ixdp425/current/src/ixdp425_strataflash.c @@ -0,0 +1,96 @@ +//========================================================================== +// +// ixdp425_strataflash.c +// +// Support for the Strata flash device on Intel IXDP425 +// +//========================================================================== +//####ECOSGPLCOPYRIGHTBEGIN#### +// ------------------------------------------- +// This file is part of eCos, the Embedded Configurable Operating System. +// Copyright (C) 2005, 2006 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): jlarmour based on original by bartv +// Date: 2006-01-17 +// +//####DESCRIPTIONEND#### +//============================================================================= + +// There is a single Intel StrataFLASH device on the IXDP425, supported via the +// generic Strata flash package. By default this is the 28F128J3 which is a +// 16MByte device, arranged as 128*128K blocks with no boot blocks, 16-bits +// wide. There is a 32-byte program buffer and locking is supported. +// +// But CFI is used to determine Flash geometry as the part is fitted in a socket +// to allow replacement with other StrataFLASH parts. + +#include <pkgconf/system.h> +#include <cyg/io/flash.h> +#include <cyg/io/flash_dev.h> +#include <cyg/io/strata_dev.h> +#include <cyg/hal/plf_io.h> + +static const CYG_FLASH_FUNS(hal_ixdp425_flash_strata_funs, + &cyg_strata_init_cfi_16, + &cyg_flash_devfn_query_nop, + &cyg_strata_erase_16, + &cyg_strata_bufprogram_16, + (int (*)(struct cyg_flash_dev*, const cyg_flashaddr_t, void*, size_t))0, + &cyg_strata_lock_j3_16, + &cyg_strata_unlock_j3_16); + +static cyg_strata_dev hal_ixdp425_flash_priv; +#ifdef notusingcfianymore + = { + .manufacturer_code = 0x0089, + .device_code = 0x0018, + .bufsize = 16, // 32 bytes -> 16 words + .block_info = { + { 0x00020000, 128 } + } +}; +#endif + +// The Flash driver initially claims to use the cached mapping of the Flash +// device, but through CYGARC_UNCACHED_ADDRESS, will actually use the *uncached* +// mapping when it comes to driver operations. That way things like +// RedBoot's FIS directory still correctly use the cached flash addresses. + +CYG_FLASH_DRIVER(hal_ixdp425_flash, + &hal_ixdp425_flash_strata_funs, + 0, + IXDP_FLASH_BASE, + (IXDP_FLASH_BASE+IXDP_FLASH_SIZE-1), + 1, + hal_ixdp425_flash_priv.block_info, + &hal_ixdp425_flash_priv +); + +// EOF ixdp425_strataflash.c
--- a/packages/hal/powerpc/adder/current/ChangeLog +++ b/packages/hal/powerpc/adder/current/ChangeLog @@ -1,3 +1,20 @@ +2008-11-13 Jonathan Larmour <jifl@eCosCentric.com> + + * src/adder_flash.c: Dev id is really 0x22f6, not 0xf6. + +2006-08-02 Jonathan Larmour <jifl@eCosCentric.com> + + * src/adder_flash.c: In CYG_FLASH_FUNS, replace query, lock and unlock + functions with generic nop versions. + Remove hwr_map_error: it no longer exists for CYG_FLASH_FUNS. + Replace use of cyg/io/flash_priv.h with cyg/io/flash_dev.h as per + io/flash changes. + +2005-08-18 Jonathan Larmour <jifl@eCosCentric.com> + + * cdl/hal_powerpc_adder.cdl: Indicate to the AMD flash driver + that Flash accesses are cached. + 2005-03-27 Andrew Lunn <andrew.lunn@ascom.ch> * src/hal_aux.c: Added prototype of _adder_set_led() to remove @@ -13,6 +30,12 @@ 2005-01-19 Jonathan Larmour <jifl@eCos * include/pkgconf/mlt_powerpc_adder_ram.h (CYGMEM_SECTION_reserved_for_rom_SIZE): Ditto. +2004-11-25 Bart Veer <bartv@ecoscentric.com> + + * cdl/hal_powerpc_adder.cdl, misc/adder_redboot_ROMRAM.ecm, + misc/adderII_redboot_ROMRAM.ecm, src/adder_flash.c: + Switch to V2 flash + 2004-11-04 John Dallaway <jld@ecoscentric.com> * cdl/hal_powerpc_adder.cdl: Remove "-fvtable-gc" and "-finit-priority"
--- a/packages/hal/powerpc/adder/current/cdl/hal_powerpc_adder.cdl +++ b/packages/hal/powerpc/adder/current/cdl/hal_powerpc_adder.cdl @@ -61,6 +61,9 @@ cdl_package CYGPKG_HAL_POWERPC_ADDER { eCos on a A&M ADDER board equipped with a PowerPC processor." compile hal_diag.c hal_aux.c adder.S + requires { CYGPKG_IO_FLASH implies CYGPKG_DEVS_FLASH_AMD_AM29XXXXX_V2 } + implements CYGHWR_DEVS_FLASH_AMD_AM29XXXXX_V2_CACHED_ONLY + compile -library=libextras.a adder_flash.c implements CYGINT_HAL_DEBUG_GDB_STUBS implements CYGINT_HAL_DEBUG_GDB_STUBS_BREAK
--- a/packages/hal/powerpc/adder/current/misc/adderII_redboot_ROMRAM.ecm +++ b/packages/hal/powerpc/adder/current/misc/adderII_redboot_ROMRAM.ecm @@ -15,8 +15,7 @@ cdl_configuration eCos { package -hardware CYGPKG_HAL_POWERPC_MPC8xx current ; package -hardware CYGPKG_HAL_POWERPC_ADDER current ; package -hardware CYGPKG_HAL_QUICC current ; - package -hardware CYGPKG_DEVS_FLASH_POWERPC_ADDER current ; - package -hardware CYGPKG_DEVS_FLASH_AMD_AM29XXXXX current ; + package -hardware CYGPKG_DEVS_FLASH_AMD_AM29XXXXX_V2 current ; package -hardware CYGPKG_DEVS_ETH_POWERPC_FEC current ; package -hardware CYGPKG_DEVS_ETH_POWERPC_ADDERII current ; package -hardware CYGPKG_IO_SERIAL_POWERPC_QUICC_SMC current ; @@ -29,6 +28,7 @@ cdl_configuration eCos { package CYGPKG_NS_DNS current ; package CYGPKG_IO_FLASH current ; package CYGPKG_IO_ETH_DRIVERS current ; + package CYGPKG_COMPRESS_ZLIB current ; }; cdl_option CYGFUN_LIBC_STRING_BSD_FUNCS { @@ -111,8 +111,5 @@ cdl_option CYGPKG_NS_DNS_BUILD { inferred_value 0 }; -cdl_option CYGHWR_DEVS_FLASH_AMD_AM29LV320D { - inferred_value 1 -};
--- a/packages/hal/powerpc/adder/current/misc/adder_redboot_ROMRAM.ecm +++ b/packages/hal/powerpc/adder/current/misc/adder_redboot_ROMRAM.ecm @@ -15,8 +15,7 @@ cdl_configuration eCos { package -hardware CYGPKG_HAL_POWERPC_MPC8xx current ; package -hardware CYGPKG_HAL_POWERPC_ADDER current ; package -hardware CYGPKG_HAL_QUICC current ; - package -hardware CYGPKG_DEVS_FLASH_POWERPC_ADDER current ; - package -hardware CYGPKG_DEVS_FLASH_AMD_AM29XXXXX current ; + package -hardware CYGPKG_DEVS_FLASH_AMD_AM29XXXXX_V2 current ; package -hardware CYGPKG_DEVS_ETH_POWERPC_QUICC current ; package -hardware CYGPKG_DEVS_ETH_POWERPC_ADDER current ; package -hardware CYGPKG_IO_SERIAL_POWERPC_QUICC_SMC current ; @@ -29,6 +28,7 @@ cdl_configuration eCos { package CYGPKG_NS_DNS current ; package CYGPKG_IO_FLASH current ; package CYGPKG_IO_ETH_DRIVERS current ; + package CYGPKG_COMPRESS_ZLIB current ; }; cdl_option CYGFUN_LIBC_STRING_BSD_FUNCS { @@ -110,9 +110,3 @@ cdl_option CYGBLD_ISO_DNS_HEADER { cdl_option CYGPKG_NS_DNS_BUILD { inferred_value 0 }; - -cdl_option CYGHWR_DEVS_FLASH_AMD_AM29LV320D { - inferred_value 1 -}; - -
new file mode 100644 --- /dev/null +++ b/packages/hal/powerpc/adder/current/src/adder_flash.c @@ -0,0 +1,85 @@ +//========================================================================== +// +// adder_flash.c +// +// Support for the external AMD flash device on Adder boards +// +//========================================================================== +//####ECOSGPLCOPYRIGHTBEGIN#### +// ------------------------------------------- +// This file is part of eCos, the Embedded Configurable Operating System. +// Copyright (C) 2004, 2006, 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. +// +// 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): bartv +// Date: 2004-11-25 +// +//####DESCRIPTIONEND#### +//============================================================================= + +// There is a single AMD AM29LV320D device. DevId 22F6, 4MB, 63*64K, +// 8*8K. + +#include <pkgconf/system.h> +#ifdef CYGPKG_IO_FLASH +#include <cyg/io/flash.h> +#include <cyg/io/flash_dev.h> +#include <cyg/io/am29xxxxx_dev.h> + +static const CYG_FLASH_FUNS(hal_adder_flash_amd_funs, + &cyg_am29xxxxx_init_cfi_16, + &cyg_flash_devfn_query_nop, + &cyg_am29xxxxx_erase_16, + &cyg_am29xxxxx_program_16, + (int (*)(struct cyg_flash_dev*, const cyg_flashaddr_t, void*, size_t))0, + &cyg_flash_devfn_lock_nop, + &cyg_flash_devfn_unlock_nop); + +static cyg_am29xxxxx_dev hal_adder_flash_priv = { + .devid = 0x22F6, + .block_info = { + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 } + } +}; + +CYG_FLASH_DRIVER(hal_adder_flash, + &hal_adder_flash_amd_funs, + 0, + 0xFE000000, + 0xFE3FFFFF, + 4, + hal_adder_flash_priv.block_info, + &hal_adder_flash_priv +); +#endif // CYGPKG_IO_FLASH + +// EOF adder_flash.c
--- a/packages/io/common/current/ChangeLog +++ b/packages/io/common/current/ChangeLog @@ -7,6 +7,11 @@ 2007-08-13 Alexey Shusharin <mrfinch@ma * include/config_keys.h: Added key set setting CAN callback configuration. +2007-05-10 Jonathan Larmour <jifl@eCosCentric.com> + + * include/config_keys.h (CYG_IO_GET_CONFIG_FLASH_DEVADDR): + Add this new key. + 2006-09-21 Jonathan Larmour <jifl@eCosCentric.com> * include/config_keys.h: Merge from eCosCentric repository.
--- a/packages/io/common/current/include/config_keys.h +++ b/packages/io/common/current/include/config_keys.h @@ -121,7 +121,9 @@ #define CYG_IO_GET_CONFIG_FLASH_VERIFY 0x604 #define CYG_IO_GET_CONFIG_FLASH_DEVSIZE 0x605 #define CYG_IO_GET_CONFIG_FLASH_BLOCKSIZE 0x606 +#define CYG_IO_GET_CONFIG_FLASH_DEVADDR 0x607 +// Note the following is now deprecated. See generic flash package for the replacement. #define CYG_IO_SET_CONFIG_FLASH_FIS_NAME 0x680 // ======== 0x700 DISK =======================================================
--- a/packages/redboot/current/src/fconfig.c +++ b/packages/redboot/current/src/fconfig.c @@ -77,7 +77,7 @@ externC bool cyg_plf_redboot_esa_validat #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 @@ -91,19 +91,20 @@ 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 @@ -775,13 +776,9 @@ flash_crc(struct _config *conf) 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 +#if defined(CYGHWR_REDBOOT_FLASH_CONFIG_MEDIA_FLASH) +#if !defined(CYGSEM_REDBOOT_FLASH_COMBINED_FIS_AND_CONFIG) cyg_flashaddr_t err_addr; -# else - void *err_addr; -# endif -#if !defined(CYGSEM_REDBOOT_FLASH_COMBINED_FIS_AND_CONFIG) int stat; #endif #endif @@ -798,21 +795,23 @@ flash_write_config(bool prompt) #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 @@ -1127,7 +1126,7 @@ 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; @@ -1151,21 +1150,21 @@ load_flash_config(void) 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' @@ -1181,6 +1180,7 @@ load_flash_config(void) 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);
--- a/packages/redboot/current/src/flash.c +++ b/packages/redboot/current/src/flash.c @@ -8,6 +8,7 @@ //####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 // @@ -33,9 +34,6 @@ // // 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#### //========================================================================== @@ -164,19 +162,20 @@ RedBoot_nested_cmd("fis", ); // 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 @@ -190,8 +189,37 @@ 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 @@ -220,9 +248,9 @@ 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); } @@ -236,7 +264,7 @@ fis_lookup(char *name, int *num) img = (struct fis_image_desc *)fis_work_block; for (i = 0; i < fisdir_size/sizeof(*img); i++, img++) { - if ((img->u.name[0] != (unsigned char)0xFF) && + if ((img->u.name[0] != '\xFF') && (strcasecmp(name, img->u.name) == 0)) { if (num) *num = i; return img; @@ -258,8 +286,9 @@ int fis_start_update_directory(int autol #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; @@ -277,13 +306,20 @@ int fis_start_update_directory(int autol //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 @@ -297,7 +333,8 @@ 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 @@ -334,7 +371,11 @@ fis_update_directory(int autolock, int e 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) @@ -343,7 +384,6 @@ fis_update_directory(int autolock, int e #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 @@ -353,22 +393,22 @@ fis_update_directory(int autolock, int e #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 @@ -428,17 +468,17 @@ fis_erase_redundant_directory(void) #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 @@ -448,7 +488,7 @@ 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; @@ -472,7 +512,7 @@ fis_init(int argc, char *argv[]) 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 @@ -491,6 +531,7 @@ fis_init(int argc, char *argv[]) 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; @@ -500,6 +541,7 @@ fis_init(int argc, char *argv[]) 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 @@ -513,6 +555,7 @@ fis_init(int argc, char *argv[]) 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 @@ -523,6 +566,7 @@ fis_init(int argc, char *argv[]) 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 @@ -533,6 +577,7 @@ fis_init(int argc, char *argv[]) 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 @@ -541,6 +586,7 @@ fis_init(int argc, char *argv[]) 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 @@ -603,10 +649,10 @@ fis_init(int argc, char *argv[]) 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 @@ -622,10 +668,9 @@ fis_init(int argc, char *argv[]) } 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) { @@ -633,29 +678,26 @@ fis_init(int argc, char *argv[]) } 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 @@ -718,7 +760,7 @@ fis_list(int argc, char *argv[]) lowest_addr = 0xFFFFFFFF; img = (struct fis_image_desc *) fis_work_block; for (i = 0; i < fisdir_size/sizeof(*img); i++, img++) { - if (img->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; @@ -744,6 +786,21 @@ fis_list(int argc, char *argv[]) } 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; @@ -752,21 +809,46 @@ struct free_chunk { 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) && @@ -775,29 +857,31 @@ find_free(struct free_chunk *chunks) 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].end = img->flash_base; + + 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; + } } break; } @@ -811,42 +895,108 @@ find_free(struct free_chunk *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; + + // 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; - // 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; + // 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; @@ -865,59 +1015,124 @@ 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; + + // 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; - // 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; + // 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; } - } - // 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; - } - 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 ) + { + if ( length <= (next_flash_addr - area_start) ) + { + *addr = (CYG_ADDRESS)area_start; + return true; + } } - } - if (area_start != fis_ptr) { - if ((fis_ptr-area_start) >= (length/sizeof(unsigned))) { - *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; } } +#endif return false; -#endif } static void @@ -925,7 +1140,7 @@ 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; @@ -934,12 +1149,13 @@ fis_create(int argc, char *argv[]) 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, @@ -974,14 +1190,16 @@ fis_create(int argc, char *argv[]) } } } - 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; @@ -1006,7 +1224,7 @@ fis_create(int argc, char *argv[]) } } - 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; @@ -1014,44 +1232,57 @@ fis_create(int argc, char *argv[]) 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); @@ -1079,13 +1310,14 @@ 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; @@ -1097,10 +1329,10 @@ fis_create(int argc, char *argv[]) } } #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; } } @@ -1111,24 +1343,44 @@ fis_create(int argc, char *argv[]) } 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 @@ -1158,7 +1410,7 @@ 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")) @@ -1206,10 +1458,10 @@ fis_delete(int argc, char *argv[]) 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); } @@ -1231,7 +1483,7 @@ fis_load(int argc, char *argv[]) #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"); @@ -1299,7 +1551,8 @@ fis_load(int argc, char *argv[]) } 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; @@ -1329,14 +1582,15 @@ 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, @@ -1355,18 +1609,19 @@ fis_write(int argc, char *argv[]) } // 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) || @@ -1375,7 +1630,7 @@ fis_write(int argc, char *argv[]) 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; } @@ -1387,15 +1642,18 @@ fis_write(int argc, char *argv[]) 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; } } @@ -1406,11 +1664,13 @@ 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"); @@ -1427,23 +1687,25 @@ fis_erase(int argc, char *argv[]) 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)); } } @@ -1458,7 +1720,7 @@ fis_lock(int argc, char *argv[]) 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, @@ -1488,13 +1750,13 @@ fis_lock(int argc, char *argv[]) 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)); } } @@ -1507,7 +1769,7 @@ fis_unlock(int argc, char *argv[]) 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, @@ -1536,27 +1798,43 @@ fis_unlock(int argc, char *argv[]) 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 @@ -1564,13 +1842,14 @@ void 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"); @@ -1582,14 +1861,39 @@ 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; @@ -1603,12 +1907,13 @@ do_flash_init(void) 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) { @@ -1629,8 +1934,8 @@ do_flash_init(void) 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) {
