Statistics
| Branch: | Revision:

root / hw / loader.c @ 6e625fc7

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

    
53
#include <zlib.h>
54

    
55
static int roms_loaded;
56

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

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

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

    
94
    buf = qemu_malloc(nbytes);
95
    did = read(fd, buf, nbytes);
96
    if (did > 0)
97
        rom_add_blob_fixed("read", buf, did, dst_addr);
98
    qemu_free(buf);
99
    return did;
100
}
101

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

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

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

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

    
131
/* A.OUT loader */
132

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

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

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

    
169
#define _N_TXTENDADDR(x, target_page_size) (N_TXTADDR(x, target_page_size)+(x).a_text)
170

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

    
175

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

    
183
    fd = open(filename, O_RDONLY | O_BINARY);
184
    if (fd < 0)
185
        return -1;
186

    
187
    size = read(fd, &e, sizeof(e));
188
    if (size < 0)
189
        goto fail;
190

    
191
    if (bswap_needed) {
192
        bswap_ahdr(&e);
193
    }
194

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

    
230
/* ELF loader */
231

    
232
static void *load_at(int fd, int offset, int size)
233
{
234
    void *ptr;
235
    if (lseek(fd, offset, SEEK_SET) < 0)
236
        return NULL;
237
    ptr = qemu_malloc(size);
238
    if (read(fd, ptr, size) != size) {
239
        qemu_free(ptr);
240
        return NULL;
241
    }
242
    return ptr;
243
}
244

    
245
#ifdef ELF_CLASS
246
#undef ELF_CLASS
247
#endif
248

    
249
#define ELF_CLASS   ELFCLASS32
250
#include "elf.h"
251

    
252
#define SZ                32
253
#define elf_word        uint32_t
254
#define elf_sword        int32_t
255
#define bswapSZs        bswap32s
256
#include "elf_ops.h"
257

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

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

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

    
310
    if (target_data_order != e_ident[EI_DATA]) {
311
        goto fail;
312
    }
313

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

    
323
    close(fd);
324
    return ret;
325

    
326
 fail:
327
    close(fd);
328
    return -1;
329
}
330

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

    
344

    
345
#define ZALLOC_ALIGNMENT        16
346

    
347
static void *zalloc(void *x, unsigned items, unsigned size)
348
{
349
    void *p;
350

    
351
    size *= items;
352
    size = (size + ZALLOC_ALIGNMENT - 1) & ~(ZALLOC_ALIGNMENT - 1);
353

    
354
    p = qemu_malloc(size);
355

    
356
    return (p);
357
}
358

    
359
static void zfree(void *x, void *addr)
360
{
361
    qemu_free(addr);
362
}
363

    
364

    
365
#define HEAD_CRC        2
366
#define EXTRA_FIELD        4
367
#define ORIG_NAME        8
368
#define COMMENT                0x10
369
#define RESERVED        0xe0
370

    
371
#define DEFLATED        8
372

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

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

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

    
406
    s.zalloc = zalloc;
407
    s.zfree = zfree;
408

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

    
426
    return dstbytes;
427
}
428

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

    
440
    fd = open(filename, O_RDONLY | O_BINARY);
441
    if (fd < 0)
442
        return -1;
443

    
444
    size = read(fd, hdr, sizeof(uboot_image_header_t));
445
    if (size < 0)
446
        goto out;
447

    
448
    bswap_uboot_header(hdr);
449

    
450
    if (hdr->ih_magic != IH_MAGIC)
451
        goto out;
452

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

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

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

    
478
    *ep = hdr->ih_ep;
479
    data = qemu_malloc(hdr->ih_size);
480

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

    
486
    if (hdr->ih_comp == IH_COMP_GZIP) {
487
        uint8_t *compressed_data;
488
        size_t max_bytes;
489
        ssize_t bytes;
490

    
491
        compressed_data = data;
492
        max_bytes = UBOOT_MAX_GUNZIP_BYTES;
493
        data = qemu_malloc(max_bytes);
494

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

    
504
    rom_add_blob_fixed(filename, data, hdr->ih_size, hdr->ih_load);
505

    
506
    if (loadaddr)
507
        *loadaddr = hdr->ih_load;
508

    
509
    ret = hdr->ih_size;
510

    
511
out:
512
    if (data)
513
        qemu_free(data);
514
    close(fd);
515
    return ret;
516
}
517

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

    
524
typedef struct Rom Rom;
525

    
526
struct Rom {
527
    char *name;
528
    char *path;
529
    size_t romsize;
530
    uint8_t *data;
531
    int isrom;
532
    char *fw_dir;
533
    char *fw_file;
534

    
535
    target_phys_addr_t addr;
536
    QTAILQ_ENTRY(Rom) next;
537
};
538

    
539
static FWCfgState *fw_cfg;
540
static QTAILQ_HEAD(, Rom) roms = QTAILQ_HEAD_INITIALIZER(roms);
541

    
542
static void rom_insert(Rom *rom)
543
{
544
    Rom *item;
545

    
546
    if (roms_loaded) {
547
        hw_error ("ROM images must be loaded at startup\n");
548
    }
549

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

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

    
567
    rom = qemu_mallocz(sizeof(*rom));
568
    rom->name = qemu_strdup(file);
569
    rom->path = qemu_find_file(QEMU_FILE_TYPE_BIOS, rom->name);
570
    if (rom->path == NULL) {
571
        rom->path = qemu_strdup(file);
572
    }
573

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

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

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

    
615
    add_boot_device_path(bootindex, NULL, devpath);
616
    return 0;
617

    
618
err:
619
    if (fd != -1)
620
        close(fd);
621
    qemu_free(rom->data);
622
    qemu_free(rom->path);
623
    qemu_free(rom->name);
624
    qemu_free(rom);
625
    return -1;
626
}
627

    
628
int rom_add_blob(const char *name, const void *blob, size_t len,
629
                 target_phys_addr_t addr)
630
{
631
    Rom *rom;
632

    
633
    rom = qemu_mallocz(sizeof(*rom));
634
    rom->name    = qemu_strdup(name);
635
    rom->addr    = addr;
636
    rom->romsize = len;
637
    rom->data    = qemu_mallocz(rom->romsize);
638
    memcpy(rom->data, blob, len);
639
    rom_insert(rom);
640
    return 0;
641
}
642

    
643
int rom_add_vga(const char *file)
644
{
645
    return rom_add_file(file, "vgaroms", 0, -1);
646
}
647

    
648
int rom_add_option(const char *file, int32_t bootindex)
649
{
650
    return rom_add_file(file, "genroms", 0, bootindex);
651
}
652

    
653
static void rom_reset(void *unused)
654
{
655
    Rom *rom;
656

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

    
673
int rom_load_all(void)
674
{
675
    target_phys_addr_t addr = 0;
676
    int memtype;
677
    Rom *rom;
678

    
679
    QTAILQ_FOREACH(rom, &roms, next) {
680
        if (rom->fw_file) {
681
            continue;
682
        }
683
        if (addr > rom->addr) {
684
            fprintf(stderr, "rom: requested regions overlap "
685
                    "(rom %s. free=0x" TARGET_FMT_plx
686
                    ", addr=0x" TARGET_FMT_plx ")\n",
687
                    rom->name, addr, rom->addr);
688
            return -1;
689
        }
690
        addr  = rom->addr;
691
        addr += rom->romsize;
692
        memtype = cpu_get_physical_page_desc(rom->addr) & (3 << IO_MEM_SHIFT);
693
        if (memtype == IO_MEM_ROM)
694
            rom->isrom = 1;
695
    }
696
    qemu_register_reset(rom_reset, NULL);
697
    roms_loaded = 1;
698
    return 0;
699
}
700

    
701
void rom_set_fw(void *f)
702
{
703
    fw_cfg = f;
704
}
705

    
706
static Rom *find_rom(target_phys_addr_t addr)
707
{
708
    Rom *rom;
709

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

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

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

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

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

    
759
        memcpy(d, s, l);
760
    }
761

    
762
    return (d + l) - dest;
763
}
764

    
765
void *rom_ptr(target_phys_addr_t addr)
766
{
767
    Rom *rom;
768

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

    
775
void do_info_roms(Monitor *mon)
776
{
777
    Rom *rom;
778

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