⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 load.c

📁 eCos操作系统源码
💻 C
📖 第 1 页 / 共 2 页
字号:
        load_address_end = base + (highest_address - lowest_address);        entry_address = base + (ehdr.e_entry - lowest_address);    } else {        load_address = lowest_address;        load_address_end = highest_address;        entry_address = ehdr.e_entry;    }    redboot_getc_terminate(false);    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);    return 1;#else // CYGSEM_REDBOOT_ELF    diag_printf("Loading ELF images not supported\n");    return 0;#endif // CYGSEM_REDBOOT_ELF}//// Scan a string of hex bytes and update the checksum//static long_hex2(int (*getc)(void), int len, long *sum){    int val, byte;    char c1, c2;    val = 0;    while (len-- > 0) {        c1 = (*getc)();        c2 = (*getc)();        if (_is_hex(c1) && _is_hex(c2)) {            val <<= 8;            byte = (_from_hex(c1)<<4) | _from_hex(c2);            val |= byte;            if (sum) {                *sum += byte;            }        } else {            return (-1);        }    }    return (val);}//// Process a set of S-records, loading the contents into memory.  // Note: if a "base" value is provided, the data will be relocated// relative to that location.  Of course, this can only work for// the first section of the data, so if there are non-contiguous// pieces of data, they will end up relocated in the same fashion.// Because of this, "base" probably only makes sense for a set of// data which has only one section, e.g. a ROM image.//static unsigned longload_srec_image(getc_t getc, unsigned long base){    int  c;    long offset = 0, count, sum, val, cksum;    unsigned char *addr, *base_addr;    char type;    bool first_addr = true;    unsigned long addr_offset = 0;    unsigned long highest_address = 0;    unsigned long lowest_address = 0xFFFFFFFF;    while ((c = (*getc)()) > 0) {        // Start of line        if (c != 'S') {            redboot_getc_terminate(true);            diag_printf("Invalid S-record at offset %p, input: %c\n",                    (void *)offset, c);            return 0;        }        type = (*getc)();        offset += 2;        sum = 0;        if ((count = _hex2(getc, 1, &sum)) < 0) {            redboot_getc_terminate(true);            diag_printf("Bad S-record count at offset %p\n", (void *)offset);            return 0;        }        offset += 1;        switch (type) {        case '0':            break;        case '1':        case '2':        case '3':            base_addr = addr = (unsigned char *)_hex2(getc, (type-'1'+2), &sum);            offset += (type-'1'+2);            if (first_addr) {                if (base) {                    addr_offset = (unsigned long)base - (unsigned long)addr;                } else {                    addr_offset = 0;                                    }                first_addr = false;            }            addr += addr_offset;            if ((unsigned long)(addr-addr_offset) < lowest_address) {                lowest_address = (unsigned long)(addr - addr_offset);            }#ifdef CYGSEM_REDBOOT_VALIDATE_USER_RAM_LOADS            if (!valid_address(addr)) {	      // 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);                return 0;            }#endif            count -= ((type-'1'+2)+1);            offset += count;            while (count-- > 0) {                val = _hex2(getc, 1, &sum);                *addr++ = val;            }            cksum = _hex2(getc, 1, 0);            offset += 1;            sum = sum & 0xFF;            cksum = (~cksum & 0xFF);            if (cksum != sum) {                redboot_getc_terminate(true);                diag_printf("*** Warning! Checksum failure - Addr: %lx, %02lX <> %02lX\n",                        (unsigned long)base_addr, sum, cksum);                return 0;            }            if ((unsigned long)(addr-addr_offset) > highest_address) {                highest_address = (unsigned long)(addr - addr_offset);            }            break;        case '7':        case '8':        case '9':            addr = (unsigned char *)_hex2(getc, ('9'-type+2), &sum);            offset += ('9'-type+2);            // Save load base/top, entry address            if (base) {                load_address = base;                load_address_end = base + (highest_address - lowest_address);                entry_address = (unsigned long)(base + (addr - lowest_address));            } else {                load_address = lowest_address;                load_address_end = highest_address;                entry_address = (unsigned long)addr;            }            redboot_getc_terminate(false);            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);            return load_address_end;        default:            redboot_getc_terminate(true);            diag_printf("Invalid S-record at offset 0x%lx, type: %x\n",                    (unsigned long)offset, type);            return 0;        }        while ((c = (*getc)()) != '\n') offset++;    }    return 0;}//// 'load' CLI command processing//   -b - specify a load [base] address//   -m - specify an I/O stream/method//   -c - Alternate serial I/O channel#ifdef CYGBLD_BUILD_REDBOOT_WITH_ZLIB//   -d - Decompress data [packed via 'zlib']#endif//void do_load(int argc, char *argv[]){    int res, num_options;    int i, err;    bool verbose, raw;    bool base_addr_set, mode_str_set;    char *mode_str;#ifdef CYGPKG_REDBOOT_NETWORKING    struct sockaddr_in host;    bool hostname_set, port_set;    char *hostname;#endif    bool decompress = false;    int chan = -1;#if CYGNUM_HAL_VIRTUAL_VECTOR_NUM_CHANNELS > 1    bool chan_set;#endif    unsigned long base = 0;    unsigned long end = 0;    char type[4];    char *filename = 0;    struct option_info opts[8];    connection_info_t info;    getc_io_funcs_t *io = NULL;    struct load_io_entry *io_tab;    unsigned int port;	//int because it's an OPTION_ARG_TYPE_NUM, but will be cast to short#ifdef CYGSEM_REDBOOT_VALIDATE_USER_RAM_LOADS    bool spillover_ok = false;#endif#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    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;#if CYGNUM_HAL_VIRTUAL_VECTOR_NUM_CHANNELS > 1    init_opts(&opts[num_options], 'c', true, OPTION_ARG_TYPE_NUM,               (void *)&chan, (bool *)&chan_set, "I/O channel");    num_options++;#endif#ifdef CYGPKG_REDBOOT_NETWORKING    init_opts(&opts[num_options], 'h', true, OPTION_ARG_TYPE_STR,               (void *)&hostname, (bool *)&hostname_set, "host name or IP address");    num_options++;    init_opts(&opts[num_options], 'p', true, OPTION_ARG_TYPE_NUM,               (void *)&port, (bool *)&port_set, "TCP port");    num_options++;#endif#ifdef CYGBLD_BUILD_REDBOOT_WITH_ZLIB    init_opts(&opts[num_options], 'd', false, OPTION_ARG_TYPE_FLG,               (void *)&decompress, 0, "decompress");    num_options++;#endif    CYG_ASSERT(num_options <= NUM_ELEMS(opts), "Too many options");        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) {        ip_route_t rt;        if (!_gethostbyname(hostname, (in_addr_t *)&host)) {            diag_printf("Invalid host: %s\n", hostname);            return;        }        /* check that the host can be accessed */        if (__arp_lookup((ip_addr_t *)&host.sin_addr, &rt) < 0) {            diag_printf("Unable to reach host %s (%s)\n",                        hostname, inet_ntoa((in_addr_t *)&host));            return;        }    }    if (port_set) 	    host.sin_port = port;#endif    if (chan >= CYGNUM_HAL_VIRTUAL_VECTOR_NUM_CHANNELS) {        diag_printf("Invalid I/O channel: %d\n", chan);        return;    }    if (mode_str_set) {        for (io_tab = __RedBoot_LOAD_TAB__;              io_tab != &__RedBoot_LOAD_TAB_END__;  io_tab++) {            if (strncasecmp(&mode_str[0], io_tab->name, strlen(&mode_str[0])) == 0) {                io = io_tab->funcs;                break;            }        }        if (!io) {            diag_printf("Invalid 'mode': %s.  Valid modes are:", mode_str);            for (io_tab = __RedBoot_LOAD_TAB__;                  io_tab != &__RedBoot_LOAD_TAB_END__;  io_tab++) {                diag_printf(" %s", io_tab->name);            }            diag_printf("\n");        }        if (!io) {            return;        }        verbose &= io_tab->can_verbose;        if (io_tab->need_filename && !filename) {            diag_printf("File name required\n");            diag_printf("usage: load %s\n", usage);            return;        }    } else {        char *which;        io_tab = (struct load_io_entry *)NULL;  // Default#ifdef CYGPKG_REDBOOT_NETWORKING#ifdef CYGSEM_REDBOOT_NET_TFTP_DOWNLOAD                which = "TFTP";        io = &tftp_io;#elif defined(CYGSEM_REDBOOT_NET_HTTP_DOWNLOAD)        which = "HTTP";        io = &http_io;#endif#endif#ifdef CYGPKG_REDBOOT_FILEIO        // Make file I/O default if mounted	if (fileio_mounted) {	    which = "file";	    io = &fileio_io;	}#endif        if (!io) {#ifdef CYGBLD_BUILD_REDBOOT_WITH_XYZMODEM            which = "Xmodem";            io = &xyzModem_io;            verbose = false;#else            diag_printf("No default protocol!\n");            return;#endif        }        diag_printf("Using default protocol (%s)\n", which);    }#ifdef CYGSEM_REDBOOT_VALIDATE_USER_RAM_LOADS    if (base_addr_set && !valid_address((unsigned char *)base)) {        if (!verify_action("Specified address (%p) is not believed to be in RAM", (void*)base))            return;        spillover_ok = true;    }#endif    if (raw && !base_addr_set) {        diag_printf("Raw load requires a memory address\n");        return;    }    info.filename = filename;    info.chan = chan;    info.mode = io_tab ? io_tab->mode : 0;#ifdef CYGPKG_REDBOOT_NETWORKING    info.server = &host;#endif    res = redboot_getc_init(&info, io, verbose, decompress);    if (res < 0) {        return;    }    // Stream open, process the data    if (raw) {        unsigned char *mp = (unsigned char *)base;        err = 0;        while ((res = redboot_getc()) >= 0) {#ifdef CYGSEM_REDBOOT_VALIDATE_USER_RAM_LOADS            if (!valid_address(mp) && !spillover_ok) {                // 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! RAW data spills over limit of user RAM at %p\n",(void*)mp);                err = -1;                break;            }#endif            *mp++ = res;        }        end = (unsigned long) mp;        // Save load base/top        load_address = base;        load_address_end = end;        entry_address = base;           // best guess        redboot_getc_terminate(false);        if (0 == err)            diag_printf("Raw file loaded %p-%p, assumed entry at %p\n",                         (void *)base, (void *)(end - 1), (void*)base);    } 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, base);            } else if ((type[0] == 'S') &&                       ((type[1] >= '0') && (type[1] <= '9'))) {		end = load_srec_image(redboot_getc, base);            } else {                redboot_getc_terminate(true);                diag_printf("Unrecognized image type: 0x%lx\n", *(unsigned long *)type);            }        }    }    redboot_getc_close();  // Clean up    return;}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -