? packages/redboot/current/include/memory_write.h
? packages/redboot/current/src/memory_write.c

Index: packages/io/flash/current/src/flash.c
===================================================================
RCS file: /cvs/ecos/ecos/packages/io/flash/current/src/flash.c,v
retrieving revision 1.26
diff -u -r1.26 flash.c
--- packages/io/flash/current/src/flash.c	20 Jun 2004 12:46:17 -0000	1.26
+++ packages/io/flash/current/src/flash.c	14 Jan 2006 00:38:16 -0000
@@ -87,8 +87,8 @@
 {
     int err;
 
-    if (flash_info.init) return FLASH_ERR_OK;
     flash_info.pf = pf; // Do this before calling into the driver
+    if (flash_info.init) return FLASH_ERR_OK;
     if ((err = flash_hwr_init()) != FLASH_ERR_OK) {
         return err;
     }
Index: packages/redboot/current/cdl/redboot.cdl
===================================================================
RCS file: /cvs/ecos/ecos/packages/redboot/current/cdl/redboot.cdl,v
retrieving revision 1.73
diff -u -r1.73 redboot.cdl
--- packages/redboot/current/cdl/redboot.cdl	8 Sep 2005 12:14:29 -0000	1.73
+++ packages/redboot/current/cdl/redboot.cdl	14 Jan 2006 00:38:28 -0000

@@ -626,6 +600,21 @@
               to manage images in FLASH memory.  These images can be loaded
               into memory for execution or executed in place."
             compile -library=libextras.a flash.c
+            
+            cdl_option CYGSEM_REDBOOT_FLASH_LOADS {
+                display         "Allow the load-command write to Flash."
+                flavor        bool
+                default_value 1
+                description "
+                    Write images direct to Flash via the load command.
+                    This option needs a flash-driver. 
+                    If the validate RAM option is active, then load get 
+                    the new option -f to control if the validation should 
+                    be done against the RAM or to the flash-space.
+                    \"load -m xmodem\" will validate RAM and 
+                    \"load -f -m xmodem\" to Flash."
+                compile memory_write.c
+            }
     
             cdl_option CYGOPT_REDBOOT_FLASH_BYTEORDER {
                 display         "Byte order used to store info in flash."
Index: packages/redboot/current/include/redboot.h
===================================================================
RCS file: /cvs/ecos/ecos/packages/redboot/current/include/redboot.h,v
retrieving revision 1.35
diff -u -r1.35 redboot.h
--- packages/redboot/current/include/redboot.h	8 Sep 2005 12:14:31 -0000	1.35
+++ packages/redboot/current/include/redboot.h	14 Jan 2006 00:38:29 -0000
@@ -125,6 +125,10 @@
 EXTERN unsigned char *fis_zlib_common_buffer;
 #endif
 
+#ifdef CYGSEM_REDBOOT_FLASH_LOADS
+EXTERN unsigned char *memory_write_flash_buffer;
+#endif
+
 #ifdef CYGSEM_REDBOOT_PLF_STARTUP
 EXTERN void cyg_plf_redboot_startup(void);
 #endif
Index: packages/redboot/current/src/flash.c
===================================================================
RCS file: /cvs/ecos/ecos/packages/redboot/current/src/flash.c,v
retrieving revision 1.76
diff -u -r1.76 flash.c
--- packages/redboot/current/src/flash.c	8 Sep 2005 12:14:33 -0000	1.76
+++ packages/redboot/current/src/flash.c	14 Jan 2006 00:38:38 -0000
@@ -101,20 +101,30 @@
 
 static char fis_load_usage[] = 
 #ifdef CYGPRI_REDBOOT_ZLIB_FLASH
-                      "[-d] "
+                "[-d] "
 #endif
-                      "[-b <memory_load_address>] [-c] name";
+#ifdef CYGSEM_REDBOOT_FLASH_LOADS
+                "[-o] "
+#endif
+                "[-b <memory_load_address>] [-c] name";
 
 local_cmd_entry("load",
+#ifdef CYGSEM_REDBOOT_FLASH_LOADS
+                "Load image into RAM, or start it from flash",
+#else
                 "Load image from FLASH Image System [FIS] into RAM",
+#endif
                 fis_load_usage,
                 fis_load,
                 FIS_cmds
     );
 local_cmd_entry("create",
                 "Create an image",
-                "[-b <mem_base>] [-l <image_length>] [-s <data_length>]\n"
-                "      [-f <flash_addr>] [-e <entry_point>] [-r <ram_addr>] [-n] <name>",
+                "[-b <mem_base>] [-l <image_length>] [-s <data_length>]"
+#ifdef CYGSEM_REDBOOT_FLASH_LOADS
+                " [-o]"
+#endif
+                "\n      [-f <flash_addr>] [-e <entry_point>] [-r <ram_addr>] [-n] <name>",
                 fis_create,
                 FIS_cmds
     );
@@ -739,10 +749,17 @@
     bool length_set = false;
     bool img_size_set = false;
     bool no_copy = false;
+#ifdef CYGSEM_REDBOOT_FLASH_LOADS
+    bool load_addresses = false;
+#endif
     void *err_addr;
     struct fis_image_desc *img = NULL;
     bool defaults_assumed;
+#ifdef CYGSEM_REDBOOT_FLASH_LOADS
     struct option_info opts[7];
+#else
+    struct option_info opts[8];
+#endif
     bool prog_ok = true;
 
     init_opts(&opts[0], 'b', true, OPTION_ARG_TYPE_NUM, 
@@ -759,7 +776,13 @@
               (void *)&img_size, (bool *)&img_size_set, "image size [actual data]");
     init_opts(&opts[6], 'n', false, OPTION_ARG_TYPE_FLG, 
               (void *)&no_copy, (bool *)0, "don't copy from RAM to FLASH, just update directory");
+#ifdef CYGSEM_REDBOOT_FLASH_LOADS
+    init_opts(&opts[7], 'o', false, OPTION_ARG_TYPE_FLG, 
+              (void *)&load_addresses, (bool *)0, "take addresses from load tor flash");
+    if (!scan_opts(argc, argv, 2, opts, 8, (void *)&name, OPTION_ARG_TYPE_STR, "file name"))
+#else
     if (!scan_opts(argc, argv, 2, opts, 7, (void *)&name, OPTION_ARG_TYPE_STR, "file name"))
+#endif
     {
         fis_usage("invalid arguments");
         return;
@@ -811,6 +834,21 @@
         }
     }
 
+#ifdef CYGSEM_REDBOOT_FLASH_LOADS
+    if (load_addresses){
+        if (mem_addr_set || exec_addr_set || entry_addr_set || flash_addr_set || length_set || img_size_set || no_copy){
+            fis_usage("-o don't accept any other option");
+            return;
+        }
+        
+        no_copy = true;
+        flash_addr = load_address;
+        flash_addr_set = true;
+        length = load_address_end - load_address;
+        length_set = true;
+    }
+#endif
+
     if ((!no_copy && !mem_addr_set) || (no_copy && !flash_addr_set) ||
         !length_set || !name) {
         fis_usage("required parameter missing");
@@ -1034,6 +1072,9 @@
 #if defined(CYGPRI_REDBOOT_ZLIB_FLASH) ||  defined(CYGSEM_REDBOOT_FIS_CRC_CHECK)
     bool decompress = false;
 #endif
+#ifdef CYGSEM_REDBOOT_FLASH_LOADS
+    bool run_in_flash = false;
+#endif
     void *err_addr;
 
     init_opts(&opts[0], 'b', true, OPTION_ARG_TYPE_NUM, 
@@ -1046,6 +1087,11 @@
               (void *)&decompress, 0, "decompress");
     num_options++;
 #endif
+#ifdef CYGSEM_REDBOOT_FLASH_LOADS
+    init_opts(&opts[num_options], 'o', false, OPTION_ARG_TYPE_FLG, 
+              (void *)&run_in_flash, 0, "run in the flash");
+    num_options++;
+#endif
 
     CYG_ASSERT(num_options <= NUM_ELEMS(opts), "Too many options");
 
@@ -1054,10 +1100,31 @@
         fis_usage("invalid arguments");
         return;
     }
+#ifdef CYGSEM_REDBOOT_FLASH_LOADS
+    if (run_in_flash){
+        if (mem_addr_set
+#ifdef CYGPRI_REDBOOT_ZLIB_FLASH
+                || decompress
+#endif
+            ){
+                diag_printf("illegal option combination\n");
+                return;
+        }
+    }
+#endif
     if ((img = fis_lookup(name, NULL)) == (struct fis_image_desc *)0) {
         diag_printf("No image '%s' found\n", name);
         return;
     }
+#ifdef CYGSEM_REDBOOT_FLASH_LOADS
+    if (run_in_flash){
+        load_address = img->flash_base;
+        load_address_end = load_address + img->data_length;
+        entry_address = img->entry_point;
+        
+        return;
+    }
+#endif
     if (!mem_addr_set) {
         mem_addr = img->mem_base;
     }
Index: packages/redboot/current/src/load.c
===================================================================
RCS file: /cvs/ecos/ecos/packages/redboot/current/src/load.c,v
retrieving revision 1.45
diff -u -r1.45 load.c
--- packages/redboot/current/src/load.c	9 Sep 2005 13:26:03 -0000	1.45
+++ packages/redboot/current/src/load.c	14 Jan 2006 00:38:40 -0000
@@ -53,6 +53,8 @@
 //
 //==========================================================================
 
+//#define CYGSEM_REDBOOT_FLASH_LOADS
+
 #include <redboot.h>
 #include <elf.h>
 #ifdef CYGBLD_BUILD_REDBOOT_WITH_XYZMODEM
@@ -74,6 +76,10 @@
 #endif
 #include <cyg/infra/cyg_ass.h>         // assertion macros
 
+#ifdef CYGSEM_REDBOOT_FLASH_LOADS
+#include <memory_write.h>
+#endif
+
 static char usage[] = "[-r] [-v] "
 #ifdef CYGBLD_BUILD_REDBOOT_WITH_ZLIB
                       "[-d] "
@@ -85,6 +91,11 @@
 #if CYGNUM_HAL_VIRTUAL_VECTOR_NUM_CHANNELS > 1
                       "[-c <channel_number>] "
 #endif
+#ifdef CYGSEM_REDBOOT_VALIDATE_USER_RAM_LOADS
+#ifdef CYGSEM_REDBOOT_FLASH_LOADS
+                      "[-f] "
+#endif
+#endif
                       "\n        [-b <base_address>] <file_name>";
 
 // Exported CLI function
@@ -119,6 +130,14 @@
 #endif
 } getc_info;
 
+
+#ifdef CYGSEM_REDBOOT_VALIDATE_USER_RAM_LOADS
+#ifdef CYGSEM_REDBOOT_FLASH_LOADS
+bool do_flash_validate;
+#endif
+#endif
+
+
 typedef int (*getc_t)(void);
 
 //
@@ -399,18 +411,34 @@
             // Copy data into memory
             while (len-- > 0) {
 #ifdef CYGSEM_REDBOOT_VALIDATE_USER_RAM_LOADS
+#ifdef CYGSEM_REDBOOT_FLASH_LOADS
+                if ((!flash_valid_address(addr) && do_flash_validate || !valid_address(addr) && !do_flash_validate)){
+#else
                 if (!valid_address(addr)) {
+#endif
                     redboot_getc_terminate(true);
+#ifdef CYGSEM_REDBOOT_FLASH_LOADS
+                    if (do_flash_validate){
+                        diag_printf("*** Abort! ELF-data is not in flash, address: %p \n", (void*)addr);
+                    } else {
+                        diag_printf("*** Abort! ELF-data is not in RAM, address: %p \n", (void*)addr);
+                    }
+#else
                     diag_printf("*** Abort! Attempt to load ELF data to address: %p which is not in RAM\n", (void*)addr);
+#endif
                     return 0;
                 }
 #endif
                 if ((ch = (*getc)()) < 0) {
                     diag_printf(SHORT_DATA);
                     redboot_getc_terminate(true);
                     return 0;
                 }
+#ifdef CYGSEM_REDBOOT_FLASH_LOADS
+                memory_write(addr, ch);
+                addr++;
+#else
                 *addr++ = ch;
+#endif
                 offset++;
                 if ((unsigned long)(addr-addr_offset) > highest_address) {
                     highest_address = (unsigned long)(addr - addr_offset);
@@ -430,10 +458,7 @@
         entry_address = ehdr.e_entry;
     }
 
     // nak everything to stop the transfer, since redboot
     // usually doesn't read all the way to the end of the
     // elf files.
     redboot_getc_terminate(true);
     if (addr_offset) diag_printf("Address offset = %p\n", (void *)addr_offset);
     diag_printf("Entry point: %p, address range: %p-%p\n", 
                 (void*)entry_address, (void *)load_address, (void *)load_address_end);
@@ -531,11 +556,23 @@
                 lowest_address = (unsigned long)(addr - addr_offset);
             }
 #ifdef CYGSEM_REDBOOT_VALIDATE_USER_RAM_LOADS
+#ifdef CYGSEM_REDBOOT_FLASH_LOADS
+            if ((!flash_valid_address(addr) && do_flash_validate || !valid_address(addr) && !do_flash_validate)){
+#else
             if (!valid_address(addr)) {
-	      // Only if there is no need to stop the download before printing
-	      // output can we ask confirmation questions.
+#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);
+#ifdef CYGSEM_REDBOOT_FLASH_LOADS
+                if (do_flash_validate){
+                    diag_printf("*** Abort! S-Rec data is not in flash, address: %p \n", (void*)addr);
+                } else {
+                    diag_printf("*** Abort! S-Rec data is not in RAM, address: %p \n", (void*)addr);
+                }
+#else
+                diag_printf("*** Abort! Attempt to load S-record to address: %p, which is not in RAM\n",(void*)addr);
+#endif
                 return 0;
             }
 #endif
@@ -543,7 +580,12 @@
             offset += count;
             while (count-- > 0) {
                 val = _hex2(getc, 1, &sum);
+#ifdef CYGSEM_REDBOOT_FLASH_LOADS
+                memory_write(addr, val);
+                addr++;
+#else
                 *addr++ = val;
+#endif
             }
             cksum = _hex2(getc, 1, 0);
             offset += 1;
@@ -631,6 +673,11 @@
 #ifdef CYGSEM_REDBOOT_VALIDATE_USER_RAM_LOADS
     bool spillover_ok = false;
 #endif
+#ifdef CYGSEM_REDBOOT_VALIDATE_USER_RAM_LOADS
+#ifdef CYGSEM_REDBOOT_FLASH_LOADS
+    do_flash_validate = false;
+#endif
+#endif
 
 #ifdef CYGPKG_REDBOOT_NETWORKING
     memset((char *)&host, 0, sizeof(host));
@@ -667,6 +714,13 @@
               (void *)&decompress, 0, "decompress");
     num_options++;
 #endif
+#ifdef CYGSEM_REDBOOT_VALIDATE_USER_RAM_LOADS
+#ifdef CYGSEM_REDBOOT_FLASH_LOADS
+    init_opts(&opts[num_options], 'f', false, OPTION_ARG_TYPE_FLG, 
+              (void *)&do_flash_validate, 0, "flash validate");
+    num_options++;
+#endif
+#endif
 
     CYG_ASSERT(num_options <= NUM_ELEMS(opts), "Too many options");
     
@@ -689,7 +743,7 @@
         }
     }
     if (port_set) 
-	    host.sin_port = port;
+        host.sin_port = port;
 #endif
     if (chan >= CYGNUM_HAL_VIRTUAL_VECTOR_NUM_CHANNELS) {
         diag_printf("Invalid I/O channel: %d\n", chan);
@@ -734,10 +788,10 @@
 #endif
 #ifdef CYGPKG_REDBOOT_FILEIO
         // Make file I/O default if mounted
-	if (fileio_mounted) {
-	    which = "file";
-	    io = &fileio_io;
-	}
+    if (fileio_mounted) {
+        which = "file";
+        io = &fileio_io;
+    }
 #endif
         if (!io) {
 #ifdef CYGBLD_BUILD_REDBOOT_WITH_XYZMODEM
@@ -752,8 +806,13 @@
         diag_printf("Using default protocol (%s)\n", which);
     }
 #ifdef CYGSEM_REDBOOT_VALIDATE_USER_RAM_LOADS
+#ifdef CYGSEM_REDBOOT_FLASH_LOADS
+    if ((!flash_valid_address((cyg_uint8 *) base) && do_flash_validate || !valid_address((cyg_uint8 *) base) && !do_flash_validate) && base_addr_set){
+        if (!verify_action("Specified address (%p) is not believed to be right", (void*)base))
+#else
     if (base_addr_set && !valid_address((unsigned char *)base)) {
         if (!verify_action("Specified address (%p) is not believed to be in RAM", (void*)base))
+#endif
             return;
         spillover_ok = true;
     }
@@ -777,20 +836,44 @@
     if (raw) {
         unsigned char *mp = (unsigned char *)base;
         err = 0;
+#ifdef CYGSEM_REDBOOT_FLASH_LOADS
+        memory_write_init();
+#endif
         while ((res = redboot_getc()) >= 0) {
 #ifdef CYGSEM_REDBOOT_VALIDATE_USER_RAM_LOADS
+#ifdef CYGSEM_REDBOOT_FLASH_LOADS
+            if ((!flash_valid_address(mp) && do_flash_validate || !valid_address(mp) && !do_flash_validate) && !spillover_ok){
+#else
             if (!valid_address(mp) && !spillover_ok) {
+#endif
                 // Only if there is no need to stop the download
                 // before printing output can we ask confirmation
                 // questions.
                 redboot_getc_terminate(true);
+#ifdef CYGSEM_REDBOOT_FLASH_LOADS
+                if (do_flash_validate){
+                    diag_printf("*** Abort! RAW data out of flash at %p\n",(void*)mp);
+                } else {
+                    diag_printf("*** Abort! RAW data out of RAM at %p\n",(void*)mp);
+                }
+#else
                 diag_printf("*** Abort! RAW data spills over limit of user RAM at %p\n",(void*)mp);
+#endif
                 err = -1;
                 break;
             }
 #endif
+
+#ifdef CYGSEM_REDBOOT_FLASH_LOADS
+            memory_write(mp, res);
+            mp++;
+#else
             *mp++ = res;
+#endif
         }
+#ifdef CYGSEM_REDBOOT_FLASH_LOADS
+        memory_write_fini();
+#endif
         end = (unsigned long) mp;
 
         // Save load base/top
@@ -815,10 +898,22 @@
             redboot_getc_rewind();  // Restore header to stream
             // Treat data as some sort of executable image
             if (strncmp(&type[1], "ELF", 3) == 0) {
+#ifdef CYGSEM_REDBOOT_FLASH_LOADS
+                memory_write_init();
+#endif
                 end = load_elf_image(redboot_getc, base);
+#ifdef CYGSEM_REDBOOT_FLASH_LOADS
+                memory_write_fini();
+#endif
             } else if ((type[0] == 'S') &&
                        ((type[1] >= '0') && (type[1] <= '9'))) {
-		end = load_srec_image(redboot_getc, base);
+#ifdef CYGSEM_REDBOOT_FLASH_LOADS
+                memory_write_init();
+#endif
+                end = load_srec_image(redboot_getc, base);
+#ifdef CYGSEM_REDBOOT_FLASH_LOADS
+                memory_write_fini();
+#endif
             } else {
                 redboot_getc_terminate(true);
                 diag_printf("Unrecognized image type: 0x%lx\n", *(unsigned long *)type);
Index: packages/redboot/current/src/main.c
===================================================================
RCS file: /cvs/ecos/ecos/packages/redboot/current/src/main.c,v
retrieving revision 1.63
diff -u -r1.63 main.c
--- packages/redboot/current/src/main.c	7 Jun 2005 18:55:52 -0000	1.63
+++ packages/redboot/current/src/main.c	14 Jan 2006 00:38:42 -0000
@@ -65,6 +65,10 @@
 #include <cyg/io/eth/eth_drv.h>            // Logical driver interfaces
 #endif
 
+#ifdef CYGSEM_REDBOOT_FLASH_LOADS
+#include <memory_write.h>   //For flash_get_block_info();
+#endif
+
 #include <cyg/hal/hal_tables.h>
 #include <cyg/infra/cyg_ass.h>         // assertion macros
 #include <cyg/infra/cyg_type.h>
@@ -308,6 +312,11 @@
     workspace_end -= CYGNUM_REDBOOT_FIS_ZLIB_COMMON_BUFFER_SIZE;
 #endif
 
+#ifdef CYGSEM_REDBOOT_FLASH_LOADS
+    memory_write_flash_buffer = 
+    workspace_end -= memory_write_init(); /* Returns flash-segment size */
+#endif
+
 #ifdef CYGFUN_REDBOOT_BOOT_SCRIPT
     script_timeout = CYGNUM_REDBOOT_BOOT_SCRIPT_DEFAULT_TIMEOUT;
 #endif
@@ -362,6 +371,7 @@
     }
 #endif
 
+    CYG_ASSERT(workspace_start < workspace_end, "ERROR: negative workspace size!");
     while (true) {
         if (prompt) {
             diag_printf("RedBoot> ");
