summaryrefslogtreecommitdiff
path: root/hw/i386/pc.c
diff options
context:
space:
mode:
authorStefano Garzarella <sgarzare@redhat.com>2019-01-15 12:18:07 +0000
committerPaolo Bonzini <pbonzini@redhat.com>2019-02-05 16:50:16 +0100
commitc5bf7847b7b281bc13795b12d09ca1f35fc62673 (patch)
tree3941c232d90f8e4733581760ccec874be622a3af /hw/i386/pc.c
parentab969087da65e2f67a546cfc664901eda7029e36 (diff)
downloadqemu-c5bf7847b7b281bc13795b12d09ca1f35fc62673.zip
pvh: load initrd and expose it through fw_cfg
When initrd is specified, load and expose it to the guest firmware through fw_cfg. The firmware will fill the hvm_start_info for the kernel. Signed-off-by: Stefano Garzarella <sgarzare@redhat.com> Based-on: <1545422632-24444-5-git-send-email-liam.merwick@oracle.com> Signed-off-by: Liam Merwick <Liam.Merwick@oracle.com> Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
Diffstat (limited to 'hw/i386/pc.c')
-rw-r--r--hw/i386/pc.c38
1 files changed, 29 insertions, 9 deletions
diff --git a/hw/i386/pc.c b/hw/i386/pc.c
index e39ef5caa1..5d61557a24 100644
--- a/hw/i386/pc.c
+++ b/hw/i386/pc.c
@@ -1222,25 +1222,45 @@ static void load_linux(PCMachineState *pcms,
*/
if (load_elfboot(kernel_filename, kernel_size,
header, pvh_start_addr, fw_cfg)) {
- struct hvm_modlist_entry ramdisk_mod = { 0 };
-
fclose(f);
fw_cfg_add_i32(fw_cfg, FW_CFG_CMDLINE_SIZE,
strlen(kernel_cmdline) + 1);
fw_cfg_add_string(fw_cfg, FW_CFG_CMDLINE_DATA, kernel_cmdline);
- assert(machine->device_memory != NULL);
- ramdisk_mod.paddr = machine->device_memory->base;
- ramdisk_mod.size =
- memory_region_size(&machine->device_memory->mr);
-
- fw_cfg_add_bytes(fw_cfg, FW_CFG_KERNEL_DATA, &ramdisk_mod,
- sizeof(ramdisk_mod));
fw_cfg_add_i32(fw_cfg, FW_CFG_SETUP_SIZE, sizeof(header));
fw_cfg_add_bytes(fw_cfg, FW_CFG_SETUP_DATA,
header, sizeof(header));
+ /* load initrd */
+ if (initrd_filename) {
+ gsize initrd_size;
+ gchar *initrd_data;
+ GError *gerr = NULL;
+
+ if (!g_file_get_contents(initrd_filename, &initrd_data,
+ &initrd_size, &gerr)) {
+ fprintf(stderr, "qemu: error reading initrd %s: %s\n",
+ initrd_filename, gerr->message);
+ exit(1);
+ }
+
+ initrd_max = pcms->below_4g_mem_size - pcmc->acpi_data_size - 1;
+ if (initrd_size >= initrd_max) {
+ fprintf(stderr, "qemu: initrd is too large, cannot support."
+ "(max: %"PRIu32", need %"PRId64")\n",
+ initrd_max, (uint64_t)initrd_size);
+ exit(1);
+ }
+
+ initrd_addr = (initrd_max - initrd_size) & ~4095;
+
+ fw_cfg_add_i32(fw_cfg, FW_CFG_INITRD_ADDR, initrd_addr);
+ fw_cfg_add_i32(fw_cfg, FW_CFG_INITRD_SIZE, initrd_size);
+ fw_cfg_add_bytes(fw_cfg, FW_CFG_INITRD_DATA, initrd_data,
+ initrd_size);
+ }
+
return;
}
/* This looks like a multiboot kernel. If it is, let's stop