(linenum→info "unix/slp.c:2238")

qemu/0.9.1/loader.c

    1: /*
    2:  * QEMU Executable loader
    3:  *
    4:  * Copyright (c) 2006 Fabrice Bellard
    5:  *
    6:  * Permission is hereby granted, free of charge, to any person obtaining a copy
    7:  * of this software and associated documentation files (the "Software"), to deal
    8:  * in the Software without restriction, including without limitation the rights
    9:  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
   10:  * copies of the Software, and to permit persons to whom the Software is
   11:  * furnished to do so, subject to the following conditions:
   12:  *
   13:  * The above copyright notice and this permission notice shall be included in
   14:  * all copies or substantial portions of the Software.
   15:  *
   16:  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
   17:  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
   18:  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
   19:  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
   20:  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
   21:  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
   22:  * THE SOFTWARE.
   23:  */
   24: #include "qemu-common.h"
   25: #include "disas.h"
   26: #include "sysemu.h"
   27: #include "uboot_image.h"
   28: 
   29: /* return the size or -1 if error */
   30: int get_image_size(const char *filename)
   31: {
   32:     int fd, size;
   33:     fd = open(filename, O_RDONLY | O_BINARY);
   34:     if (fd < 0)
   35:         return -1;
   36:     size = lseek(fd, 0, SEEK_END);
   37:     close(fd);
   38:     return size;
   39: }
   40: 
   41: /* return the size or -1 if error */
   42: int load_image(const char *filename, uint8_t *addr)
   43: {
   44:     int fd, size;
   45:     fd = open(filename, O_RDONLY | O_BINARY);
   46:     if (fd < 0)
   47:         return -1;
   48:     size = lseek(fd, 0, SEEK_END);
   49:     lseek(fd, 0, SEEK_SET);
   50:     if (read(fd, addr, size) != size) {
   51:         close(fd);
   52:         return -1;
   53:     }
   54:     close(fd);
   55:     return size;
   56: }
   57: 
   58: /* A.OUT loader */
   59: 
   60: struct exec
   61: {
   62:   uint32_t a_info;   /* Use macros N_MAGIC, etc for access */
   63:   uint32_t a_text;   /* length of text, in bytes */
   64:   uint32_t a_data;   /* length of data, in bytes */
   65:   uint32_t a_bss;    /* length of uninitialized data area, in bytes */
   66:   uint32_t a_syms;   /* length of symbol table data in file, in bytes */
   67:   uint32_t a_entry;  /* start address */
   68:   uint32_t a_trsize; /* length of relocation info for text, in bytes */
   69:   uint32_t a_drsize; /* length of relocation info for data, in bytes */
   70: };
   71: 
   72: #ifdef BSWAP_NEEDED
   73: static void bswap_ahdr(struct exec *e)
   74: {
   75:     bswap32s(&e->a_info);
   76:     bswap32s(&e->a_text);
   77:     bswap32s(&e->a_data);
   78:     bswap32s(&e->a_bss);
   79:     bswap32s(&e->a_syms);
   80:     bswap32s(&e->a_entry);
   81:     bswap32s(&e->a_trsize);
   82:     bswap32s(&e->a_drsize);
   83: }
   84: #else
   85: #define bswap_ahdr(x) do { } while (0)
   86: #endif
   87: 
   88: #define N_MAGIC(exec) ((exec).a_info & 0xffff)
   89: #define OMAGIC 0407
   90: #define NMAGIC 0410
   91: #define ZMAGIC 0413
   92: #define QMAGIC 0314
   93: #define _N_HDROFF(x) (1024 - sizeof (struct exec))
   94: #define N_TXTOFF(x)                                                     \
   95:     (N_MAGIC(x) == ZMAGIC ? _N_HDROFF((x)) + sizeof (struct exec) :     \
   96:      (N_MAGIC(x) == QMAGIC ? 0 : sizeof (struct exec)))
   97: #define N_TXTADDR(x) (N_MAGIC(x) == QMAGIC ? TARGET_PAGE_SIZE : 0)
   98: #define N_DATOFF(x) (N_TXTOFF(x) + (x).a_text)
   99: #define _N_SEGMENT_ROUND(x) (((x) + TARGET_PAGE_SIZE - 1) & ~(TARGET_PAGE_SIZE - 1))
  100: 
  101: #define _N_TXTENDADDR(x) (N_TXTADDR(x)+(x).a_text)
  102: 
  103: #define N_DATADDR(x) \
  104:     (N_MAGIC(x)==OMAGIC? (_N_TXTENDADDR(x)) \
  105:      : (_N_SEGMENT_ROUND (_N_TXTENDADDR(x))))
  106: 
  107: 
  108: int load_aout(const char *filename, uint8_t *addr)
  109: {
  110:     int fd, size, ret;
  111:     struct exec e;
  112:     uint32_t magic;
  113: 
  114:     fd = open(filename, O_RDONLY | O_BINARY);
  115:     if (fd < 0)
  116:         return -1;
  117: 
  118:     size = read(fd, &e, sizeof(e));
  119:     if (size < 0)
  120:         goto fail;
  121: 
  122:     bswap_ahdr(&e);
  123: 
  124:     magic = N_MAGIC(e);
  125:     switch (magic) {
  126:     case ZMAGIC:
  127:     case QMAGIC:
  128:     case OMAGIC:
  129:         lseek(fd, N_TXTOFF(e), SEEK_SET);
  130:         size = read(fd, addr, e.a_text + e.a_data);
  131:         if (size < 0)
  132:             goto fail;
  133:         break;
  134:     case NMAGIC:
  135:         lseek(fd, N_TXTOFF(e), SEEK_SET);
  136:         size = read(fd, addr, e.a_text);
  137:         if (size < 0)
  138:             goto fail;
  139:         ret = read(fd, addr + N_DATADDR(e), e.a_data);
  140:         if (ret < 0)
  141:             goto fail;
  142:         size += ret;
  143:         break;
  144:     default:
  145:         goto fail;
  146:     }
  147:     close(fd);
  148:     return size;
  149:  fail:
  150:     close(fd);
  151:     return -1;
  152: }
  153: 
  154: /* ELF loader */
  155: 
  156: static void *load_at(int fd, int offset, int size)
  157: {
  158:     void *ptr;
  159:     if (lseek(fd, offset, SEEK_SET) < 0)
  160:         return NULL;
  161:     ptr = qemu_malloc(size);
  162:     if (!ptr)
  163:         return NULL;
  164:     if (read(fd, ptr, size) != size) {
  165:         qemu_free(ptr);
  166:         return NULL;
  167:     }
  168:     return ptr;
  169: }
  170: 
  171: 
  172: #define ELF_CLASS   ELFCLASS32
  173: #include "elf.h"
  174: 
  175: #define SZ              32
  176: #define elf_word        uint32_t
  177: #define elf_sword        int32_t
  178: #define bswapSZs        bswap32s
  179: #include "elf_ops.h"
  180: 
  181: #undef elfhdr
  182: #undef elf_phdr
  183: #undef elf_shdr
  184: #undef elf_sym
  185: #undef elf_note
  186: #undef elf_word
  187: #undef elf_sword
  188: #undef bswapSZs
  189: #undef SZ
  190: #define elfhdr          elf64_hdr
  191: #define elf_phdr        elf64_phdr
  192: #define elf_note        elf64_note
  193: #define elf_shdr        elf64_shdr
  194: #define elf_sym         elf64_sym
  195: #define elf_word        uint64_t
  196: #define elf_sword        int64_t
  197: #define bswapSZs        bswap64s
  198: #define SZ              64
  199: #include "elf_ops.h"
  200: 
  201: /* return < 0 if error, otherwise the number of bytes loaded in memory */
  202: int load_elf(const char *filename, int64_t virt_to_phys_addend,
  203:              uint64_t *pentry, uint64_t *lowaddr, uint64_t *highaddr)
  204: {
  205:     int fd, data_order, host_data_order, must_swab, ret;
  206:     uint8_t e_ident[EI_NIDENT];
  207: 
  208:     fd = open(filename, O_RDONLY | O_BINARY);
  209:     if (fd < 0) {
  210:         perror(filename);
  211:         return -1;
  212:     }
  213:     if (read(fd, e_ident, sizeof(e_ident)) != sizeof(e_ident))
  214:         goto fail;
  215:     if (e_ident[0] != ELFMAG0 ||
  216:         e_ident[1] != ELFMAG1 ||
  217:         e_ident[2] != ELFMAG2 ||
  218:         e_ident[3] != ELFMAG3)
  219:         goto fail;
  220: #ifdef WORDS_BIGENDIAN
  221:     data_order = ELFDATA2MSB;
  222: #else
  223:     data_order = ELFDATA2LSB;
  224: #endif
  225:     must_swab = data_order != e_ident[EI_DATA];
  226: 
  227: #ifdef TARGET_WORDS_BIGENDIAN
  228:     host_data_order = ELFDATA2MSB;
  229: #else
  230:     host_data_order = ELFDATA2LSB;
  231: #endif
  232:     if (host_data_order != e_ident[EI_DATA])
  233:         return -1;
  234: 
  235:     lseek(fd, 0, SEEK_SET);
  236:     if (e_ident[EI_CLASS] == ELFCLASS64) {
  237:         ret = load_elf64(fd, virt_to_phys_addend, must_swab, pentry,
  238:                          lowaddr, highaddr);
  239:     } else {
  240:         ret = load_elf32(fd, virt_to_phys_addend, must_swab, pentry,
  241:                          lowaddr, highaddr);
  242:     }
  243: 
  244:     close(fd);
  245:     return ret;
  246: 
  247:  fail:
  248:     close(fd);
  249:     return -1;
  250: }
  251: 
  252: static void bswap_uboot_header(uboot_image_header_t *hdr)
  253: {
  254: #ifndef WORDS_BIGENDIAN
  255:     bswap32s(&hdr->ih_magic);
  256:     bswap32s(&hdr->ih_hcrc);
  257:     bswap32s(&hdr->ih_time);
  258:     bswap32s(&hdr->ih_size);
  259:     bswap32s(&hdr->ih_load);
  260:     bswap32s(&hdr->ih_ep);
  261:     bswap32s(&hdr->ih_dcrc);
  262: #endif
  263: }
  264: 
  265: /* Load a U-Boot image.  */
  266: int load_uboot(const char *filename, target_ulong *ep, int *is_linux)
  267: {
  268: 
  269:     int fd;
  270:     int size;
  271:     uboot_image_header_t h;
  272:     uboot_image_header_t *hdr = &h;
  273:     uint8_t *data = NULL;
  274: 
  275:     fd = open(filename, O_RDONLY | O_BINARY);
  276:     if (fd < 0)
  277:         return -1;
  278: 
  279:     size = read(fd, hdr, sizeof(uboot_image_header_t));
  280:     if (size < 0)
  281:         goto fail;
  282: 
  283:     bswap_uboot_header(hdr);
  284: 
  285:     if (hdr->ih_magic != IH_MAGIC)
  286:         goto fail;
  287: 
  288:     /* TODO: Implement Multi-File images.  */
  289:     if (hdr->ih_type == IH_TYPE_MULTI) {
  290:         fprintf(stderr, "Unable to load multi-file u-boot images\n");
  291:         goto fail;
  292:     }
  293: 
  294:     /* TODO: Implement compressed images.  */
  295:     if (hdr->ih_comp != IH_COMP_NONE) {
  296:         fprintf(stderr, "Unable to load compressed u-boot images\n");
  297:         goto fail;
  298:     }
  299: 
  300:     /* TODO: Check CPU type.  */
  301:     if (is_linux) {
  302:         if (hdr->ih_type == IH_TYPE_KERNEL && hdr->ih_os == IH_OS_LINUX)
  303:             *is_linux = 1;
  304:         else
  305:             *is_linux = 0;
  306:     }
  307: 
  308:     *ep = hdr->ih_ep;
  309:     data = qemu_malloc(hdr->ih_size);
  310:     if (!data)
  311:         goto fail;
  312: 
  313:     if (read(fd, data, hdr->ih_size) != hdr->ih_size) {
  314:         fprintf(stderr, "Error reading file\n");
  315:         goto fail;
  316:     }
  317: 
  318:     cpu_physical_memory_write_rom(hdr->ih_load, data, hdr->ih_size);
  319: 
  320:     return hdr->ih_size;
  321: 
  322: fail:
  323:     if (data)
  324:         qemu_free(data);
  325:     close(fd);
  326:     return -1;
  327: }
Syntax (Markdown)