diff options
Diffstat (limited to 'hw/i386')
-rw-r--r-- | hw/i386/Makefile.objs | 10 | ||||
-rw-r--r-- | hw/i386/acpi-build.c | 1 | ||||
-rw-r--r-- | hw/i386/acpi-dsdt.dsl | 1 | ||||
-rw-r--r-- | hw/i386/pc.c | 156 | ||||
-rw-r--r-- | hw/i386/pc_piix.c | 77 | ||||
-rw-r--r-- | hw/i386/pc_q35.c | 69 | ||||
-rw-r--r-- | hw/i386/q35-acpi-dsdt.dsl | 1 | ||||
-rw-r--r-- | hw/i386/smbios.c | 1102 |
8 files changed, 142 insertions, 1275 deletions
diff --git a/hw/i386/Makefile.objs b/hw/i386/Makefile.objs index bd4f147f9d..ebd1015a08 100644 --- a/hw/i386/Makefile.objs +++ b/hw/i386/Makefile.objs @@ -1,5 +1,5 @@ obj-$(CONFIG_KVM) += kvm/ -obj-y += multiboot.o smbios.o +obj-y += multiboot.o obj-y += pc.o pc_piix.o pc_q35.o obj-y += pc_sysfw.o obj-y += intel_iommu.o @@ -7,8 +7,14 @@ obj-$(CONFIG_XEN) += ../xenpv/ xen/ obj-y += kvmvapic.o obj-y += acpi-build.o + +gen-hex-y += hw/i386/acpi-dsdt.hex +gen-hex-y += hw/i386/q35-acpi-dsdt.hex + hw/i386/acpi-build.o: hw/i386/acpi-build.c \ - hw/i386/acpi-dsdt.hex hw/i386/q35-acpi-dsdt.hex + $(gen-hex-y) + +-include $(gen-hex-y:.hex=.d) iasl-option=$(shell if test -z "`$(1) $(2) 2>&1 > /dev/null`" \ ; then echo "$(2)"; else echo "$(3)"; fi ;) diff --git a/hw/i386/acpi-build.c b/hw/i386/acpi-build.c index 46eddb8e48..95e0c657a7 100644 --- a/hw/i386/acpi-build.c +++ b/hw/i386/acpi-build.c @@ -169,6 +169,7 @@ static void acpi_get_pm_info(AcpiPmInfo *pm) Object *obj = NULL; QObject *o; + pm->cpu_hp_io_base = 0; pm->pcihp_io_base = 0; pm->pcihp_io_len = 0; if (piix) { diff --git a/hw/i386/acpi-dsdt.dsl b/hw/i386/acpi-dsdt.dsl index a2d84ecf8f..8dba096dd8 100644 --- a/hw/i386/acpi-dsdt.dsl +++ b/hw/i386/acpi-dsdt.dsl @@ -43,7 +43,6 @@ DefinitionBlock ( #include "acpi-dsdt-hpet.dsl" - /**************************************************************** * PIIX4 PM ****************************************************************/ diff --git a/hw/i386/pc.c b/hw/i386/pc.c index 7661ea9cdf..9f2924e5df 100644 --- a/hw/i386/pc.c +++ b/hw/i386/pc.c @@ -33,7 +33,7 @@ #include "hw/pci/pci_bus.h" #include "hw/nvram/fw_cfg.h" #include "hw/timer/hpet.h" -#include "hw/i386/smbios.h" +#include "hw/smbios/smbios.h" #include "hw/loader.h" #include "elf.h" #include "multiboot.h" @@ -428,26 +428,24 @@ static void pc_cmos_init_late(void *opaque) qemu_unregister_reset(pc_cmos_init_late, opaque); } -void pc_cmos_init(ram_addr_t ram_size, ram_addr_t above_4g_mem_size, - const char *boot_device, MachineState *machine, +void pc_cmos_init(PCMachineState *pcms, BusState *idebus0, BusState *idebus1, ISADevice *s) { int val; static pc_cmos_init_late_arg arg; - PCMachineState *pc_machine = PC_MACHINE(machine); Error *local_err = NULL; /* various important CMOS locations needed by PC/Bochs bios */ /* memory size */ /* base memory (first MiB) */ - val = MIN(ram_size / 1024, 640); + val = MIN(pcms->below_4g_mem_size / 1024, 640); rtc_set_memory(s, 0x15, val); rtc_set_memory(s, 0x16, val >> 8); /* extended memory (next 64MiB) */ - if (ram_size > 1024 * 1024) { - val = (ram_size - 1024 * 1024) / 1024; + if (pcms->below_4g_mem_size > 1024 * 1024) { + val = (pcms->below_4g_mem_size - 1024 * 1024) / 1024; } else { val = 0; } @@ -458,8 +456,8 @@ void pc_cmos_init(ram_addr_t ram_size, ram_addr_t above_4g_mem_size, rtc_set_memory(s, 0x30, val); rtc_set_memory(s, 0x31, val >> 8); /* memory between 16MiB and 4GiB */ - if (ram_size > 16 * 1024 * 1024) { - val = (ram_size - 16 * 1024 * 1024) / 65536; + if (pcms->below_4g_mem_size > 16 * 1024 * 1024) { + val = (pcms->below_4g_mem_size - 16 * 1024 * 1024) / 65536; } else { val = 0; } @@ -468,7 +466,7 @@ void pc_cmos_init(ram_addr_t ram_size, ram_addr_t above_4g_mem_size, rtc_set_memory(s, 0x34, val); rtc_set_memory(s, 0x35, val >> 8); /* memory above 4GiB */ - val = above_4g_mem_size / 65536; + val = pcms->above_4g_mem_size / 65536; rtc_set_memory(s, 0x5b, val); rtc_set_memory(s, 0x5c, val >> 8); rtc_set_memory(s, 0x5d, val >> 16); @@ -476,15 +474,15 @@ void pc_cmos_init(ram_addr_t ram_size, ram_addr_t above_4g_mem_size, /* set the number of CPU */ rtc_set_memory(s, 0x5f, smp_cpus - 1); - object_property_add_link(OBJECT(machine), "rtc_state", + object_property_add_link(OBJECT(pcms), "rtc_state", TYPE_ISA_DEVICE, - (Object **)&pc_machine->rtc, + (Object **)&pcms->rtc, object_property_allow_set_link, OBJ_PROP_LINK_UNREF_ON_RELEASE, &error_abort); - object_property_set_link(OBJECT(machine), OBJECT(s), + object_property_set_link(OBJECT(pcms), OBJECT(s), "rtc_state", &error_abort); - set_boot_dev(s, boot_device, &local_err); + set_boot_dev(s, MACHINE(pcms)->boot_order, &local_err); if (local_err) { error_report_err(local_err); exit(1); @@ -718,11 +716,46 @@ static unsigned int pc_apic_id_limit(unsigned int max_cpus) return x86_cpu_apic_id_from_index(max_cpus - 1) + 1; } -static FWCfgState *bochs_bios_init(void) +static void pc_build_smbios(FWCfgState *fw_cfg) { - FWCfgState *fw_cfg; uint8_t *smbios_tables, *smbios_anchor; size_t smbios_tables_len, smbios_anchor_len; + struct smbios_phys_mem_area *mem_array; + unsigned i, array_count; + + smbios_tables = smbios_get_table_legacy(&smbios_tables_len); + if (smbios_tables) { + fw_cfg_add_bytes(fw_cfg, FW_CFG_SMBIOS_ENTRIES, + smbios_tables, smbios_tables_len); + } + + /* build the array of physical mem area from e820 table */ + mem_array = g_malloc0(sizeof(*mem_array) * e820_get_num_entries()); + for (i = 0, array_count = 0; i < e820_get_num_entries(); i++) { + uint64_t addr, len; + + if (e820_get_entry(i, E820_RAM, &addr, &len)) { + mem_array[array_count].address = addr; + mem_array[array_count].length = len; + array_count++; + } + } + smbios_get_tables(mem_array, array_count, + &smbios_tables, &smbios_tables_len, + &smbios_anchor, &smbios_anchor_len); + g_free(mem_array); + + if (smbios_anchor) { + fw_cfg_add_file(fw_cfg, "etc/smbios/smbios-tables", + smbios_tables, smbios_tables_len); + fw_cfg_add_file(fw_cfg, "etc/smbios/smbios-anchor", + smbios_anchor, smbios_anchor_len); + } +} + +static FWCfgState *bochs_bios_init(void) +{ + FWCfgState *fw_cfg; uint64_t *numa_fw_cfg; int i, j; unsigned int apic_id_limit = pc_apic_id_limit(max_cpus); @@ -748,20 +781,7 @@ static FWCfgState *bochs_bios_init(void) acpi_tables, acpi_tables_len); fw_cfg_add_i32(fw_cfg, FW_CFG_IRQ0_OVERRIDE, kvm_allows_irq0_override()); - smbios_tables = smbios_get_table_legacy(&smbios_tables_len); - if (smbios_tables) { - fw_cfg_add_bytes(fw_cfg, FW_CFG_SMBIOS_ENTRIES, - smbios_tables, smbios_tables_len); - } - - smbios_get_tables(&smbios_tables, &smbios_tables_len, - &smbios_anchor, &smbios_anchor_len); - if (smbios_anchor) { - fw_cfg_add_file(fw_cfg, "etc/smbios/smbios-tables", - smbios_tables, smbios_tables_len); - fw_cfg_add_file(fw_cfg, "etc/smbios/smbios-anchor", - smbios_anchor, smbios_anchor_len); - } + pc_build_smbios(fw_cfg); fw_cfg_add_bytes(fw_cfg, FW_CFG_E820_TABLE, &e820_reserve, sizeof(e820_reserve)); @@ -809,11 +829,8 @@ static long get_file_size(FILE *f) return size; } -static void load_linux(FWCfgState *fw_cfg, - const char *kernel_filename, - const char *initrd_filename, - const char *kernel_cmdline, - hwaddr max_ram_size) +static void load_linux(PCMachineState *pcms, + FWCfgState *fw_cfg) { uint16_t protocol; int setup_size, kernel_size, initrd_size = 0, cmdline_size; @@ -822,6 +839,10 @@ static void load_linux(FWCfgState *fw_cfg, hwaddr real_addr, prot_addr, cmdline_addr, initrd_addr = 0; FILE *f; char *vmode; + MachineState *machine = MACHINE(pcms); + const char *kernel_filename = machine->kernel_filename; + const char *initrd_filename = machine->initrd_filename; + const char *kernel_cmdline = machine->kernel_cmdline; /* Align to 16 bytes as a paranoia measure */ cmdline_size = (strlen(kernel_cmdline)+16) & ~15; @@ -886,8 +907,8 @@ static void load_linux(FWCfgState *fw_cfg, initrd_max = 0x37ffffff; } - if (initrd_max >= max_ram_size - acpi_data_size) { - initrd_max = max_ram_size - acpi_data_size - 1; + if (initrd_max >= pcms->below_4g_mem_size - acpi_data_size) { + initrd_max = pcms->below_4g_mem_size - acpi_data_size - 1; } fw_cfg_add_i32(fw_cfg, FW_CFG_CMDLINE_ADDR, cmdline_addr); @@ -1189,15 +1210,14 @@ void pc_guest_info_machine_done(Notifier *notifier, void *data) acpi_setup(&guest_info_state->info); } -PcGuestInfo *pc_guest_info_init(ram_addr_t below_4g_mem_size, - ram_addr_t above_4g_mem_size) +PcGuestInfo *pc_guest_info_init(PCMachineState *pcms) { PcGuestInfoState *guest_info_state = g_malloc0(sizeof *guest_info_state); PcGuestInfo *guest_info = &guest_info_state->info; int i, j; - guest_info->ram_size_below_4g = below_4g_mem_size; - guest_info->ram_size = below_4g_mem_size + above_4g_mem_size; + guest_info->ram_size_below_4g = pcms->below_4g_mem_size; + guest_info->ram_size = pcms->below_4g_mem_size + pcms->above_4g_mem_size; guest_info->apic_id_limit = pc_apic_id_limit(max_cpus); guest_info->apic_xrupt_override = kvm_allows_irq0_override(); guest_info->numa_nodes = nb_numa_nodes; @@ -1264,22 +1284,18 @@ void pc_acpi_init(const char *default_dsdt) } } -FWCfgState *xen_load_linux(const char *kernel_filename, - const char *kernel_cmdline, - const char *initrd_filename, - ram_addr_t below_4g_mem_size, +FWCfgState *xen_load_linux(PCMachineState *pcms, PcGuestInfo *guest_info) { int i; FWCfgState *fw_cfg; - assert(kernel_filename != NULL); + assert(MACHINE(pcms)->kernel_filename != NULL); fw_cfg = fw_cfg_init_io(BIOS_CFG_IOPORT); rom_set_fw(fw_cfg); - load_linux(fw_cfg, kernel_filename, initrd_filename, - kernel_cmdline, below_4g_mem_size); + load_linux(pcms, fw_cfg); for (i = 0; i < nb_option_roms; i++) { assert(!strcmp(option_rom[i].name, "linuxboot.bin") || !strcmp(option_rom[i].name, "multiboot.bin")); @@ -1289,10 +1305,8 @@ FWCfgState *xen_load_linux(const char *kernel_filename, return fw_cfg; } -FWCfgState *pc_memory_init(MachineState *machine, +FWCfgState *pc_memory_init(PCMachineState *pcms, MemoryRegion *system_memory, - ram_addr_t below_4g_mem_size, - ram_addr_t above_4g_mem_size, MemoryRegion *rom_memory, MemoryRegion **ram_memory, PcGuestInfo *guest_info) @@ -1301,9 +1315,10 @@ FWCfgState *pc_memory_init(MachineState *machine, MemoryRegion *ram, *option_rom_mr; MemoryRegion *ram_below_4g, *ram_above_4g; FWCfgState *fw_cfg; - PCMachineState *pcms = PC_MACHINE(machine); + MachineState *machine = MACHINE(pcms); - assert(machine->ram_size == below_4g_mem_size + above_4g_mem_size); + assert(machine->ram_size == pcms->below_4g_mem_size + + pcms->above_4g_mem_size); linux_boot = (machine->kernel_filename != NULL); @@ -1317,16 +1332,17 @@ FWCfgState *pc_memory_init(MachineState *machine, *ram_memory = ram; ram_below_4g = g_malloc(sizeof(*ram_below_4g)); memory_region_init_alias(ram_below_4g, NULL, "ram-below-4g", ram, - 0, below_4g_mem_size); + 0, pcms->below_4g_mem_size); memory_region_add_subregion(system_memory, 0, ram_below_4g); - e820_add_entry(0, below_4g_mem_size, E820_RAM); - if (above_4g_mem_size > 0) { + e820_add_entry(0, pcms->below_4g_mem_size, E820_RAM); + if (pcms->above_4g_mem_size > 0) { ram_above_4g = g_malloc(sizeof(*ram_above_4g)); memory_region_init_alias(ram_above_4g, NULL, "ram-above-4g", ram, - below_4g_mem_size, above_4g_mem_size); + pcms->below_4g_mem_size, + pcms->above_4g_mem_size); memory_region_add_subregion(system_memory, 0x100000000ULL, ram_above_4g); - e820_add_entry(0x100000000ULL, above_4g_mem_size, E820_RAM); + e820_add_entry(0x100000000ULL, pcms->above_4g_mem_size, E820_RAM); } if (!guest_info->has_reserved_memory && @@ -1359,7 +1375,7 @@ FWCfgState *pc_memory_init(MachineState *machine, } pcms->hotplug_memory.base = - ROUND_UP(0x100000000ULL + above_4g_mem_size, 1ULL << 30); + ROUND_UP(0x100000000ULL + pcms->above_4g_mem_size, 1ULL << 30); if (pcms->enforce_aligned_dimm) { /* size hotplug region assuming 1G page max alignment per slot */ @@ -1401,8 +1417,7 @@ FWCfgState *pc_memory_init(MachineState *machine, } if (linux_boot) { - load_linux(fw_cfg, machine->kernel_filename, machine->initrd_filename, - machine->kernel_cmdline, below_4g_mem_size); + load_linux(pcms, fw_cfg); } for (i = 0; i < nb_option_roms; i++) { @@ -1886,39 +1901,39 @@ static void pc_machine_initfn(Object *obj) object_property_add(obj, PC_MACHINE_MEMHP_REGION_SIZE, "int", pc_machine_get_hotplug_memory_region_size, - NULL, NULL, NULL, NULL); + NULL, NULL, NULL, &error_abort); pcms->max_ram_below_4g = 1ULL << 32; /* 4G */ object_property_add(obj, PC_MACHINE_MAX_RAM_BELOW_4G, "size", pc_machine_get_max_ram_below_4g, pc_machine_set_max_ram_below_4g, - NULL, NULL, NULL); + NULL, NULL, &error_abort); object_property_set_description(obj, PC_MACHINE_MAX_RAM_BELOW_4G, "Maximum ram below the 4G boundary (32bit boundary)", - NULL); + &error_abort); pcms->smm = ON_OFF_AUTO_AUTO; object_property_add(obj, PC_MACHINE_SMM, "OnOffAuto", pc_machine_get_smm, pc_machine_set_smm, - NULL, NULL, NULL); + NULL, NULL, &error_abort); object_property_set_description(obj, PC_MACHINE_SMM, "Enable SMM (pc & q35)", - NULL); + &error_abort); pcms->vmport = ON_OFF_AUTO_AUTO; object_property_add(obj, PC_MACHINE_VMPORT, "OnOffAuto", pc_machine_get_vmport, pc_machine_set_vmport, - NULL, NULL, NULL); + NULL, NULL, &error_abort); object_property_set_description(obj, PC_MACHINE_VMPORT, "Enable vmport (pc & q35)", - NULL); + &error_abort); pcms->enforce_aligned_dimm = true; object_property_add_bool(obj, PC_MACHINE_ENFORCE_ALIGNED_DIMM, pc_machine_get_aligned_dimm, - NULL, NULL); + NULL, &error_abort); } static unsigned pc_cpu_index_to_socket_id(unsigned cpu_index) @@ -1938,6 +1953,9 @@ static void pc_machine_class_init(ObjectClass *oc, void *data) pcmc->get_hotplug_handler = mc->get_hotplug_handler; mc->get_hotplug_handler = pc_get_hotpug_handler; mc->cpu_index_to_socket_id = pc_cpu_index_to_socket_id; + mc->default_boot_order = "cad"; + mc->hot_add_cpu = pc_hot_add_cpu; + mc->max_cpus = 255; hc->plug = pc_machine_device_plug_cb; hc->unplug_request = pc_machine_device_unplug_request_cb; hc->unplug = pc_machine_device_unplug_cb; diff --git a/hw/i386/pc_piix.c b/hw/i386/pc_piix.c index a896624f89..95584676e2 100644 --- a/hw/i386/pc_piix.c +++ b/hw/i386/pc_piix.c @@ -28,7 +28,7 @@ #include "hw/loader.h" #include "hw/i386/pc.h" #include "hw/i386/apic.h" -#include "hw/i386/smbios.h" +#include "hw/smbios/smbios.h" #include "hw/pci/pci.h" #include "hw/pci/pci_ids.h" #include "hw/usb.h" @@ -78,11 +78,10 @@ static bool kvmclock_enabled = true; /* PC hardware initialisation */ static void pc_init1(MachineState *machine) { - PCMachineState *pc_machine = PC_MACHINE(machine); + PCMachineState *pcms = PC_MACHINE(machine); MemoryRegion *system_memory = get_system_memory(); MemoryRegion *system_io = get_system_io(); int i; - ram_addr_t below_4g_mem_size, above_4g_mem_size; PCIBus *pci_bus; ISABus *isa_bus; PCII440FXState *i440fx_state; @@ -117,25 +116,26 @@ static void pc_init1(MachineState *machine) /* Handle the machine opt max-ram-below-4g. It is basically doing * min(qemu limit, user limit). */ - if (lowmem > pc_machine->max_ram_below_4g) { - lowmem = pc_machine->max_ram_below_4g; + if (lowmem > pcms->max_ram_below_4g) { + lowmem = pcms->max_ram_below_4g; if (machine->ram_size - lowmem > lowmem && lowmem & ((1ULL << 30) - 1)) { error_report("Warning: Large machine and max_ram_below_4g(%"PRIu64 ") not a multiple of 1G; possible bad performance.", - pc_machine->max_ram_below_4g); + pcms->max_ram_below_4g); } } if (machine->ram_size >= lowmem) { - above_4g_mem_size = machine->ram_size - lowmem; - below_4g_mem_size = lowmem; + pcms->above_4g_mem_size = machine->ram_size - lowmem; + pcms->below_4g_mem_size = lowmem; } else { - above_4g_mem_size = 0; - below_4g_mem_size = machine->ram_size; + pcms->above_4g_mem_size = 0; + pcms->below_4g_mem_size = machine->ram_size; } - if (xen_enabled() && xen_hvm_init(&below_4g_mem_size, &above_4g_mem_size, + if (xen_enabled() && xen_hvm_init(&pcms->below_4g_mem_size, + &pcms->above_4g_mem_size, &ram_memory) != 0) { fprintf(stderr, "xen hardware virtual machine initialisation failed\n"); exit(1); @@ -160,7 +160,7 @@ static void pc_init1(MachineState *machine) rom_memory = system_memory; } - guest_info = pc_guest_info_init(below_4g_mem_size, above_4g_mem_size); + guest_info = pc_guest_info_init(pcms); guest_info->has_acpi_build = has_acpi_build; guest_info->legacy_acpi_table_size = legacy_acpi_table_size; @@ -178,16 +178,11 @@ static void pc_init1(MachineState *machine) /* allocate ram and load rom/bios */ if (!xen_enabled()) { - pc_memory_init(machine, system_memory, - below_4g_mem_size, above_4g_mem_size, + pc_memory_init(pcms, system_memory, rom_memory, &ram_memory, guest_info); } else if (machine->kernel_filename != NULL) { /* For xen HVM direct kernel boot, load linux here */ - xen_load_linux(machine->kernel_filename, - machine->kernel_cmdline, - machine->initrd_filename, - below_4g_mem_size, - guest_info); + xen_load_linux(pcms, guest_info); } gsi_state = g_malloc0(sizeof(*gsi_state)); @@ -202,8 +197,8 @@ static void pc_init1(MachineState *machine) if (pci_enabled) { pci_bus = i440fx_init(&i440fx_state, &piix3_devfn, &isa_bus, gsi, system_memory, system_io, machine->ram_size, - below_4g_mem_size, - above_4g_mem_size, + pcms->below_4g_mem_size, + pcms->above_4g_mem_size, pci_memory, ram_memory); } else { pci_bus = NULL; @@ -234,14 +229,14 @@ static void pc_init1(MachineState *machine) pc_vga_init(isa_bus, pci_enabled ? pci_bus : NULL); - assert(pc_machine->vmport != ON_OFF_AUTO_MAX); - if (pc_machine->vmport == ON_OFF_AUTO_AUTO) { - pc_machine->vmport = xen_enabled() ? ON_OFF_AUTO_OFF : ON_OFF_AUTO_ON; + assert(pcms->vmport != ON_OFF_AUTO_MAX); + if (pcms->vmport == ON_OFF_AUTO_AUTO) { + pcms->vmport = xen_enabled() ? ON_OFF_AUTO_OFF : ON_OFF_AUTO_ON; } /* init basic PC hardware */ pc_basic_device_init(isa_bus, gsi, &rtc_state, true, - (pc_machine->vmport != ON_OFF_AUTO_ON), 0x4); + (pcms->vmport != ON_OFF_AUTO_ON), 0x4); pc_nic_init(isa_bus, pci_bus); @@ -271,8 +266,7 @@ static void pc_init1(MachineState *machine) } } - pc_cmos_init(below_4g_mem_size, above_4g_mem_size, machine->boot_order, - machine, idebus[0], idebus[1], rtc_state); + pc_cmos_init(pcms, idebus[0], idebus[1], rtc_state); if (pci_enabled && usb_enabled()) { pci_create_simple(pci_bus, piix3_devfn + 2, "piix3-usb-uhci"); @@ -286,13 +280,13 @@ static void pc_init1(MachineState *machine) /* TODO: Populate SPD eeprom data. */ smbus = piix4_pm_init(pci_bus, piix3_devfn + 3, 0xb100, gsi[9], smi_irq, - pc_machine_is_smm_enabled(pc_machine), + pc_machine_is_smm_enabled(pcms), &piix4_pm); smbus_eeprom_init(smbus, 8, NULL, 0); object_property_add_link(OBJECT(machine), PC_MACHINE_ACPI_DEVICE_PROP, TYPE_HOTPLUG_HANDLER, - (Object **)&pc_machine->acpi_dev, + (Object **)&pcms->acpi_dev, object_property_allow_set_link, OBJ_PROP_LINK_UNREF_ON_RELEASE, &error_abort); object_property_set_link(OBJECT(machine), OBJECT(piix4_pm), @@ -319,24 +313,6 @@ static void pc_compat_2_2(MachineState *machine) { pc_compat_2_3(machine); rsdp_in_ram = false; - x86_cpu_compat_set_features("kvm64", FEAT_1_EDX, 0, CPUID_VME); - x86_cpu_compat_set_features("kvm32", FEAT_1_EDX, 0, CPUID_VME); - x86_cpu_compat_set_features("Conroe", FEAT_1_EDX, 0, CPUID_VME); - x86_cpu_compat_set_features("Penryn", FEAT_1_EDX, 0, CPUID_VME); - x86_cpu_compat_set_features("Nehalem", FEAT_1_EDX, 0, CPUID_VME); - x86_cpu_compat_set_features("Westmere", FEAT_1_EDX, 0, CPUID_VME); - x86_cpu_compat_set_features("SandyBridge", FEAT_1_EDX, 0, CPUID_VME); - x86_cpu_compat_set_features("Haswell", FEAT_1_EDX, 0, CPUID_VME); - x86_cpu_compat_set_features("Broadwell", FEAT_1_EDX, 0, CPUID_VME); - x86_cpu_compat_set_features("Opteron_G1", FEAT_1_EDX, 0, CPUID_VME); - x86_cpu_compat_set_features("Opteron_G2", FEAT_1_EDX, 0, CPUID_VME); - x86_cpu_compat_set_features("Opteron_G3", FEAT_1_EDX, 0, CPUID_VME); - x86_cpu_compat_set_features("Opteron_G4", FEAT_1_EDX, 0, CPUID_VME); - x86_cpu_compat_set_features("Opteron_G5", FEAT_1_EDX, 0, CPUID_VME); - x86_cpu_compat_set_features("Haswell", FEAT_1_ECX, 0, CPUID_EXT_F16C); - x86_cpu_compat_set_features("Haswell", FEAT_1_ECX, 0, CPUID_EXT_RDRAND); - x86_cpu_compat_set_features("Broadwell", FEAT_1_ECX, 0, CPUID_EXT_F16C); - x86_cpu_compat_set_features("Broadwell", FEAT_1_ECX, 0, CPUID_EXT_RDRAND); machine->suppress_vmdesc = true; } @@ -346,8 +322,6 @@ static void pc_compat_2_1(MachineState *machine) pc_compat_2_2(machine); smbios_uuid_encoded = false; - x86_cpu_compat_set_features("coreduo", FEAT_1_ECX, CPUID_EXT_VMX, 0); - x86_cpu_compat_set_features("core2duo", FEAT_1_ECX, CPUID_EXT_VMX, 0); x86_cpu_compat_kvm_no_autodisable(FEAT_8000_0001_ECX, CPUID_EXT3_SVM); pcms->enforce_aligned_dimm = false; } @@ -402,8 +376,6 @@ static void pc_compat_1_5(MachineState *machine) static void pc_compat_1_4(MachineState *machine) { pc_compat_1_5(machine); - x86_cpu_compat_set_features("n270", FEAT_1_ECX, 0, CPUID_EXT_MOVBE); - x86_cpu_compat_set_features("Westmere", FEAT_1_ECX, 0, CPUID_EXT_PCLMULQDQ); } static void pc_compat_1_3(MachineState *machine) @@ -471,7 +443,6 @@ static void pc_xen_hvm_init(MachineState *machine) static void pc_i440fx_machine_options(MachineClass *m) { - pc_default_machine_options(m); m->family = "pc_piix"; m->desc = "Standard PC (i440FX + PIIX, 1996)"; m->hot_add_cpu = pc_hot_add_cpu; @@ -909,7 +880,6 @@ DEFINE_I440FX_MACHINE(v0_10, "pc-0.10", pc_compat_0_13, static void isapc_machine_options(MachineClass *m) { - pc_common_machine_options(m); m->desc = "ISA-only PC"; m->max_cpus = 1; } @@ -921,7 +891,6 @@ DEFINE_PC_MACHINE(isapc, "isapc", pc_init_isa, #ifdef CONFIG_XEN static void xenfv_machine_options(MachineClass *m) { - pc_common_machine_options(m); m->desc = "Xen Fully-virtualized PC"; m->max_cpus = HVM_MAX_VCPUS; m->default_machine_opts = "accel=xen"; diff --git a/hw/i386/pc_q35.c b/hw/i386/pc_q35.c index 974aead5a9..c07d65bc46 100644 --- a/hw/i386/pc_q35.c +++ b/hw/i386/pc_q35.c @@ -39,7 +39,7 @@ #include "hw/pci-host/q35.h" #include "exec/address-spaces.h" #include "hw/i386/ich9.h" -#include "hw/i386/smbios.h" +#include "hw/smbios/smbios.h" #include "hw/ide/pci.h" #include "hw/ide/ahci.h" #include "hw/usb.h" @@ -65,8 +65,7 @@ static bool has_reserved_memory = true; /* PC hardware initialisation */ static void pc_q35_init(MachineState *machine) { - PCMachineState *pc_machine = PC_MACHINE(machine); - ram_addr_t below_4g_mem_size, above_4g_mem_size; + PCMachineState *pcms = PC_MACHINE(machine); Q35PCIHost *q35_host; PCIHostState *phb; PCIBus *host_bus; @@ -108,25 +107,26 @@ static void pc_q35_init(MachineState *machine) /* Handle the machine opt max-ram-below-4g. It is basically doing * min(qemu limit, user limit). */ - if (lowmem > pc_machine->max_ram_below_4g) { - lowmem = pc_machine->max_ram_below_4g; + if (lowmem > pcms->max_ram_below_4g) { + lowmem = pcms->max_ram_below_4g; if (machine->ram_size - lowmem > lowmem && lowmem & ((1ULL << 30) - 1)) { error_report("Warning: Large machine and max_ram_below_4g(%"PRIu64 ") not a multiple of 1G; possible bad performance.", - pc_machine->max_ram_below_4g); + pcms->max_ram_below_4g); } } if (machine->ram_size >= lowmem) { - above_4g_mem_size = machine->ram_size - lowmem; - below_4g_mem_size = lowmem; + pcms->above_4g_mem_size = machine->ram_size - lowmem; + pcms->below_4g_mem_size = lowmem; } else { - above_4g_mem_size = 0; - below_4g_mem_size = machine->ram_size; + pcms->above_4g_mem_size = 0; + pcms->below_4g_mem_size = machine->ram_size; } - if (xen_enabled() && xen_hvm_init(&below_4g_mem_size, &above_4g_mem_size, + if (xen_enabled() && xen_hvm_init(&pcms->below_4g_mem_size, + &pcms->above_4g_mem_size, &ram_memory) != 0) { fprintf(stderr, "xen hardware virtual machine initialisation failed\n"); exit(1); @@ -151,7 +151,7 @@ static void pc_q35_init(MachineState *machine) rom_memory = get_system_memory(); } - guest_info = pc_guest_info_init(below_4g_mem_size, above_4g_mem_size); + guest_info = pc_guest_info_init(pcms); guest_info->isapc_ram_fw = false; guest_info->has_acpi_build = has_acpi_build; guest_info->has_reserved_memory = has_reserved_memory; @@ -170,8 +170,7 @@ static void pc_q35_init(MachineState *machine) /* allocate ram and load rom/bios */ if (!xen_enabled()) { - pc_memory_init(machine, get_system_memory(), - below_4g_mem_size, above_4g_mem_size, + pc_memory_init(pcms, get_system_memory(), rom_memory, &ram_memory, guest_info); } @@ -193,8 +192,8 @@ static void pc_q35_init(MachineState *machine) q35_host->mch.pci_address_space = pci_memory; q35_host->mch.system_memory = get_system_memory(); q35_host->mch.address_space_io = get_system_io(); - q35_host->mch.below_4g_mem_size = below_4g_mem_size; - q35_host->mch.above_4g_mem_size = above_4g_mem_size; + q35_host->mch.below_4g_mem_size = pcms->below_4g_mem_size; + q35_host->mch.above_4g_mem_size = pcms->above_4g_mem_size; q35_host->mch.guest_info = guest_info; /* pci */ qdev_init_nofail(DEVICE(q35_host)); @@ -207,7 +206,7 @@ static void pc_q35_init(MachineState *machine) object_property_add_link(OBJECT(machine), PC_MACHINE_ACPI_DEVICE_PROP, TYPE_HOTPLUG_HANDLER, - (Object **)&pc_machine->acpi_dev, + (Object **)&pcms->acpi_dev, object_property_allow_set_link, OBJ_PROP_LINK_UNREF_ON_RELEASE, &error_abort); object_property_set_link(OBJECT(machine), OBJECT(lpc), @@ -242,17 +241,17 @@ static void pc_q35_init(MachineState *machine) pc_register_ferr_irq(gsi[13]); - assert(pc_machine->vmport != ON_OFF_AUTO_MAX); - if (pc_machine->vmport == ON_OFF_AUTO_AUTO) { - pc_machine->vmport = xen_enabled() ? ON_OFF_AUTO_OFF : ON_OFF_AUTO_ON; + assert(pcms->vmport != ON_OFF_AUTO_MAX); + if (pcms->vmport == ON_OFF_AUTO_AUTO) { + pcms->vmport = xen_enabled() ? ON_OFF_AUTO_OFF : ON_OFF_AUTO_ON; } /* init basic PC hardware */ pc_basic_device_init(isa_bus, gsi, &rtc_state, !mc->no_floppy, - (pc_machine->vmport != ON_OFF_AUTO_ON), 0xff0104); + (pcms->vmport != ON_OFF_AUTO_ON), 0xff0104); /* connect pm stuff to lpc */ - ich9_lpc_pm_init(lpc, pc_machine_is_smm_enabled(pc_machine), !mc->no_tco); + ich9_lpc_pm_init(lpc, pc_machine_is_smm_enabled(pcms), !mc->no_tco); /* ahci and SATA device, for q35 1 ahci controller is built-in */ ahci = pci_create_simple_multifunction(host_bus, @@ -276,8 +275,7 @@ static void pc_q35_init(MachineState *machine) 0xb100), 8, NULL, 0); - pc_cmos_init(below_4g_mem_size, above_4g_mem_size, machine->boot_order, - machine, idebus[0], idebus[1], rtc_state); + pc_cmos_init(pcms, idebus[0], idebus[1], rtc_state); /* the rest devices to which pci devfn is automatically assigned */ pc_vga_init(isa_bus, host_bus); @@ -302,24 +300,6 @@ static void pc_compat_2_2(MachineState *machine) { pc_compat_2_3(machine); rsdp_in_ram = false; - x86_cpu_compat_set_features("kvm64", FEAT_1_EDX, 0, CPUID_VME); - x86_cpu_compat_set_features("kvm32", FEAT_1_EDX, 0, CPUID_VME); - x86_cpu_compat_set_features("Conroe", FEAT_1_EDX, 0, CPUID_VME); - x86_cpu_compat_set_features("Penryn", FEAT_1_EDX, 0, CPUID_VME); - x86_cpu_compat_set_features("Nehalem", FEAT_1_EDX, 0, CPUID_VME); - x86_cpu_compat_set_features("Westmere", FEAT_1_EDX, 0, CPUID_VME); - x86_cpu_compat_set_features("SandyBridge", FEAT_1_EDX, 0, CPUID_VME); - x86_cpu_compat_set_features("Haswell", FEAT_1_EDX, 0, CPUID_VME); - x86_cpu_compat_set_features("Broadwell", FEAT_1_EDX, 0, CPUID_VME); - x86_cpu_compat_set_features("Opteron_G1", FEAT_1_EDX, 0, CPUID_VME); - x86_cpu_compat_set_features("Opteron_G2", FEAT_1_EDX, 0, CPUID_VME); - x86_cpu_compat_set_features("Opteron_G3", FEAT_1_EDX, 0, CPUID_VME); - x86_cpu_compat_set_features("Opteron_G4", FEAT_1_EDX, 0, CPUID_VME); - x86_cpu_compat_set_features("Opteron_G5", FEAT_1_EDX, 0, CPUID_VME); - x86_cpu_compat_set_features("Haswell", FEAT_1_ECX, 0, CPUID_EXT_F16C); - x86_cpu_compat_set_features("Haswell", FEAT_1_ECX, 0, CPUID_EXT_RDRAND); - x86_cpu_compat_set_features("Broadwell", FEAT_1_ECX, 0, CPUID_EXT_F16C); - x86_cpu_compat_set_features("Broadwell", FEAT_1_ECX, 0, CPUID_EXT_RDRAND); machine->suppress_vmdesc = true; } @@ -330,8 +310,6 @@ static void pc_compat_2_1(MachineState *machine) pc_compat_2_2(machine); pcms->enforce_aligned_dimm = false; smbios_uuid_encoded = false; - x86_cpu_compat_set_features("coreduo", FEAT_1_ECX, CPUID_EXT_VMX, 0); - x86_cpu_compat_set_features("core2duo", FEAT_1_ECX, CPUID_EXT_VMX, 0); x86_cpu_compat_kvm_no_autodisable(FEAT_8000_0001_ECX, CPUID_EXT3_SVM); } @@ -367,8 +345,6 @@ static void pc_compat_1_5(MachineState *machine) static void pc_compat_1_4(MachineState *machine) { pc_compat_1_5(machine); - x86_cpu_compat_set_features("n270", FEAT_1_ECX, 0, CPUID_EXT_MOVBE); - x86_cpu_compat_set_features("Westmere", FEAT_1_ECX, 0, CPUID_EXT_PCLMULQDQ); } #define DEFINE_Q35_MACHINE(suffix, name, compatfn, optionfn) \ @@ -385,7 +361,6 @@ static void pc_compat_1_4(MachineState *machine) static void pc_q35_machine_options(MachineClass *m) { - pc_default_machine_options(m); m->family = "pc_q35"; m->desc = "Standard PC (Q35 + ICH9, 2009)"; m->hot_add_cpu = pc_hot_add_cpu; diff --git a/hw/i386/q35-acpi-dsdt.dsl b/hw/i386/q35-acpi-dsdt.dsl index 16eaca3fae..7be7b37b87 100644 --- a/hw/i386/q35-acpi-dsdt.dsl +++ b/hw/i386/q35-acpi-dsdt.dsl @@ -22,6 +22,7 @@ * Based on acpi-dsdt.dsl, but heavily modified for q35 chipset. */ + ACPI_EXTRACT_ALL_CODE Q35AcpiDsdtAmlCode DefinitionBlock ( diff --git a/hw/i386/smbios.c b/hw/i386/smbios.c deleted file mode 100644 index 1341e02344..0000000000 --- a/hw/i386/smbios.c +++ /dev/null @@ -1,1102 +0,0 @@ -/* - * SMBIOS Support - * - * Copyright (C) 2009 Hewlett-Packard Development Company, L.P. - * Copyright (C) 2013 Red Hat, Inc. - * - * Authors: - * Alex Williamson <alex.williamson@hp.com> - * Markus Armbruster <armbru@redhat.com> - * - * This work is licensed under the terms of the GNU GPL, version 2. See - * the COPYING file in the top-level directory. - * - * Contributions after 2012-01-13 are licensed under the terms of the - * GNU GPL, version 2 or (at your option) any later version. - */ - -#include "qemu/config-file.h" -#include "qemu/error-report.h" -#include "sysemu/sysemu.h" -#include "sysemu/cpus.h" -#include "hw/i386/pc.h" -#include "hw/i386/smbios.h" -#include "hw/loader.h" - - -/* legacy structures and constants for <= 2.0 machines */ -struct smbios_header { - uint16_t length; - uint8_t type; -} QEMU_PACKED; - -struct smbios_field { - struct smbios_header header; - uint8_t type; - uint16_t offset; - uint8_t data[]; -} QEMU_PACKED; - -struct smbios_table { - struct smbios_header header; - uint8_t data[]; -} QEMU_PACKED; - -#define SMBIOS_FIELD_ENTRY 0 -#define SMBIOS_TABLE_ENTRY 1 - -static uint8_t *smbios_entries; -static size_t smbios_entries_len; -static bool smbios_legacy = true; -static bool smbios_uuid_encoded = true; -/* end: legacy structures & constants for <= 2.0 machines */ - - -static uint8_t *smbios_tables; -static size_t smbios_tables_len; -static unsigned smbios_table_max; -static unsigned smbios_table_cnt; -static struct smbios_entry_point ep; - -static int smbios_type4_count = 0; -static bool smbios_immutable; -static bool smbios_have_defaults; -static uint32_t smbios_cpuid_version, smbios_cpuid_features, smbios_smp_sockets; - -static DECLARE_BITMAP(have_binfile_bitmap, SMBIOS_MAX_TYPE+1); -static DECLARE_BITMAP(have_fields_bitmap, SMBIOS_MAX_TYPE+1); - -static struct { - const char *vendor, *version, *date; - bool have_major_minor, uefi; - uint8_t major, minor; -} type0; - -static struct { - const char *manufacturer, *product, *version, *serial, *sku, *family; - /* uuid is in qemu_uuid[] */ -} type1; - -static struct { - const char *manufacturer, *product, *version, *serial, *asset, *location; -} type2; - -static struct { - const char *manufacturer, *version, *serial, *asset, *sku; -} type3; - -static struct { - const char *sock_pfx, *manufacturer, *version, *serial, *asset, *part; -} type4; - -static struct { - const char *loc_pfx, *bank, *manufacturer, *serial, *asset, *part; - uint16_t speed; -} type17; - -static QemuOptsList qemu_smbios_opts = { - .name = "smbios", - .head = QTAILQ_HEAD_INITIALIZER(qemu_smbios_opts.head), - .desc = { - /* - * no elements => accept any params - * validation will happen later - */ - { /* end of list */ } - } -}; - -static const QemuOptDesc qemu_smbios_file_opts[] = { - { - .name = "file", - .type = QEMU_OPT_STRING, - .help = "binary file containing an SMBIOS element", - }, - { /* end of list */ } -}; - -static const QemuOptDesc qemu_smbios_type0_opts[] = { - { - .name = "type", - .type = QEMU_OPT_NUMBER, - .help = "SMBIOS element type", - },{ - .name = "vendor", - .type = QEMU_OPT_STRING, - .help = "vendor name", - },{ - .name = "version", - .type = QEMU_OPT_STRING, - .help = "version number", - },{ - .name = "date", - .type = QEMU_OPT_STRING, - .help = "release date", - },{ - .name = "release", - .type = QEMU_OPT_STRING, - .help = "revision number", - },{ - .name = "uefi", - .type = QEMU_OPT_BOOL, - .help = "uefi support", - }, - { /* end of list */ } -}; - -static const QemuOptDesc qemu_smbios_type1_opts[] = { - { - .name = "type", - .type = QEMU_OPT_NUMBER, - .help = "SMBIOS element type", - },{ - .name = "manufacturer", - .type = QEMU_OPT_STRING, - .help = "manufacturer name", - },{ - .name = "product", - .type = QEMU_OPT_STRING, - .help = "product name", - },{ - .name = "version", - .type = QEMU_OPT_STRING, - .help = "version number", - },{ - .name = "serial", - .type = QEMU_OPT_STRING, - .help = "serial number", - },{ - .name = "uuid", - .type = QEMU_OPT_STRING, - .help = "UUID", - },{ - .name = "sku", - .type = QEMU_OPT_STRING, - .help = "SKU number", - },{ - .name = "family", - .type = QEMU_OPT_STRING, - .help = "family name", - }, - { /* end of list */ } -}; - -static const QemuOptDesc qemu_smbios_type2_opts[] = { - { - .name = "type", - .type = QEMU_OPT_NUMBER, - .help = "SMBIOS element type", - },{ - .name = "manufacturer", - .type = QEMU_OPT_STRING, - .help = "manufacturer name", - },{ - .name = "product", - .type = QEMU_OPT_STRING, - .help = "product name", - },{ - .name = "version", - .type = QEMU_OPT_STRING, - .help = "version number", - },{ - .name = "serial", - .type = QEMU_OPT_STRING, - .help = "serial number", - },{ - .name = "asset", - .type = QEMU_OPT_STRING, - .help = "asset tag number", - },{ - .name = "location", - .type = QEMU_OPT_STRING, - .help = "location in chassis", - }, - { /* end of list */ } -}; - -static const QemuOptDesc qemu_smbios_type3_opts[] = { - { - .name = "type", - .type = QEMU_OPT_NUMBER, - .help = "SMBIOS element type", - },{ - .name = "manufacturer", - .type = QEMU_OPT_STRING, - .help = "manufacturer name", - },{ - .name = "version", - .type = QEMU_OPT_STRING, - .help = "version number", - },{ - .name = "serial", - .type = QEMU_OPT_STRING, - .help = "serial number", - },{ - .name = "asset", - .type = QEMU_OPT_STRING, - .help = "asset tag number", - },{ - .name = "sku", - .type = QEMU_OPT_STRING, - .help = "SKU number", - }, - { /* end of list */ } -}; - -static const QemuOptDesc qemu_smbios_type4_opts[] = { - { - .name = "type", - .type = QEMU_OPT_NUMBER, - .help = "SMBIOS element type", - },{ - .name = "sock_pfx", - .type = QEMU_OPT_STRING, - .help = "socket designation string prefix", - },{ - .name = "manufacturer", - .type = QEMU_OPT_STRING, - .help = "manufacturer name", - },{ - .name = "version", - .type = QEMU_OPT_STRING, - .help = "version number", - },{ - .name = "serial", - .type = QEMU_OPT_STRING, - .help = "serial number", - },{ - .name = "asset", - .type = QEMU_OPT_STRING, - .help = "asset tag number", - },{ - .name = "part", - .type = QEMU_OPT_STRING, - .help = "part number", - }, - { /* end of list */ } -}; - -static const QemuOptDesc qemu_smbios_type17_opts[] = { - { - .name = "type", - .type = QEMU_OPT_NUMBER, - .help = "SMBIOS element type", - },{ - .name = "loc_pfx", - .type = QEMU_OPT_STRING, - .help = "device locator string prefix", - },{ - .name = "bank", - .type = QEMU_OPT_STRING, - .help = "bank locator string", - },{ - .name = "manufacturer", - .type = QEMU_OPT_STRING, - .help = "manufacturer name", - },{ - .name = "serial", - .type = QEMU_OPT_STRING, - .help = "serial number", - },{ - .name = "asset", - .type = QEMU_OPT_STRING, - .help = "asset tag number", - },{ - .name = "part", - .type = QEMU_OPT_STRING, - .help = "part number", - },{ - .name = "speed", - .type = QEMU_OPT_NUMBER, - .help = "maximum capable speed", - }, - { /* end of list */ } -}; - -static void smbios_register_config(void) -{ - qemu_add_opts(&qemu_smbios_opts); -} - -machine_init(smbios_register_config); - -static void smbios_validate_table(void) -{ - uint32_t expect_t4_count = smbios_legacy ? smp_cpus : smbios_smp_sockets; - - if (smbios_type4_count && smbios_type4_count != expect_t4_count) { - error_report("Expected %d SMBIOS Type 4 tables, got %d instead", - expect_t4_count, smbios_type4_count); - exit(1); - } -} - - -/* legacy setup functions for <= 2.0 machines */ -static void smbios_add_field(int type, int offset, const void *data, size_t len) -{ - struct smbios_field *field; - - if (!smbios_entries) { - smbios_entries_len = sizeof(uint16_t); - smbios_entries = g_malloc0(smbios_entries_len); - } - smbios_entries = g_realloc(smbios_entries, smbios_entries_len + - sizeof(*field) + len); - field = (struct smbios_field *)(smbios_entries + smbios_entries_len); - field->header.type = SMBIOS_FIELD_ENTRY; - field->header.length = cpu_to_le16(sizeof(*field) + len); - - field->type = type; - field->offset = cpu_to_le16(offset); - memcpy(field->data, data, len); - - smbios_entries_len += sizeof(*field) + len; - (*(uint16_t *)smbios_entries) = - cpu_to_le16(le16_to_cpu(*(uint16_t *)smbios_entries) + 1); -} - -static void smbios_maybe_add_str(int type, int offset, const char *data) -{ - if (data) { - smbios_add_field(type, offset, data, strlen(data) + 1); - } -} - -static void smbios_build_type_0_fields(void) -{ - smbios_maybe_add_str(0, offsetof(struct smbios_type_0, vendor_str), - type0.vendor); - smbios_maybe_add_str(0, offsetof(struct smbios_type_0, bios_version_str), - type0.version); - smbios_maybe_add_str(0, offsetof(struct smbios_type_0, - bios_release_date_str), - type0.date); - if (type0.have_major_minor) { - smbios_add_field(0, offsetof(struct smbios_type_0, - system_bios_major_release), - &type0.major, 1); - smbios_add_field(0, offsetof(struct smbios_type_0, - system_bios_minor_release), - &type0.minor, 1); - } -} - -static void smbios_build_type_1_fields(void) -{ - smbios_maybe_add_str(1, offsetof(struct smbios_type_1, manufacturer_str), - type1.manufacturer); - smbios_maybe_add_str(1, offsetof(struct smbios_type_1, product_name_str), - type1.product); - smbios_maybe_add_str(1, offsetof(struct smbios_type_1, version_str), - type1.version); - smbios_maybe_add_str(1, offsetof(struct smbios_type_1, serial_number_str), - type1.serial); - smbios_maybe_add_str(1, offsetof(struct smbios_type_1, sku_number_str), - type1.sku); - smbios_maybe_add_str(1, offsetof(struct smbios_type_1, family_str), - type1.family); - if (qemu_uuid_set) { - /* We don't encode the UUID in the "wire format" here because this - * function is for legacy mode and needs to keep the guest ABI, and - * because we don't know what's the SMBIOS version advertised by the - * BIOS. - */ - smbios_add_field(1, offsetof(struct smbios_type_1, uuid), - qemu_uuid, 16); - } -} - -uint8_t *smbios_get_table_legacy(size_t *length) -{ - if (!smbios_legacy) { - *length = 0; - return NULL; - } - - if (!smbios_immutable) { - smbios_build_type_0_fields(); - smbios_build_type_1_fields(); - smbios_validate_table(); - smbios_immutable = true; - } - *length = smbios_entries_len; - return smbios_entries; -} -/* end: legacy setup functions for <= 2.0 machines */ - - -static bool smbios_skip_table(uint8_t type, bool required_table) -{ - if (test_bit(type, have_binfile_bitmap)) { - return true; /* user provided their own binary blob(s) */ - } - if (test_bit(type, have_fields_bitmap)) { - return false; /* user provided fields via command line */ - } - if (smbios_have_defaults && required_table) { - return false; /* we're building tables, and this one's required */ - } - return true; -} - -#define SMBIOS_BUILD_TABLE_PRE(tbl_type, tbl_handle, tbl_required) \ - struct smbios_type_##tbl_type *t; \ - size_t t_off; /* table offset into smbios_tables */ \ - int str_index = 0; \ - do { \ - /* should we skip building this table ? */ \ - if (smbios_skip_table(tbl_type, tbl_required)) { \ - return; \ - } \ - \ - /* use offset of table t within smbios_tables */ \ - /* (pointer must be updated after each realloc) */ \ - t_off = smbios_tables_len; \ - smbios_tables_len += sizeof(*t); \ - smbios_tables = g_realloc(smbios_tables, smbios_tables_len); \ - t = (struct smbios_type_##tbl_type *)(smbios_tables + t_off); \ - \ - t->header.type = tbl_type; \ - t->header.length = sizeof(*t); \ - t->header.handle = cpu_to_le16(tbl_handle); \ - } while (0) - -#define SMBIOS_TABLE_SET_STR(tbl_type, field, value) \ - do { \ - int len = (value != NULL) ? strlen(value) + 1 : 0; \ - if (len > 1) { \ - smbios_tables = g_realloc(smbios_tables, \ - smbios_tables_len + len); \ - memcpy(smbios_tables + smbios_tables_len, value, len); \ - smbios_tables_len += len; \ - /* update pointer post-realloc */ \ - t = (struct smbios_type_##tbl_type *)(smbios_tables + t_off); \ - t->field = ++str_index; \ - } else { \ - t->field = 0; \ - } \ - } while (0) - -#define SMBIOS_BUILD_TABLE_POST \ - do { \ - size_t term_cnt, t_size; \ - \ - /* add '\0' terminator (add two if no strings defined) */ \ - term_cnt = (str_index == 0) ? 2 : 1; \ - smbios_tables = g_realloc(smbios_tables, \ - smbios_tables_len + term_cnt); \ - memset(smbios_tables + smbios_tables_len, 0, term_cnt); \ - smbios_tables_len += term_cnt; \ - \ - /* update smbios max. element size */ \ - t_size = smbios_tables_len - t_off; \ - if (t_size > smbios_table_max) { \ - smbios_table_max = t_size; \ - } \ - \ - /* update smbios element count */ \ - smbios_table_cnt++; \ - } while (0) - -static void smbios_build_type_0_table(void) -{ - SMBIOS_BUILD_TABLE_PRE(0, 0x000, false); /* optional, leave up to BIOS */ - - SMBIOS_TABLE_SET_STR(0, vendor_str, type0.vendor); - SMBIOS_TABLE_SET_STR(0, bios_version_str, type0.version); - - t->bios_starting_address_segment = cpu_to_le16(0xE800); /* from SeaBIOS */ - - SMBIOS_TABLE_SET_STR(0, bios_release_date_str, type0.date); - - t->bios_rom_size = 0; /* hardcoded in SeaBIOS with FIXME comment */ - - t->bios_characteristics = cpu_to_le64(0x08); /* Not supported */ - t->bios_characteristics_extension_bytes[0] = 0; - t->bios_characteristics_extension_bytes[1] = 0x14; /* TCD/SVVP | VM */ - if (type0.uefi) { - t->bios_characteristics_extension_bytes[1] |= 0x08; /* |= UEFI */ - } - - if (type0.have_major_minor) { - t->system_bios_major_release = type0.major; - t->system_bios_minor_release = type0.minor; - } else { - t->system_bios_major_release = 0; - t->system_bios_minor_release = 0; - } - - /* hardcoded in SeaBIOS */ - t->embedded_controller_major_release = 0xFF; - t->embedded_controller_minor_release = 0xFF; - - SMBIOS_BUILD_TABLE_POST; -} - -/* Encode UUID from the big endian encoding described on RFC4122 to the wire - * format specified by SMBIOS version 2.6. - */ -static void smbios_encode_uuid(struct smbios_uuid *uuid, const uint8_t *buf) -{ - memcpy(uuid, buf, 16); - if (smbios_uuid_encoded) { - uuid->time_low = bswap32(uuid->time_low); - uuid->time_mid = bswap16(uuid->time_mid); - uuid->time_hi_and_version = bswap16(uuid->time_hi_and_version); - } -} - -static void smbios_build_type_1_table(void) -{ - SMBIOS_BUILD_TABLE_PRE(1, 0x100, true); /* required */ - - SMBIOS_TABLE_SET_STR(1, manufacturer_str, type1.manufacturer); - SMBIOS_TABLE_SET_STR(1, product_name_str, type1.product); - SMBIOS_TABLE_SET_STR(1, version_str, type1.version); - SMBIOS_TABLE_SET_STR(1, serial_number_str, type1.serial); - if (qemu_uuid_set) { - smbios_encode_uuid(&t->uuid, qemu_uuid); - } else { - memset(&t->uuid, 0, 16); - } - t->wake_up_type = 0x06; /* power switch */ - SMBIOS_TABLE_SET_STR(1, sku_number_str, type1.sku); - SMBIOS_TABLE_SET_STR(1, family_str, type1.family); - - SMBIOS_BUILD_TABLE_POST; -} - -static void smbios_build_type_2_table(void) -{ - SMBIOS_BUILD_TABLE_PRE(2, 0x200, false); /* optional */ - - SMBIOS_TABLE_SET_STR(2, manufacturer_str, type2.manufacturer); - SMBIOS_TABLE_SET_STR(2, product_str, type2.product); - SMBIOS_TABLE_SET_STR(2, version_str, type2.version); - SMBIOS_TABLE_SET_STR(2, serial_number_str, type2.serial); - SMBIOS_TABLE_SET_STR(2, asset_tag_number_str, type2.asset); - t->feature_flags = 0x01; /* Motherboard */ - SMBIOS_TABLE_SET_STR(2, location_str, type2.location); - t->chassis_handle = cpu_to_le16(0x300); /* Type 3 (System enclosure) */ - t->board_type = 0x0A; /* Motherboard */ - t->contained_element_count = 0; - - SMBIOS_BUILD_TABLE_POST; -} - -static void smbios_build_type_3_table(void) -{ - SMBIOS_BUILD_TABLE_PRE(3, 0x300, true); /* required */ - - SMBIOS_TABLE_SET_STR(3, manufacturer_str, type3.manufacturer); - t->type = 0x01; /* Other */ - SMBIOS_TABLE_SET_STR(3, version_str, type3.version); - SMBIOS_TABLE_SET_STR(3, serial_number_str, type3.serial); - SMBIOS_TABLE_SET_STR(3, asset_tag_number_str, type3.asset); - t->boot_up_state = 0x03; /* Safe */ - t->power_supply_state = 0x03; /* Safe */ - t->thermal_state = 0x03; /* Safe */ - t->security_status = 0x02; /* Unknown */ - t->oem_defined = cpu_to_le32(0); - t->height = 0; - t->number_of_power_cords = 0; - t->contained_element_count = 0; - SMBIOS_TABLE_SET_STR(3, sku_number_str, type3.sku); - - SMBIOS_BUILD_TABLE_POST; -} - -static void smbios_build_type_4_table(unsigned instance) -{ - char sock_str[128]; - - SMBIOS_BUILD_TABLE_PRE(4, 0x400 + instance, true); /* required */ - - snprintf(sock_str, sizeof(sock_str), "%s%2x", type4.sock_pfx, instance); - SMBIOS_TABLE_SET_STR(4, socket_designation_str, sock_str); - t->processor_type = 0x03; /* CPU */ - t->processor_family = 0x01; /* Other */ - SMBIOS_TABLE_SET_STR(4, processor_manufacturer_str, type4.manufacturer); - t->processor_id[0] = cpu_to_le32(smbios_cpuid_version); - t->processor_id[1] = cpu_to_le32(smbios_cpuid_features); - SMBIOS_TABLE_SET_STR(4, processor_version_str, type4.version); - t->voltage = 0; - t->external_clock = cpu_to_le16(0); /* Unknown */ - /* SVVP requires max_speed and current_speed to not be unknown. */ - t->max_speed = cpu_to_le16(2000); /* 2000 MHz */ - t->current_speed = cpu_to_le16(2000); /* 2000 MHz */ - t->status = 0x41; /* Socket populated, CPU enabled */ - t->processor_upgrade = 0x01; /* Other */ - t->l1_cache_handle = cpu_to_le16(0xFFFF); /* N/A */ - t->l2_cache_handle = cpu_to_le16(0xFFFF); /* N/A */ - t->l3_cache_handle = cpu_to_le16(0xFFFF); /* N/A */ - SMBIOS_TABLE_SET_STR(4, serial_number_str, type4.serial); - SMBIOS_TABLE_SET_STR(4, asset_tag_number_str, type4.asset); - SMBIOS_TABLE_SET_STR(4, part_number_str, type4.part); - t->core_count = t->core_enabled = smp_cores; - t->thread_count = smp_threads; - t->processor_characteristics = cpu_to_le16(0x02); /* Unknown */ - t->processor_family2 = cpu_to_le16(0x01); /* Other */ - - SMBIOS_BUILD_TABLE_POST; - smbios_type4_count++; -} - -#define ONE_KB ((ram_addr_t)1 << 10) -#define ONE_MB ((ram_addr_t)1 << 20) -#define ONE_GB ((ram_addr_t)1 << 30) - -#define MAX_T16_STD_SZ 0x80000000 /* 2T in Kilobytes */ - -static void smbios_build_type_16_table(unsigned dimm_cnt) -{ - uint64_t size_kb; - - SMBIOS_BUILD_TABLE_PRE(16, 0x1000, true); /* required */ - - t->location = 0x01; /* Other */ - t->use = 0x03; /* System memory */ - t->error_correction = 0x06; /* Multi-bit ECC (for Microsoft, per SeaBIOS) */ - size_kb = QEMU_ALIGN_UP(ram_size, ONE_KB) / ONE_KB; - if (size_kb < MAX_T16_STD_SZ) { - t->maximum_capacity = cpu_to_le32(size_kb); - t->extended_maximum_capacity = cpu_to_le64(0); - } else { - t->maximum_capacity = cpu_to_le32(MAX_T16_STD_SZ); - t->extended_maximum_capacity = cpu_to_le64(ram_size); - } - t->memory_error_information_handle = cpu_to_le16(0xFFFE); /* Not provided */ - t->number_of_memory_devices = cpu_to_le16(dimm_cnt); - - SMBIOS_BUILD_TABLE_POST; -} - -#define MAX_T17_STD_SZ 0x7FFF /* (32G - 1M), in Megabytes */ -#define MAX_T17_EXT_SZ 0x80000000 /* 2P, in Megabytes */ - -static void smbios_build_type_17_table(unsigned instance, uint64_t size) -{ - char loc_str[128]; - uint64_t size_mb; - - SMBIOS_BUILD_TABLE_PRE(17, 0x1100 + instance, true); /* required */ - - t->physical_memory_array_handle = cpu_to_le16(0x1000); /* Type 16 above */ - t->memory_error_information_handle = cpu_to_le16(0xFFFE); /* Not provided */ - t->total_width = cpu_to_le16(0xFFFF); /* Unknown */ - t->data_width = cpu_to_le16(0xFFFF); /* Unknown */ - size_mb = QEMU_ALIGN_UP(size, ONE_MB) / ONE_MB; - if (size_mb < MAX_T17_STD_SZ) { - t->size = cpu_to_le16(size_mb); - t->extended_size = cpu_to_le32(0); - } else { - assert(size_mb < MAX_T17_EXT_SZ); - t->size = cpu_to_le16(MAX_T17_STD_SZ); - t->extended_size = cpu_to_le32(size_mb); - } - t->form_factor = 0x09; /* DIMM */ - t->device_set = 0; /* Not in a set */ - snprintf(loc_str, sizeof(loc_str), "%s %d", type17.loc_pfx, instance); - SMBIOS_TABLE_SET_STR(17, device_locator_str, loc_str); - SMBIOS_TABLE_SET_STR(17, bank_locator_str, type17.bank); - t->memory_type = 0x07; /* RAM */ - t->type_detail = cpu_to_le16(0x02); /* Other */ - t->speed = cpu_to_le16(type17.speed); - SMBIOS_TABLE_SET_STR(17, manufacturer_str, type17.manufacturer); - SMBIOS_TABLE_SET_STR(17, serial_number_str, type17.serial); - SMBIOS_TABLE_SET_STR(17, asset_tag_number_str, type17.asset); - SMBIOS_TABLE_SET_STR(17, part_number_str, type17.part); - t->attributes = 0; /* Unknown */ - t->configured_clock_speed = t->speed; /* reuse value for max speed */ - t->minimum_voltage = cpu_to_le16(0); /* Unknown */ - t->maximum_voltage = cpu_to_le16(0); /* Unknown */ - t->configured_voltage = cpu_to_le16(0); /* Unknown */ - - SMBIOS_BUILD_TABLE_POST; -} - -static void smbios_build_type_19_table(unsigned instance, - uint64_t start, uint64_t size) -{ - uint64_t end, start_kb, end_kb; - - SMBIOS_BUILD_TABLE_PRE(19, 0x1300 + instance, true); /* required */ - - end = start + size - 1; - assert(end > start); - start_kb = start / ONE_KB; - end_kb = end / ONE_KB; - if (start_kb < UINT32_MAX && end_kb < UINT32_MAX) { - t->starting_address = cpu_to_le32(start_kb); - t->ending_address = cpu_to_le32(end_kb); - t->extended_starting_address = - t->extended_ending_address = cpu_to_le64(0); - } else { - t->starting_address = t->ending_address = cpu_to_le32(UINT32_MAX); - t->extended_starting_address = cpu_to_le64(start); - t->extended_ending_address = cpu_to_le64(end); - } - t->memory_array_handle = cpu_to_le16(0x1000); /* Type 16 above */ - t->partition_width = 1; /* One device per row */ - - SMBIOS_BUILD_TABLE_POST; -} - -static void smbios_build_type_32_table(void) -{ - SMBIOS_BUILD_TABLE_PRE(32, 0x2000, true); /* required */ - - memset(t->reserved, 0, 6); - t->boot_status = 0; /* No errors detected */ - - SMBIOS_BUILD_TABLE_POST; -} - -static void smbios_build_type_127_table(void) -{ - SMBIOS_BUILD_TABLE_PRE(127, 0x7F00, true); /* required */ - SMBIOS_BUILD_TABLE_POST; -} - -void smbios_set_cpuid(uint32_t version, uint32_t features) -{ - smbios_cpuid_version = version; - smbios_cpuid_features = features; -} - -#define SMBIOS_SET_DEFAULT(field, value) \ - if (!field) { \ - field = value; \ - } - -void smbios_set_defaults(const char *manufacturer, const char *product, - const char *version, bool legacy_mode, - bool uuid_encoded) -{ - smbios_have_defaults = true; - smbios_legacy = legacy_mode; - smbios_uuid_encoded = uuid_encoded; - - /* drop unwanted version of command-line file blob(s) */ - if (smbios_legacy) { - g_free(smbios_tables); - /* in legacy mode, also complain if fields were given for types > 1 */ - if (find_next_bit(have_fields_bitmap, - SMBIOS_MAX_TYPE+1, 2) < SMBIOS_MAX_TYPE+1) { - error_report("can't process fields for smbios " - "types > 1 on machine versions < 2.1!"); - exit(1); - } - } else { - g_free(smbios_entries); - } - - SMBIOS_SET_DEFAULT(type1.manufacturer, manufacturer); - SMBIOS_SET_DEFAULT(type1.product, product); - SMBIOS_SET_DEFAULT(type1.version, version); - SMBIOS_SET_DEFAULT(type2.manufacturer, manufacturer); - SMBIOS_SET_DEFAULT(type2.product, product); - SMBIOS_SET_DEFAULT(type2.version, version); - SMBIOS_SET_DEFAULT(type3.manufacturer, manufacturer); - SMBIOS_SET_DEFAULT(type3.version, version); - SMBIOS_SET_DEFAULT(type4.sock_pfx, "CPU"); - SMBIOS_SET_DEFAULT(type4.manufacturer, manufacturer); - SMBIOS_SET_DEFAULT(type4.version, version); - SMBIOS_SET_DEFAULT(type17.loc_pfx, "DIMM"); - SMBIOS_SET_DEFAULT(type17.manufacturer, manufacturer); -} - -static void smbios_entry_point_setup(void) -{ - memcpy(ep.anchor_string, "_SM_", 4); - memcpy(ep.intermediate_anchor_string, "_DMI_", 5); - ep.length = sizeof(struct smbios_entry_point); - ep.entry_point_revision = 0; /* formatted_area reserved, per spec v2.1+ */ - memset(ep.formatted_area, 0, 5); - - /* compliant with smbios spec v2.8 */ - ep.smbios_major_version = 2; - ep.smbios_minor_version = 8; - ep.smbios_bcd_revision = 0x28; - - /* set during table construction, but BIOS may override: */ - ep.structure_table_length = cpu_to_le16(smbios_tables_len); - ep.max_structure_size = cpu_to_le16(smbios_table_max); - ep.number_of_structures = cpu_to_le16(smbios_table_cnt); - - /* BIOS must recalculate: */ - ep.checksum = 0; - ep.intermediate_checksum = 0; - ep.structure_table_address = cpu_to_le32(0); -} - -void smbios_get_tables(uint8_t **tables, size_t *tables_len, - uint8_t **anchor, size_t *anchor_len) -{ - unsigned i, dimm_cnt, instance; - - if (smbios_legacy) { - *tables = *anchor = NULL; - *tables_len = *anchor_len = 0; - return; - } - - if (!smbios_immutable) { - smbios_build_type_0_table(); - smbios_build_type_1_table(); - smbios_build_type_2_table(); - smbios_build_type_3_table(); - - smbios_smp_sockets = DIV_ROUND_UP(smp_cpus, smp_cores * smp_threads); - assert(smbios_smp_sockets >= 1); - - for (i = 0; i < smbios_smp_sockets; i++) { - smbios_build_type_4_table(i); - } - -#define MAX_DIMM_SZ (16ll * ONE_GB) -#define GET_DIMM_SZ ((i < dimm_cnt - 1) ? MAX_DIMM_SZ \ - : ((ram_size - 1) % MAX_DIMM_SZ) + 1) - - dimm_cnt = QEMU_ALIGN_UP(ram_size, MAX_DIMM_SZ) / MAX_DIMM_SZ; - - smbios_build_type_16_table(dimm_cnt); - - for (i = 0; i < dimm_cnt; i++) { - smbios_build_type_17_table(i, GET_DIMM_SZ); - } - - for (i = 0, instance = 0; i < e820_get_num_entries(); i++) { - uint64_t address, length; - if (e820_get_entry(i, E820_RAM, &address, &length)) { - smbios_build_type_19_table(instance++, address, length); - } - } - - smbios_build_type_32_table(); - smbios_build_type_127_table(); - - smbios_validate_table(); - smbios_entry_point_setup(); - smbios_immutable = true; - } - - /* return tables blob and entry point (anchor), and their sizes */ - *tables = smbios_tables; - *tables_len = smbios_tables_len; - *anchor = (uint8_t *)&ep; - *anchor_len = sizeof(struct smbios_entry_point); -} - -static void save_opt(const char **dest, QemuOpts *opts, const char *name) -{ - const char *val = qemu_opt_get(opts, name); - - if (val) { - *dest = val; - } -} - -void smbios_entry_add(QemuOpts *opts) -{ - Error *local_err = NULL; - const char *val; - - assert(!smbios_immutable); - - val = qemu_opt_get(opts, "file"); - if (val) { - struct smbios_structure_header *header; - int size; - struct smbios_table *table; /* legacy mode only */ - - qemu_opts_validate(opts, qemu_smbios_file_opts, &local_err); - if (local_err) { - error_report_err(local_err); - exit(1); - } - - size = get_image_size(val); - if (size == -1 || size < sizeof(struct smbios_structure_header)) { - error_report("Cannot read SMBIOS file %s", val); - exit(1); - } - - /* - * NOTE: standard double '\0' terminator expected, per smbios spec. - * (except in legacy mode, where the second '\0' is implicit and - * will be inserted by the BIOS). - */ - smbios_tables = g_realloc(smbios_tables, smbios_tables_len + size); - header = (struct smbios_structure_header *)(smbios_tables + - smbios_tables_len); - - if (load_image(val, (uint8_t *)header) != size) { - error_report("Failed to load SMBIOS file %s", val); - exit(1); - } - - if (test_bit(header->type, have_fields_bitmap)) { - error_report("can't load type %d struct, fields already specified!", - header->type); - exit(1); - } - set_bit(header->type, have_binfile_bitmap); - - if (header->type == 4) { - smbios_type4_count++; - } - - smbios_tables_len += size; - if (size > smbios_table_max) { - smbios_table_max = size; - } - smbios_table_cnt++; - - /* add a copy of the newly loaded blob to legacy smbios_entries */ - /* NOTE: This code runs before smbios_set_defaults(), so we don't - * yet know which mode (legacy vs. aggregate-table) will be - * required. We therefore add the binary blob to both legacy - * (smbios_entries) and aggregate (smbios_tables) tables, and - * delete the one we don't need from smbios_set_defaults(), - * once we know which machine version has been requested. - */ - if (!smbios_entries) { - smbios_entries_len = sizeof(uint16_t); - smbios_entries = g_malloc0(smbios_entries_len); - } - smbios_entries = g_realloc(smbios_entries, smbios_entries_len + - size + sizeof(*table)); - table = (struct smbios_table *)(smbios_entries + smbios_entries_len); - table->header.type = SMBIOS_TABLE_ENTRY; - table->header.length = cpu_to_le16(sizeof(*table) + size); - memcpy(table->data, header, size); - smbios_entries_len += sizeof(*table) + size; - (*(uint16_t *)smbios_entries) = - cpu_to_le16(le16_to_cpu(*(uint16_t *)smbios_entries) + 1); - /* end: add a copy of the newly loaded blob to legacy smbios_entries */ - - return; - } - - val = qemu_opt_get(opts, "type"); - if (val) { - unsigned long type = strtoul(val, NULL, 0); - - if (type > SMBIOS_MAX_TYPE) { - error_report("out of range!"); - exit(1); - } - - if (test_bit(type, have_binfile_bitmap)) { - error_report("can't add fields, binary file already loaded!"); - exit(1); - } - set_bit(type, have_fields_bitmap); - - switch (type) { - case 0: - qemu_opts_validate(opts, qemu_smbios_type0_opts, &local_err); - if (local_err) { - error_report_err(local_err); - exit(1); - } - save_opt(&type0.vendor, opts, "vendor"); - save_opt(&type0.version, opts, "version"); - save_opt(&type0.date, opts, "date"); - type0.uefi = qemu_opt_get_bool(opts, "uefi", false); - - val = qemu_opt_get(opts, "release"); - if (val) { - if (sscanf(val, "%hhu.%hhu", &type0.major, &type0.minor) != 2) { - error_report("Invalid release"); - exit(1); - } - type0.have_major_minor = true; - } - return; - case 1: - qemu_opts_validate(opts, qemu_smbios_type1_opts, &local_err); - if (local_err) { - error_report_err(local_err); - exit(1); - } - save_opt(&type1.manufacturer, opts, "manufacturer"); - save_opt(&type1.product, opts, "product"); - save_opt(&type1.version, opts, "version"); - save_opt(&type1.serial, opts, "serial"); - save_opt(&type1.sku, opts, "sku"); - save_opt(&type1.family, opts, "family"); - - val = qemu_opt_get(opts, "uuid"); - if (val) { - if (qemu_uuid_parse(val, qemu_uuid) != 0) { - error_report("Invalid UUID"); - exit(1); - } - qemu_uuid_set = true; - } - return; - case 2: - qemu_opts_validate(opts, qemu_smbios_type2_opts, &local_err); - if (local_err) { - error_report_err(local_err); - exit(1); - } - save_opt(&type2.manufacturer, opts, "manufacturer"); - save_opt(&type2.product, opts, "product"); - save_opt(&type2.version, opts, "version"); - save_opt(&type2.serial, opts, "serial"); - save_opt(&type2.asset, opts, "asset"); - save_opt(&type2.location, opts, "location"); - return; - case 3: - qemu_opts_validate(opts, qemu_smbios_type3_opts, &local_err); - if (local_err) { - error_report_err(local_err); - exit(1); - } - save_opt(&type3.manufacturer, opts, "manufacturer"); - save_opt(&type3.version, opts, "version"); - save_opt(&type3.serial, opts, "serial"); - save_opt(&type3.asset, opts, "asset"); - save_opt(&type3.sku, opts, "sku"); - return; - case 4: - qemu_opts_validate(opts, qemu_smbios_type4_opts, &local_err); - if (local_err) { - error_report_err(local_err); - exit(1); - } - save_opt(&type4.sock_pfx, opts, "sock_pfx"); - save_opt(&type4.manufacturer, opts, "manufacturer"); - save_opt(&type4.version, opts, "version"); - save_opt(&type4.serial, opts, "serial"); - save_opt(&type4.asset, opts, "asset"); - save_opt(&type4.part, opts, "part"); - return; - case 17: - qemu_opts_validate(opts, qemu_smbios_type17_opts, &local_err); - if (local_err) { - error_report_err(local_err); - exit(1); - } - save_opt(&type17.loc_pfx, opts, "loc_pfx"); - save_opt(&type17.bank, opts, "bank"); - save_opt(&type17.manufacturer, opts, "manufacturer"); - save_opt(&type17.serial, opts, "serial"); - save_opt(&type17.asset, opts, "asset"); - save_opt(&type17.part, opts, "part"); - type17.speed = qemu_opt_get_number(opts, "speed", 0); - return; - default: - error_report("Don't know how to build fields for SMBIOS type %ld", - type); - exit(1); - } - } - - error_report("Must specify type= or file="); - exit(1); -} |