mirror of https://github.com/xemu-project/xemu.git
loader: Allow a custom AddressSpace when loading ROMs
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>
This commit is contained in:
parent
d6ac342a48
commit
3e76099aac
|
@ -777,6 +777,7 @@ struct Rom {
|
||||||
|
|
||||||
uint8_t *data;
|
uint8_t *data;
|
||||||
MemoryRegion *mr;
|
MemoryRegion *mr;
|
||||||
|
AddressSpace *as;
|
||||||
int isrom;
|
int isrom;
|
||||||
char *fw_dir;
|
char *fw_dir;
|
||||||
char *fw_file;
|
char *fw_file;
|
||||||
|
@ -788,6 +789,12 @@ struct Rom {
|
||||||
static FWCfgState *fw_cfg;
|
static FWCfgState *fw_cfg;
|
||||||
static QTAILQ_HEAD(, Rom) roms = QTAILQ_HEAD_INITIALIZER(roms);
|
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)
|
static void rom_insert(Rom *rom)
|
||||||
{
|
{
|
||||||
Rom *item;
|
Rom *item;
|
||||||
|
@ -796,10 +803,16 @@ static void rom_insert(Rom *rom)
|
||||||
hw_error ("ROM images must be loaded at startup\n");
|
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) {
|
QTAILQ_FOREACH(item, &roms, next) {
|
||||||
if (rom->addr >= item->addr)
|
if (rom_order_compare(rom, item)) {
|
||||||
continue;
|
continue;
|
||||||
|
}
|
||||||
QTAILQ_INSERT_BEFORE(item, rom, next);
|
QTAILQ_INSERT_BEFORE(item, rom, next);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -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,
|
int rom_add_file(const char *file, const char *fw_dir,
|
||||||
hwaddr addr, int32_t bootindex,
|
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());
|
MachineClass *mc = MACHINE_GET_CLASS(qdev_get_machine());
|
||||||
Rom *rom;
|
Rom *rom;
|
||||||
int rc, fd = -1;
|
int rc, fd = -1;
|
||||||
char devpath[100];
|
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 = g_malloc0(sizeof(*rom));
|
||||||
rom->name = g_strdup(file);
|
rom->name = g_strdup(file);
|
||||||
rom->path = qemu_find_file(QEMU_FILE_TYPE_BIOS, rom->name);
|
rom->path = qemu_find_file(QEMU_FILE_TYPE_BIOS, rom->name);
|
||||||
|
rom->as = as;
|
||||||
if (rom->path == NULL) {
|
if (rom->path == NULL) {
|
||||||
rom->path = g_strdup(file);
|
rom->path = g_strdup(file);
|
||||||
}
|
}
|
||||||
|
@ -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.
|
* 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,
|
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;
|
Rom *rom;
|
||||||
|
|
||||||
|
@ -979,18 +1001,19 @@ int rom_add_elf_program(const char *name, void *data, size_t datasize,
|
||||||
rom->datasize = datasize;
|
rom->datasize = datasize;
|
||||||
rom->romsize = romsize;
|
rom->romsize = romsize;
|
||||||
rom->data = data;
|
rom->data = data;
|
||||||
|
rom->as = as;
|
||||||
rom_insert(rom);
|
rom_insert(rom);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int rom_add_vga(const char *file)
|
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)
|
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)
|
static void rom_reset(void *unused)
|
||||||
|
@ -1008,8 +1031,8 @@ static void rom_reset(void *unused)
|
||||||
void *host = memory_region_get_ram_ptr(rom->mr);
|
void *host = memory_region_get_ram_ptr(rom->mr);
|
||||||
memcpy(host, rom->data, rom->datasize);
|
memcpy(host, rom->data, rom->datasize);
|
||||||
} else {
|
} else {
|
||||||
cpu_physical_memory_write_rom(&address_space_memory,
|
cpu_physical_memory_write_rom(rom->as, rom->addr, rom->data,
|
||||||
rom->addr, rom->data, rom->datasize);
|
rom->datasize);
|
||||||
}
|
}
|
||||||
if (rom->isrom) {
|
if (rom->isrom) {
|
||||||
/* rom needs to be written only once */
|
/* rom needs to be written only once */
|
||||||
|
@ -1031,12 +1054,13 @@ int rom_check_and_register_reset(void)
|
||||||
hwaddr addr = 0;
|
hwaddr addr = 0;
|
||||||
MemoryRegionSection section;
|
MemoryRegionSection section;
|
||||||
Rom *rom;
|
Rom *rom;
|
||||||
|
AddressSpace *as = NULL;
|
||||||
|
|
||||||
QTAILQ_FOREACH(rom, &roms, next) {
|
QTAILQ_FOREACH(rom, &roms, next) {
|
||||||
if (rom->fw_file) {
|
if (rom->fw_file) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (addr > rom->addr) {
|
if ((addr > rom->addr) && (as == rom->as)) {
|
||||||
fprintf(stderr, "rom: requested regions overlap "
|
fprintf(stderr, "rom: requested regions overlap "
|
||||||
"(rom %s. free=0x" TARGET_FMT_plx
|
"(rom %s. free=0x" TARGET_FMT_plx
|
||||||
", addr=0x" TARGET_FMT_plx ")\n",
|
", addr=0x" TARGET_FMT_plx ")\n",
|
||||||
|
@ -1049,6 +1073,7 @@ int rom_check_and_register_reset(void)
|
||||||
rom->addr, 1);
|
rom->addr, 1);
|
||||||
rom->isrom = int128_nz(section.size) && memory_region_is_rom(section.mr);
|
rom->isrom = int128_nz(section.size) && memory_region_is_rom(section.mr);
|
||||||
memory_region_unref(section.mr);
|
memory_region_unref(section.mr);
|
||||||
|
as = rom->as;
|
||||||
}
|
}
|
||||||
qemu_register_reset(rom_reset, NULL);
|
qemu_register_reset(rom_reset, NULL);
|
||||||
roms_loaded = 1;
|
roms_loaded = 1;
|
||||||
|
|
|
@ -405,7 +405,7 @@ static int glue(load_elf, SZ)(const char *name, int fd,
|
||||||
snprintf(label, sizeof(label), "phdr #%d: %s", i, name);
|
snprintf(label, sizeof(label), "phdr #%d: %s", i, name);
|
||||||
|
|
||||||
/* rom_add_elf_program() seize the ownership of 'data' */
|
/* 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;
|
total_size += mem_size;
|
||||||
if (addr < low)
|
if (addr < low)
|
||||||
|
|
|
@ -120,14 +120,14 @@ extern bool rom_file_has_mr;
|
||||||
|
|
||||||
int rom_add_file(const char *file, const char *fw_dir,
|
int rom_add_file(const char *file, const char *fw_dir,
|
||||||
hwaddr addr, int32_t bootindex,
|
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,
|
MemoryRegion *rom_add_blob(const char *name, const void *blob, size_t len,
|
||||||
size_t max_len, hwaddr addr,
|
size_t max_len, hwaddr addr,
|
||||||
const char *fw_file_name,
|
const char *fw_file_name,
|
||||||
FWCfgReadCallback fw_callback,
|
FWCfgReadCallback fw_callback,
|
||||||
void *callback_opaque);
|
void *callback_opaque);
|
||||||
int rom_add_elf_program(const char *name, void *data, size_t datasize,
|
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);
|
int rom_check_and_register_reset(void);
|
||||||
void rom_set_fw(FWCfgState *f);
|
void rom_set_fw(FWCfgState *f);
|
||||||
void rom_set_order_override(int order);
|
void rom_set_order_override(int order);
|
||||||
|
@ -137,11 +137,13 @@ void *rom_ptr(hwaddr addr);
|
||||||
void hmp_info_roms(Monitor *mon, const QDict *qdict);
|
void hmp_info_roms(Monitor *mon, const QDict *qdict);
|
||||||
|
|
||||||
#define rom_add_file_fixed(_f, _a, _i) \
|
#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) \
|
#define rom_add_blob_fixed(_f, _b, _l, _a) \
|
||||||
rom_add_blob(_f, _b, _l, _l, _a, NULL, NULL, NULL)
|
rom_add_blob(_f, _b, _l, _l, _a, NULL, NULL, NULL)
|
||||||
#define rom_add_file_mr(_f, _mr, _i) \
|
#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_VGA 0xc0000
|
||||||
#define PC_ROM_MIN_OPTION 0xc8000
|
#define PC_ROM_MIN_OPTION 0xc8000
|
||||||
|
|
Loading…
Reference in New Issue