Mercurial > ecos
changeset 2144:36bfd6474600
* src/xyzModem.c (xyzModem_stream_open): Fix compiler warnings.
* src/flash_load.c (NEW): Implements access to flash
* src/load.c: Allow load command to load directly into flash
* cdl/redboot.c (CYGBLD_REDBOOT_LOAD_INTO_FLASH) Control new
feature, disabled by default.
* cdl/main.c (cyg_start): Assert check to see if we have
overflowed the workspace.
* doc/redboot_cmds.sgml: Document new flag.
| author | asl |
|---|---|
| date | Sat, 25 Feb 2006 14:21:12 +0000 |
| parents | 247a73554cd0 |
| children | accf1e9370f5 |
| files | packages/redboot/current/ChangeLog packages/redboot/current/cdl/redboot.cdl packages/redboot/current/doc/redboot_cmds.sgml packages/redboot/current/src/flash_load.c packages/redboot/current/src/flash_load.h packages/redboot/current/src/load.c packages/redboot/current/src/main.c packages/redboot/current/src/xyzModem.c |
| diffstat | 8 files changed, 370 insertions(+), 17 deletions(-) [+] |
line wrap: on
line diff
--- a/packages/redboot/current/ChangeLog +++ b/packages/redboot/current/ChangeLog @@ -1,3 +1,15 @@ +2006-02-25 Oliver Munz <munz@speag.ch> + Andrew Lunn <andrew.lunn@ascom.ch> + + * src/xyzModem.c (xyzModem_stream_open): Fix compiler warnings. + * src/flash_load.c (NEW): Implements access to flash + * src/load.c: Allow load command to load directly into flash + * cdl/redboot.c (CYGBLD_REDBOOT_LOAD_INTO_FLASH) Control new + feature, disabled by default. + * cdl/main.c (cyg_start): Assert check to see if we have + overflowed the workspace. + * doc/redboot_cmds.sgml: Document new flag. + 2006-02-17 Andrew Lunn <andrew.lunn@ascom.ch> * src/flash.c (fis_lock & fis_unlock): Allow compilation without
--- a/packages/redboot/current/cdl/redboot.cdl +++ b/packages/redboot/current/cdl/redboot.cdl @@ -208,7 +208,6 @@ cdl_package CYGPKG_REDBOOT { than five bytes are available initially so this is the minimum." } - cdl_option CYGPRI_REDBOOT_ZLIB_FLASH { display "Support compression of Flash images" active_if CYGPKG_REDBOOT_FLASH @@ -238,6 +237,14 @@ cdl_package CYGPKG_REDBOOT { compile -library=libextras.a xyzModem.c } + cdl_option CYGBLD_REDBOOT_LOAD_INTO_FLASH { + display "Allow the load-command write into Flash." + default_value 0 + active_if CYGPKG_REDBOOT_FLASH + compile flash_load.c + description " + Write images direct to Flash via the load command." + } cdl_option CYGBLD_BUILD_REDBOOT_WITH_CKSUM { display "Include POSIX checksum command" doc ref/cksum-command.html
--- a/packages/redboot/current/doc/redboot_cmds.sgml +++ b/packages/redboot/current/doc/redboot_cmds.sgml @@ -875,7 +875,7 @@ Set/change IP addresses ip_address [-l <local_ip_address>[/<mask_length>]] [-h <server_address>] Load a file load [-r] [-v] [-d] [-h <host>] [-m {TFTP | HTTP | {x|y}MODEM -c <channel_number>}] - [-b <base_address>] <file_name> + [-f <flash_address>] [-b <base_address>] <file_name> Compare two blocks of memory mcmp -s <location> -d <location> -l <length> [-1|-2|-4] Fill a block of memory with a pattern @@ -1295,6 +1295,7 @@ IP: 192.168.1.32, Default server: 192.16 </group> </arg> <arg>-h <replaceable> server_IP_address</replaceable></arg> + <arg>-f <replaceable> location</replaceable></arg> <arg>-b <replaceable> location</replaceable></arg> <arg>-c <replaceable> channel</replaceable></arg> <arg><replaceable>file_name</replaceable></arg> @@ -1335,7 +1336,7 @@ serial download method since it would in <row> <entry>-r</entry> <entry>Boolean</entry> - <entry>Raw (or binary) data</entry> + <entry>Raw (or binary) data. -b or -f must be used</entry> <entry><emphasis>formatted (S-records, ELF image, etc)</emphasis></entry> </row> <row> @@ -1382,6 +1383,13 @@ an implied load address which this optio <entry><emphasis>Depends on data format</emphasis></entry> </row> <row> + <entry>-f <replaceable>location</replaceable></entry> + <entry>Number</entry> + <entry>Address in flash to load the data. Formatted data streams will have +an implied load address which this option may override.</entry> + <entry><emphasis>Depends on data format</emphasis></entry> + </row> + <row> <entry>-c <replaceable>channel</replaceable></entry> <entry>Number</entry> <entry>Specify which I/O channel to
new file mode 100644 --- /dev/null +++ b/packages/redboot/current/src/flash_load.c @@ -0,0 +1,183 @@ +//========================================================================== +// +// flash_load.c +// +// RedBoot file/image loader into flash +// +//========================================================================== +//####ECOSGPLCOPYRIGHTBEGIN#### +// ------------------------------------------- +// This file is part of eCos, the Embedded Configurable Operating System. +// Copyright (C) 2006 eCosCentric LTD +// +// eCos is free software; you can redistribute it and/or modify it under +// the terms of the GNU General Public License as published by the Free +// Software Foundation; either version 2 or (at your option) any later version. +// +// eCos is distributed in the hope that it will be useful, but WITHOUT ANY +// WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +// for more details. +// +// You should have received a copy of the GNU General Public License along +// with eCos; if not, write to the Free Software Foundation, Inc., +// 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. +// +// As a special exception, if other files instantiate templates or use macros +// or inline functions from this file, or you compile this file and link it +// with other works to produce a work based on this file, this file does not +// by itself cause the resulting work to be covered by the GNU General Public +// License. However the source code for this file must still be made available +// in accordance with section (3) of the GNU General Public License. +// +// This exception does not invalidate any other reasons why a work based on +// this file might be covered by the GNU General Public License. +// +// Alternative licenses for eCos may be arranged by contacting Red Hat, Inc. +// at http://sources.redhat.com/ecos/ecos-license/ +// ------------------------------------------- +//####ECOSGPLCOPYRIGHTEND#### +//========================================================================== +//#####DESCRIPTIONBEGIN#### +// +// Author(s): Oliver Munz +// Contributors: om, asl +// Date: 2006-02-21 +// Purpose: +// Description: +// +// This code is part of RedBoot (tm). +// +//####DESCRIPTIONEND#### +// +//========================================================================== + +#include <redboot.h> +#include <flash_load.h> + +#include <cyg/io/flash.h> +#include <cyg/infra/cyg_ass.h> + +static int flash_block_size; + +static cyg_uint8 * current_flash_page; + +/* Allocation of the flash-sector size RAM-buffer is done */ +static bool init_done = false; + +/* We have initialized the current page ready for writing */ +static bool flash_page_init = false; + +static cyg_uint8 *flash_buffer; + +// If the io flash code outputs when erasing/writing it will upset the +// download over the communications channel. So we install a dummy +// print function. +static int dummy_printf(const char *fmt, ...){ + return 0; +} + +// Calculate the address of the first byte in a flash block +static cyg_uint8 * flash_block_begin(cyg_uint32 addr) +{ + return (cyg_uint8 *) + ((addr / flash_block_size) * flash_block_size); +} + +// Initialize the loading process +void flash_load_start(void) +{ + flash_init(dummy_printf); + + init_done = true; + flash_page_init = false; +} + +// Write a byte into flash. We maintain a copy in RAM of the FLASH +// page we are currently "writing" into. This copy is loaded with the +// current contents of the FLASH page when the first byte is "written" +// to the page. The "writes" are then made into the RAM copy. We only +// write to FLASH when there is a "write" outside of the current page, +// or the flash_load_finish function is called. +void flash_load_write(cyg_uint8 *flash_addr, cyg_uint8 value) +{ + + cyg_uint32 retcode = FLASH_ERR_OK; + void * err_addr; + cyg_uint32 addr = (cyg_uint32)flash_addr; + cyg_uint32 offset; + + if (!flash_page_init) { + /* First Byte for the current flash block. Read the current contents */ + current_flash_page = flash_block_begin(addr); + flash_read(flash_buffer, current_flash_page, flash_block_size, &err_addr); + flash_page_init = true; + } + if (flash_block_begin(addr) != current_flash_page) { + /* We have moved into the next flash page. Write the current + page so we can move on */ + retcode = flash_erase(current_flash_page, flash_block_size, &err_addr); + if (retcode != FLASH_ERR_OK){ /* Flash ERROR */ + diag_printf("Error erase at %p: %s\n", err_addr, flash_errmsg(retcode)); + return; + } + + retcode = flash_program(current_flash_page, flash_buffer, + flash_block_size, &err_addr); + if (retcode != FLASH_ERR_OK){ + diag_printf("Error writing at %p: %s\n", + err_addr, flash_errmsg(retcode)); + return; + } + current_flash_page = flash_block_begin(addr); + flash_read(flash_buffer, current_flash_page, flash_block_size, &err_addr); + } + + offset = flash_addr - current_flash_page; + CYG_ASSERT(offset < flash_block_size, "offset not inside flash block"); + + flash_buffer[offset] = value; +} + +// Program the current page into flash. +void flash_load_finish(void) +{ + cyg_uint32 retcode = FLASH_ERR_OK; + void * err_addr; + + if (init_done && flash_page_init) { + flash_page_init = false; + + retcode = flash_erase(current_flash_page, flash_block_size, &err_addr); + if (retcode != FLASH_ERR_OK){ + diag_printf("Error erase at %p: %s\n", err_addr, flash_errmsg(retcode)); + } else { + retcode = flash_program(current_flash_page, flash_buffer, + flash_block_size, &err_addr); + if (retcode != FLASH_ERR_OK){ + diag_printf("Error writing at %p: %s\n", + err_addr, flash_errmsg(retcode)); + } + } + } + flash_init(diag_printf); +} + +// This is called during redboot start up. We allocate a buffer the +// size of the flash page. +void +flash_load_init(void) +{ + int flash_blocks; + + flash_get_block_info(&flash_block_size, &flash_blocks); + workspace_end -= flash_block_size; + + flash_buffer = workspace_end; +} + +// Register this initialization function in the table +RedBoot_init(flash_load_init, RedBoot_INIT_LAST); + + +
new file mode 100644 --- /dev/null +++ b/packages/redboot/current/src/flash_load.h @@ -0,0 +1,67 @@ +//========================================================================== +// +// flash_load.h +// +// Interfaces to byte writing into FLASH during load +// +//========================================================================== +//####ECOSGPLCOPYRIGHTBEGIN#### +// ------------------------------------------- +// This file is part of eCos, the Embedded Configurable Operating System. +// Copyright (C) 2006 eCosCentric Ltd +// Copyright (C) 2006 Andrew Lunn <andrew.lunn@ascom.ch> +// +// 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): Oliver Munz +// Contributors: om, asl +// Date: 2005-02-21 +// Purpose: +// Description: +// +// This code is part of RedBoot (tm). +// +//####DESCRIPTIONEND#### +// +//========================================================================== + +#ifndef FLASH_LOAD_H +#define FLASH_LOAd_H + +// Prepare a write to flash. +void flash_load_start(void); + +// Finish a write to flash +void flash_load_finish(void); + +// Write a single byte. This will be buffered until either a full page +// is available or flash_write_finish is called. +void flash_load_write(cyg_uint8 *addr, cyg_uint8 value); + +#endif // FLASH_LOAD_H +
--- a/packages/redboot/current/src/load.c +++ b/packages/redboot/current/src/load.c @@ -73,6 +73,10 @@ #endif #endif #include <cyg/infra/cyg_ass.h> // assertion macros +#ifdef CYGBLD_REDBOOT_LOAD_INTO_FLASH +#include <cyg/io/flash.h> +#include "flash_load.h" +#endif static char usage[] = "[-r] [-v] " #ifdef CYGBLD_BUILD_REDBOOT_WITH_ZLIB @@ -85,6 +89,9 @@ static char usage[] = "[-r] [-v] " #if CYGNUM_HAL_VIRTUAL_VECTOR_NUM_CHANNELS > 1 "[-c <channel_number>] " #endif +#ifdef CYGBLD_REDBOOT_LOAD_INTO_FLASH + "[-f <flash_address>] " +#endif "\n [-b <base_address>] <file_name>"; // Exported CLI function @@ -399,9 +406,13 @@ load_elf_image(getc_t getc, unsigned lon // Copy data into memory while (len-- > 0) { #ifdef CYGSEM_REDBOOT_VALIDATE_USER_RAM_LOADS - if (!valid_address(addr)) { + if (!(valid_address(addr) +#ifdef CYGBLD_REDBOOT_LOAD_INTO_FLASH + || (flash_verify_addr(addr) == FLASH_ERR_OK) +#endif + )) { redboot_getc_terminate(true); - diag_printf("*** Abort! Attempt to load ELF data to address: %p which is not in RAM\n", (void*)addr); + diag_printf("*** Abort! Attempt to load ELF data to address: %p which is not valid\n", (void*)addr); return 0; } #endif @@ -410,7 +421,15 @@ load_elf_image(getc_t getc, unsigned lon redboot_getc_terminate(true); return 0; } - *addr++ = ch; + if (valid_address(addr)) { + *addr++ = ch; + } +#ifdef CYGBLD_REDBOOT_LOAD_INTO_FLASH + else { + flash_load_write(addr, ch); + addr++; + } +#endif offset++; if ((unsigned long)(addr-addr_offset) > highest_address) { highest_address = (unsigned long)(addr - addr_offset); @@ -531,11 +550,15 @@ load_srec_image(getc_t getc, unsigned lo lowest_address = (unsigned long)(addr - addr_offset); } #ifdef CYGSEM_REDBOOT_VALIDATE_USER_RAM_LOADS - if (!valid_address(addr)) { + if (!(valid_address(addr) +#ifdef CYGBLD_REDBOOT_LOAD_INTO_FLASH + || (flash_verify_addr(addr) == FLASH_ERR_OK) +#endif + )) { // Only if there is no need to stop the download before printing // output can we ask confirmation questions. redboot_getc_terminate(true); - diag_printf("*** Abort! Attempt to load S-record to address: %p, which is not in RAM\n",(void*)addr); + diag_printf("*** Abort! Attempt to load S-record to address: %p, which is not valid\n",(void*)addr); return 0; } #endif @@ -543,7 +566,15 @@ load_srec_image(getc_t getc, unsigned lo offset += count; while (count-- > 0) { val = _hex2(getc, 1, &sum); - *addr++ = val; + if (valid_address(addr)) { + *addr++ = val; + } +#ifdef CYGBLD_REDBOOT_LOAD_INTO_FLASH + else { + flash_load_write(addr, val); + addr++; + } +#endif } cksum = _hex2(getc, 1, 0); offset += 1; @@ -599,6 +630,9 @@ load_srec_image(getc_t getc, unsigned lo #ifdef CYGBLD_BUILD_REDBOOT_WITH_ZLIB // -d - Decompress data [packed via 'zlib'] #endif +#ifdef CYGBLD_REDBOOT_LOAD_INTO_FLASH +// -f - specify a flash address +#endif // void do_load(int argc, char *argv[]) @@ -615,6 +649,9 @@ do_load(int argc, char *argv[]) // but will be cast to short char *hostname; #endif +#ifdef CYGBLD_REDBOOT_LOAD_INTO_FLASH + bool flash_addr_set = false; +#endif bool decompress = false; int chan = -1; #if CYGNUM_HAL_VIRTUAL_VECTOR_NUM_CHANNELS > 1 @@ -624,7 +661,7 @@ do_load(int argc, char *argv[]) unsigned long end = 0; char type[4]; char *filename = 0; - struct option_info opts[8]; + struct option_info opts[9]; connection_info_t info; getc_io_funcs_t *io = NULL; struct load_io_entry *io_tab; @@ -667,7 +704,11 @@ do_load(int argc, char *argv[]) (void *)&decompress, 0, "decompress"); num_options++; #endif - +#ifdef CYGBLD_REDBOOT_LOAD_INTO_FLASH + init_opts(&opts[num_options], 'f', true, OPTION_ARG_TYPE_NUM, + (void *)&base, (bool *)&flash_addr_set, "flash address"); + num_options++; +#endif CYG_ASSERT(num_options <= NUM_ELEMS(opts), "Too many options"); if (!scan_opts(argc, argv, 1, opts, num_options, @@ -721,7 +762,7 @@ do_load(int argc, char *argv[]) return; } } else { - char *which; + char *which = ""; io_tab = (struct load_io_entry *)NULL; // Default #ifdef CYGPKG_REDBOOT_NETWORKING #ifdef CYGSEM_REDBOOT_NET_TFTP_DOWNLOAD @@ -752,13 +793,24 @@ do_load(int argc, char *argv[]) diag_printf("Using default protocol (%s)\n", which); } #ifdef CYGSEM_REDBOOT_VALIDATE_USER_RAM_LOADS +#ifdef CYGBLD_REDBOOT_LOAD_INTO_FLASH + if (flash_addr_set && flash_verify_addr((unsigned char *)base)) { + if (!verify_action("Specified address (%p) is not believed to be in FLASH", (void*)base)) + return; + spillover_ok = true; + } +#endif if (base_addr_set && !valid_address((unsigned char *)base)) { if (!verify_action("Specified address (%p) is not believed to be in RAM", (void*)base)) return; spillover_ok = true; } #endif - if (raw && !base_addr_set) { + if (raw && !(base_addr_set +#ifdef CYGBLD_REDBOOT_LOAD_INTO_FLASH + || flash_addr_set +#endif + )) { diag_printf("Raw load requires a memory address\n"); return; } @@ -772,14 +824,27 @@ do_load(int argc, char *argv[]) if (res < 0) { return; } - +#ifdef CYGBLD_REDBOOT_LOAD_INTO_FLASH + flash_load_start(); +#endif // Stream open, process the data if (raw) { unsigned char *mp = (unsigned char *)base; err = 0; while ((res = redboot_getc()) >= 0) { #ifdef CYGSEM_REDBOOT_VALIDATE_USER_RAM_LOADS - if (!valid_address(mp) && !spillover_ok) { +#ifdef CYGBLD_REDBOOT_LOAD_INTO_FLASH + if (flash_addr_set && flash_verify_addr(mp) && !spillover_ok) { + // Only if there is no need to stop the download + // before printing output can we ask confirmation + // questions. + redboot_getc_terminate(true); + diag_printf("*** Abort! RAW data spills over limit of FLASH at %p\n",(void*)mp); + err = -1; + break; + } +#endif + if (base_addr_set && !valid_address(mp) && !spillover_ok) { // Only if there is no need to stop the download // before printing output can we ask confirmation // questions. @@ -789,6 +854,13 @@ do_load(int argc, char *argv[]) break; } #endif +#ifdef CYGBLD_REDBOOT_LOAD_INTO_FLASH + if (flash_addr_set) { + flash_load_write(mp, res); + mp++; + res++; + } else +#endif *mp++ = res; } end = (unsigned long) mp; @@ -825,6 +897,9 @@ do_load(int argc, char *argv[]) } } } +#ifdef CYGBLD_REDBOOT_LOAD_INTO_FLASH + flash_load_finish(); +#endif redboot_getc_close(); // Clean up return;
--- a/packages/redboot/current/src/main.c +++ b/packages/redboot/current/src/main.c @@ -361,7 +361,8 @@ cyg_start(void) } } #endif - + CYG_ASSERT(workspace_start < workspace_end, + "negative workspace size"); while (true) { if (prompt) { diag_printf("RedBoot> ");
--- a/packages/redboot/current/src/xyzModem.c +++ b/packages/redboot/current/src/xyzModem.c @@ -319,7 +319,7 @@ xyzModem_get_hdr(void) int xyzModem_stream_open(connection_info_t *info, int *err) { - int console_chan, stat; + int console_chan, stat=0; int retries = xyzModem_MAX_RETRIES; int crc_retries = xyzModem_MAX_RETRIES_WITH_CRC;
