📄 load.c
字号:
void
redboot_getc_rewind(void)
{
getc_info.bufp = getc_info.buf;
getc_info.avail = getc_info.len;
}
#define MODE_TFTP 0
#define MODE_XMODEM xyzModem_xmodem // 1
#define MODE_YMODEM xyzModem_ymodem // 2
#define MODE_ZMODEM xyzModem_zmodem // 3
#define MODE_DISK 4
void
do_load(int argc, char *argv[])
{
int res, num_options;
int i, err, mode;
bool verbose, raw;
bool base_addr_set, mode_str_set;
char *mode_str;
#ifdef CYGPKG_REDBOOT_NETWORKING
struct sockaddr_in host;
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[6];
#ifdef CYGPKG_REDBOOT_NETWORKING
memset((char *)&host, 0, sizeof(host));
host.sin_len = sizeof(host);
host.sin_family = AF_INET;
host.sin_addr = my_bootp_info.bp_siaddr;
host.sin_port = 0;
#endif
#ifdef CYGPKG_REDBOOT_NETWORKING
mode = MODE_TFTP;
#else
mode = MODE_YMODEM;
#endif
init_opts(&opts[0], 'v', false, OPTION_ARG_TYPE_FLG,
(void **)&verbose, 0, "verbose");
init_opts(&opts[1], 'r', false, OPTION_ARG_TYPE_FLG,
(void **)&raw, 0, "load raw data");
init_opts(&opts[2], 'b', true, OPTION_ARG_TYPE_NUM,
(void **)&base, (bool *)&base_addr_set, "load address");
init_opts(&opts[3], 'm', true, OPTION_ARG_TYPE_STR,
(void **)&mode_str, (bool *)&mode_str_set, "download mode (TFTP, xyzMODEM, or disk)");
num_options = 4;
#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++;
#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;
}
#ifdef CYGPKG_REDBOOT_NETWORKING
if (hostname_set) {
if (!inet_aton(hostname, (in_addr_t *)&host)) {
printf("Invalid IP address: %s\n", hostname);
return;
}
}
#endif
if (mode_str_set) {
if (strncmpci(&mode_str[1], "modem", strlen(&mode_str[1])) == 0) {
switch (tolower(mode_str[0])) {
case 'x':
mode = MODE_XMODEM;
break;
case 'y':
mode = MODE_YMODEM;
break;
case 'z':
mode = MODE_ZMODEM;
break;
default:
printf("Invalid 'mode': %s\n", mode_str);
return;
}
// When using a serial download type, override verbose
// setting: spinner interferes with the protocol.
verbose = false;
#ifdef CYGPKG_REDBOOT_DISK
} else if (strcmpci(mode_str, "disk") == 0) {
mode = MODE_DISK;
#endif
#ifdef CYGPKG_REDBOOT_NETWORKING
} else if (strcmpci(mode_str, "tftp") == 0) {
mode = MODE_TFTP;
if (!have_net) {
printf("TFTP mode requires a working network\n");
return;
}
#endif
} else {
printf("Invalid 'mode': %s\n", mode_str);
return;
}
}
#if defined(CYGPKG_REDBOOT_NETWORKING) || defined(CYGPKG_REDBOOT_DISK)
if ((mode == MODE_TFTP || mode == MODE_DISK) && !filename) {
printf("File name missing\n");
printf("usage: load %s\n", usage);
return;
}
#endif
#ifdef CYGSEM_REDBOOT_VALIDATE_USER_RAM_LOADS
if (base_addr_set &&
((base < (unsigned long)user_ram_start) ||
(base > (unsigned long)user_ram_end))) {
if (!verify_action("Specified address (%p) is not believed to be in RAM", (void*)base))
return;
}
#endif
if (raw && !base_addr_set) {
printf("Raw load requires a memory address\n");
return;
}
#ifdef CYGPKG_REDBOOT_NETWORKING
if (mode == MODE_TFTP) {
res = tftp_stream_open(filename, &host, TFTP_OCTET, &err);
if (res < 0) {
printf("Can't load '%s': %s\n", filename, tftp_error(err));
return;
}
redboot_getc_init(tftp_stream_read, verbose);
}
#endif
#ifdef CYGPKG_REDBOOT_DISK
else if (mode == MODE_DISK) {
res = disk_stream_open(filename, &err);
if (res < 0) {
printf("Can't load '%s': %s\n", filename, disk_error(err));
return;
}
redboot_getc_init(disk_stream_read, verbose);
}
#endif
else {
res = xyzModem_stream_open(filename, mode, &err);
if (res < 0) {
printf("Can't load '%s': %s\n", filename, xyzModem_error(err));
return;
}
// Suppress verbosity when using xyz modem download
redboot_getc_init(xyzModem_stream_read, 0 && verbose);
}
if (raw) {
#ifdef CYGPKG_COMPRESS_ZLIB
if (decompress) {
_pipe_t load_pipe;
_pipe_t* p = &load_pipe;
unsigned char _buffer[CYGNUM_REDBOOT_LOAD_ZLIB_BUFFER];
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("decompression error: %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;
}
if (0 == err)
printf("Raw file loaded %p-%p\n", (void *)base, (void *)end);
} else {
// Read initial header - to determine file [image] type
for (i = 0; i < sizeof(type); i++) {
if ((res = redboot_getc()) < 0) {
err = getc_info.err;
break;
}
type[i] = res;
}
if (res >= 0) {
redboot_getc_rewind(); // Restore header to stream
// Treat data as some sort of executable image
if (strncmp(&type[1], "ELF", 3) == 0) {
end = load_elf_image(redboot_getc);
} else if ((type[0] == 'S') &&
((type[1] >= '0') && (type[1] <= '9'))) {
end = load_srec_image(redboot_getc, base);
} else {
printf("Unrecognized image type: 0x%lx\n", *(unsigned long *)type);
}
}
}
switch (mode) {
#ifdef CYGPKG_REDBOOT_DISK
case MODE_DISK:
disk_stream_close(&err);
break;
#endif
#ifdef CYGPKG_REDBOOT_NETWORKING
case MODE_TFTP:
tftp_stream_close(&err);
break;
#endif
default:
xyzModem_stream_close(&err);
break;
}
return;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -