Skip to content

Commit

Permalink
loader: Allow a custom AddressSpace when loading ROMs
Browse files Browse the repository at this point in the history
When loading ROMs allow the caller to specify an AddressSpace to use for
the load.

Signed-off-by: Alistair Francis <alistair.francis@xilinx.com>
Message-id: 85f86b94ea94879e7ce8b12e85ac8de26658f7eb.1474331683.git.alistair.francis@xilinx.com
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
  • Loading branch information
alistair23 authored and pm215 committed Sep 22, 2016
1 parent d6ac342 commit 3e76099
Show file tree
Hide file tree
Showing 3 changed files with 41 additions and 14 deletions.
43 changes: 34 additions & 9 deletions hw/core/loader.c
Expand Up @@ -777,6 +777,7 @@ struct Rom {

uint8_t *data;
MemoryRegion *mr;
AddressSpace *as;
int isrom;
char *fw_dir;
char *fw_file;
Expand All @@ -788,6 +789,12 @@ struct Rom {
static FWCfgState *fw_cfg;
static QTAILQ_HEAD(, Rom) roms = QTAILQ_HEAD_INITIALIZER(roms);

static inline bool rom_order_compare(Rom *rom, Rom *item)
{
return (rom->as > item->as) ||
(rom->as == item->as && rom->addr >= item->addr);
}

static void rom_insert(Rom *rom)
{
Rom *item;
Expand All @@ -796,10 +803,16 @@ static void rom_insert(Rom *rom)
hw_error ("ROM images must be loaded at startup\n");
}

/* list is ordered by load address */
/* The user didn't specify an address space, this is the default */
if (!rom->as) {
rom->as = &address_space_memory;
}

/* List is ordered by load address in the same address space */
QTAILQ_FOREACH(item, &roms, next) {
if (rom->addr >= item->addr)
if (rom_order_compare(rom, item)) {
continue;
}
QTAILQ_INSERT_BEFORE(item, rom, next);
return;
}
Expand Down Expand Up @@ -833,16 +846,25 @@ static void *rom_set_mr(Rom *rom, Object *owner, const char *name)

int rom_add_file(const char *file, const char *fw_dir,
hwaddr addr, int32_t bootindex,
bool option_rom, MemoryRegion *mr)
bool option_rom, MemoryRegion *mr,
AddressSpace *as)
{
MachineClass *mc = MACHINE_GET_CLASS(qdev_get_machine());
Rom *rom;
int rc, fd = -1;
char devpath[100];

if (as && mr) {
fprintf(stderr, "Specifying an Address Space and Memory Region is " \
"not valid when loading a rom\n");
/* We haven't allocated anything so we don't need any cleanup */
return -1;
}

rom = g_malloc0(sizeof(*rom));
rom->name = g_strdup(file);
rom->path = qemu_find_file(QEMU_FILE_TYPE_BIOS, rom->name);
rom->as = as;
if (rom->path == NULL) {
rom->path = g_strdup(file);
}
Expand Down Expand Up @@ -969,7 +991,7 @@ MemoryRegion *rom_add_blob(const char *name, const void *blob, size_t len,
* memory ownership of "data", so we don't have to allocate and copy the buffer.
*/
int rom_add_elf_program(const char *name, void *data, size_t datasize,
size_t romsize, hwaddr addr)
size_t romsize, hwaddr addr, AddressSpace *as)
{
Rom *rom;

Expand All @@ -979,18 +1001,19 @@ int rom_add_elf_program(const char *name, void *data, size_t datasize,
rom->datasize = datasize;
rom->romsize = romsize;
rom->data = data;
rom->as = as;
rom_insert(rom);
return 0;
}

int rom_add_vga(const char *file)
{
return rom_add_file(file, "vgaroms", 0, -1, true, NULL);
return rom_add_file(file, "vgaroms", 0, -1, true, NULL, NULL);
}

int rom_add_option(const char *file, int32_t bootindex)
{
return rom_add_file(file, "genroms", 0, bootindex, true, NULL);
return rom_add_file(file, "genroms", 0, bootindex, true, NULL, NULL);
}

static void rom_reset(void *unused)
Expand All @@ -1008,8 +1031,8 @@ static void rom_reset(void *unused)
void *host = memory_region_get_ram_ptr(rom->mr);
memcpy(host, rom->data, rom->datasize);
} else {
cpu_physical_memory_write_rom(&address_space_memory,
rom->addr, rom->data, rom->datasize);
cpu_physical_memory_write_rom(rom->as, rom->addr, rom->data,
rom->datasize);
}
if (rom->isrom) {
/* rom needs to be written only once */
Expand All @@ -1031,12 +1054,13 @@ int rom_check_and_register_reset(void)
hwaddr addr = 0;
MemoryRegionSection section;
Rom *rom;
AddressSpace *as = NULL;

QTAILQ_FOREACH(rom, &roms, next) {
if (rom->fw_file) {
continue;
}
if (addr > rom->addr) {
if ((addr > rom->addr) && (as == rom->as)) {
fprintf(stderr, "rom: requested regions overlap "
"(rom %s. free=0x" TARGET_FMT_plx
", addr=0x" TARGET_FMT_plx ")\n",
Expand All @@ -1049,6 +1073,7 @@ int rom_check_and_register_reset(void)
rom->addr, 1);
rom->isrom = int128_nz(section.size) && memory_region_is_rom(section.mr);
memory_region_unref(section.mr);
as = rom->as;
}
qemu_register_reset(rom_reset, NULL);
roms_loaded = 1;
Expand Down
2 changes: 1 addition & 1 deletion include/hw/elf_ops.h
Expand Up @@ -405,7 +405,7 @@ static int glue(load_elf, SZ)(const char *name, int fd,
snprintf(label, sizeof(label), "phdr #%d: %s", i, name);

/* rom_add_elf_program() seize the ownership of 'data' */
rom_add_elf_program(label, data, file_size, mem_size, addr);
rom_add_elf_program(label, data, file_size, mem_size, addr, NULL);

total_size += mem_size;
if (addr < low)
Expand Down
10 changes: 6 additions & 4 deletions include/hw/loader.h
Expand Up @@ -120,14 +120,14 @@ extern bool rom_file_has_mr;

int rom_add_file(const char *file, const char *fw_dir,
hwaddr addr, int32_t bootindex,
bool option_rom, MemoryRegion *mr);
bool option_rom, MemoryRegion *mr, AddressSpace *as);
MemoryRegion *rom_add_blob(const char *name, const void *blob, size_t len,
size_t max_len, hwaddr addr,
const char *fw_file_name,
FWCfgReadCallback fw_callback,
void *callback_opaque);
int rom_add_elf_program(const char *name, void *data, size_t datasize,
size_t romsize, hwaddr addr);
size_t romsize, hwaddr addr, AddressSpace *as);
int rom_check_and_register_reset(void);
void rom_set_fw(FWCfgState *f);
void rom_set_order_override(int order);
Expand All @@ -137,11 +137,13 @@ void *rom_ptr(hwaddr addr);
void hmp_info_roms(Monitor *mon, const QDict *qdict);

#define rom_add_file_fixed(_f, _a, _i) \
rom_add_file(_f, NULL, _a, _i, false, NULL)
rom_add_file(_f, NULL, _a, _i, false, NULL, NULL)
#define rom_add_blob_fixed(_f, _b, _l, _a) \
rom_add_blob(_f, _b, _l, _l, _a, NULL, NULL, NULL)
#define rom_add_file_mr(_f, _mr, _i) \
rom_add_file(_f, NULL, 0, _i, false, _mr)
rom_add_file(_f, NULL, 0, _i, false, _mr, NULL)
#define rom_add_file_as(_f, _as, _i) \
rom_add_file(_f, NULL, 0, _i, false, NULL, _as)

#define PC_ROM_MIN_VGA 0xc0000
#define PC_ROM_MIN_OPTION 0xc8000
Expand Down

0 comments on commit 3e76099

Please sign in to comment.