Mercurial > ecos
comparison 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 |
comparison
equal
deleted
inserted
replaced
| 155:70a4cc6d69d2 | 156:b939e9cada46 |
|---|---|
| 44 //========================================================================== | 44 //========================================================================== |
| 45 | 45 |
| 46 #include <redboot.h> | 46 #include <redboot.h> |
| 47 #include <xyzModem.h> | 47 #include <xyzModem.h> |
| 48 | 48 |
| 49 #ifdef CYGPKG_COMPRESS_ZLIB | |
| 50 static unsigned char _buffer[CYGNUM_REDBOOT_LOAD_ZLIB_BUFFER]; | |
| 51 static _pipe_t load_pipe; | |
| 52 #endif | |
| 53 | |
| 49 // Buffer used by redboot_getc | 54 // Buffer used by redboot_getc |
| 50 getc_info_t getc_info; | 55 getc_info_t getc_info; |
| 51 | 56 |
| 52 static char usage[] = "[-r] [-v] [-h <host>] [-m {TFTP | xyzMODEM}]\n" | 57 static char usage[] = "[-r] [-v] " |
| 58 #ifdef CYGPKG_COMPRESS_ZLIB | |
| 59 "[-d] " | |
| 60 #endif | |
| 61 "[-h <host>] [-m {TFTP | xyzMODEM}]\n" | |
| 53 " [-b <base_address>] <file_name>"; | 62 " [-b <base_address>] <file_name>"; |
| 54 | 63 |
| 55 // Exported CLI function | 64 // Exported CLI function |
| 56 RedBoot_cmd("load", | 65 RedBoot_cmd("load", |
| 57 "Load a file", | 66 "Load a file", |
| 58 usage, | 67 usage, |
| 59 do_load | 68 do_load |
| 60 ); | 69 ); |
| 61 | 70 |
| 62 static void | 71 static unsigned long |
| 63 load_elf_image(int (*getc)(void)) | 72 load_elf_image(int (*getc)(void)) |
| 64 { | 73 { |
| 65 printf("ELF images not supported\n"); | 74 printf("ELF images not supported\n"); |
| 75 return 0; | |
| 66 } | 76 } |
| 67 | 77 |
| 68 // | 78 // |
| 69 // Scan a string of hex bytes and update the checksum | 79 // Scan a string of hex bytes and update the checksum |
| 70 // | 80 // |
| 100 // pieces of data, they will end up relocated in the same fashion. | 110 // pieces of data, they will end up relocated in the same fashion. |
| 101 // Because of this, "base" probably only makes sense for a set of | 111 // Because of this, "base" probably only makes sense for a set of |
| 102 // data which has only one section, e.g. a ROM image. | 112 // data which has only one section, e.g. a ROM image. |
| 103 // | 113 // |
| 104 #define MAX_LINE 80 | 114 #define MAX_LINE 80 |
| 105 static void | 115 static unsigned long |
| 106 load_srec_image(int (*getc)(void), unsigned long base) | 116 load_srec_image(int (*getc)(void), unsigned long base) |
| 107 { | 117 { |
| 108 char line[MAX_LINE]; | 118 char line[MAX_LINE]; |
| 109 char *lp; | 119 char *lp; |
| 110 int c, len; | 120 int c, len; |
| 120 lp = line; len = 0; | 130 lp = line; len = 0; |
| 121 // Start of line | 131 // Start of line |
| 122 if (c != 'S') { | 132 if (c != 'S') { |
| 123 printf("Invalid S-record at offset %p, input: %c\n", | 133 printf("Invalid S-record at offset %p, input: %c\n", |
| 124 (void *)offset, c); | 134 (void *)offset, c); |
| 125 return; | 135 return 0; |
| 126 } | 136 } |
| 127 type = (*getc)(); | 137 type = (*getc)(); |
| 128 offset += 2; | 138 offset += 2; |
| 129 sum = 0; | 139 sum = 0; |
| 130 if ((count = _hex2(getc, 1, &sum)) < 0) { | 140 if ((count = _hex2(getc, 1, &sum)) < 0) { |
| 131 printf("Bad S-record count at offset %p\n", (void *)offset); | 141 printf("Bad S-record count at offset %p\n", (void *)offset); |
| 132 return; | 142 return 0; |
| 133 } | 143 } |
| 134 offset += 1; | 144 offset += 1; |
| 135 switch (type) { | 145 switch (type) { |
| 136 case '0': | 146 case '0': |
| 137 break; | 147 break; |
| 151 } | 161 } |
| 152 addr += addr_offset; | 162 addr += addr_offset; |
| 153 if ((unsigned long)(addr-addr_offset) < lowest_address) { | 163 if ((unsigned long)(addr-addr_offset) < lowest_address) { |
| 154 lowest_address = (unsigned long)(addr - addr_offset); | 164 lowest_address = (unsigned long)(addr - addr_offset); |
| 155 } | 165 } |
| 156 if ((addr < ram_start) || (addr > ram_end)) { | 166 if ((addr < user_ram_start) || (addr > user_ram_end)) { |
| 157 printf("Attempt to load S-record data to address: %p [not in RAM]\n", (void*)addr); | 167 printf("Attempt to load S-record data to address: %p [not in RAM]\n", (void*)addr); |
| 158 return; | 168 return 0; |
| 159 } | 169 } |
| 160 count -= ((type-'1'+2)+1); | 170 count -= ((type-'1'+2)+1); |
| 161 offset += count; | 171 offset += count; |
| 162 while (count-- > 0) { | 172 while (count-- > 0) { |
| 163 val = _hex2(getc, 1, &sum); | 173 val = _hex2(getc, 1, &sum); |
| 168 sum = sum & 0xFF; | 178 sum = sum & 0xFF; |
| 169 cksum = (~cksum & 0xFF); | 179 cksum = (~cksum & 0xFF); |
| 170 if (cksum != sum) { | 180 if (cksum != sum) { |
| 171 printf("*** Warning! Checksum failure - Addr: %lx, %02lX <> %02lX\n", | 181 printf("*** Warning! Checksum failure - Addr: %lx, %02lX <> %02lX\n", |
| 172 (unsigned long)base_addr, sum, cksum); | 182 (unsigned long)base_addr, sum, cksum); |
| 173 return; | 183 return 0; |
| 174 } | 184 } |
| 175 if ((unsigned long)(addr-addr_offset) > highest_address) { | 185 if ((unsigned long)(addr-addr_offset) > highest_address) { |
| 176 highest_address = (unsigned long)(addr - addr_offset); | 186 highest_address = (unsigned long)(addr - addr_offset); |
| 177 } | 187 } |
| 178 break; | 188 break; |
| 183 offset += ('9'-type+2); | 193 offset += ('9'-type+2); |
| 184 entry_address = (unsigned long *)addr; | 194 entry_address = (unsigned long *)addr; |
| 185 printf("Entry point: %p, address range: %p-%p\n", | 195 printf("Entry point: %p, address range: %p-%p\n", |
| 186 (void*)entry_address, (void *)lowest_address, (void *)highest_address); | 196 (void*)entry_address, (void *)lowest_address, (void *)highest_address); |
| 187 while ((c = (*getc)()) > 0) ; // Swallow rest of data | 197 while ((c = (*getc)()) > 0) ; // Swallow rest of data |
| 188 return; | 198 return highest_address; |
| 189 default: | 199 default: |
| 190 printf("Invalid S-record at offset 0x%lx, type: %x\n", | 200 printf("Invalid S-record at offset 0x%lx, type: %x\n", |
| 191 (unsigned long)offset, type); | 201 (unsigned long)offset, type); |
| 192 return; | 202 return 0; |
| 193 } | 203 } |
| 194 while ((c = (*getc)()) != '\n') offset++; | 204 while ((c = (*getc)()) != '\n') offset++; |
| 195 } | 205 } |
| 206 return 0; | |
| 196 } | 207 } |
| 197 | 208 |
| 198 | 209 |
| 199 int | 210 int |
| 200 redboot_getc(void) | 211 redboot_getc(void) |
| 259 #ifdef CYGPKG_REDBOOT_NETWORKING | 270 #ifdef CYGPKG_REDBOOT_NETWORKING |
| 260 struct sockaddr_in host; | 271 struct sockaddr_in host; |
| 261 bool hostname_set; | 272 bool hostname_set; |
| 262 char *hostname; | 273 char *hostname; |
| 263 #endif | 274 #endif |
| 275 #ifdef CYGPKG_COMPRESS_ZLIB | |
| 276 bool decompress; | |
| 277 #endif | |
| 264 unsigned long base = 0; | 278 unsigned long base = 0; |
| 279 unsigned long end = 0; | |
| 265 char type[4]; | 280 char type[4]; |
| 266 char *filename = 0; | 281 char *filename = 0; |
| 267 struct option_info opts[5]; | 282 struct option_info opts[6]; |
| 268 | 283 |
| 269 #ifdef CYGPKG_REDBOOT_NETWORKING | 284 #ifdef CYGPKG_REDBOOT_NETWORKING |
| 270 memset((char *)&host, 0, sizeof(host)); | 285 memset((char *)&host, 0, sizeof(host)); |
| 271 host.sin_len = sizeof(host); | 286 host.sin_len = sizeof(host); |
| 272 host.sin_family = AF_INET; | 287 host.sin_family = AF_INET; |
| 289 (void **)&mode_str, (bool *)&mode_str_set, "download mode (TFTP or xyzMODEM)"); | 304 (void **)&mode_str, (bool *)&mode_str_set, "download mode (TFTP or xyzMODEM)"); |
| 290 num_options = 4; | 305 num_options = 4; |
| 291 #ifdef CYGPKG_REDBOOT_NETWORKING | 306 #ifdef CYGPKG_REDBOOT_NETWORKING |
| 292 init_opts(&opts[4], 'h', true, OPTION_ARG_TYPE_STR, | 307 init_opts(&opts[4], 'h', true, OPTION_ARG_TYPE_STR, |
| 293 (void **)&hostname, (bool *)&hostname_set, "host name (IP address)"); | 308 (void **)&hostname, (bool *)&hostname_set, "host name (IP address)"); |
| 294 num_options = 5; | 309 num_options++; |
| 295 #endif | 310 #endif |
| 311 #ifdef CYGPKG_COMPRESS_ZLIB | |
| 312 init_opts(&opts[5], 'd', false, OPTION_ARG_TYPE_FLG, | |
| 313 (void **)&decompress, 0, "decompress"); | |
| 314 num_options++; | |
| 315 #endif | |
| 316 | |
| 296 if (!scan_opts(argc, argv, 1, opts, num_options, (void *)&filename, OPTION_ARG_TYPE_STR, "file name")) | 317 if (!scan_opts(argc, argv, 1, opts, num_options, (void *)&filename, OPTION_ARG_TYPE_STR, "file name")) |
| 297 { | 318 { |
| 298 return; | 319 return; |
| 299 } | 320 } |
| 300 #ifdef CYGPKG_REDBOOT_NETWORKING | 321 #ifdef CYGPKG_REDBOOT_NETWORKING |
| 338 printf("File name missing\n"); | 359 printf("File name missing\n"); |
| 339 printf("usage: load %s\n", usage); | 360 printf("usage: load %s\n", usage); |
| 340 return; | 361 return; |
| 341 } | 362 } |
| 342 if (base_addr_set && | 363 if (base_addr_set && |
| 343 ((base < (unsigned long)ram_start) || | 364 ((base < (unsigned long)user_ram_start) || |
| 344 (base > (unsigned long)ram_end))) { | 365 (base > (unsigned long)user_ram_end))) { |
| 345 printf("Specified address (%p) is not in RAM.\n", (void*)base); | 366 printf("Specified address (%p) is not in RAM.\n", (void*)base); |
| 346 return; | 367 return; |
| 347 } | 368 } |
| 348 #ifdef CYGPKG_REDBOOT_NETWORKING | 369 #ifdef CYGPKG_REDBOOT_NETWORKING |
| 349 if (mode == MODE_TFTP) { | 370 if (mode == MODE_TFTP) { |
| 376 redboot_getc_rewind(); // Restore header to stream | 397 redboot_getc_rewind(); // Restore header to stream |
| 377 if (raw) { | 398 if (raw) { |
| 378 if (!base_addr_set) { | 399 if (!base_addr_set) { |
| 379 printf("Raw load requires a memory address\n"); | 400 printf("Raw load requires a memory address\n"); |
| 380 } else { | 401 } else { |
| 381 unsigned char *mp = (unsigned char *)base; | 402 #ifdef CYGPKG_COMPRESS_ZLIB |
| 382 while ((res = redboot_getc()) >= 0) { | 403 if (decompress) { |
| 383 *mp++ = res; | 404 _pipe_t* p = &load_pipe; |
| 405 p->out_buf = (unsigned char*) base; | |
| 406 p->out_size = 0; | |
| 407 p->in_buf = _buffer; | |
| 408 | |
| 409 err = (*_dc_init)(p); | |
| 410 | |
| 411 while (0 == err) { | |
| 412 p->in_avail = 0; | |
| 413 for (i = 0; i < CYGNUM_REDBOOT_LOAD_ZLIB_BUFFER; i++) { | |
| 414 res = redboot_getc(); | |
| 415 if (res < 0) break; | |
| 416 p->in_buf[p->in_avail++] = res; | |
| 417 } | |
| 418 if (0 == p->in_avail) break; | |
| 419 | |
| 420 err = (*_dc_inflate)(p); | |
| 421 } | |
| 422 | |
| 423 // Free used resources, do final translation of | |
| 424 // error value. | |
| 425 err = (*_dc_close)(p, err); | |
| 426 | |
| 427 if (0 != err && p->msg) | |
| 428 printf("zlib: %s\n", p->msg); | |
| 429 | |
| 430 end = (unsigned long) base + p->out_size; | |
| 431 } else // dangling block | |
| 432 #endif | |
| 433 { | |
| 434 unsigned char *mp = (unsigned char *)base; | |
| 435 while ((res = redboot_getc()) >= 0) { | |
| 436 *mp++ = res; | |
| 437 } | |
| 438 err = 0; | |
| 439 end = (unsigned long) mp; | |
| 384 } | 440 } |
| 385 printf("Raw file loaded %p-%p\n", (void *)base, (void *)mp); | 441 if (0 == err) |
| 442 printf("Raw file loaded %p-%p\n", (void *)base, (void *)end); | |
| 386 } | 443 } |
| 387 } else { | 444 } else { |
| 388 // Treat data as some sort of executable image | 445 // Treat data as some sort of executable image |
| 389 if (strncmp(&type[1], "ELF", 3) == 0) { | 446 if (strncmp(&type[1], "ELF", 3) == 0) { |
| 390 load_elf_image(redboot_getc); | 447 end = load_elf_image(redboot_getc); |
| 391 } else if ((type[0] == 'S') && | 448 } else if ((type[0] == 'S') && |
| 392 ((type[1] >= '0') && (type[1] <= '9'))) { | 449 ((type[1] >= '0') && (type[1] <= '9'))) { |
| 393 load_srec_image(redboot_getc, base); | 450 end = load_srec_image(redboot_getc, base); |
| 394 } else { | 451 } else { |
| 395 printf("Unrecognized image type: %lx\n", *(unsigned long *)type); | 452 printf("Unrecognized image type: %lx\n", *(unsigned long *)type); |
| 396 } | 453 } |
| 397 } | 454 } |
| 398 } | 455 } |
