Statistics
| Branch: | Revision:

root / hw / loader.c @ be62a2eb

History | View | Annotate | Download (19.7 kB)

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, see <http://www.gnu.org/licenses/>.
43
 */
44

    
45
#include "hw.h"
46
#include "disas.h"
47
#include "monitor.h"
48
#include "sysemu.h"
49
#include "uboot_image.h"
50
#include "loader.h"
51
#include "fw_cfg.h"
52
#include "memory.h"
53
#include "exec-memory.h"
54

    
55
#include <zlib.h>
56

    
57
static int roms_loaded;
58

    
59
/* return the size or -1 if error */
60
int get_image_size(const char *filename)
61
{
62
    int fd, size;
63
    fd = open(filename, O_RDONLY | O_BINARY);
64
    if (fd < 0)
65
        return -1;
66
    size = lseek(fd, 0, SEEK_END);
67
    close(fd);
68
    return size;
69
}
70

    
71
/* return the size or -1 if error */
72
/* deprecated, because caller does not specify buffer size! */
73
int load_image(const char *filename, uint8_t *addr)
74
{
75
    int fd, size;
76
    fd = open(filename, O_RDONLY | O_BINARY);
77
    if (fd < 0)
78
        return -1;
79
    size = lseek(fd, 0, SEEK_END);
80
    lseek(fd, 0, SEEK_SET);
81
    if (read(fd, addr, size) != size) {
82
        close(fd);
83
        return -1;
84
    }
85
    close(fd);
86
    return size;
87
}
88

    
89
/* read()-like version */
90
ssize_t read_targphys(const char *name,
91
                      int fd, target_phys_addr_t dst_addr, size_t nbytes)
92
{
93
    uint8_t *buf;
94
    ssize_t did;
95

    
96
    buf = g_malloc(nbytes);
97
    did = read(fd, buf, nbytes);
98
    if (did > 0)
99
        rom_add_blob_fixed("read", buf, did, dst_addr);
100
    g_free(buf);
101
    return did;
102
}
103

    
104
/* return the size or -1 if error */
105
int load_image_targphys(const char *filename,
106
                        target_phys_addr_t addr, int max_sz)
107
{
108
    int size;
109

    
110
    size = get_image_size(filename);
111
    if (size > 0)
112
        rom_add_file_fixed(filename, addr, -1);
113
    return size;
114
}
115

    
116
void pstrcpy_targphys(const char *name, target_phys_addr_t dest, int buf_size,
117
                      const char *source)
118
{
119
    const char *nulp;
120
    char *ptr;
121

    
122
    if (buf_size <= 0) return;
123
    nulp = memchr(source, 0, buf_size);
124
    if (nulp) {
125
        rom_add_blob_fixed(name, source, (nulp - source) + 1, dest);
126
    } else {
127
        rom_add_blob_fixed(name, source, buf_size, dest);
128
        ptr = rom_ptr(dest + buf_size - 1);
129
        *ptr = 0;
130
    }
131
}
132

    
133
/* A.OUT loader */
134

    
135
struct exec
136
{
137
  uint32_t a_info;   /* Use macros N_MAGIC, etc for access */
138
  uint32_t a_text;   /* length of text, in bytes */
139
  uint32_t a_data;   /* length of data, in bytes */
140
  uint32_t a_bss;    /* length of uninitialized data area, in bytes */
141
  uint32_t a_syms;   /* length of symbol table data in file, in bytes */
142
  uint32_t a_entry;  /* start address */
143
  uint32_t a_trsize; /* length of relocation info for text, in bytes */
144
  uint32_t a_drsize; /* length of relocation info for data, in bytes */
145
};
146

    
147
static void bswap_ahdr(struct exec *e)
148
{
149
    bswap32s(&e->a_info);
150
    bswap32s(&e->a_text);
151
    bswap32s(&e->a_data);
152
    bswap32s(&e->a_bss);
153
    bswap32s(&e->a_syms);
154
    bswap32s(&e->a_entry);
155
    bswap32s(&e->a_trsize);
156
    bswap32s(&e->a_drsize);
157
}
158

    
159
#define N_MAGIC(exec) ((exec).a_info & 0xffff)
160
#define OMAGIC 0407
161
#define NMAGIC 0410
162
#define ZMAGIC 0413
163
#define QMAGIC 0314
164
#define _N_HDROFF(x) (1024 - sizeof (struct exec))
165
#define N_TXTOFF(x)                                                        \
166
    (N_MAGIC(x) == ZMAGIC ? _N_HDROFF((x)) + sizeof (struct exec) :        \
167
     (N_MAGIC(x) == QMAGIC ? 0 : sizeof (struct exec)))
168
#define N_TXTADDR(x, target_page_size) (N_MAGIC(x) == QMAGIC ? target_page_size : 0)
169
#define _N_SEGMENT_ROUND(x, target_page_size) (((x) + target_page_size - 1) & ~(target_page_size - 1))
170

    
171
#define _N_TXTENDADDR(x, target_page_size) (N_TXTADDR(x, target_page_size)+(x).a_text)
172

    
173
#define N_DATADDR(x, target_page_size) \
174
    (N_MAGIC(x)==OMAGIC? (_N_TXTENDADDR(x, target_page_size)) \
175
     : (_N_SEGMENT_ROUND (_N_TXTENDADDR(x, target_page_size), target_page_size)))
176

    
177

    
178
int load_aout(const char *filename, target_phys_addr_t addr, int max_sz,
179
              int bswap_needed, target_phys_addr_t target_page_size)
180
{
181
    int fd;
182
    ssize_t size, ret;
183
    struct exec e;
184
    uint32_t magic;
185

    
186
    fd = open(filename, O_RDONLY | O_BINARY);
187
    if (fd < 0)
188
        return -1;
189

    
190
    size = read(fd, &e, sizeof(e));
191
    if (size < 0)
192
        goto fail;
193

    
194
    if (bswap_needed) {
195
        bswap_ahdr(&e);
196
    }
197

    
198
    magic = N_MAGIC(e);
199
    switch (magic) {
200
    case ZMAGIC:
201
    case QMAGIC:
202
    case OMAGIC:
203
        if (e.a_text + e.a_data > max_sz)
204
            goto fail;
205
        lseek(fd, N_TXTOFF(e), SEEK_SET);
206
        size = read_targphys(filename, fd, addr, e.a_text + e.a_data);
207
        if (size < 0)
208
            goto fail;
209
        break;
210
    case NMAGIC:
211
        if (N_DATADDR(e, target_page_size) + e.a_data > max_sz)
212
            goto fail;
213
        lseek(fd, N_TXTOFF(e), SEEK_SET);
214
        size = read_targphys(filename, fd, addr, e.a_text);
215
        if (size < 0)
216
            goto fail;
217
        ret = read_targphys(filename, fd, addr + N_DATADDR(e, target_page_size),
218
                            e.a_data);
219
        if (ret < 0)
220
            goto fail;
221
        size += ret;
222
        break;
223
    default:
224
        goto fail;
225
    }
226
    close(fd);
227
    return size;
228
 fail:
229
    close(fd);
230
    return -1;
231
}
232

    
233
/* ELF loader */
234

    
235
static void *load_at(int fd, int offset, int size)
236
{
237
    void *ptr;
238
    if (lseek(fd, offset, SEEK_SET) < 0)
239
        return NULL;
240
    ptr = g_malloc(size);
241
    if (read(fd, ptr, size) != size) {
242
        g_free(ptr);
243
        return NULL;
244
    }
245
    return ptr;
246
}
247

    
248
#ifdef ELF_CLASS
249
#undef ELF_CLASS
250
#endif
251

    
252
#define ELF_CLASS   ELFCLASS32
253
#include "elf.h"
254

    
255
#define SZ                32
256
#define elf_word        uint32_t
257
#define elf_sword        int32_t
258
#define bswapSZs        bswap32s
259
#include "elf_ops.h"
260

    
261
#undef elfhdr
262
#undef elf_phdr
263
#undef elf_shdr
264
#undef elf_sym
265
#undef elf_note
266
#undef elf_word
267
#undef elf_sword
268
#undef bswapSZs
269
#undef SZ
270
#define elfhdr                elf64_hdr
271
#define elf_phdr        elf64_phdr
272
#define elf_note        elf64_note
273
#define elf_shdr        elf64_shdr
274
#define elf_sym                elf64_sym
275
#define elf_word        uint64_t
276
#define elf_sword        int64_t
277
#define bswapSZs        bswap64s
278
#define SZ                64
279
#include "elf_ops.h"
280

    
281
/* return < 0 if error, otherwise the number of bytes loaded in memory */
282
int load_elf(const char *filename, uint64_t (*translate_fn)(void *, uint64_t),
283
             void *translate_opaque, uint64_t *pentry, uint64_t *lowaddr,
284
             uint64_t *highaddr, int big_endian, int elf_machine, int clear_lsb)
285
{
286
    int fd, data_order, target_data_order, must_swab, ret;
287
    uint8_t e_ident[EI_NIDENT];
288

    
289
    fd = open(filename, O_RDONLY | O_BINARY);
290
    if (fd < 0) {
291
        perror(filename);
292
        return -1;
293
    }
294
    if (read(fd, e_ident, sizeof(e_ident)) != sizeof(e_ident))
295
        goto fail;
296
    if (e_ident[0] != ELFMAG0 ||
297
        e_ident[1] != ELFMAG1 ||
298
        e_ident[2] != ELFMAG2 ||
299
        e_ident[3] != ELFMAG3)
300
        goto fail;
301
#ifdef HOST_WORDS_BIGENDIAN
302
    data_order = ELFDATA2MSB;
303
#else
304
    data_order = ELFDATA2LSB;
305
#endif
306
    must_swab = data_order != e_ident[EI_DATA];
307
    if (big_endian) {
308
        target_data_order = ELFDATA2MSB;
309
    } else {
310
        target_data_order = ELFDATA2LSB;
311
    }
312

    
313
    if (target_data_order != e_ident[EI_DATA]) {
314
        goto fail;
315
    }
316

    
317
    lseek(fd, 0, SEEK_SET);
318
    if (e_ident[EI_CLASS] == ELFCLASS64) {
319
        ret = load_elf64(filename, fd, translate_fn, translate_opaque, must_swab,
320
                         pentry, lowaddr, highaddr, elf_machine, clear_lsb);
321
    } else {
322
        ret = load_elf32(filename, fd, translate_fn, translate_opaque, must_swab,
323
                         pentry, lowaddr, highaddr, elf_machine, clear_lsb);
324
    }
325

    
326
    close(fd);
327
    return ret;
328

    
329
 fail:
330
    close(fd);
331
    return -1;
332
}
333

    
334
static void bswap_uboot_header(uboot_image_header_t *hdr)
335
{
336
#ifndef HOST_WORDS_BIGENDIAN
337
    bswap32s(&hdr->ih_magic);
338
    bswap32s(&hdr->ih_hcrc);
339
    bswap32s(&hdr->ih_time);
340
    bswap32s(&hdr->ih_size);
341
    bswap32s(&hdr->ih_load);
342
    bswap32s(&hdr->ih_ep);
343
    bswap32s(&hdr->ih_dcrc);
344
#endif
345
}
346

    
347

    
348
#define ZALLOC_ALIGNMENT        16
349

    
350
static void *zalloc(void *x, unsigned items, unsigned size)
351
{
352
    void *p;
353

    
354
    size *= items;
355
    size = (size + ZALLOC_ALIGNMENT - 1) & ~(ZALLOC_ALIGNMENT - 1);
356

    
357
    p = g_malloc(size);
358

    
359
    return (p);
360
}
361

    
362
static void zfree(void *x, void *addr)
363
{
364
    g_free(addr);
365
}
366

    
367

    
368
#define HEAD_CRC        2
369
#define EXTRA_FIELD        4
370
#define ORIG_NAME        8
371
#define COMMENT                0x10
372
#define RESERVED        0xe0
373

    
374
#define DEFLATED        8
375

    
376
/* This is the maximum in uboot, so if a uImage overflows this, it would
377
 * overflow on real hardware too. */
378
#define UBOOT_MAX_GUNZIP_BYTES 0x800000
379

    
380
static ssize_t gunzip(void *dst, size_t dstlen, uint8_t *src,
381
                      size_t srclen)
382
{
383
    z_stream s;
384
    ssize_t dstbytes;
385
    int r, i, flags;
386

    
387
    /* skip header */
388
    i = 10;
389
    flags = src[3];
390
    if (src[2] != DEFLATED || (flags & RESERVED) != 0) {
391
        puts ("Error: Bad gzipped data\n");
392
        return -1;
393
    }
394
    if ((flags & EXTRA_FIELD) != 0)
395
        i = 12 + src[10] + (src[11] << 8);
396
    if ((flags & ORIG_NAME) != 0)
397
        while (src[i++] != 0)
398
            ;
399
    if ((flags & COMMENT) != 0)
400
        while (src[i++] != 0)
401
            ;
402
    if ((flags & HEAD_CRC) != 0)
403
        i += 2;
404
    if (i >= srclen) {
405
        puts ("Error: gunzip out of data in header\n");
406
        return -1;
407
    }
408

    
409
    s.zalloc = zalloc;
410
    s.zfree = zfree;
411

    
412
    r = inflateInit2(&s, -MAX_WBITS);
413
    if (r != Z_OK) {
414
        printf ("Error: inflateInit2() returned %d\n", r);
415
        return (-1);
416
    }
417
    s.next_in = src + i;
418
    s.avail_in = srclen - i;
419
    s.next_out = dst;
420
    s.avail_out = dstlen;
421
    r = inflate(&s, Z_FINISH);
422
    if (r != Z_OK && r != Z_STREAM_END) {
423
        printf ("Error: inflate() returned %d\n", r);
424
        return -1;
425
    }
426
    dstbytes = s.next_out - (unsigned char *) dst;
427
    inflateEnd(&s);
428

    
429
    return dstbytes;
430
}
431

    
432
/* Load a U-Boot image.  */
433
int load_uimage(const char *filename, target_phys_addr_t *ep,
434
                target_phys_addr_t *loadaddr, int *is_linux)
435
{
436
    int fd;
437
    int size;
438
    uboot_image_header_t h;
439
    uboot_image_header_t *hdr = &h;
440
    uint8_t *data = NULL;
441
    int ret = -1;
442

    
443
    fd = open(filename, O_RDONLY | O_BINARY);
444
    if (fd < 0)
445
        return -1;
446

    
447
    size = read(fd, hdr, sizeof(uboot_image_header_t));
448
    if (size < 0)
449
        goto out;
450

    
451
    bswap_uboot_header(hdr);
452

    
453
    if (hdr->ih_magic != IH_MAGIC)
454
        goto out;
455

    
456
    /* TODO: Implement other image types.  */
457
    if (hdr->ih_type != IH_TYPE_KERNEL) {
458
        fprintf(stderr, "Can only load u-boot image type \"kernel\"\n");
459
        goto out;
460
    }
461

    
462
    switch (hdr->ih_comp) {
463
    case IH_COMP_NONE:
464
    case IH_COMP_GZIP:
465
        break;
466
    default:
467
        fprintf(stderr,
468
                "Unable to load u-boot images with compression type %d\n",
469
                hdr->ih_comp);
470
        goto out;
471
    }
472

    
473
    /* TODO: Check CPU type.  */
474
    if (is_linux) {
475
        if (hdr->ih_os == IH_OS_LINUX)
476
            *is_linux = 1;
477
        else
478
            *is_linux = 0;
479
    }
480

    
481
    *ep = hdr->ih_ep;
482
    data = g_malloc(hdr->ih_size);
483

    
484
    if (read(fd, data, hdr->ih_size) != hdr->ih_size) {
485
        fprintf(stderr, "Error reading file\n");
486
        goto out;
487
    }
488

    
489
    if (hdr->ih_comp == IH_COMP_GZIP) {
490
        uint8_t *compressed_data;
491
        size_t max_bytes;
492
        ssize_t bytes;
493

    
494
        compressed_data = data;
495
        max_bytes = UBOOT_MAX_GUNZIP_BYTES;
496
        data = g_malloc(max_bytes);
497

    
498
        bytes = gunzip(data, max_bytes, compressed_data, hdr->ih_size);
499
        g_free(compressed_data);
500
        if (bytes < 0) {
501
            fprintf(stderr, "Unable to decompress gzipped image!\n");
502
            goto out;
503
        }
504
        hdr->ih_size = bytes;
505
    }
506

    
507
    rom_add_blob_fixed(filename, data, hdr->ih_size, hdr->ih_load);
508

    
509
    if (loadaddr)
510
        *loadaddr = hdr->ih_load;
511

    
512
    ret = hdr->ih_size;
513

    
514
out:
515
    if (data)
516
        g_free(data);
517
    close(fd);
518
    return ret;
519
}
520

    
521
/*
522
 * Functions for reboot-persistent memory regions.
523
 *  - used for vga bios and option roms.
524
 *  - also linux kernel (-kernel / -initrd).
525
 */
526

    
527
typedef struct Rom Rom;
528

    
529
struct Rom {
530
    char *name;
531
    char *path;
532
    size_t romsize;
533
    uint8_t *data;
534
    int isrom;
535
    char *fw_dir;
536
    char *fw_file;
537

    
538
    target_phys_addr_t addr;
539
    QTAILQ_ENTRY(Rom) next;
540
};
541

    
542
static FWCfgState *fw_cfg;
543
static QTAILQ_HEAD(, Rom) roms = QTAILQ_HEAD_INITIALIZER(roms);
544

    
545
static void rom_insert(Rom *rom)
546
{
547
    Rom *item;
548

    
549
    if (roms_loaded) {
550
        hw_error ("ROM images must be loaded at startup\n");
551
    }
552

    
553
    /* list is ordered by load address */
554
    QTAILQ_FOREACH(item, &roms, next) {
555
        if (rom->addr >= item->addr)
556
            continue;
557
        QTAILQ_INSERT_BEFORE(item, rom, next);
558
        return;
559
    }
560
    QTAILQ_INSERT_TAIL(&roms, rom, next);
561
}
562

    
563
int rom_add_file(const char *file, const char *fw_dir,
564
                 target_phys_addr_t addr, int32_t bootindex)
565
{
566
    Rom *rom;
567
    int rc, fd = -1;
568
    char devpath[100];
569

    
570
    rom = g_malloc0(sizeof(*rom));
571
    rom->name = g_strdup(file);
572
    rom->path = qemu_find_file(QEMU_FILE_TYPE_BIOS, rom->name);
573
    if (rom->path == NULL) {
574
        rom->path = g_strdup(file);
575
    }
576

    
577
    fd = open(rom->path, O_RDONLY | O_BINARY);
578
    if (fd == -1) {
579
        fprintf(stderr, "Could not open option rom '%s': %s\n",
580
                rom->path, strerror(errno));
581
        goto err;
582
    }
583

    
584
    if (fw_dir) {
585
        rom->fw_dir  = g_strdup(fw_dir);
586
        rom->fw_file = g_strdup(file);
587
    }
588
    rom->addr    = addr;
589
    rom->romsize = lseek(fd, 0, SEEK_END);
590
    rom->data    = g_malloc0(rom->romsize);
591
    lseek(fd, 0, SEEK_SET);
592
    rc = read(fd, rom->data, rom->romsize);
593
    if (rc != rom->romsize) {
594
        fprintf(stderr, "rom: file %-20s: read error: rc=%d (expected %zd)\n",
595
                rom->name, rc, rom->romsize);
596
        goto err;
597
    }
598
    close(fd);
599
    rom_insert(rom);
600
    if (rom->fw_file && fw_cfg) {
601
        const char *basename;
602
        char fw_file_name[56];
603

    
604
        basename = strrchr(rom->fw_file, '/');
605
        if (basename) {
606
            basename++;
607
        } else {
608
            basename = rom->fw_file;
609
        }
610
        snprintf(fw_file_name, sizeof(fw_file_name), "%s/%s", rom->fw_dir,
611
                 basename);
612
        fw_cfg_add_file(fw_cfg, fw_file_name, rom->data, rom->romsize);
613
        snprintf(devpath, sizeof(devpath), "/rom@%s", fw_file_name);
614
    } else {
615
        snprintf(devpath, sizeof(devpath), "/rom@" TARGET_FMT_plx, addr);
616
    }
617

    
618
    add_boot_device_path(bootindex, NULL, devpath);
619
    return 0;
620

    
621
err:
622
    if (fd != -1)
623
        close(fd);
624
    g_free(rom->data);
625
    g_free(rom->path);
626
    g_free(rom->name);
627
    g_free(rom);
628
    return -1;
629
}
630

    
631
int rom_add_blob(const char *name, const void *blob, size_t len,
632
                 target_phys_addr_t addr)
633
{
634
    Rom *rom;
635

    
636
    rom = g_malloc0(sizeof(*rom));
637
    rom->name    = g_strdup(name);
638
    rom->addr    = addr;
639
    rom->romsize = len;
640
    rom->data    = g_malloc0(rom->romsize);
641
    memcpy(rom->data, blob, len);
642
    rom_insert(rom);
643
    return 0;
644
}
645

    
646
int rom_add_vga(const char *file)
647
{
648
    return rom_add_file(file, "vgaroms", 0, -1);
649
}
650

    
651
int rom_add_option(const char *file, int32_t bootindex)
652
{
653
    return rom_add_file(file, "genroms", 0, bootindex);
654
}
655

    
656
static void rom_reset(void *unused)
657
{
658
    Rom *rom;
659

    
660
    QTAILQ_FOREACH(rom, &roms, next) {
661
        if (rom->fw_file) {
662
            continue;
663
        }
664
        if (rom->data == NULL) {
665
            continue;
666
        }
667
        cpu_physical_memory_write_rom(rom->addr, rom->data, rom->romsize);
668
        if (rom->isrom) {
669
            /* rom needs to be written only once */
670
            g_free(rom->data);
671
            rom->data = NULL;
672
        }
673
    }
674
}
675

    
676
int rom_load_all(void)
677
{
678
    target_phys_addr_t addr = 0;
679
    MemoryRegionSection section;
680
    Rom *rom;
681

    
682
    QTAILQ_FOREACH(rom, &roms, next) {
683
        if (rom->fw_file) {
684
            continue;
685
        }
686
        if (addr > rom->addr) {
687
            fprintf(stderr, "rom: requested regions overlap "
688
                    "(rom %s. free=0x" TARGET_FMT_plx
689
                    ", addr=0x" TARGET_FMT_plx ")\n",
690
                    rom->name, addr, rom->addr);
691
            return -1;
692
        }
693
        addr  = rom->addr;
694
        addr += rom->romsize;
695
        section = memory_region_find(get_system_memory(), rom->addr, 1);
696
        rom->isrom = section.size && memory_region_is_rom(section.mr);
697
    }
698
    qemu_register_reset(rom_reset, NULL);
699
    roms_loaded = 1;
700
    return 0;
701
}
702

    
703
void rom_set_fw(void *f)
704
{
705
    fw_cfg = f;
706
}
707

    
708
static Rom *find_rom(target_phys_addr_t addr)
709
{
710
    Rom *rom;
711

    
712
    QTAILQ_FOREACH(rom, &roms, next) {
713
        if (rom->fw_file) {
714
            continue;
715
        }
716
        if (rom->addr > addr) {
717
            continue;
718
        }
719
        if (rom->addr + rom->romsize < addr) {
720
            continue;
721
        }
722
        return rom;
723
    }
724
    return NULL;
725
}
726

    
727
/*
728
 * Copies memory from registered ROMs to dest. Any memory that is contained in
729
 * a ROM between addr and addr + size is copied. Note that this can involve
730
 * multiple ROMs, which need not start at addr and need not end at addr + size.
731
 */
732
int rom_copy(uint8_t *dest, target_phys_addr_t addr, size_t size)
733
{
734
    target_phys_addr_t end = addr + size;
735
    uint8_t *s, *d = dest;
736
    size_t l = 0;
737
    Rom *rom;
738

    
739
    QTAILQ_FOREACH(rom, &roms, next) {
740
        if (rom->fw_file) {
741
            continue;
742
        }
743
        if (rom->addr + rom->romsize < addr) {
744
            continue;
745
        }
746
        if (rom->addr > end) {
747
            break;
748
        }
749
        if (!rom->data) {
750
            continue;
751
        }
752

    
753
        d = dest + (rom->addr - addr);
754
        s = rom->data;
755
        l = rom->romsize;
756

    
757
        if ((d + l) > (dest + size)) {
758
            l = dest - d;
759
        }
760

    
761
        memcpy(d, s, l);
762
    }
763

    
764
    return (d + l) - dest;
765
}
766

    
767
void *rom_ptr(target_phys_addr_t addr)
768
{
769
    Rom *rom;
770

    
771
    rom = find_rom(addr);
772
    if (!rom || !rom->data)
773
        return NULL;
774
    return rom->data + (addr - rom->addr);
775
}
776

    
777
void do_info_roms(Monitor *mon)
778
{
779
    Rom *rom;
780

    
781
    QTAILQ_FOREACH(rom, &roms, next) {
782
        if (!rom->fw_file) {
783
            monitor_printf(mon, "addr=" TARGET_FMT_plx
784
                           " size=0x%06zx mem=%s name=\"%s\"\n",
785
                           rom->addr, rom->romsize,
786
                           rom->isrom ? "rom" : "ram",
787
                           rom->name);
788
        } else {
789
            monitor_printf(mon, "fw=%s/%s"
790
                           " size=0x%06zx name=\"%s\"\n",
791
                           rom->fw_dir,
792
                           rom->fw_file,
793
                           rom->romsize,
794
                           rom->name);
795
        }
796
    }
797
}