diff options
Diffstat (limited to 'hw/core')
-rw-r--r-- | hw/core/loader.c | 67 | ||||
-rw-r--r-- | hw/core/machine.c | 1 |
2 files changed, 55 insertions, 13 deletions
diff --git a/hw/core/loader.c b/hw/core/loader.c index fea22d265c..9feca32de9 100644 --- a/hw/core/loader.c +++ b/hw/core/loader.c @@ -1166,34 +1166,77 @@ static void rom_reset(void *unused) } } +/* Return true if two consecutive ROMs in the ROM list overlap */ +static bool roms_overlap(Rom *last_rom, Rom *this_rom) +{ + if (!last_rom) { + return false; + } + return last_rom->as == this_rom->as && + last_rom->addr + last_rom->romsize > this_rom->addr; +} + +static const char *rom_as_name(Rom *rom) +{ + const char *name = rom->as ? rom->as->name : NULL; + return name ?: "anonymous"; +} + +static void rom_print_overlap_error_header(void) +{ + error_report("Some ROM regions are overlapping"); + error_printf( + "These ROM regions might have been loaded by " + "direct user request or by default.\n" + "They could be BIOS/firmware images, a guest kernel, " + "initrd or some other file loaded into guest memory.\n" + "Check whether you intended to load all this guest code, and " + "whether it has been built to load to the correct addresses.\n"); +} + +static void rom_print_one_overlap_error(Rom *last_rom, Rom *rom) +{ + error_printf( + "\nThe following two regions overlap (in the %s address space):\n", + rom_as_name(rom)); + error_printf( + " %s (addresses 0x" TARGET_FMT_plx " - 0x" TARGET_FMT_plx ")\n", + last_rom->name, last_rom->addr, last_rom->addr + last_rom->romsize); + error_printf( + " %s (addresses 0x" TARGET_FMT_plx " - 0x" TARGET_FMT_plx ")\n", + rom->name, rom->addr, rom->addr + rom->romsize); +} + int rom_check_and_register_reset(void) { - hwaddr addr = 0; MemoryRegionSection section; - Rom *rom; - AddressSpace *as = NULL; + Rom *rom, *last_rom = NULL; + bool found_overlap = false; QTAILQ_FOREACH(rom, &roms, next) { if (rom->fw_file) { continue; } if (!rom->mr) { - 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", - rom->name, addr, rom->addr); - return -1; + if (roms_overlap(last_rom, rom)) { + if (!found_overlap) { + found_overlap = true; + rom_print_overlap_error_header(); + } + rom_print_one_overlap_error(last_rom, rom); + /* Keep going through the list so we report all overlaps */ } - addr = rom->addr; - addr += rom->romsize; - as = rom->as; + last_rom = rom; } section = memory_region_find(rom->mr ? rom->mr : get_system_memory(), rom->addr, 1); rom->isrom = int128_nz(section.size) && memory_region_is_rom(section.mr); memory_region_unref(section.mr); } + if (found_overlap) { + return -1; + } + qemu_register_reset(rom_reset, NULL); roms_loaded = 1; return 0; diff --git a/hw/core/machine.c b/hw/core/machine.c index 607eb88291..05dcaf09c9 100644 --- a/hw/core/machine.c +++ b/hw/core/machine.c @@ -1224,7 +1224,6 @@ void qdev_machine_creation_done(void) notifier_list_notify(&machine_init_done_notifiers, NULL); if (rom_check_and_register_reset() != 0) { - error_report("rom check and register reset failed"); exit(1); } |