From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 19055 invoked by alias); 18 Nov 2008 01:32:10 -0000 Received: (qmail 18094 invoked by uid 22791); 18 Nov 2008 01:31:59 -0000 X-Spam-Status: No, hits=0.9 required=5.0 tests=AWL,BAYES_50,J_CHICKENPOX_14,J_CHICKENPOX_23,J_CHICKENPOX_43,J_CHICKENPOX_45,J_CHICKENPOX_63,J_CHICKENPOX_66,SPF_PASS X-Spam-Check-By: sourceware.org Received: from hagrid.ecoscentric.com (HELO mail.ecoscentric.com) (212.13.207.197) by sourceware.org (qpsmtpd/0.31) with ESMTP; Tue, 18 Nov 2008 01:31:08 +0000 Received: from localhost (hagrid.ecoscentric.com [127.0.0.1]) by mail.ecoscentric.com (Postfix) with ESMTP id 41D583B4006F for ; Tue, 18 Nov 2008 01:31:05 +0000 (GMT) X-Virus-Scanned: amavisd-new at ecoscentric.com Received: from mail.ecoscentric.com ([127.0.0.1]) by localhost (hagrid.ecoscentric.com [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id DZhgCWIlITtD; Tue, 18 Nov 2008 01:31:01 +0000 (GMT) Message-ID: <49221AD3.8090809@eCosCentric.com> Date: Tue, 18 Nov 2008 01:32:00 -0000 From: Jonathan Larmour User-Agent: Thunderbird 1.5.0.12 (X11/20070530) MIME-Version: 1.0 To: eCos Patches List Subject: Re: [flashv2 merge] RedBoot References: <4922135C.4080207@eCosCentric.com> In-Reply-To: <4922135C.4080207@eCosCentric.com> X-Enigmail-Version: 0.94.4.0 OpenPGP: id=A5FB74E6 Content-Type: multipart/mixed; boundary="------------050008080307060804020105" X-Virus-Checked: Checked by ClamAV on sourceware.org Mailing-List: contact ecos-patches-help@ecos.sourceware.org; run by ezmlm Precedence: bulk List-Id: List-Subscribe: List-Post: List-Help: , Sender: ecos-patches-owner@ecos.sourceware.org X-SW-Source: 2008-11/txt/msg00057.txt.bz2 This is a multi-part message in MIME format. --------------050008080307060804020105 Content-Type: text/plain; charset=ISO-8859-1 Content-Transfer-Encoding: 7bit Content-length: 395 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 --------------050008080307060804020105 Content-Type: text/x-patch; name="flashv2.redboot.diff" Content-Transfer-Encoding: 8bit Content-Disposition: inline; filename="flashv2.redboot.diff" Content-length: 88771 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 + + * 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 + + * 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 + + * 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 * 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 + + * src/flash.c (fis_create): Allow length to be inferred if same + mem address given as prior load address. + 2007-08-28 Gary Thomas * 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 + + * src/flash.c (fis_list): don't skip entries at location 0x0 + 2007-01-22 Peter Korsgaard * 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 + + * src/flash.c, src/fconfig.c: Eliminate some compiler warnings. + +2006-12-06 Jonathan Larmour + + * 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 + + * src/flash.c, src/main.c: eliminate some compiler warnings. + 2006-11-28 David Fernandez * 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 * src/load.c: Only call valid_address() if CYGSEM_REDBOOT_VALIDATE_USER_RAM_LOADS is enabled. +2006-11-01 Jonathan Larmour + + * src/flash.c (fis_create): Ensure flash_addr is always inferred + to come from unused space if not set. + +2006-10-19 Jonathan Larmour + + * src/flash.c (fis_create): If not copying, no reason to insist + on a flash address being set. + 2006-09-06 Andrew Lunn * 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 * 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 + + * 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 + + * 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 * src/net/net_io.c (do_ip_addr): Bail out if no networking. 2006-05-23 Gary Thomas @@ -127,10 +192,28 @@ 2006-03-27 Gary Thomas * src/net/tcp.c (__tcp_write_block): Fix calculation of actual total number of bytes sent (from Wolfgang Koebler) +2006-03-21 Jonathan Larmour + + * src/flash.c (find_free): Fix typo in last change. + +2006-03-16 Jonathan Larmour + + * 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 + + * src/flash.c (find_free): fix boundary condition when an fis img + is right at the end of memory. + 2006-02-25 Oliver Munz Andrew Lunn * 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 + + * src/flash.c (_flash_info): Tidy presentation of flash block info. + +2006-01-17 Jonathan Larmour + + * src/flash.c (fis_init): Default data_length = FIS partition + size for special partitions. + +2005-12-22 Jonathan Larmour + + * 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 + + * 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 * src/gunzip.c (do_gunzip): Fixed diag_printf format string warnings. 2005-10-17 Gary Thomas * src/iomem.c (do_iopeek): Correct number of options. +2005-10-05 Nick Garnett + + * 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 + + * 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 + + * 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 * 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 - - * cdl/redboot.cdl, doc/redboot_cmds.sgml, src/gunzip.c: Added - gunzip command to uncompress GZIP compressed data. - 2005-04-11 Peter Korsgaard * src/flash.c (find_free): Correctly split chunks in two when not final chunk. +2005-04-07 Peter Korsgaard + + * cdl/redboot.cdl, doc/redboot_cmds.sgml, src/gunzip.c: Added + gunzip command to uncompress GZIP compressed data. + 2005-03-07 Alexander Neundorf * src/net/arp.c: use correct sizeof(rt->enet_addr) in __arp_lookup() +2005-02-17  Bart Veer   + + * 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 + + * 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 * 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 + + * Merge from flash V2 branch + + 2004-11-21 Bart Veer + + * 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 + + * src/flash.c (do_flash_init): info.end already holds the last + flash byte, no need to adjust. + + 2004-10-07 Andrew Lunn + + * src/flash.c (do_flash_init): Fix compiler warning about an + unused variable. + + 2004-10-06 Andrew Lunn + + * src/flash.c (do_flash_init): We need info independent of + CYGNUM_REDBOOT_FLASH_BASE being set or not. + + 2004-09-14 Andrew Lunn + + * 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 + + * src/flash.c (do_flash_init): cyg_flash_get_limits has been removed. + Reimplement this functionality using other calls. + + 2004-08-13 Andrew Lunn + + * 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 + + * 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 + + * src/flash.c: + * src/fconfig.c: Make use of the new flash API. + 2004-11-24 Nick Garnett * 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 + + * src/flash.c (find_free): allow for flash blocks larger than the + RedBoot MIN_IMAGE_SIZE + 2004-11-09 Ian Campbell * 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 + + * 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 * 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 + + * src/flash.c (fis_create): Made unlock/lock operations dependent + on CYGHWR_IO_FLASH_BLOCK_LOCKING. + 2004-05-31 Jani Monoses * src/main.c: * include/redboot.h: Get rid of unused workspace_size. @@ -539,10 +748,17 @@ 2004-05-21 Ian Campbell * src/main.c: Make it build without CYGSEM_REDBOOT_FLASH_ALIASES. +2004-05-07 Nick Garnett + + * 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 * 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 #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= (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= (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)); } --------------050008080307060804020105--