diff packages/redboot/current/src/load.c @ 156:b939e9cada46

Merge from eCos master repository on 2001-03-29-21:44:39-BST
author jlarmour
date Fri, 06 Apr 2001 17:20:13 +0000
parents e2d866e32dac
children b65ec671dd4c
line wrap: on
line diff
--- a/packages/redboot/current/src/load.c
+++ b/packages/redboot/current/src/load.c
@@ -46,10 +46,19 @@
 #include <redboot.h>
 #include <xyzModem.h>
 
+#ifdef CYGPKG_COMPRESS_ZLIB
+static unsigned char _buffer[CYGNUM_REDBOOT_LOAD_ZLIB_BUFFER];
+static _pipe_t load_pipe;
+#endif
+
 // Buffer used by redboot_getc
 getc_info_t getc_info;
 
-static char usage[] = "[-r] [-v] [-h <host>] [-m {TFTP | xyzMODEM}]\n"
+static char usage[] = "[-r] [-v] "
+#ifdef CYGPKG_COMPRESS_ZLIB
+                      "[-d] "
+#endif
+                      "[-h <host>] [-m {TFTP | xyzMODEM}]\n"
                       "        [-b <base_address>] <file_name>";
 
 // Exported CLI function
@@ -59,10 +68,11 @@ RedBoot_cmd("load",
             do_load 
     );
 
-static void
+static unsigned long
 load_elf_image(int (*getc)(void))
 {
     printf("ELF images not supported\n");
+    return 0;
 }
 
 //
@@ -102,7 +112,7 @@ static long
 // data which has only one section, e.g. a ROM image.
 //
 #define MAX_LINE 80
-static void
+static unsigned long
 load_srec_image(int (*getc)(void), unsigned long base)
 {
     char line[MAX_LINE];
@@ -122,14 +132,14 @@ load_srec_image(int (*getc)(void), unsig
         if (c != 'S') {
             printf("Invalid S-record at offset %p, input: %c\n", 
                    (void *)offset, c);
-            return;
+            return 0;
         }
         type = (*getc)();
         offset += 2;
         sum = 0;
         if ((count = _hex2(getc, 1, &sum)) < 0) {
             printf("Bad S-record count at offset %p\n", (void *)offset);
-            return;
+            return 0;
         }
         offset += 1;
         switch (type) {
@@ -153,9 +163,9 @@ load_srec_image(int (*getc)(void), unsig
             if ((unsigned long)(addr-addr_offset) < lowest_address) {
                 lowest_address = (unsigned long)(addr - addr_offset);
             }
-            if ((addr < ram_start) || (addr > ram_end)) {
+            if ((addr < user_ram_start) || (addr > user_ram_end)) {
                 printf("Attempt to load S-record data to address: %p [not in RAM]\n", (void*)addr);
-                return;
+                return 0;
             }
             count -= ((type-'1'+2)+1);
             offset += count;
@@ -170,7 +180,7 @@ load_srec_image(int (*getc)(void), unsig
             if (cksum != sum) {
                 printf("*** Warning! Checksum failure - Addr: %lx, %02lX <> %02lX\n", 
                        (unsigned long)base_addr, sum, cksum);
-                return;
+                return 0;
             }
             if ((unsigned long)(addr-addr_offset) > highest_address) {
                 highest_address = (unsigned long)(addr - addr_offset);
@@ -185,14 +195,15 @@ load_srec_image(int (*getc)(void), unsig
             printf("Entry point: %p, address range: %p-%p\n", 
                    (void*)entry_address, (void *)lowest_address, (void *)highest_address);
             while ((c = (*getc)()) > 0) ;  // Swallow rest of data
-            return;
+            return highest_address;
         default:
             printf("Invalid S-record at offset 0x%lx, type: %x\n", 
                    (unsigned long)offset, type);
-            return;
+            return 0;
         }
         while ((c = (*getc)()) != '\n') offset++;
     }
+    return 0;
 }
 
 
@@ -261,10 +272,14 @@ do_load(int argc, char *argv[])
     bool hostname_set;
     char *hostname;
 #endif
+#ifdef CYGPKG_COMPRESS_ZLIB
+    bool decompress;
+#endif
     unsigned long base = 0;
+    unsigned long end = 0;
     char type[4];
     char *filename = 0;
-    struct option_info opts[5];
+    struct option_info opts[6];
 
 #ifdef CYGPKG_REDBOOT_NETWORKING
     memset((char *)&host, 0, sizeof(host));
@@ -291,8 +306,14 @@ do_load(int argc, char *argv[])
 #ifdef CYGPKG_REDBOOT_NETWORKING
     init_opts(&opts[4], 'h', true, OPTION_ARG_TYPE_STR, 
               (void **)&hostname, (bool *)&hostname_set, "host name (IP address)");
-    num_options = 5;
+    num_options++;
 #endif
+#ifdef CYGPKG_COMPRESS_ZLIB
+    init_opts(&opts[5], 'd', false, OPTION_ARG_TYPE_FLG, 
+              (void **)&decompress, 0, "decompress");
+    num_options++;
+#endif
+
     if (!scan_opts(argc, argv, 1, opts, num_options, (void *)&filename, OPTION_ARG_TYPE_STR, "file name"))
     {
         return;
@@ -340,8 +361,8 @@ do_load(int argc, char *argv[])
         return;
     }
     if (base_addr_set &&
-        ((base < (unsigned long)ram_start) ||
-         (base > (unsigned long)ram_end))) {
+        ((base < (unsigned long)user_ram_start) ||
+         (base > (unsigned long)user_ram_end))) {
         printf("Specified address (%p) is not in RAM.\n", (void*)base);
         return;
     }
@@ -378,19 +399,55 @@ do_load(int argc, char *argv[])
             if (!base_addr_set) {
                 printf("Raw load requires a memory address\n");
             } else {
-                unsigned char *mp = (unsigned char *)base;
-                while ((res = redboot_getc()) >= 0) {
-                    *mp++ = res;
+#ifdef CYGPKG_COMPRESS_ZLIB
+                if (decompress) {
+                    _pipe_t* p = &load_pipe;
+                    p->out_buf = (unsigned char*) base;
+                    p->out_size = 0;
+                    p->in_buf = _buffer;
+                
+                    err = (*_dc_init)(p);
+
+                    while (0 == err) {
+                        p->in_avail = 0;
+                        for (i = 0; i < CYGNUM_REDBOOT_LOAD_ZLIB_BUFFER; i++) {
+                            res = redboot_getc();
+                            if (res < 0) break;
+                            p->in_buf[p->in_avail++] = res;
+                        }
+                        if (0 == p->in_avail) break;
+
+                        err = (*_dc_inflate)(p);
+                    }
+
+                    // Free used resources, do final translation of
+                    // error value.
+                    err = (*_dc_close)(p, err);
+
+                    if (0 != err && p->msg)
+                        printf("zlib: %s\n", p->msg);
+
+                    end = (unsigned long) base + p->out_size;
+                } else // dangling block
+#endif
+                {
+                    unsigned char *mp = (unsigned char *)base;
+                    while ((res = redboot_getc()) >= 0) {
+                        *mp++ = res;
+                    }
+                    err = 0;
+                    end = (unsigned long) mp;
                 }
-                printf("Raw file loaded %p-%p\n", (void *)base, (void *)mp);
+                if (0 == err)
+                    printf("Raw file loaded %p-%p\n", (void *)base, (void *)end);
             }
         } else {
             // Treat data as some sort of executable image
             if (strncmp(&type[1], "ELF", 3) == 0) {
-                load_elf_image(redboot_getc);
+                end = load_elf_image(redboot_getc);
             } else if ((type[0] == 'S') &&
                        ((type[1] >= '0') && (type[1] <= '9'))) {
-                load_srec_image(redboot_getc, base);
+                end = load_srec_image(redboot_getc, base);
             } else {
                 printf("Unrecognized image type: %lx\n", *(unsigned long *)type);
             }