Merge lp:~dannf/qemu-linaro/highbank into lp:ubuntu/quantal/qemu-linaro
- highbank
- Merge into quantal
Proposed by
dann frazier
Status: | Merged | ||||
---|---|---|---|---|---|
Approved by: | Stéphane Graber | ||||
Approved revision: | 12924 | ||||
Merge reported by: | Adam Conrad | ||||
Merged at revision: | not available | ||||
Proposed branch: | lp:~dannf/qemu-linaro/highbank | ||||
Merge into: | lp:ubuntu/quantal/qemu-linaro | ||||
Diff against target: |
970 lines (+897/-2) 9 files modified
.pc/applied-patches (+1/-0) .pc/use-an-uint64_t-for-the-max_sz-parameter-in-load_image_targphys.patch/hw/loader.c (+801/-0) .pc/use-an-uint64_t-for-the-max_sz-parameter-in-load_image_targphys.patch/hw/loader.h (+48/-0) debian/changelog (+8/-0) debian/control (+1/-0) debian/patches/series (+1/-0) debian/patches/use-an-uint64_t-for-the-max_sz-parameter-in-load_image_targphys.patch (+34/-0) hw/loader.c (+1/-1) hw/loader.h (+2/-1) |
||||
To merge this branch: | bzr merge lp:~dannf/qemu-linaro/highbank | ||||
Related bugs: |
|
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Ubuntu branches | Pending | ||
Review via email: mp+117327@code.launchpad.net |
Commit message
Description of the change
To post a comment you must log in.
Revision history for this message
Stéphane Graber (stgraber) wrote : | # |
Preview Diff
[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1 | === modified file '.pc/applied-patches' |
2 | --- .pc/applied-patches 2012-04-22 13:53:58 +0000 |
3 | +++ .pc/applied-patches 2012-07-30 19:32:20 +0000 |
4 | @@ -1,2 +1,3 @@ |
5 | define_AT_EMPTY_PATH.patch |
6 | powerpc-missing-include.patch |
7 | +use-an-uint64_t-for-the-max_sz-parameter-in-load_image_targphys.patch |
8 | |
9 | === added directory '.pc/use-an-uint64_t-for-the-max_sz-parameter-in-load_image_targphys.patch' |
10 | === added directory '.pc/use-an-uint64_t-for-the-max_sz-parameter-in-load_image_targphys.patch/hw' |
11 | === added file '.pc/use-an-uint64_t-for-the-max_sz-parameter-in-load_image_targphys.patch/hw/loader.c' |
12 | --- .pc/use-an-uint64_t-for-the-max_sz-parameter-in-load_image_targphys.patch/hw/loader.c 1970-01-01 00:00:00 +0000 |
13 | +++ .pc/use-an-uint64_t-for-the-max_sz-parameter-in-load_image_targphys.patch/hw/loader.c 2012-07-30 19:32:20 +0000 |
14 | @@ -0,0 +1,801 @@ |
15 | +/* |
16 | + * QEMU Executable loader |
17 | + * |
18 | + * Copyright (c) 2006 Fabrice Bellard |
19 | + * |
20 | + * Permission is hereby granted, free of charge, to any person obtaining a copy |
21 | + * of this software and associated documentation files (the "Software"), to deal |
22 | + * in the Software without restriction, including without limitation the rights |
23 | + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell |
24 | + * copies of the Software, and to permit persons to whom the Software is |
25 | + * furnished to do so, subject to the following conditions: |
26 | + * |
27 | + * The above copyright notice and this permission notice shall be included in |
28 | + * all copies or substantial portions of the Software. |
29 | + * |
30 | + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
31 | + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
32 | + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL |
33 | + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER |
34 | + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, |
35 | + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN |
36 | + * THE SOFTWARE. |
37 | + * |
38 | + * Gunzip functionality in this file is derived from u-boot: |
39 | + * |
40 | + * (C) Copyright 2008 Semihalf |
41 | + * |
42 | + * (C) Copyright 2000-2005 |
43 | + * Wolfgang Denk, DENX Software Engineering, wd@denx.de. |
44 | + * |
45 | + * This program is free software; you can redistribute it and/or |
46 | + * modify it under the terms of the GNU General Public License as |
47 | + * published by the Free Software Foundation; either version 2 of |
48 | + * the License, or (at your option) any later version. |
49 | + * |
50 | + * This program is distributed in the hope that it will be useful, |
51 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
52 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
53 | + * GNU General Public License for more details. |
54 | + * |
55 | + * You should have received a copy of the GNU General Public License along |
56 | + * with this program; if not, see <http://www.gnu.org/licenses/>. |
57 | + */ |
58 | + |
59 | +#include "hw.h" |
60 | +#include "disas.h" |
61 | +#include "monitor.h" |
62 | +#include "sysemu.h" |
63 | +#include "uboot_image.h" |
64 | +#include "loader.h" |
65 | +#include "fw_cfg.h" |
66 | +#include "memory.h" |
67 | +#include "exec-memory.h" |
68 | + |
69 | +#include <zlib.h> |
70 | + |
71 | +static int roms_loaded; |
72 | + |
73 | +/* return the size or -1 if error */ |
74 | +int get_image_size(const char *filename) |
75 | +{ |
76 | + int fd, size; |
77 | + fd = open(filename, O_RDONLY | O_BINARY); |
78 | + if (fd < 0) |
79 | + return -1; |
80 | + size = lseek(fd, 0, SEEK_END); |
81 | + close(fd); |
82 | + return size; |
83 | +} |
84 | + |
85 | +/* return the size or -1 if error */ |
86 | +/* deprecated, because caller does not specify buffer size! */ |
87 | +int load_image(const char *filename, uint8_t *addr) |
88 | +{ |
89 | + int fd, size; |
90 | + fd = open(filename, O_RDONLY | O_BINARY); |
91 | + if (fd < 0) |
92 | + return -1; |
93 | + size = lseek(fd, 0, SEEK_END); |
94 | + lseek(fd, 0, SEEK_SET); |
95 | + if (read(fd, addr, size) != size) { |
96 | + close(fd); |
97 | + return -1; |
98 | + } |
99 | + close(fd); |
100 | + return size; |
101 | +} |
102 | + |
103 | +/* read()-like version */ |
104 | +ssize_t read_targphys(const char *name, |
105 | + int fd, target_phys_addr_t dst_addr, size_t nbytes) |
106 | +{ |
107 | + uint8_t *buf; |
108 | + ssize_t did; |
109 | + |
110 | + buf = g_malloc(nbytes); |
111 | + did = read(fd, buf, nbytes); |
112 | + if (did > 0) |
113 | + rom_add_blob_fixed("read", buf, did, dst_addr); |
114 | + g_free(buf); |
115 | + return did; |
116 | +} |
117 | + |
118 | +/* return the size or -1 if error */ |
119 | +int load_image_targphys(const char *filename, |
120 | + target_phys_addr_t addr, int max_sz) |
121 | +{ |
122 | + int size; |
123 | + |
124 | + size = get_image_size(filename); |
125 | + if (size > max_sz) { |
126 | + return -1; |
127 | + } |
128 | + if (size > 0) { |
129 | + rom_add_file_fixed(filename, addr, -1); |
130 | + } |
131 | + return size; |
132 | +} |
133 | + |
134 | +void pstrcpy_targphys(const char *name, target_phys_addr_t dest, int buf_size, |
135 | + const char *source) |
136 | +{ |
137 | + const char *nulp; |
138 | + char *ptr; |
139 | + |
140 | + if (buf_size <= 0) return; |
141 | + nulp = memchr(source, 0, buf_size); |
142 | + if (nulp) { |
143 | + rom_add_blob_fixed(name, source, (nulp - source) + 1, dest); |
144 | + } else { |
145 | + rom_add_blob_fixed(name, source, buf_size, dest); |
146 | + ptr = rom_ptr(dest + buf_size - 1); |
147 | + *ptr = 0; |
148 | + } |
149 | +} |
150 | + |
151 | +/* A.OUT loader */ |
152 | + |
153 | +struct exec |
154 | +{ |
155 | + uint32_t a_info; /* Use macros N_MAGIC, etc for access */ |
156 | + uint32_t a_text; /* length of text, in bytes */ |
157 | + uint32_t a_data; /* length of data, in bytes */ |
158 | + uint32_t a_bss; /* length of uninitialized data area, in bytes */ |
159 | + uint32_t a_syms; /* length of symbol table data in file, in bytes */ |
160 | + uint32_t a_entry; /* start address */ |
161 | + uint32_t a_trsize; /* length of relocation info for text, in bytes */ |
162 | + uint32_t a_drsize; /* length of relocation info for data, in bytes */ |
163 | +}; |
164 | + |
165 | +static void bswap_ahdr(struct exec *e) |
166 | +{ |
167 | + bswap32s(&e->a_info); |
168 | + bswap32s(&e->a_text); |
169 | + bswap32s(&e->a_data); |
170 | + bswap32s(&e->a_bss); |
171 | + bswap32s(&e->a_syms); |
172 | + bswap32s(&e->a_entry); |
173 | + bswap32s(&e->a_trsize); |
174 | + bswap32s(&e->a_drsize); |
175 | +} |
176 | + |
177 | +#define N_MAGIC(exec) ((exec).a_info & 0xffff) |
178 | +#define OMAGIC 0407 |
179 | +#define NMAGIC 0410 |
180 | +#define ZMAGIC 0413 |
181 | +#define QMAGIC 0314 |
182 | +#define _N_HDROFF(x) (1024 - sizeof (struct exec)) |
183 | +#define N_TXTOFF(x) \ |
184 | + (N_MAGIC(x) == ZMAGIC ? _N_HDROFF((x)) + sizeof (struct exec) : \ |
185 | + (N_MAGIC(x) == QMAGIC ? 0 : sizeof (struct exec))) |
186 | +#define N_TXTADDR(x, target_page_size) (N_MAGIC(x) == QMAGIC ? target_page_size : 0) |
187 | +#define _N_SEGMENT_ROUND(x, target_page_size) (((x) + target_page_size - 1) & ~(target_page_size - 1)) |
188 | + |
189 | +#define _N_TXTENDADDR(x, target_page_size) (N_TXTADDR(x, target_page_size)+(x).a_text) |
190 | + |
191 | +#define N_DATADDR(x, target_page_size) \ |
192 | + (N_MAGIC(x)==OMAGIC? (_N_TXTENDADDR(x, target_page_size)) \ |
193 | + : (_N_SEGMENT_ROUND (_N_TXTENDADDR(x, target_page_size), target_page_size))) |
194 | + |
195 | + |
196 | +int load_aout(const char *filename, target_phys_addr_t addr, int max_sz, |
197 | + int bswap_needed, target_phys_addr_t target_page_size) |
198 | +{ |
199 | + int fd; |
200 | + ssize_t size, ret; |
201 | + struct exec e; |
202 | + uint32_t magic; |
203 | + |
204 | + fd = open(filename, O_RDONLY | O_BINARY); |
205 | + if (fd < 0) |
206 | + return -1; |
207 | + |
208 | + size = read(fd, &e, sizeof(e)); |
209 | + if (size < 0) |
210 | + goto fail; |
211 | + |
212 | + if (bswap_needed) { |
213 | + bswap_ahdr(&e); |
214 | + } |
215 | + |
216 | + magic = N_MAGIC(e); |
217 | + switch (magic) { |
218 | + case ZMAGIC: |
219 | + case QMAGIC: |
220 | + case OMAGIC: |
221 | + if (e.a_text + e.a_data > max_sz) |
222 | + goto fail; |
223 | + lseek(fd, N_TXTOFF(e), SEEK_SET); |
224 | + size = read_targphys(filename, fd, addr, e.a_text + e.a_data); |
225 | + if (size < 0) |
226 | + goto fail; |
227 | + break; |
228 | + case NMAGIC: |
229 | + if (N_DATADDR(e, target_page_size) + e.a_data > max_sz) |
230 | + goto fail; |
231 | + lseek(fd, N_TXTOFF(e), SEEK_SET); |
232 | + size = read_targphys(filename, fd, addr, e.a_text); |
233 | + if (size < 0) |
234 | + goto fail; |
235 | + ret = read_targphys(filename, fd, addr + N_DATADDR(e, target_page_size), |
236 | + e.a_data); |
237 | + if (ret < 0) |
238 | + goto fail; |
239 | + size += ret; |
240 | + break; |
241 | + default: |
242 | + goto fail; |
243 | + } |
244 | + close(fd); |
245 | + return size; |
246 | + fail: |
247 | + close(fd); |
248 | + return -1; |
249 | +} |
250 | + |
251 | +/* ELF loader */ |
252 | + |
253 | +static void *load_at(int fd, int offset, int size) |
254 | +{ |
255 | + void *ptr; |
256 | + if (lseek(fd, offset, SEEK_SET) < 0) |
257 | + return NULL; |
258 | + ptr = g_malloc(size); |
259 | + if (read(fd, ptr, size) != size) { |
260 | + g_free(ptr); |
261 | + return NULL; |
262 | + } |
263 | + return ptr; |
264 | +} |
265 | + |
266 | +#ifdef ELF_CLASS |
267 | +#undef ELF_CLASS |
268 | +#endif |
269 | + |
270 | +#define ELF_CLASS ELFCLASS32 |
271 | +#include "elf.h" |
272 | + |
273 | +#define SZ 32 |
274 | +#define elf_word uint32_t |
275 | +#define elf_sword int32_t |
276 | +#define bswapSZs bswap32s |
277 | +#include "elf_ops.h" |
278 | + |
279 | +#undef elfhdr |
280 | +#undef elf_phdr |
281 | +#undef elf_shdr |
282 | +#undef elf_sym |
283 | +#undef elf_note |
284 | +#undef elf_word |
285 | +#undef elf_sword |
286 | +#undef bswapSZs |
287 | +#undef SZ |
288 | +#define elfhdr elf64_hdr |
289 | +#define elf_phdr elf64_phdr |
290 | +#define elf_note elf64_note |
291 | +#define elf_shdr elf64_shdr |
292 | +#define elf_sym elf64_sym |
293 | +#define elf_word uint64_t |
294 | +#define elf_sword int64_t |
295 | +#define bswapSZs bswap64s |
296 | +#define SZ 64 |
297 | +#include "elf_ops.h" |
298 | + |
299 | +/* return < 0 if error, otherwise the number of bytes loaded in memory */ |
300 | +int load_elf(const char *filename, uint64_t (*translate_fn)(void *, uint64_t), |
301 | + void *translate_opaque, uint64_t *pentry, uint64_t *lowaddr, |
302 | + uint64_t *highaddr, int big_endian, int elf_machine, int clear_lsb) |
303 | +{ |
304 | + int fd, data_order, target_data_order, must_swab, ret; |
305 | + uint8_t e_ident[EI_NIDENT]; |
306 | + |
307 | + fd = open(filename, O_RDONLY | O_BINARY); |
308 | + if (fd < 0) { |
309 | + perror(filename); |
310 | + return -1; |
311 | + } |
312 | + if (read(fd, e_ident, sizeof(e_ident)) != sizeof(e_ident)) |
313 | + goto fail; |
314 | + if (e_ident[0] != ELFMAG0 || |
315 | + e_ident[1] != ELFMAG1 || |
316 | + e_ident[2] != ELFMAG2 || |
317 | + e_ident[3] != ELFMAG3) |
318 | + goto fail; |
319 | +#ifdef HOST_WORDS_BIGENDIAN |
320 | + data_order = ELFDATA2MSB; |
321 | +#else |
322 | + data_order = ELFDATA2LSB; |
323 | +#endif |
324 | + must_swab = data_order != e_ident[EI_DATA]; |
325 | + if (big_endian) { |
326 | + target_data_order = ELFDATA2MSB; |
327 | + } else { |
328 | + target_data_order = ELFDATA2LSB; |
329 | + } |
330 | + |
331 | + if (target_data_order != e_ident[EI_DATA]) { |
332 | + goto fail; |
333 | + } |
334 | + |
335 | + lseek(fd, 0, SEEK_SET); |
336 | + if (e_ident[EI_CLASS] == ELFCLASS64) { |
337 | + ret = load_elf64(filename, fd, translate_fn, translate_opaque, must_swab, |
338 | + pentry, lowaddr, highaddr, elf_machine, clear_lsb); |
339 | + } else { |
340 | + ret = load_elf32(filename, fd, translate_fn, translate_opaque, must_swab, |
341 | + pentry, lowaddr, highaddr, elf_machine, clear_lsb); |
342 | + } |
343 | + |
344 | + close(fd); |
345 | + return ret; |
346 | + |
347 | + fail: |
348 | + close(fd); |
349 | + return -1; |
350 | +} |
351 | + |
352 | +static void bswap_uboot_header(uboot_image_header_t *hdr) |
353 | +{ |
354 | +#ifndef HOST_WORDS_BIGENDIAN |
355 | + bswap32s(&hdr->ih_magic); |
356 | + bswap32s(&hdr->ih_hcrc); |
357 | + bswap32s(&hdr->ih_time); |
358 | + bswap32s(&hdr->ih_size); |
359 | + bswap32s(&hdr->ih_load); |
360 | + bswap32s(&hdr->ih_ep); |
361 | + bswap32s(&hdr->ih_dcrc); |
362 | +#endif |
363 | +} |
364 | + |
365 | + |
366 | +#define ZALLOC_ALIGNMENT 16 |
367 | + |
368 | +static void *zalloc(void *x, unsigned items, unsigned size) |
369 | +{ |
370 | + void *p; |
371 | + |
372 | + size *= items; |
373 | + size = (size + ZALLOC_ALIGNMENT - 1) & ~(ZALLOC_ALIGNMENT - 1); |
374 | + |
375 | + p = g_malloc(size); |
376 | + |
377 | + return (p); |
378 | +} |
379 | + |
380 | +static void zfree(void *x, void *addr) |
381 | +{ |
382 | + g_free(addr); |
383 | +} |
384 | + |
385 | + |
386 | +#define HEAD_CRC 2 |
387 | +#define EXTRA_FIELD 4 |
388 | +#define ORIG_NAME 8 |
389 | +#define COMMENT 0x10 |
390 | +#define RESERVED 0xe0 |
391 | + |
392 | +#define DEFLATED 8 |
393 | + |
394 | +/* This is the maximum in uboot, so if a uImage overflows this, it would |
395 | + * overflow on real hardware too. */ |
396 | +#define UBOOT_MAX_GUNZIP_BYTES 0x800000 |
397 | + |
398 | +static ssize_t gunzip(void *dst, size_t dstlen, uint8_t *src, |
399 | + size_t srclen) |
400 | +{ |
401 | + z_stream s; |
402 | + ssize_t dstbytes; |
403 | + int r, i, flags; |
404 | + |
405 | + /* skip header */ |
406 | + i = 10; |
407 | + flags = src[3]; |
408 | + if (src[2] != DEFLATED || (flags & RESERVED) != 0) { |
409 | + puts ("Error: Bad gzipped data\n"); |
410 | + return -1; |
411 | + } |
412 | + if ((flags & EXTRA_FIELD) != 0) |
413 | + i = 12 + src[10] + (src[11] << 8); |
414 | + if ((flags & ORIG_NAME) != 0) |
415 | + while (src[i++] != 0) |
416 | + ; |
417 | + if ((flags & COMMENT) != 0) |
418 | + while (src[i++] != 0) |
419 | + ; |
420 | + if ((flags & HEAD_CRC) != 0) |
421 | + i += 2; |
422 | + if (i >= srclen) { |
423 | + puts ("Error: gunzip out of data in header\n"); |
424 | + return -1; |
425 | + } |
426 | + |
427 | + s.zalloc = zalloc; |
428 | + s.zfree = zfree; |
429 | + |
430 | + r = inflateInit2(&s, -MAX_WBITS); |
431 | + if (r != Z_OK) { |
432 | + printf ("Error: inflateInit2() returned %d\n", r); |
433 | + return (-1); |
434 | + } |
435 | + s.next_in = src + i; |
436 | + s.avail_in = srclen - i; |
437 | + s.next_out = dst; |
438 | + s.avail_out = dstlen; |
439 | + r = inflate(&s, Z_FINISH); |
440 | + if (r != Z_OK && r != Z_STREAM_END) { |
441 | + printf ("Error: inflate() returned %d\n", r); |
442 | + return -1; |
443 | + } |
444 | + dstbytes = s.next_out - (unsigned char *) dst; |
445 | + inflateEnd(&s); |
446 | + |
447 | + return dstbytes; |
448 | +} |
449 | + |
450 | +/* Load a U-Boot image. */ |
451 | +int load_uimage(const char *filename, target_phys_addr_t *ep, |
452 | + target_phys_addr_t *loadaddr, int *is_linux) |
453 | +{ |
454 | + int fd; |
455 | + int size; |
456 | + uboot_image_header_t h; |
457 | + uboot_image_header_t *hdr = &h; |
458 | + uint8_t *data = NULL; |
459 | + int ret = -1; |
460 | + |
461 | + fd = open(filename, O_RDONLY | O_BINARY); |
462 | + if (fd < 0) |
463 | + return -1; |
464 | + |
465 | + size = read(fd, hdr, sizeof(uboot_image_header_t)); |
466 | + if (size < 0) |
467 | + goto out; |
468 | + |
469 | + bswap_uboot_header(hdr); |
470 | + |
471 | + if (hdr->ih_magic != IH_MAGIC) |
472 | + goto out; |
473 | + |
474 | + /* TODO: Implement other image types. */ |
475 | + if (hdr->ih_type != IH_TYPE_KERNEL) { |
476 | + fprintf(stderr, "Can only load u-boot image type \"kernel\"\n"); |
477 | + goto out; |
478 | + } |
479 | + |
480 | + switch (hdr->ih_comp) { |
481 | + case IH_COMP_NONE: |
482 | + case IH_COMP_GZIP: |
483 | + break; |
484 | + default: |
485 | + fprintf(stderr, |
486 | + "Unable to load u-boot images with compression type %d\n", |
487 | + hdr->ih_comp); |
488 | + goto out; |
489 | + } |
490 | + |
491 | + /* TODO: Check CPU type. */ |
492 | + if (is_linux) { |
493 | + if (hdr->ih_os == IH_OS_LINUX) |
494 | + *is_linux = 1; |
495 | + else |
496 | + *is_linux = 0; |
497 | + } |
498 | + |
499 | + *ep = hdr->ih_ep; |
500 | + data = g_malloc(hdr->ih_size); |
501 | + |
502 | + if (read(fd, data, hdr->ih_size) != hdr->ih_size) { |
503 | + fprintf(stderr, "Error reading file\n"); |
504 | + goto out; |
505 | + } |
506 | + |
507 | + if (hdr->ih_comp == IH_COMP_GZIP) { |
508 | + uint8_t *compressed_data; |
509 | + size_t max_bytes; |
510 | + ssize_t bytes; |
511 | + |
512 | + compressed_data = data; |
513 | + max_bytes = UBOOT_MAX_GUNZIP_BYTES; |
514 | + data = g_malloc(max_bytes); |
515 | + |
516 | + bytes = gunzip(data, max_bytes, compressed_data, hdr->ih_size); |
517 | + g_free(compressed_data); |
518 | + if (bytes < 0) { |
519 | + fprintf(stderr, "Unable to decompress gzipped image!\n"); |
520 | + goto out; |
521 | + } |
522 | + hdr->ih_size = bytes; |
523 | + } |
524 | + |
525 | + rom_add_blob_fixed(filename, data, hdr->ih_size, hdr->ih_load); |
526 | + |
527 | + if (loadaddr) |
528 | + *loadaddr = hdr->ih_load; |
529 | + |
530 | + ret = hdr->ih_size; |
531 | + |
532 | +out: |
533 | + if (data) |
534 | + g_free(data); |
535 | + close(fd); |
536 | + return ret; |
537 | +} |
538 | + |
539 | +/* |
540 | + * Functions for reboot-persistent memory regions. |
541 | + * - used for vga bios and option roms. |
542 | + * - also linux kernel (-kernel / -initrd). |
543 | + */ |
544 | + |
545 | +typedef struct Rom Rom; |
546 | + |
547 | +struct Rom { |
548 | + char *name; |
549 | + char *path; |
550 | + size_t romsize; |
551 | + uint8_t *data; |
552 | + int isrom; |
553 | + char *fw_dir; |
554 | + char *fw_file; |
555 | + |
556 | + target_phys_addr_t addr; |
557 | + QTAILQ_ENTRY(Rom) next; |
558 | +}; |
559 | + |
560 | +static FWCfgState *fw_cfg; |
561 | +static QTAILQ_HEAD(, Rom) roms = QTAILQ_HEAD_INITIALIZER(roms); |
562 | + |
563 | +static void rom_insert(Rom *rom) |
564 | +{ |
565 | + Rom *item; |
566 | + |
567 | + if (roms_loaded) { |
568 | + hw_error ("ROM images must be loaded at startup\n"); |
569 | + } |
570 | + |
571 | + /* list is ordered by load address */ |
572 | + QTAILQ_FOREACH(item, &roms, next) { |
573 | + if (rom->addr >= item->addr) |
574 | + continue; |
575 | + QTAILQ_INSERT_BEFORE(item, rom, next); |
576 | + return; |
577 | + } |
578 | + QTAILQ_INSERT_TAIL(&roms, rom, next); |
579 | +} |
580 | + |
581 | +int rom_add_file(const char *file, const char *fw_dir, |
582 | + target_phys_addr_t addr, int32_t bootindex) |
583 | +{ |
584 | + Rom *rom; |
585 | + int rc, fd = -1; |
586 | + char devpath[100]; |
587 | + |
588 | + rom = g_malloc0(sizeof(*rom)); |
589 | + rom->name = g_strdup(file); |
590 | + rom->path = qemu_find_file(QEMU_FILE_TYPE_BIOS, rom->name); |
591 | + if (rom->path == NULL) { |
592 | + rom->path = g_strdup(file); |
593 | + } |
594 | + |
595 | + fd = open(rom->path, O_RDONLY | O_BINARY); |
596 | + if (fd == -1) { |
597 | + fprintf(stderr, "Could not open option rom '%s': %s\n", |
598 | + rom->path, strerror(errno)); |
599 | + goto err; |
600 | + } |
601 | + |
602 | + if (fw_dir) { |
603 | + rom->fw_dir = g_strdup(fw_dir); |
604 | + rom->fw_file = g_strdup(file); |
605 | + } |
606 | + rom->addr = addr; |
607 | + rom->romsize = lseek(fd, 0, SEEK_END); |
608 | + rom->data = g_malloc0(rom->romsize); |
609 | + lseek(fd, 0, SEEK_SET); |
610 | + rc = read(fd, rom->data, rom->romsize); |
611 | + if (rc != rom->romsize) { |
612 | + fprintf(stderr, "rom: file %-20s: read error: rc=%d (expected %zd)\n", |
613 | + rom->name, rc, rom->romsize); |
614 | + goto err; |
615 | + } |
616 | + close(fd); |
617 | + rom_insert(rom); |
618 | + if (rom->fw_file && fw_cfg) { |
619 | + const char *basename; |
620 | + char fw_file_name[56]; |
621 | + |
622 | + basename = strrchr(rom->fw_file, '/'); |
623 | + if (basename) { |
624 | + basename++; |
625 | + } else { |
626 | + basename = rom->fw_file; |
627 | + } |
628 | + snprintf(fw_file_name, sizeof(fw_file_name), "%s/%s", rom->fw_dir, |
629 | + basename); |
630 | + fw_cfg_add_file(fw_cfg, fw_file_name, rom->data, rom->romsize); |
631 | + snprintf(devpath, sizeof(devpath), "/rom@%s", fw_file_name); |
632 | + } else { |
633 | + snprintf(devpath, sizeof(devpath), "/rom@" TARGET_FMT_plx, addr); |
634 | + } |
635 | + |
636 | + add_boot_device_path(bootindex, NULL, devpath); |
637 | + return 0; |
638 | + |
639 | +err: |
640 | + if (fd != -1) |
641 | + close(fd); |
642 | + g_free(rom->data); |
643 | + g_free(rom->path); |
644 | + g_free(rom->name); |
645 | + g_free(rom); |
646 | + return -1; |
647 | +} |
648 | + |
649 | +int rom_add_blob(const char *name, const void *blob, size_t len, |
650 | + target_phys_addr_t addr) |
651 | +{ |
652 | + Rom *rom; |
653 | + |
654 | + rom = g_malloc0(sizeof(*rom)); |
655 | + rom->name = g_strdup(name); |
656 | + rom->addr = addr; |
657 | + rom->romsize = len; |
658 | + rom->data = g_malloc0(rom->romsize); |
659 | + memcpy(rom->data, blob, len); |
660 | + rom_insert(rom); |
661 | + return 0; |
662 | +} |
663 | + |
664 | +int rom_add_vga(const char *file) |
665 | +{ |
666 | + return rom_add_file(file, "vgaroms", 0, -1); |
667 | +} |
668 | + |
669 | +int rom_add_option(const char *file, int32_t bootindex) |
670 | +{ |
671 | + return rom_add_file(file, "genroms", 0, bootindex); |
672 | +} |
673 | + |
674 | +static void rom_reset(void *unused) |
675 | +{ |
676 | + Rom *rom; |
677 | + |
678 | + QTAILQ_FOREACH(rom, &roms, next) { |
679 | + if (rom->fw_file) { |
680 | + continue; |
681 | + } |
682 | + if (rom->data == NULL) { |
683 | + continue; |
684 | + } |
685 | + cpu_physical_memory_write_rom(rom->addr, rom->data, rom->romsize); |
686 | + if (rom->isrom) { |
687 | + /* rom needs to be written only once */ |
688 | + g_free(rom->data); |
689 | + rom->data = NULL; |
690 | + } |
691 | + } |
692 | +} |
693 | + |
694 | +int rom_load_all(void) |
695 | +{ |
696 | + target_phys_addr_t addr = 0; |
697 | + MemoryRegionSection section; |
698 | + Rom *rom; |
699 | + |
700 | + QTAILQ_FOREACH(rom, &roms, next) { |
701 | + if (rom->fw_file) { |
702 | + continue; |
703 | + } |
704 | + if (addr > rom->addr) { |
705 | + fprintf(stderr, "rom: requested regions overlap " |
706 | + "(rom %s. free=0x" TARGET_FMT_plx |
707 | + ", addr=0x" TARGET_FMT_plx ")\n", |
708 | + rom->name, addr, rom->addr); |
709 | + return -1; |
710 | + } |
711 | + addr = rom->addr; |
712 | + addr += rom->romsize; |
713 | + section = memory_region_find(get_system_memory(), rom->addr, 1); |
714 | + rom->isrom = section.size && memory_region_is_rom(section.mr); |
715 | + } |
716 | + qemu_register_reset(rom_reset, NULL); |
717 | + roms_loaded = 1; |
718 | + return 0; |
719 | +} |
720 | + |
721 | +void rom_set_fw(void *f) |
722 | +{ |
723 | + fw_cfg = f; |
724 | +} |
725 | + |
726 | +static Rom *find_rom(target_phys_addr_t addr) |
727 | +{ |
728 | + Rom *rom; |
729 | + |
730 | + QTAILQ_FOREACH(rom, &roms, next) { |
731 | + if (rom->fw_file) { |
732 | + continue; |
733 | + } |
734 | + if (rom->addr > addr) { |
735 | + continue; |
736 | + } |
737 | + if (rom->addr + rom->romsize < addr) { |
738 | + continue; |
739 | + } |
740 | + return rom; |
741 | + } |
742 | + return NULL; |
743 | +} |
744 | + |
745 | +/* |
746 | + * Copies memory from registered ROMs to dest. Any memory that is contained in |
747 | + * a ROM between addr and addr + size is copied. Note that this can involve |
748 | + * multiple ROMs, which need not start at addr and need not end at addr + size. |
749 | + */ |
750 | +int rom_copy(uint8_t *dest, target_phys_addr_t addr, size_t size) |
751 | +{ |
752 | + target_phys_addr_t end = addr + size; |
753 | + uint8_t *s, *d = dest; |
754 | + size_t l = 0; |
755 | + Rom *rom; |
756 | + |
757 | + QTAILQ_FOREACH(rom, &roms, next) { |
758 | + if (rom->fw_file) { |
759 | + continue; |
760 | + } |
761 | + if (rom->addr + rom->romsize < addr) { |
762 | + continue; |
763 | + } |
764 | + if (rom->addr > end) { |
765 | + break; |
766 | + } |
767 | + if (!rom->data) { |
768 | + continue; |
769 | + } |
770 | + |
771 | + d = dest + (rom->addr - addr); |
772 | + s = rom->data; |
773 | + l = rom->romsize; |
774 | + |
775 | + if ((d + l) > (dest + size)) { |
776 | + l = dest - d; |
777 | + } |
778 | + |
779 | + memcpy(d, s, l); |
780 | + } |
781 | + |
782 | + return (d + l) - dest; |
783 | +} |
784 | + |
785 | +void *rom_ptr(target_phys_addr_t addr) |
786 | +{ |
787 | + Rom *rom; |
788 | + |
789 | + rom = find_rom(addr); |
790 | + if (!rom || !rom->data) |
791 | + return NULL; |
792 | + return rom->data + (addr - rom->addr); |
793 | +} |
794 | + |
795 | +void do_info_roms(Monitor *mon) |
796 | +{ |
797 | + Rom *rom; |
798 | + |
799 | + QTAILQ_FOREACH(rom, &roms, next) { |
800 | + if (!rom->fw_file) { |
801 | + monitor_printf(mon, "addr=" TARGET_FMT_plx |
802 | + " size=0x%06zx mem=%s name=\"%s\"\n", |
803 | + rom->addr, rom->romsize, |
804 | + rom->isrom ? "rom" : "ram", |
805 | + rom->name); |
806 | + } else { |
807 | + monitor_printf(mon, "fw=%s/%s" |
808 | + " size=0x%06zx name=\"%s\"\n", |
809 | + rom->fw_dir, |
810 | + rom->fw_file, |
811 | + rom->romsize, |
812 | + rom->name); |
813 | + } |
814 | + } |
815 | +} |
816 | |
817 | === added file '.pc/use-an-uint64_t-for-the-max_sz-parameter-in-load_image_targphys.patch/hw/loader.h' |
818 | --- .pc/use-an-uint64_t-for-the-max_sz-parameter-in-load_image_targphys.patch/hw/loader.h 1970-01-01 00:00:00 +0000 |
819 | +++ .pc/use-an-uint64_t-for-the-max_sz-parameter-in-load_image_targphys.patch/hw/loader.h 2012-07-30 19:32:20 +0000 |
820 | @@ -0,0 +1,48 @@ |
821 | +#ifndef LOADER_H |
822 | +#define LOADER_H |
823 | + |
824 | +/* loader.c */ |
825 | +int get_image_size(const char *filename); |
826 | +int load_image(const char *filename, uint8_t *addr); /* deprecated */ |
827 | +int load_image_targphys(const char *filename, target_phys_addr_t, int max_sz); |
828 | +int load_elf(const char *filename, uint64_t (*translate_fn)(void *, uint64_t), |
829 | + void *translate_opaque, uint64_t *pentry, uint64_t *lowaddr, |
830 | + uint64_t *highaddr, int big_endian, int elf_machine, |
831 | + int clear_lsb); |
832 | +int load_aout(const char *filename, target_phys_addr_t addr, int max_sz, |
833 | + int bswap_needed, target_phys_addr_t target_page_size); |
834 | +int load_uimage(const char *filename, target_phys_addr_t *ep, |
835 | + target_phys_addr_t *loadaddr, int *is_linux); |
836 | + |
837 | +ssize_t read_targphys(const char *name, |
838 | + int fd, target_phys_addr_t dst_addr, size_t nbytes); |
839 | +void pstrcpy_targphys(const char *name, |
840 | + target_phys_addr_t dest, int buf_size, |
841 | + const char *source); |
842 | + |
843 | + |
844 | +int rom_add_file(const char *file, const char *fw_dir, |
845 | + target_phys_addr_t addr, int32_t bootindex); |
846 | +int rom_add_blob(const char *name, const void *blob, size_t len, |
847 | + target_phys_addr_t addr); |
848 | +int rom_load_all(void); |
849 | +void rom_set_fw(void *f); |
850 | +int rom_copy(uint8_t *dest, target_phys_addr_t addr, size_t size); |
851 | +void *rom_ptr(target_phys_addr_t addr); |
852 | +void do_info_roms(Monitor *mon); |
853 | + |
854 | +#define rom_add_file_fixed(_f, _a, _i) \ |
855 | + rom_add_file(_f, NULL, _a, _i) |
856 | +#define rom_add_blob_fixed(_f, _b, _l, _a) \ |
857 | + rom_add_blob(_f, _b, _l, _a) |
858 | + |
859 | +#define PC_ROM_MIN_VGA 0xc0000 |
860 | +#define PC_ROM_MIN_OPTION 0xc8000 |
861 | +#define PC_ROM_MAX 0xe0000 |
862 | +#define PC_ROM_ALIGN 0x800 |
863 | +#define PC_ROM_SIZE (PC_ROM_MAX - PC_ROM_MIN_VGA) |
864 | + |
865 | +int rom_add_vga(const char *file); |
866 | +int rom_add_option(const char *file, int32_t bootindex); |
867 | + |
868 | +#endif |
869 | |
870 | === modified file 'debian/changelog' |
871 | --- debian/changelog 2012-04-22 14:34:29 +0000 |
872 | +++ debian/changelog 2012-07-30 19:32:20 +0000 |
873 | @@ -1,3 +1,11 @@ |
874 | +qemu-linaro (1.0.50-2012.03-0ubuntu3) UNRELEASED; urgency=low |
875 | + |
876 | + * debian/patches/use-an-uint64_t-for-the-max_sz-parameter-in-load_image_targphys.patch: |
877 | + Allow loading kernels on systems w/ > 2G emulated memory. LP: #1030588. |
878 | + * Enable flat device tree support. LP: #1030594. |
879 | + |
880 | + -- dann frazier <dann.frazier@canonical.com> Sun, 29 Jul 2012 12:40:25 -0600 |
881 | + |
882 | qemu-linaro (1.0.50-2012.03-0ubuntu2) precise; urgency=low |
883 | |
884 | * Add missing #include that caused a build failure on powerpc. |
885 | |
886 | === modified file 'debian/control' |
887 | --- debian/control 2012-02-07 23:34:36 +0000 |
888 | +++ debian/control 2012-07-30 19:32:20 +0000 |
889 | @@ -14,6 +14,7 @@ |
890 | libncurses5-dev, |
891 | libbrlapi-dev, |
892 | libcurl4-gnutls-dev, |
893 | + libfdt-dev, |
894 | libgnutls-dev, |
895 | libsasl2-dev, |
896 | libspice-protocol-dev [amd64], |
897 | |
898 | === modified file 'debian/patches/series' |
899 | --- debian/patches/series 2012-04-22 13:53:58 +0000 |
900 | +++ debian/patches/series 2012-07-30 19:32:20 +0000 |
901 | @@ -1,2 +1,3 @@ |
902 | define_AT_EMPTY_PATH.patch |
903 | powerpc-missing-include.patch |
904 | +use-an-uint64_t-for-the-max_sz-parameter-in-load_image_targphys.patch |
905 | |
906 | === added file 'debian/patches/use-an-uint64_t-for-the-max_sz-parameter-in-load_image_targphys.patch' |
907 | --- debian/patches/use-an-uint64_t-for-the-max_sz-parameter-in-load_image_targphys.patch 1970-01-01 00:00:00 +0000 |
908 | +++ debian/patches/use-an-uint64_t-for-the-max_sz-parameter-in-load_image_targphys.patch 2012-07-30 19:32:20 +0000 |
909 | @@ -0,0 +1,34 @@ |
910 | +Description: use an uint64_t for the max_sz parameter in load_image_targphys |
911 | + Allow load_image_targphys to load files on systems with more than 2G of |
912 | + emulated memory by changing the max_sz parameter from an int to an |
913 | + uint64_t. |
914 | +Author: Mark Langsdorf <mark.langsdorf@calxeda.com> |
915 | + |
916 | +--- |
917 | + |
918 | +Origin: upstream, http://git.linaro.org/gitweb?p=qemu/qemu-linaro.git;a=commitdiff;h=80a2ba3d3cf33b777d6a45776b0625b9a4283951 |
919 | +Last-Update: 2012-07-27 |
920 | + |
921 | +--- qemu-linaro-1.0.50-2012.03.orig/hw/loader.h |
922 | ++++ qemu-linaro-1.0.50-2012.03/hw/loader.h |
923 | +@@ -4,7 +4,8 @@ |
924 | + /* loader.c */ |
925 | + int get_image_size(const char *filename); |
926 | + int load_image(const char *filename, uint8_t *addr); /* deprecated */ |
927 | +-int load_image_targphys(const char *filename, target_phys_addr_t, int max_sz); |
928 | ++int load_image_targphys(const char *filename, target_phys_addr_t, |
929 | ++ uint64_t max_sz); |
930 | + int load_elf(const char *filename, uint64_t (*translate_fn)(void *, uint64_t), |
931 | + void *translate_opaque, uint64_t *pentry, uint64_t *lowaddr, |
932 | + uint64_t *highaddr, int big_endian, int elf_machine, |
933 | +--- qemu-linaro-1.0.50-2012.03.orig/hw/loader.c |
934 | ++++ qemu-linaro-1.0.50-2012.03/hw/loader.c |
935 | +@@ -103,7 +103,7 @@ ssize_t read_targphys(const char *name, |
936 | + |
937 | + /* return the size or -1 if error */ |
938 | + int load_image_targphys(const char *filename, |
939 | +- target_phys_addr_t addr, int max_sz) |
940 | ++ target_phys_addr_t addr, uint64_t max_sz) |
941 | + { |
942 | + int size; |
943 | + |
944 | |
945 | === modified file 'hw/loader.c' |
946 | --- hw/loader.c 2012-02-20 17:32:06 +0000 |
947 | +++ hw/loader.c 2012-07-30 19:32:20 +0000 |
948 | @@ -103,7 +103,7 @@ |
949 | |
950 | /* return the size or -1 if error */ |
951 | int load_image_targphys(const char *filename, |
952 | - target_phys_addr_t addr, int max_sz) |
953 | + target_phys_addr_t addr, uint64_t max_sz) |
954 | { |
955 | int size; |
956 | |
957 | |
958 | === modified file 'hw/loader.h' |
959 | --- hw/loader.h 2011-12-14 16:58:18 +0000 |
960 | +++ hw/loader.h 2012-07-30 19:32:20 +0000 |
961 | @@ -4,7 +4,8 @@ |
962 | /* loader.c */ |
963 | int get_image_size(const char *filename); |
964 | int load_image(const char *filename, uint8_t *addr); /* deprecated */ |
965 | -int load_image_targphys(const char *filename, target_phys_addr_t, int max_sz); |
966 | +int load_image_targphys(const char *filename, target_phys_addr_t, |
967 | + uint64_t max_sz); |
968 | int load_elf(const char *filename, uint64_t (*translate_fn)(void *, uint64_t), |
969 | void *translate_opaque, uint64_t *pentry, uint64_t *lowaddr, |
970 | uint64_t *highaddr, int big_endian, int elf_machine, |
Marking as approved as it was uploaded by mvo.