Statistics
| Branch: | Revision:

root / hw / loader.c @ cde844fa

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
ssize_t read_targphys(const char *name,
89
                      int fd, target_phys_addr_t dst_addr, size_t nbytes)
90
{
91
    uint8_t *buf;
92
    ssize_t did;
93

    
94
    buf = g_malloc(nbytes);
95
    did = read(fd, buf, nbytes);
96
    if (did > 0)
97
        rom_add_blob_fixed("read", buf, did, dst_addr);
98
    g_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;
180
    ssize_t size, ret;
181
    struct exec e;
182
    uint32_t magic;
183

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

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

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

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

    
231
/* ELF loader */
232

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

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

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

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

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

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

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

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

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

    
324
    close(fd);
325
    return ret;
326

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

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

    
345

    
346
#define ZALLOC_ALIGNMENT        16
347

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

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

    
355
    p = g_malloc(size);
356

    
357
    return (p);
358
}
359

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

    
365

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

    
372
#define DEFLATED        8
373

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

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

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

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

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

    
427
    return dstbytes;
428
}
429

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

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

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

    
449
    bswap_uboot_header(hdr);
450

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

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

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

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

    
479
    *ep = hdr->ih_ep;
480
    data = g_malloc(hdr->ih_size);
481

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

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

    
492
        compressed_data = data;
493
        max_bytes = UBOOT_MAX_GUNZIP_BYTES;
494
        data = g_malloc(max_bytes);
495

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

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

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

    
510
    ret = hdr->ih_size;
511

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

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

    
525
typedef struct Rom Rom;
526

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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