File:  [Qemu by Fabrice Bellard] / qemu / loader.c
Revision 1.1.1.5 (vendor branch): download - view: text, annotated - select for diffs
Tue Apr 24 16:51:03 2018 UTC (3 years, 1 month ago) by root
Branches: qemu, MAIN
CVS tags: qemu0101, qemu0100, HEAD
qemu 0.10.0

    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:  * Gunzip functionality in this file is derived from u-boot:
   25:  *
   26:  * (C) Copyright 2008 Semihalf
   27:  *
   28:  * (C) Copyright 2000-2005
   29:  * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
   30:  *
   31:  * This program is free software; you can redistribute it and/or
   32:  * modify it under the terms of the GNU General Public License as
   33:  * published by the Free Software Foundation; either version 2 of
   34:  * the License, or (at your option) any later version.
   35:  *
   36:  * This program is distributed in the hope that it will be useful,
   37:  * but WITHOUT ANY WARRANTY; without even the implied warranty of
   38:  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.	 See the
   39:  * GNU General Public License for more details.
   40:  *
   41:  * You should have received a copy of the GNU General Public License along
   42:  * with this program; if not, write to the Free Software Foundation, Inc.,
   43:  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
   44:  */
   45: 
   46: #include "qemu-common.h"
   47: #include "disas.h"
   48: #include "sysemu.h"
   49: #include "uboot_image.h"
   50: 
   51: #include <zlib.h>
   52: 
   53: /* return the size or -1 if error */
   54: int get_image_size(const char *filename)
   55: {
   56:     int fd, size;
   57:     fd = open(filename, O_RDONLY | O_BINARY);
   58:     if (fd < 0)
   59:         return -1;
   60:     size = lseek(fd, 0, SEEK_END);
   61:     close(fd);
   62:     return size;
   63: }
   64: 
   65: /* return the size or -1 if error */
   66: /* deprecated, because caller does not specify buffer size! */
   67: int load_image(const char *filename, uint8_t *addr)
   68: {
   69:     int fd, size;
   70:     fd = open(filename, O_RDONLY | O_BINARY);
   71:     if (fd < 0)
   72:         return -1;
   73:     size = lseek(fd, 0, SEEK_END);
   74:     lseek(fd, 0, SEEK_SET);
   75:     if (read(fd, addr, size) != size) {
   76:         close(fd);
   77:         return -1;
   78:     }
   79:     close(fd);
   80:     return size;
   81: }
   82: 
   83: /* return the amount read, just like fread.  0 may mean error or eof */
   84: int fread_targphys(target_phys_addr_t dst_addr, size_t nbytes, FILE *f)
   85: {
   86:     uint8_t buf[4096];
   87:     target_phys_addr_t dst_begin = dst_addr;
   88:     size_t want, did;
   89: 
   90:     while (nbytes) {
   91: 	want = nbytes > sizeof(buf) ? sizeof(buf) : nbytes;
   92: 	did = fread(buf, 1, want, f);
   93: 	if (did != want) break;
   94: 
   95: 	cpu_physical_memory_write_rom(dst_addr, buf, did);
   96: 	dst_addr += did;
   97: 	nbytes -= did;
   98:     }
   99:     return dst_addr - dst_begin;
  100: }
  101: 
  102: /* returns 0 on error, 1 if ok */
  103: int fread_targphys_ok(target_phys_addr_t dst_addr, size_t nbytes, FILE *f)
  104: {
  105:     return fread_targphys(dst_addr, nbytes, f) == nbytes;
  106: }
  107: 
  108: /* read()-like version */
  109: int read_targphys(int fd, target_phys_addr_t dst_addr, size_t nbytes)
  110: {
  111:     uint8_t buf[4096];
  112:     target_phys_addr_t dst_begin = dst_addr;
  113:     size_t want, did;
  114: 
  115:     while (nbytes) {
  116: 	want = nbytes > sizeof(buf) ? sizeof(buf) : nbytes;
  117: 	did = read(fd, buf, want);
  118: 	if (did != want) break;
  119: 
  120: 	cpu_physical_memory_write_rom(dst_addr, buf, did);
  121: 	dst_addr += did;
  122: 	nbytes -= did;
  123:     }
  124:     return dst_addr - dst_begin;
  125: }
  126: 
  127: /* return the size or -1 if error */
  128: int load_image_targphys(const char *filename,
  129: 			target_phys_addr_t addr, int max_sz)
  130: {
  131:     FILE *f;
  132:     size_t got;
  133: 
  134:     f = fopen(filename, "rb");
  135:     if (!f) return -1;
  136: 
  137:     got = fread_targphys(addr, max_sz, f);
  138:     if (ferror(f)) { fclose(f); return -1; }
  139:     fclose(f);
  140: 
  141:     return got;
  142: }
  143: 
  144: void pstrcpy_targphys(target_phys_addr_t dest, int buf_size,
  145:                       const char *source)
  146: {
  147:     static const uint8_t nul_byte = 0;
  148:     const char *nulp;
  149: 
  150:     if (buf_size <= 0) return;
  151:     nulp = memchr(source, 0, buf_size);
  152:     if (nulp) {
  153: 	cpu_physical_memory_write_rom(dest, (uint8_t *)source,
  154:                                       (nulp - source) + 1);
  155:     } else {
  156: 	cpu_physical_memory_write_rom(dest, (uint8_t *)source, buf_size - 1);
  157: 	cpu_physical_memory_write_rom(dest, &nul_byte, 1);
  158:     }
  159: }
  160: 
  161: /* A.OUT loader */
  162: 
  163: struct exec
  164: {
  165:   uint32_t a_info;   /* Use macros N_MAGIC, etc for access */
  166:   uint32_t a_text;   /* length of text, in bytes */
  167:   uint32_t a_data;   /* length of data, in bytes */
  168:   uint32_t a_bss;    /* length of uninitialized data area, in bytes */
  169:   uint32_t a_syms;   /* length of symbol table data in file, in bytes */
  170:   uint32_t a_entry;  /* start address */
  171:   uint32_t a_trsize; /* length of relocation info for text, in bytes */
  172:   uint32_t a_drsize; /* length of relocation info for data, in bytes */
  173: };
  174: 
  175: #ifdef BSWAP_NEEDED
  176: static void bswap_ahdr(struct exec *e)
  177: {
  178:     bswap32s(&e->a_info);
  179:     bswap32s(&e->a_text);
  180:     bswap32s(&e->a_data);
  181:     bswap32s(&e->a_bss);
  182:     bswap32s(&e->a_syms);
  183:     bswap32s(&e->a_entry);
  184:     bswap32s(&e->a_trsize);
  185:     bswap32s(&e->a_drsize);
  186: }
  187: #else
  188: #define bswap_ahdr(x) do { } while (0)
  189: #endif
  190: 
  191: #define N_MAGIC(exec) ((exec).a_info & 0xffff)
  192: #define OMAGIC 0407
  193: #define NMAGIC 0410
  194: #define ZMAGIC 0413
  195: #define QMAGIC 0314
  196: #define _N_HDROFF(x) (1024 - sizeof (struct exec))
  197: #define N_TXTOFF(x)							\
  198:     (N_MAGIC(x) == ZMAGIC ? _N_HDROFF((x)) + sizeof (struct exec) :	\
  199:      (N_MAGIC(x) == QMAGIC ? 0 : sizeof (struct exec)))
  200: #define N_TXTADDR(x) (N_MAGIC(x) == QMAGIC ? TARGET_PAGE_SIZE : 0)
  201: #define N_DATOFF(x) (N_TXTOFF(x) + (x).a_text)
  202: #define _N_SEGMENT_ROUND(x) (((x) + TARGET_PAGE_SIZE - 1) & ~(TARGET_PAGE_SIZE - 1))
  203: 
  204: #define _N_TXTENDADDR(x) (N_TXTADDR(x)+(x).a_text)
  205: 
  206: #define N_DATADDR(x) \
  207:     (N_MAGIC(x)==OMAGIC? (_N_TXTENDADDR(x)) \
  208:      : (_N_SEGMENT_ROUND (_N_TXTENDADDR(x))))
  209: 
  210: 
  211: int load_aout(const char *filename, target_phys_addr_t addr, int max_sz)
  212: {
  213:     int fd, size, ret;
  214:     struct exec e;
  215:     uint32_t magic;
  216: 
  217:     fd = open(filename, O_RDONLY | O_BINARY);
  218:     if (fd < 0)
  219:         return -1;
  220: 
  221:     size = read(fd, &e, sizeof(e));
  222:     if (size < 0)
  223:         goto fail;
  224: 
  225:     bswap_ahdr(&e);
  226: 
  227:     magic = N_MAGIC(e);
  228:     switch (magic) {
  229:     case ZMAGIC:
  230:     case QMAGIC:
  231:     case OMAGIC:
  232:         if (e.a_text + e.a_data > max_sz)
  233:             goto fail;
  234: 	lseek(fd, N_TXTOFF(e), SEEK_SET);
  235: 	size = read_targphys(fd, addr, e.a_text + e.a_data);
  236: 	if (size < 0)
  237: 	    goto fail;
  238: 	break;
  239:     case NMAGIC:
  240:         if (N_DATADDR(e) + e.a_data > max_sz)
  241:             goto fail;
  242: 	lseek(fd, N_TXTOFF(e), SEEK_SET);
  243: 	size = read_targphys(fd, addr, e.a_text);
  244: 	if (size < 0)
  245: 	    goto fail;
  246: 	ret = read_targphys(fd, addr + N_DATADDR(e), e.a_data);
  247: 	if (ret < 0)
  248: 	    goto fail;
  249: 	size += ret;
  250: 	break;
  251:     default:
  252: 	goto fail;
  253:     }
  254:     close(fd);
  255:     return size;
  256:  fail:
  257:     close(fd);
  258:     return -1;
  259: }
  260: 
  261: /* ELF loader */
  262: 
  263: static void *load_at(int fd, int offset, int size)
  264: {
  265:     void *ptr;
  266:     if (lseek(fd, offset, SEEK_SET) < 0)
  267:         return NULL;
  268:     ptr = qemu_malloc(size);
  269:     if (read(fd, ptr, size) != size) {
  270:         qemu_free(ptr);
  271:         return NULL;
  272:     }
  273:     return ptr;
  274: }
  275: 
  276: 
  277: #define ELF_CLASS   ELFCLASS32
  278: #include "elf.h"
  279: 
  280: #define SZ		32
  281: #define elf_word        uint32_t
  282: #define elf_sword        int32_t
  283: #define bswapSZs	bswap32s
  284: #include "elf_ops.h"
  285: 
  286: #undef elfhdr
  287: #undef elf_phdr
  288: #undef elf_shdr
  289: #undef elf_sym
  290: #undef elf_note
  291: #undef elf_word
  292: #undef elf_sword
  293: #undef bswapSZs
  294: #undef SZ
  295: #define elfhdr		elf64_hdr
  296: #define elf_phdr	elf64_phdr
  297: #define elf_note	elf64_note
  298: #define elf_shdr	elf64_shdr
  299: #define elf_sym		elf64_sym
  300: #define elf_word        uint64_t
  301: #define elf_sword        int64_t
  302: #define bswapSZs	bswap64s
  303: #define SZ		64
  304: #include "elf_ops.h"
  305: 
  306: /* return < 0 if error, otherwise the number of bytes loaded in memory */
  307: int load_elf(const char *filename, int64_t address_offset,
  308:              uint64_t *pentry, uint64_t *lowaddr, uint64_t *highaddr)
  309: {
  310:     int fd, data_order, host_data_order, must_swab, ret;
  311:     uint8_t e_ident[EI_NIDENT];
  312: 
  313:     fd = open(filename, O_RDONLY | O_BINARY);
  314:     if (fd < 0) {
  315:         perror(filename);
  316:         return -1;
  317:     }
  318:     if (read(fd, e_ident, sizeof(e_ident)) != sizeof(e_ident))
  319:         goto fail;
  320:     if (e_ident[0] != ELFMAG0 ||
  321:         e_ident[1] != ELFMAG1 ||
  322:         e_ident[2] != ELFMAG2 ||
  323:         e_ident[3] != ELFMAG3)
  324:         goto fail;
  325: #ifdef WORDS_BIGENDIAN
  326:     data_order = ELFDATA2MSB;
  327: #else
  328:     data_order = ELFDATA2LSB;
  329: #endif
  330:     must_swab = data_order != e_ident[EI_DATA];
  331: 
  332: #ifdef TARGET_WORDS_BIGENDIAN
  333:     host_data_order = ELFDATA2MSB;
  334: #else
  335:     host_data_order = ELFDATA2LSB;
  336: #endif
  337:     if (host_data_order != e_ident[EI_DATA])
  338:         return -1;
  339: 
  340:     lseek(fd, 0, SEEK_SET);
  341:     if (e_ident[EI_CLASS] == ELFCLASS64) {
  342:         ret = load_elf64(fd, address_offset, must_swab, pentry,
  343:                          lowaddr, highaddr);
  344:     } else {
  345:         ret = load_elf32(fd, address_offset, must_swab, pentry,
  346:                          lowaddr, highaddr);
  347:     }
  348: 
  349:     close(fd);
  350:     return ret;
  351: 
  352:  fail:
  353:     close(fd);
  354:     return -1;
  355: }
  356: 
  357: static void bswap_uboot_header(uboot_image_header_t *hdr)
  358: {
  359: #ifndef WORDS_BIGENDIAN
  360:     bswap32s(&hdr->ih_magic);
  361:     bswap32s(&hdr->ih_hcrc);
  362:     bswap32s(&hdr->ih_time);
  363:     bswap32s(&hdr->ih_size);
  364:     bswap32s(&hdr->ih_load);
  365:     bswap32s(&hdr->ih_ep);
  366:     bswap32s(&hdr->ih_dcrc);
  367: #endif
  368: }
  369: 
  370: 
  371: #define ZALLOC_ALIGNMENT	16
  372: 
  373: static void *zalloc(void *x, unsigned items, unsigned size)
  374: {
  375:     void *p;
  376: 
  377:     size *= items;
  378:     size = (size + ZALLOC_ALIGNMENT - 1) & ~(ZALLOC_ALIGNMENT - 1);
  379: 
  380:     p = qemu_malloc(size);
  381: 
  382:     return (p);
  383: }
  384: 
  385: static void zfree(void *x, void *addr, unsigned nb)
  386: {
  387:     qemu_free(addr);
  388: }
  389: 
  390: 
  391: #define HEAD_CRC	2
  392: #define EXTRA_FIELD	4
  393: #define ORIG_NAME	8
  394: #define COMMENT		0x10
  395: #define RESERVED	0xe0
  396: 
  397: #define DEFLATED	8
  398: 
  399: /* This is the maximum in uboot, so if a uImage overflows this, it would
  400:  * overflow on real hardware too. */
  401: #define UBOOT_MAX_GUNZIP_BYTES 0x800000
  402: 
  403: static ssize_t gunzip(void *dst, size_t dstlen, uint8_t *src,
  404:                       size_t srclen)
  405: {
  406:     z_stream s;
  407:     ssize_t dstbytes;
  408:     int r, i, flags;
  409: 
  410:     /* skip header */
  411:     i = 10;
  412:     flags = src[3];
  413:     if (src[2] != DEFLATED || (flags & RESERVED) != 0) {
  414:         puts ("Error: Bad gzipped data\n");
  415:         return -1;
  416:     }
  417:     if ((flags & EXTRA_FIELD) != 0)
  418:         i = 12 + src[10] + (src[11] << 8);
  419:     if ((flags & ORIG_NAME) != 0)
  420:         while (src[i++] != 0)
  421:             ;
  422:     if ((flags & COMMENT) != 0)
  423:         while (src[i++] != 0)
  424:             ;
  425:     if ((flags & HEAD_CRC) != 0)
  426:         i += 2;
  427:     if (i >= srclen) {
  428:         puts ("Error: gunzip out of data in header\n");
  429:         return -1;
  430:     }
  431: 
  432:     s.zalloc = zalloc;
  433:     s.zfree = (free_func)zfree;
  434: 
  435:     r = inflateInit2(&s, -MAX_WBITS);
  436:     if (r != Z_OK) {
  437:         printf ("Error: inflateInit2() returned %d\n", r);
  438:         return (-1);
  439:     }
  440:     s.next_in = src + i;
  441:     s.avail_in = srclen - i;
  442:     s.next_out = dst;
  443:     s.avail_out = dstlen;
  444:     r = inflate(&s, Z_FINISH);
  445:     if (r != Z_OK && r != Z_STREAM_END) {
  446:         printf ("Error: inflate() returned %d\n", r);
  447:         return -1;
  448:     }
  449:     dstbytes = s.next_out - (unsigned char *) dst;
  450:     inflateEnd(&s);
  451: 
  452:     return dstbytes;
  453: }
  454: 
  455: /* Load a U-Boot image.  */
  456: int load_uimage(const char *filename, target_ulong *ep, target_ulong *loadaddr,
  457:                 int *is_linux)
  458: {
  459:     int fd;
  460:     int size;
  461:     uboot_image_header_t h;
  462:     uboot_image_header_t *hdr = &h;
  463:     uint8_t *data = NULL;
  464:     int ret = -1;
  465: 
  466:     fd = open(filename, O_RDONLY | O_BINARY);
  467:     if (fd < 0)
  468:         return -1;
  469: 
  470:     size = read(fd, hdr, sizeof(uboot_image_header_t));
  471:     if (size < 0)
  472:         goto out;
  473: 
  474:     bswap_uboot_header(hdr);
  475: 
  476:     if (hdr->ih_magic != IH_MAGIC)
  477:         goto out;
  478: 
  479:     /* TODO: Implement other image types.  */
  480:     if (hdr->ih_type != IH_TYPE_KERNEL) {
  481:         fprintf(stderr, "Can only load u-boot image type \"kernel\"\n");
  482:         goto out;
  483:     }
  484: 
  485:     switch (hdr->ih_comp) {
  486:     case IH_COMP_NONE:
  487:     case IH_COMP_GZIP:
  488:         break;
  489:     default:
  490:         fprintf(stderr,
  491:                 "Unable to load u-boot images with compression type %d\n",
  492:                 hdr->ih_comp);
  493:         goto out;
  494:     }
  495: 
  496:     /* TODO: Check CPU type.  */
  497:     if (is_linux) {
  498:         if (hdr->ih_os == IH_OS_LINUX)
  499:             *is_linux = 1;
  500:         else
  501:             *is_linux = 0;
  502:     }
  503: 
  504:     *ep = hdr->ih_ep;
  505:     data = qemu_malloc(hdr->ih_size);
  506: 
  507:     if (read(fd, data, hdr->ih_size) != hdr->ih_size) {
  508:         fprintf(stderr, "Error reading file\n");
  509:         goto out;
  510:     }
  511: 
  512:     if (hdr->ih_comp == IH_COMP_GZIP) {
  513:         uint8_t *compressed_data;
  514:         size_t max_bytes;
  515:         ssize_t bytes;
  516: 
  517:         compressed_data = data;
  518:         max_bytes = UBOOT_MAX_GUNZIP_BYTES;
  519:         data = qemu_malloc(max_bytes);
  520: 
  521:         bytes = gunzip(data, max_bytes, compressed_data, hdr->ih_size);
  522:         qemu_free(compressed_data);
  523:         if (bytes < 0) {
  524:             fprintf(stderr, "Unable to decompress gzipped image!\n");
  525:             goto out;
  526:         }
  527:         hdr->ih_size = bytes;
  528:     }
  529: 
  530:     cpu_physical_memory_write_rom(hdr->ih_load, data, hdr->ih_size);
  531: 
  532:     if (loadaddr)
  533:         *loadaddr = hdr->ih_load;
  534: 
  535:     ret = hdr->ih_size;
  536: 
  537: out:
  538:     if (data)
  539:         qemu_free(data);
  540:     close(fd);
  541:     return ret;
  542: }

unix.superglobalmegacorp.com