Separate thread for IO handling
[qemu-kvm/fedora.git] / loader.c
blob5cf079ae7afcea5c34a2ec94a50e39aaded0f5cb
1 /*
2 * QEMU Executable loader
4 * Copyright (c) 2006 Fabrice Bellard
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:
13 * The above copyright notice and this permission notice shall be included in
14 * all copies or substantial portions of the Software.
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.
24 #include "qemu-common.h"
25 #include "disas.h"
26 #include "sysemu.h"
27 #include "uboot_image.h"
29 #include <zlib.h>
31 /* return the size or -1 if error */
32 int get_image_size(const char *filename)
34 int fd, size;
35 fd = open(filename, O_RDONLY | O_BINARY);
36 if (fd < 0)
37 return -1;
38 size = lseek(fd, 0, SEEK_END);
39 close(fd);
40 return size;
43 /* return the size or -1 if error */
44 int load_image(const char *filename, uint8_t *addr)
46 int fd, size;
47 fd = open(filename, O_RDONLY | O_BINARY);
48 if (fd < 0)
49 return -1;
50 size = lseek(fd, 0, SEEK_END);
51 lseek(fd, 0, SEEK_SET);
52 if (read(fd, addr, size) != size) {
53 close(fd);
54 return -1;
56 close(fd);
57 return size;
60 /* A.OUT loader */
62 struct exec
64 uint32_t a_info; /* Use macros N_MAGIC, etc for access */
65 uint32_t a_text; /* length of text, in bytes */
66 uint32_t a_data; /* length of data, in bytes */
67 uint32_t a_bss; /* length of uninitialized data area, in bytes */
68 uint32_t a_syms; /* length of symbol table data in file, in bytes */
69 uint32_t a_entry; /* start address */
70 uint32_t a_trsize; /* length of relocation info for text, in bytes */
71 uint32_t a_drsize; /* length of relocation info for data, in bytes */
74 #ifdef BSWAP_NEEDED
75 static void bswap_ahdr(struct exec *e)
77 bswap32s(&e->a_info);
78 bswap32s(&e->a_text);
79 bswap32s(&e->a_data);
80 bswap32s(&e->a_bss);
81 bswap32s(&e->a_syms);
82 bswap32s(&e->a_entry);
83 bswap32s(&e->a_trsize);
84 bswap32s(&e->a_drsize);
86 #else
87 #define bswap_ahdr(x) do { } while (0)
88 #endif
90 #define N_MAGIC(exec) ((exec).a_info & 0xffff)
91 #define OMAGIC 0407
92 #define NMAGIC 0410
93 #define ZMAGIC 0413
94 #define QMAGIC 0314
95 #define _N_HDROFF(x) (1024 - sizeof (struct exec))
96 #define N_TXTOFF(x) \
97 (N_MAGIC(x) == ZMAGIC ? _N_HDROFF((x)) + sizeof (struct exec) : \
98 (N_MAGIC(x) == QMAGIC ? 0 : sizeof (struct exec)))
99 #define N_TXTADDR(x) (N_MAGIC(x) == QMAGIC ? TARGET_PAGE_SIZE : 0)
100 #define N_DATOFF(x) (N_TXTOFF(x) + (x).a_text)
101 #define _N_SEGMENT_ROUND(x) (((x) + TARGET_PAGE_SIZE - 1) & ~(TARGET_PAGE_SIZE - 1))
103 #define _N_TXTENDADDR(x) (N_TXTADDR(x)+(x).a_text)
105 #define N_DATADDR(x) \
106 (N_MAGIC(x)==OMAGIC? (_N_TXTENDADDR(x)) \
107 : (_N_SEGMENT_ROUND (_N_TXTENDADDR(x))))
110 int load_aout(const char *filename, uint8_t *addr)
112 int fd, size, ret;
113 struct exec e;
114 uint32_t magic;
116 fd = open(filename, O_RDONLY | O_BINARY);
117 if (fd < 0)
118 return -1;
120 size = read(fd, &e, sizeof(e));
121 if (size < 0)
122 goto fail;
124 bswap_ahdr(&e);
126 magic = N_MAGIC(e);
127 switch (magic) {
128 case ZMAGIC:
129 case QMAGIC:
130 case OMAGIC:
131 lseek(fd, N_TXTOFF(e), SEEK_SET);
132 size = read(fd, addr, e.a_text + e.a_data);
133 if (size < 0)
134 goto fail;
135 break;
136 case NMAGIC:
137 lseek(fd, N_TXTOFF(e), SEEK_SET);
138 size = read(fd, addr, e.a_text);
139 if (size < 0)
140 goto fail;
141 ret = read(fd, addr + N_DATADDR(e), e.a_data);
142 if (ret < 0)
143 goto fail;
144 size += ret;
145 break;
146 default:
147 goto fail;
149 close(fd);
150 return size;
151 fail:
152 close(fd);
153 return -1;
156 /* ELF loader */
158 static void *load_at(int fd, int offset, int size)
160 void *ptr;
161 if (lseek(fd, offset, SEEK_SET) < 0)
162 return NULL;
163 ptr = qemu_malloc(size);
164 if (!ptr)
165 return NULL;
166 if (read(fd, ptr, size) != size) {
167 qemu_free(ptr);
168 return NULL;
170 return ptr;
174 #define ELF_CLASS ELFCLASS32
175 #include "elf.h"
177 #define SZ 32
178 #define elf_word uint32_t
179 #define elf_sword int32_t
180 #define bswapSZs bswap32s
181 #include "elf_ops.h"
183 #undef elfhdr
184 #undef elf_phdr
185 #undef elf_shdr
186 #undef elf_sym
187 #undef elf_note
188 #undef elf_word
189 #undef elf_sword
190 #undef bswapSZs
191 #undef SZ
192 #define elfhdr elf64_hdr
193 #define elf_phdr elf64_phdr
194 #define elf_note elf64_note
195 #define elf_shdr elf64_shdr
196 #define elf_sym elf64_sym
197 #define elf_word uint64_t
198 #define elf_sword int64_t
199 #define bswapSZs bswap64s
200 #define SZ 64
201 #include "elf_ops.h"
203 /* return < 0 if error, otherwise the number of bytes loaded in memory */
204 int load_elf(const char *filename, int64_t virt_to_phys_addend,
205 uint64_t *pentry, uint64_t *lowaddr, uint64_t *highaddr)
207 int fd, data_order, host_data_order, must_swab, ret;
208 uint8_t e_ident[EI_NIDENT];
210 fd = open(filename, O_RDONLY | O_BINARY);
211 if (fd < 0) {
212 perror(filename);
213 return -1;
215 if (read(fd, e_ident, sizeof(e_ident)) != sizeof(e_ident))
216 goto fail;
217 if (e_ident[0] != ELFMAG0 ||
218 e_ident[1] != ELFMAG1 ||
219 e_ident[2] != ELFMAG2 ||
220 e_ident[3] != ELFMAG3)
221 goto fail;
222 #ifdef WORDS_BIGENDIAN
223 data_order = ELFDATA2MSB;
224 #else
225 data_order = ELFDATA2LSB;
226 #endif
227 must_swab = data_order != e_ident[EI_DATA];
229 #ifdef TARGET_WORDS_BIGENDIAN
230 host_data_order = ELFDATA2MSB;
231 #else
232 host_data_order = ELFDATA2LSB;
233 #endif
234 if (host_data_order != e_ident[EI_DATA])
235 return -1;
237 lseek(fd, 0, SEEK_SET);
238 if (e_ident[EI_CLASS] == ELFCLASS64) {
239 ret = load_elf64(fd, virt_to_phys_addend, must_swab, pentry,
240 lowaddr, highaddr);
241 } else {
242 ret = load_elf32(fd, virt_to_phys_addend, must_swab, pentry,
243 lowaddr, highaddr);
246 close(fd);
247 return ret;
249 fail:
250 close(fd);
251 return -1;
254 static void bswap_uboot_header(uboot_image_header_t *hdr)
256 #ifndef WORDS_BIGENDIAN
257 bswap32s(&hdr->ih_magic);
258 bswap32s(&hdr->ih_hcrc);
259 bswap32s(&hdr->ih_time);
260 bswap32s(&hdr->ih_size);
261 bswap32s(&hdr->ih_load);
262 bswap32s(&hdr->ih_ep);
263 bswap32s(&hdr->ih_dcrc);
264 #endif
267 /* Load a U-Boot image. */
269 /* gunzip functionality is derived from gunzip function
270 * in uboot source code
273 #define ZALLOC_ALIGNMENT 16
275 static void *zalloc(void *x, unsigned items, unsigned size)
277 void *p;
279 size *= items;
280 size = (size + ZALLOC_ALIGNMENT - 1) & ~(ZALLOC_ALIGNMENT - 1);
282 p = malloc (size);
284 return (p);
287 static void zfree(void *x, void *addr, unsigned nb)
289 free (addr);
293 #define HEAD_CRC 2
294 #define EXTRA_FIELD 4
295 #define ORIG_NAME 8
296 #define COMMENT 0x10
297 #define RESERVED 0xe0
299 #define DEFLATED 8
301 static int gunzip(void *dst, int dstlen, unsigned char *src,
302 unsigned long *lenp)
304 z_stream s;
305 int r, i, flags;
307 /* skip header */
308 i = 10;
309 flags = src[3];
310 if (src[2] != DEFLATED || (flags & RESERVED) != 0) {
311 puts ("Error: Bad gzipped data\n");
312 return -1;
314 if ((flags & EXTRA_FIELD) != 0)
315 i = 12 + src[10] + (src[11] << 8);
316 if ((flags & ORIG_NAME) != 0)
317 while (src[i++] != 0)
319 if ((flags & COMMENT) != 0)
320 while (src[i++] != 0)
322 if ((flags & HEAD_CRC) != 0)
323 i += 2;
324 if (i >= *lenp) {
325 puts ("Error: gunzip out of data in header\n");
326 return -1;
329 s.zalloc = zalloc;
330 s.zfree = (free_func)zfree;
332 r = inflateInit2(&s, -MAX_WBITS);
333 if (r != Z_OK) {
334 printf ("Error: inflateInit2() returned %d\n", r);
335 return (-1);
337 s.next_in = src + i;
338 s.avail_in = *lenp - i;
339 s.next_out = dst;
340 s.avail_out = dstlen;
341 r = inflate(&s, Z_FINISH);
342 if (r != Z_OK && r != Z_STREAM_END) {
343 printf ("Error: inflate() returned %d\n", r);
344 return -1;
346 *lenp = s.next_out - (unsigned char *) dst;
347 inflateEnd(&s);
349 return 0;
353 #define MAX_KERNEL_SIZE 8<<20 //8MB
354 /* This functions can load uImage & cuImage files */
355 int load_uimage(const char *filename, target_ulong *ep,
356 target_ulong *load_address,
357 target_ulong *loaded_image_size,
358 int *is_linux)
360 int fd;
361 int size;
362 int ret;
363 uboot_image_header_t h;
364 uboot_image_header_t *hdr = &h;
365 uint8_t *data = NULL;
366 uint8_t *uncompressed_data = NULL;
367 unsigned long tmp_loaded_image_size;
369 fd = open(filename, O_RDONLY | O_BINARY);
370 if (fd < 0)
371 return -1;
373 size = read(fd, hdr, sizeof(uboot_image_header_t));
374 if (size < 0)
375 goto fail;
377 bswap_uboot_header(hdr);
379 if (hdr->ih_magic != IH_MAGIC)
380 goto fail;
382 /* TODO: Implement Multi-File images. */
383 if (hdr->ih_type == IH_TYPE_MULTI) {
384 fprintf(stderr, "Unable to load multi-file u-boot images\n");
385 goto fail;
388 /* TODO bzip2 support */
389 if (hdr->ih_comp == IH_COMP_BZIP2) {
390 fprintf(stderr, "Unable to load bzip2 compressed u-boot images\n");
391 goto fail;
394 /* TODO: Check CPU type. */
396 if (is_linux) {
397 if (hdr->ih_type == IH_TYPE_KERNEL && hdr->ih_os == IH_OS_LINUX)
398 *is_linux = 1;
399 else
400 *is_linux = 0;
403 *ep = hdr->ih_ep;
405 data = qemu_malloc(hdr->ih_size);
406 if (!data)
407 goto fail;
409 if (read(fd, data, hdr->ih_size) != hdr->ih_size) {
410 fprintf(stderr, "Error reading file\n");
411 goto fail;
414 tmp_loaded_image_size = hdr->ih_size;
416 if (hdr->ih_comp == IH_COMP_GZIP) {
417 uncompressed_data = qemu_malloc(MAX_KERNEL_SIZE);
418 ret = gunzip(uncompressed_data, MAX_KERNEL_SIZE,
419 (unsigned char *) data,
420 &tmp_loaded_image_size);
422 if (ret < 0) {
423 fprintf(stderr, "Unable to decompress gziped image!\n");
424 goto fail;
427 qemu_free(data);
428 cpu_physical_memory_write_rom(hdr->ih_load, uncompressed_data,
429 tmp_loaded_image_size);
430 } else {
431 cpu_physical_memory_write_rom(hdr->ih_load, data,
432 tmp_loaded_image_size);
435 if (loaded_image_size != NULL)
436 *loaded_image_size = tmp_loaded_image_size;
438 if (load_address != NULL)
439 *load_address = hdr->ih_load;
441 return 0;
443 fail:
444 if (data)
445 qemu_free(data);
446 close(fd);
447 return -1;
450 /* XXX this function is to keep compatibility with other
451 * qemu callers. Once those callers are modified. This function
452 * should be removed from here & sysemu.h
454 int load_uboot(const char *filename, target_ulong *ep, int *is_linux)
456 int ret;
457 target_ulong size;
459 ret = load_uimage(filename, ep, NULL, &size, is_linux);
461 if (ret < 0)
462 return ret;
463 else
464 return (int)size;