1 //==========================================================================
5 // RedBoot file/image loader
7 //==========================================================================
8 //####ECOSGPLCOPYRIGHTBEGIN####
9 // -------------------------------------------
10 // This file is part of eCos, the Embedded Configurable Operating System.
11 // Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc.
12 // Copyright (C) 2002, 2003, 2004 Gary Thomas
13 // Copyright (C) 2004 eCosCentric Limited
15 // eCos is free software; you can redistribute it and/or modify it under
16 // the terms of the GNU General Public License as published by the Free
17 // Software Foundation; either version 2 or (at your option) any later version.
19 // eCos is distributed in the hope that it will be useful, but WITHOUT ANY
20 // WARRANTY; without even the implied warranty of MERCHANTABILITY or
21 // FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
24 // You should have received a copy of the GNU General Public License along
25 // with eCos; if not, write to the Free Software Foundation, Inc.,
26 // 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
28 // As a special exception, if other files instantiate templates or use macros
29 // or inline functions from this file, or you compile this file and link it
30 // with other works to produce a work based on this file, this file does not
31 // by itself cause the resulting work to be covered by the GNU General Public
32 // License. However the source code for this file must still be made available
33 // in accordance with section (3) of the GNU General Public License.
35 // This exception does not invalidate any other reasons why a work based on
36 // this file might be covered by the GNU General Public License.
38 // Alternative licenses for eCos may be arranged by contacting Red Hat, Inc.
39 // at http://sources.redhat.com/ecos/ecos-license/
40 // -------------------------------------------
41 //####ECOSGPLCOPYRIGHTEND####
42 //==========================================================================
43 //#####DESCRIPTIONBEGIN####
46 // Contributors: gthomas, tsmith
51 // This code is part of RedBoot (tm).
53 //####DESCRIPTIONEND####
55 //==========================================================================
59 #ifdef CYGBLD_BUILD_REDBOOT_WITH_XYZMODEM
62 #ifdef CYGPKG_REDBOOT_DISK
65 #ifdef CYGPKG_REDBOOT_FILEIO
66 #include <fs/fileio.h>
68 #ifdef CYGPKG_REDBOOT_NETWORKING
69 #ifdef CYGSEM_REDBOOT_NET_TFTP_DOWNLOAD
70 #include <net/tftp_support.h>
72 #ifdef CYGSEM_REDBOOT_NET_HTTP_DOWNLOAD
76 #include <cyg/infra/cyg_ass.h> // assertion macros
77 #ifdef CYGBLD_REDBOOT_LOAD_INTO_FLASH
78 #include <cyg/io/flash.h>
79 #include "flash_load.h"
82 static char usage[] = "[-r] [-v] [-z to swap endianness on 16 bit] "
83 #ifdef CYGBLD_BUILD_REDBOOT_WITH_ZLIB
86 #ifdef CYGPKG_REDBOOT_NETWORKING
87 "[-h <host>] [-p <TCP port>]"
90 #if CYGNUM_HAL_VIRTUAL_VECTOR_NUM_CHANNELS > 1
91 "[-c <channel_number>] "
93 #ifdef CYGBLD_REDBOOT_LOAD_INTO_FLASH
94 "[-f <flash_address>] "
96 "\n [-b <base_address>] <file_name>";
98 // Exported CLI function
106 // Stream I/O support
109 // Table describing the various I/O methods
110 CYG_HAL_TABLE_BEGIN( __RedBoot_LOAD_TAB__, RedBoot_load );
111 CYG_HAL_TABLE_END( __RedBoot_LOAD_TAB_END__, RedBoot_load );
112 extern struct load_io_entry __RedBoot_LOAD_TAB__[], __RedBoot_LOAD_TAB_END__;
114 // Buffers, data used by redboot_getc
115 #define BUF_SIZE CYGNUM_REDBOOT_GETC_BUFFER
118 int (*fun)(void *, int len, int *err);
119 unsigned char buf[BUF_SIZE];
122 int verbose, decompress, tick;
123 #ifdef CYGBLD_BUILD_REDBOOT_WITH_ZLIB
124 int (*raw_fun)(void *, int len, int *err);
126 unsigned char _buffer[CYGNUM_REDBOOT_LOAD_ZLIB_BUFFER];
130 typedef int (*getc_t)(void);
133 // Read the next data byte from the stream.
135 // >= 0 - actual data
136 // -1 - error or EOF, status in getc_info.err
141 static char spin[] = "|/-\\|-";
142 if (getc_info.avail < 0) {
145 if (getc_info.avail == 0) {
146 if (getc_info.verbose) {
147 err_printf("%c\b", spin[getc_info.tick++]);
148 if (getc_info.tick >= sizeof(spin)) {
152 if (getc_info.len < BUF_SIZE) {
153 // No more data available
154 if (getc_info.verbose) diag_printf("\n");
157 getc_info.bufp = getc_info.buf;
158 getc_info.len = (*getc_info.fun)(getc_info.bufp, BUF_SIZE, &getc_info.err);
159 if ((getc_info.avail = getc_info.len) <= 0) {
160 if (getc_info.len < 0) {
161 diag_printf("I/O error: %s\n", (getc_info.io->error)(getc_info.err));
163 if (getc_info.verbose) diag_printf("\n");
168 return *getc_info.bufp++;
171 #ifdef CYGBLD_BUILD_REDBOOT_WITH_ZLIB
173 // Called to fetch a new chunk of data and decompress it
176 _decompress_stream(void *buf, int len, int *err)
178 _pipe_t *p = &getc_info.load_pipe;
183 if (p->in_avail == 0) {
184 p->in_buf = &getc_info._buffer[0];
185 res = (*getc_info.raw_fun)(p->in_buf, CYGNUM_REDBOOT_LOAD_ZLIB_BUFFER,
187 if ((p->in_avail = res) <= 0) {
195 res = (*_dc_inflate)(p);
201 buf = (char *)buf + p->out_size;
202 total += p->out_size;
209 redboot_getc_init(connection_info_t *info, getc_io_funcs_t *funcs,
210 int verbose, int decompress)
214 res = (funcs->open)(info, &getc_info.err);
216 err_printf("Can't load '%s': %s\n", info->filename, (funcs->error)(getc_info.err));
219 getc_info.io = funcs;
220 getc_info.fun = funcs->read;
222 getc_info.len = BUF_SIZE;
223 getc_info.verbose = verbose;
224 getc_info.decompress = decompress;
226 #ifdef CYGBLD_BUILD_REDBOOT_WITH_ZLIB
228 _pipe_t *p = &getc_info.load_pipe;
229 p->out_buf = &getc_info.buf[0];
232 getc_info.raw_fun = getc_info.fun;
233 getc_info.fun = _decompress_stream;
234 getc_info.err = (*_dc_init)(p);
235 if (0 != getc_info.err && p->msg) {
236 err_printf("open decompression error: %s\n", p->msg);
244 redboot_getc_rewind(void)
246 getc_info.bufp = getc_info.buf;
247 getc_info.avail = getc_info.len;
251 redboot_getc_terminate(bool abort)
253 if (getc_info.io->terminate) {
254 (getc_info.io->terminate)(abort, redboot_getc);
259 redboot_getc_close(void)
261 (getc_info.io->close)(&getc_info.err);
262 #ifdef CYGBLD_BUILD_REDBOOT_WITH_ZLIB
263 if (getc_info.decompress) {
264 _pipe_t *p = &getc_info.load_pipe;
265 int err = getc_info.err;
266 if (0 != err && p->msg) {
267 diag_printf("decompression error: %s\n", p->msg);
269 err = (*_dc_close)(p, getc_info.err);
274 #ifdef CYGSEM_REDBOOT_ELF
276 // Support function - used to read bytes into a buffer
277 // Returns the number of bytes read (stops short on errors)
280 _read(int (*getc)(void), unsigned char *buf, int len)
298 // Load an ELF [binary] image
301 // Note that in case of multicore and the core we wanna load the
302 // image for is not in the same endianness that the core we run
303 // redboot from, have to invert bytes on 16-bit boundary
307 load_elf_image(getc_t getc, unsigned long base, bool swap16bit)
309 #ifdef CYGSEM_REDBOOT_ELF
312 Elf32_Phdr phdr[MAX_PHDR];
313 unsigned long offset = 0;
315 unsigned char *addr, *addr_swap;
316 unsigned long addr_offset = 0;
317 unsigned long highest_address = 0;
318 unsigned long lowest_address = 0xFFFFFFFF;
319 const char *SHORT_DATA = "Short data reading ELF file\n";
322 if (_read(getc, (unsigned char *)&ehdr, sizeof(ehdr)) != sizeof(ehdr)) {
323 err_printf("Can't read ELF header\n");
324 redboot_getc_terminate(true);
327 offset += sizeof(ehdr);
329 diag_printf("Type: %d, Machine: %d, Version: %d, Entry: %p, PHoff: %p/%d/%d, SHoff: %p/%d/%d\n",
330 ehdr.e_type, ehdr.e_machine, ehdr.e_version, ehdr.e_entry,
331 ehdr.e_phoff, ehdr.e_phentsize, ehdr.e_phnum,
332 ehdr.e_shoff, ehdr.e_shentsize, ehdr.e_shnum);
334 if (ehdr.e_type != ET_EXEC) {
335 err_printf("Only absolute ELF images supported\n");
336 redboot_getc_terminate(true);
339 if (ehdr.e_phnum > MAX_PHDR) {
340 err_printf("Too many program headers\n");
341 redboot_getc_terminate(true);
344 while (offset < ehdr.e_phoff) {
346 err_printf(SHORT_DATA);
347 redboot_getc_terminate(true);
352 for (phx = 0; phx < ehdr.e_phnum; phx++) {
353 if (_read(getc, (unsigned char *)&phdr[phx], sizeof(phdr[0])) != sizeof(phdr[0])) {
354 err_printf("Can't read ELF program header\n");
355 redboot_getc_terminate(true);
359 diag_printf("Program header: type: %d, off: %p, va: %p, pa: %p, len: %d/%d, flags: %d\n",
360 phdr[phx].p_type, phdr[phx].p_offset, phdr[phx].p_vaddr, phdr[phx].p_paddr,
361 phdr[phx].p_filesz, phdr[phx].p_memsz, phdr[phx].p_flags);
363 offset += sizeof(phdr[0]);
366 // Set address offset based on lowest address in file.
367 addr_offset = 0xFFFFFFFF;
368 for (phx = 0; phx < ehdr.e_phnum; phx++) {
369 #ifdef CYGOPT_REDBOOT_ELF_VIRTUAL_ADDRESS
370 if ((phdr[phx].p_type == PT_LOAD) && (phdr[phx].p_vaddr < addr_offset)) {
371 addr_offset = phdr[phx].p_vaddr;
373 if ((phdr[phx].p_type == PT_LOAD) && (phdr[phx].p_paddr < addr_offset)) {
374 addr_offset = phdr[phx].p_paddr;
378 addr_offset = (unsigned long)base - addr_offset;
382 for (phx = 0; phx < ehdr.e_phnum; phx++) {
383 if (phdr[phx].p_type == PT_LOAD) {
385 #ifdef CYGOPT_REDBOOT_ELF_VIRTUAL_ADDRESS
386 addr = (unsigned char *)phdr[phx].p_vaddr;
388 addr = (unsigned char *)phdr[phx].p_paddr;
390 len = phdr[phx].p_filesz;
391 if ((unsigned long)addr < lowest_address) {
392 lowest_address = (unsigned long)addr;
395 if (offset > phdr[phx].p_offset) {
396 if ((phdr[phx].p_offset + len) < offset) {
397 err_printf("Can't load ELF file - program headers out of order\n");
398 redboot_getc_terminate(true);
401 addr += offset - phdr[phx].p_offset;
403 while (offset < phdr[phx].p_offset) {
405 err_printf(SHORT_DATA);
406 redboot_getc_terminate(true);
413 // Copy data into memory
415 #ifdef CYGSEM_REDBOOT_VALIDATE_USER_RAM_LOADS
416 if (!(valid_address(addr)
417 #ifdef CYGBLD_REDBOOT_LOAD_INTO_FLASH
418 || (flash_verify_addr(addr) == FLASH_ERR_OK)
421 redboot_getc_terminate(true);
422 err_printf("*** Abort! Attempt to load ELF data to address: %p which is not valid\n",
427 if ((ch = (*getc)()) < 0) {
428 err_printf(SHORT_DATA);
429 redboot_getc_terminate(true);
433 /* In case of multicore and the core we wanna load the image for is not in the same endianness
434 that the core we run redboot from, have to invert bytes on 16-bit boundary (16-bit memory)*/
436 // addr is even, have to write char data to the last address
437 if (((unsigned long)addr) % 2) {
438 addr_swap = addr - 1;
441 // addr is odd, have to write char data to the next address
442 addr_swap = addr + 1;
448 #ifdef CYGSEM_REDBOOT_VALIDATE_USER_RAM_LOADS
449 if (valid_address(addr))
453 #ifdef CYGBLD_REDBOOT_LOAD_INTO_FLASH
455 flash_load_write(addr, ch);
461 if ((unsigned long)(addr-addr_offset) > highest_address) {
462 highest_address = (unsigned long)(addr - addr_offset);
468 // Save load base/top and entry
471 load_address_end = base + (highest_address - lowest_address);
472 entry_address = base + (ehdr.e_entry - lowest_address);
474 load_address = lowest_address;
475 load_address_end = highest_address;
476 entry_address = ehdr.e_entry;
479 // nak everything to stop the transfer, since redboot
480 // usually doesn't read all the way to the end of the
482 redboot_getc_terminate(true);
483 if (addr_offset) diag_printf("Address offset = %p\n", (void *)addr_offset);
484 diag_printf("Entry point: %p, address range: %p-%p\n",
485 (void*)entry_address, (void *)load_address, (void *)load_address_end);
487 #else // CYGSEM_REDBOOT_ELF
488 err_printf("Loading ELF images not supported\n");
490 #endif // CYGSEM_REDBOOT_ELF
494 // Scan a string of hex bytes and update the checksum
497 _hex2(int (*getc)(void), int len, long *sum)
506 if (_is_hex(c1) && _is_hex(c2)) {
508 byte = (_from_hex(c1) << 4) | _from_hex(c2);
521 // Process a set of S-records, loading the contents into memory.
522 // Note: if a "base" value is provided, the data will be relocated
523 // relative to that location. Of course, this can only work for
524 // the first section of the data, so if there are non-contiguous
525 // pieces of data, they will end up relocated in the same fashion.
526 // Because of this, "base" probably only makes sense for a set of
527 // data which has only one section, e.g. a ROM image.
529 // Note that in case of multicore and the core we wanna load the
530 // image for is not in the same endianness that the core we run
531 // redboot from, have to invert bytes on 16-bit boundary
535 load_srec_image(getc_t getc, unsigned long base, bool swap16bit)
538 long offset = 0, count, sum, val, cksum;
539 unsigned char *addr, *base_addr, *addr_swap;
541 bool first_addr = true;
542 unsigned long addr_offset = 0;
543 unsigned long highest_address = 0;
544 unsigned long lowest_address = 0xFFFFFFFF;
546 while ((c = (*getc)()) > 0) {
549 redboot_getc_terminate(true);
550 err_printf("Invalid S-record at offset %p, input: %c\n",
557 if ((count = _hex2(getc, 1, &sum)) < 0) {
558 redboot_getc_terminate(true);
559 err_printf("Bad S-record count at offset %p\n", (void *)offset);
569 base_addr = addr = (unsigned char *)_hex2(getc, type - '1' + 2, &sum);
570 offset += type - '1' + 2;
573 addr_offset = (unsigned long)base - (unsigned long)addr;
580 if ((unsigned long)(addr-addr_offset) < lowest_address) {
581 lowest_address = (unsigned long)(addr - addr_offset);
583 #ifdef CYGSEM_REDBOOT_VALIDATE_USER_RAM_LOADS
584 if (!(valid_address(addr)
585 #ifdef CYGBLD_REDBOOT_LOAD_INTO_FLASH
586 || (flash_verify_addr(addr) == FLASH_ERR_OK)
589 // Only if there is no need to stop the download before printing
590 // output can we ask confirmation questions.
591 redboot_getc_terminate(true);
592 err_printf("*** Abort! Attempt to load S-record to address: %p, which is not valid\n",(void*)addr);
596 count -= type - '1' + 2 + 1;
598 while (count-- > 0) {
599 val = _hex2(getc, 1, &sum);
600 /* In case of multicore and the core we wanna load the image for is not in the same endianness
601 that the core we run redboot from, have to invert bytes on 16-bit boundary (16-bit memory)*/
603 // addr is even, have to write char data to the last address
604 if (((unsigned long)addr) % 2) {
605 addr_swap = addr - 1;
608 // addr is odd, have to write char data to the next address
609 addr_swap = addr + 1;
614 #ifdef CYGSEM_REDBOOT_VALIDATE_USER_RAM_LOADS
615 if (valid_address(addr))
619 #ifdef CYGBLD_REDBOOT_LOAD_INTO_FLASH
621 flash_load_write(addr, val);
627 cksum = _hex2(getc, 1, 0);
630 cksum = ~cksum & 0xFF;
632 redboot_getc_terminate(true);
633 err_printf("*** Warning! Checksum failure - Addr: %lx, %02lX <> %02lX\n",
634 (unsigned long)base_addr, sum, cksum);
637 if ((unsigned long)(addr-addr_offset) > highest_address) {
638 highest_address = (unsigned long)(addr - addr_offset);
644 addr = (unsigned char *)_hex2(getc, '9' - type + 2, &sum);
645 offset += '9' - type + 2;
646 // Save load base/top, entry address
649 load_address_end = base + (highest_address - lowest_address);
650 entry_address = (unsigned long)(base + (addr - lowest_address));
652 load_address = lowest_address;
653 load_address_end = highest_address;
654 entry_address = (unsigned long)addr;
656 redboot_getc_terminate(false);
657 if (addr_offset) diag_printf("Address offset = %p\n", (void *)addr_offset);
658 diag_printf("Entry point: %p, address range: %p-%p\n",
659 (void*)entry_address, (void *)load_address, (void *)load_address_end);
661 return load_address_end;
663 redboot_getc_terminate(true);
664 err_printf("Invalid S-record at offset 0x%lx, type: %x\n",
665 (unsigned long)offset, type);
668 while ((c = getc()) != '\n') offset++;
674 // 'load' CLI command processing
675 // -b - specify a load [base] address
676 // -m - specify an I/O stream/method
677 // -c - Alternate serial I/O channel
678 #ifdef CYGBLD_BUILD_REDBOOT_WITH_ZLIB
679 // -d - Decompress data [packed via 'zlib']
681 #ifdef CYGBLD_REDBOOT_LOAD_INTO_FLASH
682 // -f - specify a flash address
686 do_load(int argc, char *argv[])
688 int res, num_options;
690 bool verbose, raw, swap16bit;
691 bool base_addr_set, mode_str_set;
693 #ifdef CYGPKG_REDBOOT_NETWORKING
694 struct sockaddr_in host;
695 bool hostname_set, port_set;
696 unsigned int port; // int because it's an OPTION_ARG_TYPE_NUM,
697 // but will be cast to short
700 #ifdef CYGBLD_REDBOOT_LOAD_INTO_FLASH
701 bool flash_addr_set = false;
703 bool decompress = false;
705 #if CYGNUM_HAL_VIRTUAL_VECTOR_NUM_CHANNELS > 1
708 unsigned long base = 0;
709 unsigned long end = 0;
712 struct option_info opts[9];
713 connection_info_t info;
714 getc_io_funcs_t *io = NULL;
715 struct load_io_entry *io_tab;
716 #ifdef CYGSEM_REDBOOT_VALIDATE_USER_RAM_LOADS
717 bool spillover_ok = false;
720 #ifdef CYGPKG_REDBOOT_NETWORKING
721 memset((char *)&host, 0, sizeof(host));
722 host.sin_len = sizeof(host);
723 host.sin_family = AF_INET;
724 host.sin_addr = my_bootp_info.bp_siaddr;
728 init_opts(&opts[0], 'v', false, OPTION_ARG_TYPE_FLG,
729 &verbose, 0, "verbose");
730 init_opts(&opts[1], 'r', false, OPTION_ARG_TYPE_FLG,
731 &raw, 0, "load raw data");
732 init_opts(&opts[2], 'b', true, OPTION_ARG_TYPE_NUM,
733 &base, &base_addr_set, "load address");
734 init_opts(&opts[3], 'm', true, OPTION_ARG_TYPE_STR,
735 &mode_str, &mode_str_set, "download mode (TFTP, xyzMODEM, or disk)");
736 init_opts(&opts[4], 'z', false, OPTION_ARG_TYPE_FLG,
737 &swap16bit, 0, "swap endianness on 16 bit");
739 #if CYGNUM_HAL_VIRTUAL_VECTOR_NUM_CHANNELS > 1
740 init_opts(&opts[num_options], 'c', true, OPTION_ARG_TYPE_NUM,
741 &chan, &chan_set, "I/O channel");
744 #ifdef CYGPKG_REDBOOT_NETWORKING
745 init_opts(&opts[num_options], 'h', true, OPTION_ARG_TYPE_STR,
746 &hostname, &hostname_set, "host name or IP address");
748 init_opts(&opts[num_options], 'p', true, OPTION_ARG_TYPE_NUM,
749 &port, &port_set, "TCP port");
752 #ifdef CYGBLD_BUILD_REDBOOT_WITH_ZLIB
753 init_opts(&opts[num_options], 'd', false, OPTION_ARG_TYPE_FLG,
754 &decompress, 0, "decompress");
757 #ifdef CYGBLD_REDBOOT_LOAD_INTO_FLASH
758 init_opts(&opts[num_options], 'f', true, OPTION_ARG_TYPE_NUM,
759 &base, &flash_addr_set, "flash address");
762 CYG_ASSERT(num_options <= NUM_ELEMS(opts), "Too many options");
764 if (!scan_opts(argc, argv, 1, opts, num_options,
765 &filename, OPTION_ARG_TYPE_STR, "file name")) {
769 /* make sure any future go/exec's will fail until a successful upload */
770 entry_address = (unsigned long)NO_MEMORY;
772 #ifdef CYGPKG_REDBOOT_NETWORKING
775 if (!_gethostbyname(hostname, (in_addr_t *)&host)) {
776 err_printf("Invalid host: %s\n", hostname);
779 /* check that the host can be accessed */
780 if (__arp_lookup((ip_addr_t *)&host.sin_addr, &rt) < 0) {
781 err_printf("Unable to reach host %s (%s)\n",
782 hostname, inet_ntoa((in_addr_t *)&host));
787 host.sin_port = port;
789 if (chan >= CYGNUM_HAL_VIRTUAL_VECTOR_NUM_CHANNELS) {
790 err_printf("Invalid I/O channel: %d\n", chan);
794 for (io_tab = __RedBoot_LOAD_TAB__;
795 io_tab != &__RedBoot_LOAD_TAB_END__; io_tab++) {
796 if (strncasecmp(&mode_str[0], io_tab->name, strlen(&mode_str[0])) == 0) {
802 diag_printf("Invalid 'mode': %s. Valid modes are:", mode_str);
803 for (io_tab = __RedBoot_LOAD_TAB__;
804 io_tab != &__RedBoot_LOAD_TAB_END__; io_tab++) {
805 diag_printf(" %s", io_tab->name);
812 verbose &= io_tab->can_verbose;
813 if (io_tab->need_filename && !filename) {
814 diag_printf("File name required\n");
815 err_printf("usage: load %s\n", usage);
820 io_tab = NULL; // Default
821 #ifdef CYGPKG_REDBOOT_NETWORKING
822 #ifdef CYGSEM_REDBOOT_NET_TFTP_DOWNLOAD
825 #elif defined(CYGSEM_REDBOOT_NET_HTTP_DOWNLOAD)
830 #if 0 //def CYGPKG_REDBOOT_FILEIO
831 // Make file I/O default if mounted
832 if (fileio_mounted) {
838 #ifdef CYGBLD_BUILD_REDBOOT_WITH_XYZMODEM
843 err_printf("No default protocol!\n");
847 diag_printf("Using default protocol (%s)\n", which);
849 #ifdef CYGSEM_REDBOOT_VALIDATE_USER_RAM_LOADS
850 #ifdef CYGBLD_REDBOOT_LOAD_INTO_FLASH
851 if (flash_addr_set && flash_verify_addr((unsigned char *)base)) {
852 if (!verify_action("Specified address (%p) is not believed to be in FLASH", (void*)base))
857 if (base_addr_set && !valid_address((unsigned char *)base)) {
858 if (!verify_action("Specified address (%p) is not believed to be in RAM", (void*)base))
863 if (raw && !(base_addr_set
864 #ifdef CYGBLD_REDBOOT_LOAD_INTO_FLASH
868 err_printf("Raw load requires a memory address\n");
871 info.filename = filename;
873 info.mode = io_tab ? io_tab->mode : 0;
874 #ifdef CYGPKG_REDBOOT_NETWORKING
877 res = redboot_getc_init(&info, io, verbose, decompress);
881 #ifdef CYGBLD_REDBOOT_LOAD_INTO_FLASH
884 // Stream open, process the data
886 unsigned char *mp = (unsigned char *)base;
887 unsigned char *addr_swap;
890 while ((res = redboot_getc()) >= 0) {
891 #ifdef CYGSEM_REDBOOT_VALIDATE_USER_RAM_LOADS
892 #ifdef CYGBLD_REDBOOT_LOAD_INTO_FLASH
893 if (flash_addr_set && flash_verify_addr(mp) && !spillover_ok) {
894 // Only if there is no need to stop the download
895 // before printing output can we ask confirmation
897 redboot_getc_terminate(true);
898 err_printf("*** Abort! RAW data spills over limit of FLASH at %p\n",(void*)mp);
903 if (base_addr_set && !valid_address(mp) && !spillover_ok) {
904 // Only if there is no need to stop the download
905 // before printing output can we ask confirmation
907 redboot_getc_terminate(true);
908 err_printf("*** Abort! RAW data spills over limit of user RAM at %p\n",(void*)mp);
914 /* In case of multicore and the core we wanna load the image for is not in the same endianness
915 that the core we run redboot from, have to invert bytes on 16-bit boundary (16-bit memory)*/
917 // addr is even, have to write char data to the last address
918 if (((unsigned long)mp) % 2) {
922 // addr is odd, have to write char data to the next address
928 #ifdef CYGBLD_REDBOOT_LOAD_INTO_FLASH
929 if (flash_addr_set) {
930 flash_load_write(mp, res);
938 end = (unsigned long)mp;
940 // Save load base/top
941 load_address_end = end;
942 entry_address = base; // best guess
944 redboot_getc_terminate(false);
946 diag_printf("Raw file loaded %p-%p, assumed entry at %p\n",
947 (void *)load_address, (void *)(load_address_end - 1), (void*)entry_address);
949 // Read initial header - to determine file [image] type
950 for (i = 0; i < sizeof(type); i++) {
951 if ((res = redboot_getc()) < 0) {
958 redboot_getc_rewind(); // Restore header to stream
959 // Treat data as some sort of executable image
960 if (strncmp(&type[1], "ELF", 3) == 0) {
962 end = load_elf_image(redboot_getc, base, true);
964 end = load_elf_image(redboot_getc, base, false);
966 } else if ((type[0] == 'S') &&
967 ((type[1] >= '0') && (type[1] <= '9'))) {
969 end = load_srec_image(redboot_getc, base, true);
971 end = load_srec_image(redboot_getc, base, false);
974 unsigned long *tt = (unsigned long *)type;
975 redboot_getc_terminate(true);
976 err_printf("Unrecognized image type: 0x%lx\n", *tt);
980 #ifdef CYGBLD_REDBOOT_LOAD_INTO_FLASH
984 redboot_getc_close(); // Clean up