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

📄 load.c

📁 eCos操作系统源码
💻 C
📖 第 1 页 / 共 2 页
字号:
//==========================================================================////      load.c////      RedBoot file/image loader////==========================================================================//####ECOSGPLCOPYRIGHTBEGIN####// -------------------------------------------// This file is part of eCos, the Embedded Configurable Operating System.// Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc.// Copyright (C) 2002, 2003, 2004 Gary Thomas//// eCos is free software; you can redistribute it and/or modify it under// the terms of the GNU General Public License as published by the Free// Software Foundation; either version 2 or (at your option) any later version.//// eCos is distributed in the hope that it will be useful, but WITHOUT ANY// WARRANTY; without even the implied warranty of MERCHANTABILITY or// FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License// for more details.//// You should have received a copy of the GNU General Public License along// with eCos; if not, write to the Free Software Foundation, Inc.,// 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.//// As a special exception, if other files instantiate templates or use macros// or inline functions from this file, or you compile this file and link it// with other works to produce a work based on this file, this file does not// by itself cause the resulting work to be covered by the GNU General Public// License. However the source code for this file must still be made available// in accordance with section (3) of the GNU General Public License.//// This exception does not invalidate any other reasons why a work based on// this file might be covered by the GNU General Public License.//// Alternative licenses for eCos may be arranged by contacting Red Hat, Inc.// at http://sources.redhat.com/ecos/ecos-license/// -------------------------------------------//####ECOSGPLCOPYRIGHTEND####//==========================================================================//#####DESCRIPTIONBEGIN####//// Author(s):    gthomas// Contributors: gthomas, tsmith// Date:         2000-07-14// Purpose:      // Description:  //              // This code is part of RedBoot (tm).////####DESCRIPTIONEND####////==========================================================================#include <redboot.h>#include <elf.h>#ifdef CYGBLD_BUILD_REDBOOT_WITH_XYZMODEM#include <xyzModem.h>#endif#ifdef CYGPKG_REDBOOT_DISK#include <fs/disk.h>#endif#ifdef CYGPKG_REDBOOT_FILEIO#include <fs/fileio.h>#endif#ifdef CYGPKG_REDBOOT_NETWORKING#ifdef CYGSEM_REDBOOT_NET_TFTP_DOWNLOAD#include <net/tftp_support.h>#endif#ifdef CYGSEM_REDBOOT_NET_HTTP_DOWNLOAD#include <net/http.h>#endif#endif#include <cyg/infra/cyg_ass.h>         // assertion macrosstatic char usage[] = "[-r] [-v] "#ifdef CYGBLD_BUILD_REDBOOT_WITH_ZLIB                      "[-d] "#endif#ifdef CYGPKG_REDBOOT_NETWORKING                      "[-h <host>] [-p <TCP port>]"#endif                      "[-m <varies>] "#if CYGNUM_HAL_VIRTUAL_VECTOR_NUM_CHANNELS > 1                      "[-c <channel_number>] "#endif                      "\n        [-b <base_address>] <file_name>";// Exported CLI functionRedBoot_cmd("load",             "Load a file",             usage,            do_load     );//// Stream I/O support//// Table describing the various I/O methodsCYG_HAL_TABLE_BEGIN( __RedBoot_LOAD_TAB__, RedBoot_load );CYG_HAL_TABLE_END( __RedBoot_LOAD_TAB_END__, RedBoot_load );extern struct load_io_entry __RedBoot_LOAD_TAB__[], __RedBoot_LOAD_TAB_END__;// Buffers, data used by redboot_getc#define BUF_SIZE 256struct {    getc_io_funcs_t *io;    int (*fun)(char *, int len, int *err);    unsigned char  buf[BUF_SIZE];    unsigned char *bufp;    int   avail, len, err;    int   verbose, decompress, tick;#ifdef CYGBLD_BUILD_REDBOOT_WITH_ZLIB    int (*raw_fun)(char *, int len, int *err);    _pipe_t load_pipe;    unsigned char _buffer[CYGNUM_REDBOOT_LOAD_ZLIB_BUFFER];#endif} getc_info;typedef int (*getc_t)(void);//// Read the next data byte from the stream.// Returns://    >= 0 - actual data//      -1 - error or EOF, status in getc_info.err//static int redboot_getc(void){    static char spin[] = "|/-\\|-";    if (getc_info.avail < 0) {      return -1;    }    if (getc_info.avail == 0) {        if (getc_info.verbose) {            diag_printf("%c\b", spin[getc_info.tick++]);            if (getc_info.tick >= sizeof(spin)) {                getc_info.tick = 0;            }        }        if (getc_info.len < BUF_SIZE) {            // No more data available            if (getc_info.verbose) diag_printf("\n");            return -1;        }        getc_info.bufp = getc_info.buf;        getc_info.len = (*getc_info.fun)(getc_info.bufp, BUF_SIZE, &getc_info.err);        if ((getc_info.avail = getc_info.len) <= 0) {            if (getc_info.len < 0) {                diag_printf("I/O error: %s\n", (getc_info.io->error)(getc_info.err));            }            if (getc_info.verbose) diag_printf("\n");            return -1;        }    }    getc_info.avail--;    return *getc_info.bufp++;}#ifdef CYGBLD_BUILD_REDBOOT_WITH_ZLIB//// Called to fetch a new chunk of data and decompress it//static int _decompress_stream(char *buf, int len, int *err){    _pipe_t* p = &getc_info.load_pipe;    int res, total;    total = 0;    while (len > 0) {        if (p->in_avail == 0) {            p->in_buf = &getc_info._buffer[0];            res = (*getc_info.raw_fun)(p->in_buf, CYGNUM_REDBOOT_LOAD_ZLIB_BUFFER,                                        &getc_info.err);            if ((p->in_avail = res) <= 0) {                // No more data                return total;            }        }        p->out_buf = buf;        p->out_size = 0;        p->out_max = len;        res = (*_dc_inflate)(p);        if (res != 0) {            *err = res;            return total;        }                len -= p->out_size;        buf += p->out_size;        total += p->out_size;    }    return total;}#endifstatic intredboot_getc_init(connection_info_t *info, getc_io_funcs_t *funcs,                   int verbose, int decompress){    int res;    res = (funcs->open)(info, &getc_info.err);        if (res < 0) {        diag_printf("Can't load '%s': %s\n", info->filename, (funcs->error)(getc_info.err));            return res;    }    getc_info.io = funcs;    getc_info.fun = funcs->read;    getc_info.avail = 0;    getc_info.len = BUF_SIZE;    getc_info.verbose = verbose;    getc_info.decompress = decompress;    getc_info.tick = 0;#ifdef CYGBLD_BUILD_REDBOOT_WITH_ZLIB    if (decompress) {        _pipe_t* p = &getc_info.load_pipe;        p->out_buf = &getc_info.buf[0];        p->out_size = 0;        p->in_avail = 0;        getc_info.raw_fun = getc_info.fun;        getc_info.fun = _decompress_stream;        getc_info.err = (*_dc_init)(p);        if (0 != getc_info.err && p->msg) {            diag_printf("open decompression error: %s\n", p->msg);        }    }#endif    return 0;}static voidredboot_getc_rewind(void){    getc_info.bufp = getc_info.buf;    getc_info.avail = getc_info.len;}static voidredboot_getc_terminate(bool abort){    if (getc_info.io->terminate) {        (getc_info.io->terminate)(abort, redboot_getc);    }}static voidredboot_getc_close(void){    (getc_info.io->close)(&getc_info.err);#ifdef CYGBLD_BUILD_REDBOOT_WITH_ZLIB    if (getc_info.decompress) {        _pipe_t* p = &getc_info.load_pipe;        int err = getc_info.err;        if (0 != err && p->msg) {            diag_printf("decompression error: %s\n", p->msg);        }        err = (*_dc_close)(p, getc_info.err);    }#endif}#ifdef CYGSEM_REDBOOT_ELF//// Support function - used to read bytes into a buffer// Returns the number of bytes read (stops short on errors)//static int_read(int (*getc)(void), unsigned char *buf, int len){    int total = 0;    int ch;    while (len-- > 0) {        ch = (*getc)();        if (ch < 0) {            // EOF or error            break;        }        *buf++ = ch;        total++;    }    return total;}#endif//// Load an ELF [binary] image //static unsigned longload_elf_image(getc_t getc, unsigned long base){#ifdef CYGSEM_REDBOOT_ELF    Elf32_Ehdr ehdr;#define MAX_PHDR 8    Elf32_Phdr phdr[MAX_PHDR];    unsigned long offset = 0;    int phx, len, ch;    unsigned char *addr;    unsigned long addr_offset = 0;    unsigned long highest_address = 0;    unsigned long lowest_address = 0xFFFFFFFF;    unsigned char *SHORT_DATA = "Short data reading ELF file\n";    // Read the header    if (_read(getc, (unsigned char *)&ehdr, sizeof(ehdr)) != sizeof(ehdr)) {        diag_printf("Can't read ELF header\n");        return 0;    }    offset += sizeof(ehdr);    #if 0 // DEBUG    diag_printf("Type: %d, Machine: %d, Version: %d, Entry: %p, PHoff: %p/%d/%d, SHoff: %p/%d/%d\n",                ehdr.e_type, ehdr.e_machine, ehdr.e_version, ehdr.e_entry,                 ehdr.e_phoff, ehdr.e_phentsize, ehdr.e_phnum,                ehdr.e_shoff, ehdr.e_shentsize, ehdr.e_shnum);#endif    if (ehdr.e_type != ET_EXEC) {        diag_printf("Only absolute ELF images supported\n");        return 0;    }    if (ehdr.e_phnum > MAX_PHDR) {        diag_printf("Too many program headers\n");        return 0;    }    while (offset < ehdr.e_phoff) {        if ((*getc)() < 0) {            diag_printf(SHORT_DATA);            return 0;        }        offset++;    }    for (phx = 0;  phx < ehdr.e_phnum;  phx++) {        if (_read(getc, (unsigned char *)&phdr[phx], sizeof(phdr[0])) != sizeof(phdr[0])) {            diag_printf("Can't read ELF program header\n");            return 0;        }#if 0 // DEBUG        diag_printf("Program header: type: %d, off: %p, va: %p, pa: %p, len: %d/%d, flags: %d\n",                    phdr[phx].p_type, phdr[phx].p_offset, phdr[phx].p_vaddr, phdr[phx].p_paddr,                    phdr[phx].p_filesz, phdr[phx].p_memsz, phdr[phx].p_flags);#endif        offset += sizeof(phdr[0]);    }    if (base) {        // Set address offset based on lowest address in file.        addr_offset = 0xFFFFFFFF;        for (phx = 0;  phx < ehdr.e_phnum;  phx++) {                if ((phdr[phx].p_type == PT_LOAD) && (phdr[phx].p_paddr < addr_offset)) {                addr_offset = phdr[phx].p_paddr;            }        }        addr_offset = (unsigned long)base - addr_offset;    } else {        addr_offset = 0;    }    for (phx = 0;  phx < ehdr.e_phnum;  phx++) {        if (phdr[phx].p_type == PT_LOAD) {            // Loadable segment            addr = (unsigned char *)phdr[phx].p_paddr;            len = phdr[phx].p_filesz;            if ((unsigned long)addr < lowest_address) {                lowest_address = (unsigned long)addr;            }            addr += addr_offset;            if (offset > phdr[phx].p_offset) {                if ((phdr[phx].p_offset + len) < offset) {                    diag_printf("Can't load ELF file - program headers out of order\n");                    return 0;                }                addr += offset - phdr[phx].p_offset;            } else {                while (offset < phdr[phx].p_offset) {                    if ((*getc)() < 0) {                        diag_printf(SHORT_DATA);                        return 0;                    }                    offset++;                }            }            // Copy data into memory            while (len-- > 0) {#ifdef CYGSEM_REDBOOT_VALIDATE_USER_RAM_LOADS                if (!valid_address(addr)) {                    redboot_getc_terminate(true);                    diag_printf("*** Abort! Attempt to load ELF data to address: %p which is not in RAM\n", (void*)addr);                    return 0;                }#endif                if ((ch = (*getc)()) < 0) {                    diag_printf(SHORT_DATA);                    return 0;                }                *addr++ = ch;                offset++;                if ((unsigned long)(addr-addr_offset) > highest_address) {                    highest_address = (unsigned long)(addr - addr_offset);                }            }        }    }    // Save load base/top and entry    if (base) {        load_address = base;

⌨️ 快捷键说明

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