diff --git a/hw/pc.c b/hw/pc.c index 70be346249..917d9724a4 100644 --- a/hw/pc.c +++ b/hw/pc.c @@ -451,7 +451,7 @@ static void pc_init1(int ram_size, int vga_ram_size, int boot_device, { char buf[1024]; int ret, linux_boot, initrd_size, i; - unsigned long bios_offset, vga_bios_offset; + unsigned long bios_offset, vga_bios_offset, option_rom_offset; int bios_size, isa_bios_size; PCIBus *pci_bus; int piix3_devfn = -1; @@ -518,6 +518,23 @@ static void pc_init1(int ram_size, int vga_ram_size, int boot_device, cpu_register_physical_memory(0x100000 - isa_bios_size, isa_bios_size, (bios_offset + bios_size - isa_bios_size) | IO_MEM_ROM); + + option_rom_offset = 0; + for (i = 0; i < nb_option_roms; i++) { + int offset = bios_offset + bios_size + option_rom_offset; + int size; + + size = load_image(option_rom[i], phys_ram_base + offset); + if ((size + option_rom_offset) > 0x10000) { + fprintf(stderr, "Too many option ROMS\n"); + exit(1); + } + cpu_register_physical_memory(0xd0000 + option_rom_offset, + size, offset | IO_MEM_ROM); + option_rom_offset += size + 2047; + option_rom_offset -= (option_rom_offset % 2048); + } + /* map all the bios at the top of memory */ cpu_register_physical_memory((uint32_t)(-bios_size), bios_size, bios_offset | IO_MEM_ROM); diff --git a/qemu-doc.texi b/qemu-doc.texi index f76ffd0032..1dd33fe9b3 100644 --- a/qemu-doc.texi +++ b/qemu-doc.texi @@ -326,6 +326,10 @@ Use it when installing Windows 2000 to avoid a disk full bug. After Windows 2000 is installed, you no longer need this option (this option slows down the IDE transfers). +@item -option-rom file +Load the contents of file as an option ROM. This option is useful to load +things like EtherBoot. + @end table USB options: diff --git a/vl.c b/vl.c index 5e06b0d77c..cfe94c8162 100644 --- a/vl.c +++ b/vl.c @@ -174,6 +174,8 @@ int acpi_enabled = 1; int fd_bootchk = 1; int no_reboot = 0; int daemonize = 0; +const char *option_rom[MAX_OPTION_ROMS]; +int nb_option_roms; /***********************************************************/ /* x86 ISA bus support */ @@ -6336,6 +6338,7 @@ void help(void) #ifndef _WIN32 "-daemonize daemonize QEMU after initializing\n" #endif + "-option-rom rom load a file, rom, into the option ROM space\n" "\n" "During emulation, the following keys are useful:\n" "ctrl-alt-f toggle full screen\n" @@ -6418,6 +6421,7 @@ enum { QEMU_OPTION_no_reboot, QEMU_OPTION_daemonize, QEMU_OPTION_disk, + QEMU_OPTION_option_rom, }; typedef struct QEMUOption { @@ -6500,6 +6504,7 @@ const QEMUOption qemu_options[] = { { "no-acpi", 0, QEMU_OPTION_no_acpi }, { "no-reboot", 0, QEMU_OPTION_no_reboot }, { "daemonize", 0, QEMU_OPTION_daemonize }, + { "option-rom", HAS_ARG, QEMU_OPTION_option_rom }, { NULL }, }; @@ -7276,6 +7281,14 @@ int main(int argc, char **argv) case QEMU_OPTION_daemonize: daemonize = 1; break; + case QEMU_OPTION_option_rom: + if (nb_option_roms >= MAX_OPTION_ROMS) { + fprintf(stderr, "Too many option ROMs\n"); + exit(1); + } + option_rom[nb_option_roms] = optarg; + nb_option_roms++; + break; } } } @@ -7368,6 +7381,15 @@ int main(int argc, char **argv) /* init the memory */ phys_ram_size = ram_size + vga_ram_size + bios_size; + for (i = 0; i < nb_option_roms; i++) { + int ret = get_image_size(option_rom[i]); + if (ret == -1) { + fprintf(stderr, "Could not load option rom '%s'\n", option_rom[i]); + exit(1); + } + phys_ram_size += ret; + } + phys_ram_base = qemu_vmalloc(phys_ram_size); if (!phys_ram_base) { fprintf(stderr, "Could not allocate physical memory\n"); diff --git a/vl.h b/vl.h index 5561a27c99..b63145e352 100644 --- a/vl.h +++ b/vl.h @@ -154,6 +154,10 @@ extern int usb_enabled; extern int smp_cpus; extern int no_quit; +#define MAX_OPTION_ROMS 16 +extern const char *option_rom[MAX_OPTION_ROMS]; +extern int nb_option_roms; + /* XXX: make it dynamic */ #if defined (TARGET_PPC) || defined (TARGET_SPARC64) #define BIOS_SIZE ((512 + 32) * 1024)