From 9d3ce7cd74d1746dce058e680a8993184cfd23de Mon Sep 17 00:00:00 2001 From: Miroslav Rezanina Date: Mon, 18 Mar 2024 05:10:41 -0400 Subject: [PATCH] * Mon Mar 18 2024 Miroslav Rezanina - 8.2.0-8 - kvm-ui-clipboard-mark-type-as-not-available-when-there-i.patch [RHEL-19629] - kvm-ui-clipboard-add-asserts-for-update-and-request.patch [RHEL-19629] - kvm-hw-i386-pc-Defer-smbios_set_defaults-to-machine_done.patch [RHEL-21705] - kvm-Implement-base-of-SMBIOS-type-9-descriptor.patch [RHEL-21705] - kvm-Implement-SMBIOS-type-9-v2.6.patch [RHEL-21705] - kvm-smbios-cleanup-smbios_get_tables-from-legacy-handlin.patch [RHEL-21705] - kvm-smbios-get-rid-of-smbios_smp_sockets-global.patch [RHEL-21705] - kvm-smbios-get-rid-of-smbios_legacy-global.patch [RHEL-21705] - kvm-smbios-avoid-mangling-user-provided-tables.patch [RHEL-21705] - kvm-smbios-don-t-check-type4-structures-in-legacy-mode.patch [RHEL-21705] - kvm-smbios-add-smbios_add_usr_blob_size-helper.patch [RHEL-21705] - kvm-smbios-rename-expose-structures-bitmaps-used-by-both.patch [RHEL-21705] - kvm-smbios-build-legacy-mode-code-only-for-pc-machine.patch [RHEL-21705] - kvm-smbios-handle-errors-consistently.patch [RHEL-21705] - kvm-smbios-get-rid-of-global-smbios_ep_type.patch [RHEL-21705] - kvm-smbios-clear-smbios_type4_count-before-building-tabl.patch [RHEL-21705] - kvm-smbios-extend-smbios-entry-point-type-with-auto-valu.patch [RHEL-21705] - kvm-smbios-in-case-of-entry-point-is-auto-try-to-build-v.patch [RHEL-21705] - kvm-smbios-error-out-when-building-type-4-table-is-not-p.patch [RHEL-21705] - kvm-pc-q35-set-SMBIOS-entry-point-type-to-auto-by-defaul.patch [RHEL-21705] - Resolves: RHEL-19629 (CVE-2023-6683 qemu-kvm: QEMU: VNC: NULL pointer dereference in qemu_clipboard_request() [rhel-9]) - Resolves: RHEL-21705 (pc-q35-rhel9.4.0 does not provide proper computer information) --- kvm-Implement-SMBIOS-type-9-v2.6.patch | 155 ++++++ ...ent-base-of-SMBIOS-type-9-descriptor.patch | 218 ++++++++ ...-smbios_set_defaults-to-machine_done.patch | 186 +++++++ ...S-entry-point-type-to-auto-by-defaul.patch | 115 ++++ ...-add-smbios_add_usr_blob_size-helper.patch | 62 +++ ...-avoid-mangling-user-provided-tables.patch | 309 +++++++++++ ...legacy-mode-code-only-for-pc-machine.patch | 517 ++++++++++++++++++ ...mbios_get_tables-from-legacy-handlin.patch | 65 +++ ...ios_type4_count-before-building-tabl.patch | 38 ++ ...heck-type4-structures-in-legacy-mode.patch | 133 +++++ ...-when-building-type-4-table-is-not-p.patch | 72 +++ ...bios-entry-point-type-with-auto-valu.patch | 48 ++ ...ios-get-rid-of-global-smbios_ep_type.patch | 281 ++++++++++ ...bios-get-rid-of-smbios_legacy-global.patch | 198 +++++++ ...get-rid-of-smbios_smp_sockets-global.patch | 134 +++++ kvm-smbios-handle-errors-consistently.patch | 217 ++++++++ ...f-entry-point-is-auto-try-to-build-v.patch | 131 +++++ ...pose-structures-bitmaps-used-by-both.patch | 330 +++++++++++ ...d-add-asserts-for-update-and-request.patch | 81 +++ ...k-type-as-not-available-when-there-i.patch | 107 ++++ qemu-kvm.spec | 68 ++- 21 files changed, 3464 insertions(+), 1 deletion(-) create mode 100644 kvm-Implement-SMBIOS-type-9-v2.6.patch create mode 100644 kvm-Implement-base-of-SMBIOS-type-9-descriptor.patch create mode 100644 kvm-hw-i386-pc-Defer-smbios_set_defaults-to-machine_done.patch create mode 100644 kvm-pc-q35-set-SMBIOS-entry-point-type-to-auto-by-defaul.patch create mode 100644 kvm-smbios-add-smbios_add_usr_blob_size-helper.patch create mode 100644 kvm-smbios-avoid-mangling-user-provided-tables.patch create mode 100644 kvm-smbios-build-legacy-mode-code-only-for-pc-machine.patch create mode 100644 kvm-smbios-cleanup-smbios_get_tables-from-legacy-handlin.patch create mode 100644 kvm-smbios-clear-smbios_type4_count-before-building-tabl.patch create mode 100644 kvm-smbios-don-t-check-type4-structures-in-legacy-mode.patch create mode 100644 kvm-smbios-error-out-when-building-type-4-table-is-not-p.patch create mode 100644 kvm-smbios-extend-smbios-entry-point-type-with-auto-valu.patch create mode 100644 kvm-smbios-get-rid-of-global-smbios_ep_type.patch create mode 100644 kvm-smbios-get-rid-of-smbios_legacy-global.patch create mode 100644 kvm-smbios-get-rid-of-smbios_smp_sockets-global.patch create mode 100644 kvm-smbios-handle-errors-consistently.patch create mode 100644 kvm-smbios-in-case-of-entry-point-is-auto-try-to-build-v.patch create mode 100644 kvm-smbios-rename-expose-structures-bitmaps-used-by-both.patch create mode 100644 kvm-ui-clipboard-add-asserts-for-update-and-request.patch create mode 100644 kvm-ui-clipboard-mark-type-as-not-available-when-there-i.patch diff --git a/kvm-Implement-SMBIOS-type-9-v2.6.patch b/kvm-Implement-SMBIOS-type-9-v2.6.patch new file mode 100644 index 0000000..31439d7 --- /dev/null +++ b/kvm-Implement-SMBIOS-type-9-v2.6.patch @@ -0,0 +1,155 @@ +From 5c639f8ce65183ce8e44ee8e0230e9d627a440d7 Mon Sep 17 00:00:00 2001 +From: Igor Mammedov +Date: Wed, 21 Feb 2024 17:00:27 +0000 +Subject: [PATCH 05/20] Implement SMBIOS type 9 v2.6 + +RH-Author: Igor Mammedov +RH-MergeRequest: 230: Workaround Windows failing to find 64bit SMBIOS entry point with SeaBIOS +RH-Jira: RHEL-21705 +RH-Acked-by: MST +RH-Acked-by: Ani Sinha +RH-Commit: [3/18] ead230527d93938907a561cf5b985ee4f54d82b1 + +JIRA: https://issues.redhat.com/browse/RHEL-21705 +Author: Felix Wu + + Signed-off-by: Felix Wu + Signed-off-by: Nabih Estefan + Message-Id: <20240221170027.1027325-3-nabihestefan@google.com> + Reviewed-by: Michael S. Tsirkin + Signed-off-by: Michael S. Tsirkin + +(cherry picked from commit 04f143d828845d0fd52dd4a52664d81a4f5431f7) +Signed-off-by: Igor Mammedov +--- + hw/smbios/smbios.c | 49 +++++++++++++++++++++++++++++++++--- + include/hw/firmware/smbios.h | 4 +++ + qemu-options.hx | 2 +- + 3 files changed, 51 insertions(+), 4 deletions(-) + +diff --git a/hw/smbios/smbios.c b/hw/smbios/smbios.c +index 4f5637d445..074705fa4c 100644 +--- a/hw/smbios/smbios.c ++++ b/hw/smbios/smbios.c +@@ -124,7 +124,7 @@ static QTAILQ_HEAD(, type8_instance) type8 = QTAILQ_HEAD_INITIALIZER(type8); + + /* type 9 instance for parsing */ + struct type9_instance { +- const char *slot_designation; ++ const char *slot_designation, *pcidev; + uint8_t slot_type, slot_data_bus_width, current_usage, slot_length, + slot_characteristics1, slot_characteristics2; + uint16_t slot_id; +@@ -427,6 +427,11 @@ static const QemuOptDesc qemu_smbios_type9_opts[] = { + .type = QEMU_OPT_NUMBER, + .help = "slot characteristics2, see the spec", + }, ++ { ++ .name = "pci_device", ++ .type = QEMU_OPT_STRING, ++ .help = "PCI device, if provided." ++ } + }; + + static const QemuOptDesc qemu_smbios_type11_opts[] = { +@@ -851,7 +856,7 @@ static void smbios_build_type_8_table(void) + } + } + +-static void smbios_build_type_9_table(void) ++static void smbios_build_type_9_table(Error **errp) + { + unsigned instance = 0; + struct type9_instance *t9; +@@ -868,6 +873,43 @@ static void smbios_build_type_9_table(void) + t->slot_characteristics1 = t9->slot_characteristics1; + t->slot_characteristics2 = t9->slot_characteristics2; + ++ if (t9->pcidev) { ++ PCIDevice *pdev = NULL; ++ int rc = pci_qdev_find_device(t9->pcidev, &pdev); ++ if (rc != 0) { ++ error_setg(errp, ++ "No PCI device %s for SMBIOS type 9 entry %s", ++ t9->pcidev, t9->slot_designation); ++ return; ++ } ++ /* ++ * We only handle the case were the device is attached to ++ * the PCI root bus. The general case is more complex as ++ * bridges are enumerated later and the table would need ++ * to be updated at this moment. ++ */ ++ if (!pci_bus_is_root(pci_get_bus(pdev))) { ++ error_setg(errp, ++ "Cannot create type 9 entry for PCI device %s: " ++ "not attached to the root bus", ++ t9->pcidev); ++ return; ++ } ++ t->segment_group_number = cpu_to_le16(0); ++ t->bus_number = pci_dev_bus_num(pdev); ++ t->device_number = pdev->devfn; ++ } else { ++ /* ++ * Per SMBIOS spec, For slots that are not of the PCI, AGP, PCI-X, ++ * or PCI-Express type that do not have bus/device/function ++ * information, 0FFh should be populated in the fields of Segment ++ * Group Number, Bus Number, Device/Function Number. ++ */ ++ t->segment_group_number = 0xff; ++ t->bus_number = 0xff; ++ t->device_number = 0xff; ++ } ++ + SMBIOS_BUILD_TABLE_POST; + instance++; + } +@@ -1222,7 +1264,7 @@ void smbios_get_tables(MachineState *ms, + } + + smbios_build_type_8_table(); +- smbios_build_type_9_table(); ++ smbios_build_type_9_table(errp); + smbios_build_type_11_table(); + + #define MAX_DIMM_SZ (16 * GiB) +@@ -1568,6 +1610,7 @@ void smbios_entry_add(QemuOpts *opts, Error **errp) + t->slot_id = qemu_opt_get_number(opts, "slot_id", 0); + t->slot_characteristics1 = qemu_opt_get_number(opts, "slot_characteristics1", 0); + t->slot_characteristics2 = qemu_opt_get_number(opts, "slot_characteristics2", 0); ++ save_opt(&t->pcidev, opts, "pcidev"); + QTAILQ_INSERT_TAIL(&type9, t, next); + return; + } +diff --git a/include/hw/firmware/smbios.h b/include/hw/firmware/smbios.h +index 6bbd5a4c20..f8dd07fe4c 100644 +--- a/include/hw/firmware/smbios.h ++++ b/include/hw/firmware/smbios.h +@@ -222,6 +222,10 @@ struct smbios_type_9 { + uint16_t slot_id; + uint8_t slot_characteristics1; + uint8_t slot_characteristics2; ++ /* SMBIOS spec v2.6+ */ ++ uint16_t segment_group_number; ++ uint8_t bus_number; ++ uint8_t device_number; + } QEMU_PACKED; + + /* SMBIOS type 11 - OEM strings */ +diff --git a/qemu-options.hx b/qemu-options.hx +index 94cacc2c63..93364e1765 100644 +--- a/qemu-options.hx ++++ b/qemu-options.hx +@@ -2710,7 +2710,7 @@ SRST + ``-smbios type=4[,sock_pfx=str][,manufacturer=str][,version=str][,serial=str][,asset=str][,part=str][,processor-id=%d]`` + Specify SMBIOS type 4 fields + +-``-smbios type=9[,slot_designation=str][,slot_type=%d][,slot_data_bus_width=%d][,current_usage=%d][,slot_length=%d][,slot_id=%d][,slot_characteristics1=%d][,slot_characteristics12=%d]`` ++``-smbios type=9[,slot_designation=str][,slot_type=%d][,slot_data_bus_width=%d][,current_usage=%d][,slot_length=%d][,slot_id=%d][,slot_characteristics1=%d][,slot_characteristics12=%d][,pci_device=str]`` + Specify SMBIOS type 9 fields + + ``-smbios type=11[,value=str][,path=filename]`` +-- +2.39.3 + diff --git a/kvm-Implement-base-of-SMBIOS-type-9-descriptor.patch b/kvm-Implement-base-of-SMBIOS-type-9-descriptor.patch new file mode 100644 index 0000000..89466c7 --- /dev/null +++ b/kvm-Implement-base-of-SMBIOS-type-9-descriptor.patch @@ -0,0 +1,218 @@ +From 84fc607d678bd72397a41d706e91fa241fd97266 Mon Sep 17 00:00:00 2001 +From: Igor Mammedov +Date: Wed, 21 Feb 2024 17:00:26 +0000 +Subject: [PATCH 04/20] Implement base of SMBIOS type 9 descriptor. + +RH-Author: Igor Mammedov +RH-MergeRequest: 230: Workaround Windows failing to find 64bit SMBIOS entry point with SeaBIOS +RH-Jira: RHEL-21705 +RH-Acked-by: MST +RH-Acked-by: Ani Sinha +RH-Commit: [2/18] 2678cc080bfbf3357fa2f94ceaf42fc61b690d32 + +JIRA: https://issues.redhat.com/browse/RHEL-21705 + +commit: 735eee07d1f963635d3c3bf9f5e4bf1bc000870e +Author: Felix Wu + + Version 2.1+. + + Signed-off-by: Felix Wu + Signed-off-by: Nabih Estefan + Message-Id: <20240221170027.1027325-2-nabihestefan@google.com> + Reviewed-by: Michael S. Tsirkin + Signed-off-by: Michael S. Tsirkin + +Signed-off-by: Igor Mammedov +--- + hw/smbios/smbios.c | 99 ++++++++++++++++++++++++++++++++++++ + include/hw/firmware/smbios.h | 13 +++++ + qemu-options.hx | 3 ++ + 3 files changed, 115 insertions(+) + +diff --git a/hw/smbios/smbios.c b/hw/smbios/smbios.c +index 7bde23e59d..4f5637d445 100644 +--- a/hw/smbios/smbios.c ++++ b/hw/smbios/smbios.c +@@ -122,6 +122,16 @@ struct type8_instance { + }; + static QTAILQ_HEAD(, type8_instance) type8 = QTAILQ_HEAD_INITIALIZER(type8); + ++/* type 9 instance for parsing */ ++struct type9_instance { ++ const char *slot_designation; ++ uint8_t slot_type, slot_data_bus_width, current_usage, slot_length, ++ slot_characteristics1, slot_characteristics2; ++ uint16_t slot_id; ++ QTAILQ_ENTRY(type9_instance) next; ++}; ++static QTAILQ_HEAD(, type9_instance) type9 = QTAILQ_HEAD_INITIALIZER(type9); ++ + static struct { + size_t nvalues; + char **values; +@@ -371,6 +381,54 @@ static const QemuOptDesc qemu_smbios_type8_opts[] = { + }, + }; + ++static const QemuOptDesc qemu_smbios_type9_opts[] = { ++ { ++ .name = "type", ++ .type = QEMU_OPT_NUMBER, ++ .help = "SMBIOS element type", ++ }, ++ { ++ .name = "slot_designation", ++ .type = QEMU_OPT_STRING, ++ .help = "string number for reference designation", ++ }, ++ { ++ .name = "slot_type", ++ .type = QEMU_OPT_NUMBER, ++ .help = "connector type", ++ }, ++ { ++ .name = "slot_data_bus_width", ++ .type = QEMU_OPT_NUMBER, ++ .help = "port type", ++ }, ++ { ++ .name = "current_usage", ++ .type = QEMU_OPT_NUMBER, ++ .help = "current usage", ++ }, ++ { ++ .name = "slot_length", ++ .type = QEMU_OPT_NUMBER, ++ .help = "system slot length", ++ }, ++ { ++ .name = "slot_id", ++ .type = QEMU_OPT_NUMBER, ++ .help = "system slot id", ++ }, ++ { ++ .name = "slot_characteristics1", ++ .type = QEMU_OPT_NUMBER, ++ .help = "slot characteristics1, see the spec", ++ }, ++ { ++ .name = "slot_characteristics2", ++ .type = QEMU_OPT_NUMBER, ++ .help = "slot characteristics2, see the spec", ++ }, ++}; ++ + static const QemuOptDesc qemu_smbios_type11_opts[] = { + { + .name = "value", +@@ -594,6 +652,7 @@ bool smbios_skip_table(uint8_t type, bool required_table) + #define T2_BASE 0x200 + #define T3_BASE 0x300 + #define T4_BASE 0x400 ++#define T9_BASE 0x900 + #define T11_BASE 0xe00 + + #define T16_BASE 0x1000 +@@ -792,6 +851,28 @@ static void smbios_build_type_8_table(void) + } + } + ++static void smbios_build_type_9_table(void) ++{ ++ unsigned instance = 0; ++ struct type9_instance *t9; ++ ++ QTAILQ_FOREACH(t9, &type9, next) { ++ SMBIOS_BUILD_TABLE_PRE(9, T9_BASE + instance, true); ++ ++ SMBIOS_TABLE_SET_STR(9, slot_designation, t9->slot_designation); ++ t->slot_type = t9->slot_type; ++ t->slot_data_bus_width = t9->slot_data_bus_width; ++ t->current_usage = t9->current_usage; ++ t->slot_length = t9->slot_length; ++ t->slot_id = t9->slot_id; ++ t->slot_characteristics1 = t9->slot_characteristics1; ++ t->slot_characteristics2 = t9->slot_characteristics2; ++ ++ SMBIOS_BUILD_TABLE_POST; ++ instance++; ++ } ++} ++ + static void smbios_build_type_11_table(void) + { + char count_str[128]; +@@ -1141,6 +1222,7 @@ void smbios_get_tables(MachineState *ms, + } + + smbios_build_type_8_table(); ++ smbios_build_type_9_table(); + smbios_build_type_11_table(); + + #define MAX_DIMM_SZ (16 * GiB) +@@ -1472,6 +1554,23 @@ void smbios_entry_add(QemuOpts *opts, Error **errp) + t8_i->port_type = qemu_opt_get_number(opts, "port_type", 0); + QTAILQ_INSERT_TAIL(&type8, t8_i, next); + return; ++ case 9: { ++ if (!qemu_opts_validate(opts, qemu_smbios_type9_opts, errp)) { ++ return; ++ } ++ struct type9_instance *t; ++ t = g_new0(struct type9_instance, 1); ++ save_opt(&t->slot_designation, opts, "slot_designation"); ++ t->slot_type = qemu_opt_get_number(opts, "slot_type", 0); ++ t->slot_data_bus_width = qemu_opt_get_number(opts, "slot_data_bus_width", 0); ++ t->current_usage = qemu_opt_get_number(opts, "current_usage", 0); ++ t->slot_length = qemu_opt_get_number(opts, "slot_length", 0); ++ t->slot_id = qemu_opt_get_number(opts, "slot_id", 0); ++ t->slot_characteristics1 = qemu_opt_get_number(opts, "slot_characteristics1", 0); ++ t->slot_characteristics2 = qemu_opt_get_number(opts, "slot_characteristics2", 0); ++ QTAILQ_INSERT_TAIL(&type9, t, next); ++ return; ++ } + case 11: + if (!qemu_opts_validate(opts, qemu_smbios_type11_opts, errp)) { + return; +diff --git a/include/hw/firmware/smbios.h b/include/hw/firmware/smbios.h +index d24b3ccd32..6bbd5a4c20 100644 +--- a/include/hw/firmware/smbios.h ++++ b/include/hw/firmware/smbios.h +@@ -211,6 +211,19 @@ struct smbios_type_8 { + uint8_t port_type; + } QEMU_PACKED; + ++/* SMBIOS type 9 - System Slots (v2.1+) */ ++struct smbios_type_9 { ++ struct smbios_structure_header header; ++ uint8_t slot_designation; ++ uint8_t slot_type; ++ uint8_t slot_data_bus_width; ++ uint8_t current_usage; ++ uint8_t slot_length; ++ uint16_t slot_id; ++ uint8_t slot_characteristics1; ++ uint8_t slot_characteristics2; ++} QEMU_PACKED; ++ + /* SMBIOS type 11 - OEM strings */ + struct smbios_type_11 { + struct smbios_structure_header header; +diff --git a/qemu-options.hx b/qemu-options.hx +index 0814f43066..94cacc2c63 100644 +--- a/qemu-options.hx ++++ b/qemu-options.hx +@@ -2710,6 +2710,9 @@ SRST + ``-smbios type=4[,sock_pfx=str][,manufacturer=str][,version=str][,serial=str][,asset=str][,part=str][,processor-id=%d]`` + Specify SMBIOS type 4 fields + ++``-smbios type=9[,slot_designation=str][,slot_type=%d][,slot_data_bus_width=%d][,current_usage=%d][,slot_length=%d][,slot_id=%d][,slot_characteristics1=%d][,slot_characteristics12=%d]`` ++ Specify SMBIOS type 9 fields ++ + ``-smbios type=11[,value=str][,path=filename]`` + Specify SMBIOS type 11 fields + +-- +2.39.3 + diff --git a/kvm-hw-i386-pc-Defer-smbios_set_defaults-to-machine_done.patch b/kvm-hw-i386-pc-Defer-smbios_set_defaults-to-machine_done.patch new file mode 100644 index 0000000..5470bdf --- /dev/null +++ b/kvm-hw-i386-pc-Defer-smbios_set_defaults-to-machine_done.patch @@ -0,0 +1,186 @@ +From ea2e2368dcf4140be47288472f2c2a094358e0c7 Mon Sep 17 00:00:00 2001 +From: Igor Mammedov +Date: Thu, 8 Feb 2024 23:03:45 +0100 +Subject: [PATCH 03/20] hw/i386/pc: Defer smbios_set_defaults() to machine_done +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +RH-Author: Igor Mammedov +RH-MergeRequest: 230: Workaround Windows failing to find 64bit SMBIOS entry point with SeaBIOS +RH-Jira: RHEL-21705 +RH-Acked-by: MST +RH-Acked-by: Ani Sinha +RH-Commit: [1/18] 9d4c1d1a910fec7d310429d6fc0b10c798932db7 + +JIRA: https://issues.redhat.com/browse/RHEL-21705 + +commit: a0204a5ed091dfe79aced7ec8f3ce1931fd25816 +Author: Bernhard Beschow + + Handling most of smbios data generation in the machine_done notifier is similar + to how the ARM virt machine handles it which also calls smbios_set_defaults() + there. The result is that all pc machines are freed from explicitly worrying + about smbios setup. + + Signed-off-by: Bernhard Beschow + Reviewed-by: Philippe Mathieu-Daudé + Message-ID: <20240208220349.4948-6-shentey@gmail.com> + Signed-off-by: Philippe Mathieu-Daudé + +Conflicts: hw/i386/pc_q35.c, hw/i386/pc_piix.c + due to missing 4d3457fef9 (w/i386/pc: Merge pc_guest_info_init() into pc_machine_initfn()) + and different signature of smbios_set_defaults() downstream +Fixup: hw/i386/fw_cfg.c to account for downstream changes smbios_set_defaults() + +Signed-off-by: Igor Mammedov +--- + hw/i386/fw_cfg.c | 14 +++++++++++++- + hw/i386/fw_cfg.h | 3 ++- + hw/i386/pc.c | 2 +- + hw/i386/pc_piix.c | 12 ------------ + hw/i386/pc_q35.c | 11 ----------- + include/hw/i386/pc.h | 1 - + 6 files changed, 16 insertions(+), 27 deletions(-) + +diff --git a/hw/i386/fw_cfg.c b/hw/i386/fw_cfg.c +index 7362daa45a..6a5466faf0 100644 +--- a/hw/i386/fw_cfg.c ++++ b/hw/i386/fw_cfg.c +@@ -48,15 +48,27 @@ const char *fw_cfg_arch_key_name(uint16_t key) + return NULL; + } + +-void fw_cfg_build_smbios(MachineState *ms, FWCfgState *fw_cfg) ++void fw_cfg_build_smbios(PCMachineState *pcms, FWCfgState *fw_cfg) + { + #ifdef CONFIG_SMBIOS + 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; ++ MachineState *ms = MACHINE(pcms); ++ PCMachineClass *pcmc = PC_MACHINE_GET_CLASS(pcms); ++ MachineClass *mc = MACHINE_GET_CLASS(pcms); + X86CPU *cpu = X86_CPU(ms->possible_cpus->cpus[0].cpu); + ++ if (pcmc->smbios_defaults) { ++ /* These values are guest ABI, do not change */ ++ smbios_set_defaults("QEMU", mc->desc, mc->name, ++ pcmc->smbios_legacy_mode, pcmc->smbios_uuid_encoded, ++ pcmc->smbios_stream_product, ++ pcmc->smbios_stream_version, ++ pcms->smbios_entry_point_type); ++ } ++ + /* tell smbios about cpuid version and features */ + smbios_set_cpuid(cpu->env.cpuid_version, cpu->env.features[FEAT_1_EDX]); + +diff --git a/hw/i386/fw_cfg.h b/hw/i386/fw_cfg.h +index 86ca7c1c0c..1e1de6b4a3 100644 +--- a/hw/i386/fw_cfg.h ++++ b/hw/i386/fw_cfg.h +@@ -10,6 +10,7 @@ + #define HW_I386_FW_CFG_H + + #include "hw/boards.h" ++#include "hw/i386/pc.h" + #include "hw/nvram/fw_cfg.h" + + #define FW_CFG_IO_BASE 0x510 +@@ -22,7 +23,7 @@ + FWCfgState *fw_cfg_arch_create(MachineState *ms, + uint16_t boot_cpus, + uint16_t apic_id_limit); +-void fw_cfg_build_smbios(MachineState *ms, FWCfgState *fw_cfg); ++void fw_cfg_build_smbios(PCMachineState *ms, FWCfgState *fw_cfg); + void fw_cfg_build_feature_control(MachineState *ms, FWCfgState *fw_cfg); + void fw_cfg_add_acpi_dsdt(Aml *scope, FWCfgState *fw_cfg); + +diff --git a/hw/i386/pc.c b/hw/i386/pc.c +index a1faa9e92c..16de2a59e8 100644 +--- a/hw/i386/pc.c ++++ b/hw/i386/pc.c +@@ -847,7 +847,7 @@ void pc_machine_done(Notifier *notifier, void *data) + + acpi_setup(); + if (x86ms->fw_cfg) { +- fw_cfg_build_smbios(MACHINE(pcms), x86ms->fw_cfg); ++ fw_cfg_build_smbios(pcms, x86ms->fw_cfg); + fw_cfg_build_feature_control(MACHINE(pcms), x86ms->fw_cfg); + /* update FW_CFG_NB_CPUS to account for -device added CPUs */ + fw_cfg_modify_i16(x86ms->fw_cfg, FW_CFG_NB_CPUS, x86ms->boot_cpus); +diff --git a/hw/i386/pc_piix.c b/hw/i386/pc_piix.c +index 09d02cc91f..7344b35cf1 100644 +--- a/hw/i386/pc_piix.c ++++ b/hw/i386/pc_piix.c +@@ -36,7 +36,6 @@ + #include "hw/rtc/mc146818rtc.h" + #include "hw/southbridge/piix.h" + #include "hw/display/ramfb.h" +-#include "hw/firmware/smbios.h" + #include "hw/pci/pci.h" + #include "hw/pci/pci_ids.h" + #include "hw/usb.h" +@@ -233,17 +232,6 @@ static void pc_init1(MachineState *machine, + + pc_guest_info_init(pcms); + +- if (pcmc->smbios_defaults) { +- MachineClass *mc = MACHINE_GET_CLASS(machine); +- /* These values are guest ABI, do not change */ +- smbios_set_defaults("Red Hat", "KVM", +- mc->desc, pcmc->smbios_legacy_mode, +- pcmc->smbios_uuid_encoded, +- pcmc->smbios_stream_product, +- pcmc->smbios_stream_version, +- pcms->smbios_entry_point_type); +- } +- + /* allocate ram and load rom/bios */ + if (!xen_enabled()) { + pc_memory_init(pcms, system_memory, rom_memory, hole64_size); +diff --git a/hw/i386/pc_q35.c b/hw/i386/pc_q35.c +index c6967e1846..9a22ff5dd6 100644 +--- a/hw/i386/pc_q35.c ++++ b/hw/i386/pc_q35.c +@@ -45,7 +45,6 @@ + #include "hw/i386/amd_iommu.h" + #include "hw/i386/intel_iommu.h" + #include "hw/display/ramfb.h" +-#include "hw/firmware/smbios.h" + #include "hw/ide/pci.h" + #include "hw/ide/ahci.h" + #include "hw/intc/ioapic.h" +@@ -201,16 +200,6 @@ static void pc_q35_init(MachineState *machine) + + pc_guest_info_init(pcms); + +- if (pcmc->smbios_defaults) { +- /* These values are guest ABI, do not change */ +- smbios_set_defaults("Red Hat", "KVM", +- mc->desc, pcmc->smbios_legacy_mode, +- pcmc->smbios_uuid_encoded, +- pcmc->smbios_stream_product, +- pcmc->smbios_stream_version, +- pcms->smbios_entry_point_type); +- } +- + /* create pci host bus */ + phb = OBJECT(qdev_new(TYPE_Q35_HOST_DEVICE)); + +diff --git a/include/hw/i386/pc.h b/include/hw/i386/pc.h +index 37644ede7e..c286c10bc3 100644 +--- a/include/hw/i386/pc.h ++++ b/include/hw/i386/pc.h +@@ -12,7 +12,6 @@ + #include "hw/hotplug.h" + #include "qom/object.h" + #include "hw/i386/sgx-epc.h" +-#include "hw/firmware/smbios.h" + #include "hw/cxl/cxl.h" + + #define HPET_INTCAP "hpet-intcap" +-- +2.39.3 + diff --git a/kvm-pc-q35-set-SMBIOS-entry-point-type-to-auto-by-defaul.patch b/kvm-pc-q35-set-SMBIOS-entry-point-type-to-auto-by-defaul.patch new file mode 100644 index 0000000..f37f65f --- /dev/null +++ b/kvm-pc-q35-set-SMBIOS-entry-point-type-to-auto-by-defaul.patch @@ -0,0 +1,115 @@ +From 9ca64f73238d9f1b9f13d8e941ba42771a992afb Mon Sep 17 00:00:00 2001 +From: Igor Mammedov +Date: Fri, 29 Dec 2023 14:06:05 +0100 +Subject: [PATCH 20/20] pc/q35: set SMBIOS entry point type to 'auto' by + default + +RH-Author: Igor Mammedov +RH-MergeRequest: 230: Workaround Windows failing to find 64bit SMBIOS entry point with SeaBIOS +RH-Jira: RHEL-21705 +RH-Acked-by: MST +RH-Acked-by: Ani Sinha +RH-Commit: [18/18] c7fc6ac7350bca3ff99e58620710a86218385781 + +JIRA: https://issues.redhat.com/browse/RHEL-21705 + + Use smbios-entry-point-type='auto' for newer machine types as a workaround + for Windows not detecting SMBIOS tables. Which makes QEMU pick SMBIOS tables + based on configuration (with 2.x preferred and fallback to 3.x if the former + isn't compatible with configuration) + + Default compat setting of smbios-entry-point-type after series + for pc/q35 machines: + * 9.0-newer: 'auto' + * 8.1-8.2: '64' + * 8.0-older: '32' + Resolves: https://gitlab.com/qemu-project/qemu/-/issues/2008 + Signed-off-by: Igor Mammedov + Reviewed-by: Ani Sinha + Tested-by: Fiona Ebner + +Conflicts: hw/i386/pc_piix.c hw/i386/pc_q35.c + due to RHEL machine types + +REHL only parts: + Fix RHEL 'pc' machine types at SMBIOS 2.X + for the latest RHEL 'q35' machine type use version autoselect + which propagates to RHEL 9.4 q35 macine type while RHEL 9.2 q35 and older + are kept at SMBIOS_ENTRY_POINT_TYPE_32 (see: pc_q35_machine_rhel920_options) + +Signed-off-by: Igor Mammedov +--- + hw/i386/pc.c | 2 +- + hw/i386/pc_piix.c | 7 +++++++ + hw/i386/pc_q35.c | 5 +++++ + 3 files changed, 13 insertions(+), 1 deletion(-) + +diff --git a/hw/i386/pc.c b/hw/i386/pc.c +index ae6777fc1a..d6f267b220 100644 +--- a/hw/i386/pc.c ++++ b/hw/i386/pc.c +@@ -2004,7 +2004,7 @@ static void pc_machine_class_init(ObjectClass *oc, void *data) + mc->nvdimm_supported = true; + mc->smp_props.dies_supported = true; + mc->default_ram_id = "pc.ram"; +- pcmc->default_smbios_ep_type = SMBIOS_ENTRY_POINT_TYPE_64; ++ pcmc->default_smbios_ep_type = SMBIOS_ENTRY_POINT_TYPE_AUTO; + + object_class_property_add(oc, PC_MACHINE_MAX_RAM_BELOW_4G, "size", + pc_machine_get_max_ram_below_4g, pc_machine_set_max_ram_below_4g, +diff --git a/hw/i386/pc_piix.c b/hw/i386/pc_piix.c +index 7344b35cf1..54d1c58bce 100644 +--- a/hw/i386/pc_piix.c ++++ b/hw/i386/pc_piix.c +@@ -539,9 +539,14 @@ static void pc_i440fx_machine_options(MachineClass *m) + + static void pc_i440fx_8_2_machine_options(MachineClass *m) + { ++ PCMachineClass *pcmc = PC_MACHINE_CLASS(m); ++ + pc_i440fx_machine_options(m); + m->alias = "pc"; + m->is_default = true; ++ ++ /* For pc-i44fx-8.2 and 8.1, use SMBIOS 3.X by default */ ++ pcmc->default_smbios_ep_type = SMBIOS_ENTRY_POINT_TYPE_64; + } + + DEFINE_I440FX_MACHINE(v8_2, "pc-i440fx-8.2", NULL, +@@ -982,6 +987,8 @@ static void pc_machine_rhel7_options(MachineClass *m) + m->alias = "pc"; + m->is_default = 1; + m->smp_props.prefer_sockets = true; ++ /* there aren't ne PC macine types in RHEL9, keep it at SMBIOS 2.X */ ++ pcmc->default_smbios_ep_type = SMBIOS_ENTRY_POINT_TYPE_32; + } + + static void pc_init_rhel760(MachineState *machine) +diff --git a/hw/i386/pc_q35.c b/hw/i386/pc_q35.c +index 9a22ff5dd6..cd5fb7380e 100644 +--- a/hw/i386/pc_q35.c ++++ b/hw/i386/pc_q35.c +@@ -377,8 +377,11 @@ static void pc_q35_machine_options(MachineClass *m) + + static void pc_q35_8_2_machine_options(MachineClass *m) + { ++ PCMachineClass *pcmc = PC_MACHINE_CLASS(m); + pc_q35_machine_options(m); + m->alias = "q35"; ++ /* For pc-q35-8.2 and 8.1, use SMBIOS 3.X by default */ ++ pcmc->default_smbios_ep_type = SMBIOS_ENTRY_POINT_TYPE_64; + } + + DEFINE_Q35_MACHINE(v8_2, "pc-q35-8.2", NULL, +@@ -712,6 +715,8 @@ static void pc_q35_machine_rhel_options(MachineClass *m) + m->alias = "q35"; + m->max_cpus = 710; + compat_props_add(m->compat_props, pc_rhel_compat, pc_rhel_compat_len); ++ /* use SMBIOS version autoselect by default for the latest RHEL machine */ ++ pcmc->default_smbios_ep_type = SMBIOS_ENTRY_POINT_TYPE_AUTO; + } + + static void pc_q35_init_rhel940(MachineState *machine) +-- +2.39.3 + diff --git a/kvm-smbios-add-smbios_add_usr_blob_size-helper.patch b/kvm-smbios-add-smbios_add_usr_blob_size-helper.patch new file mode 100644 index 0000000..a9d24a0 --- /dev/null +++ b/kvm-smbios-add-smbios_add_usr_blob_size-helper.patch @@ -0,0 +1,62 @@ +From 93cf5b82771f1d1e8182be168dae7a45d42069e9 Mon Sep 17 00:00:00 2001 +From: Igor Mammedov +Date: Mon, 4 Mar 2024 15:39:57 +0100 +Subject: [PATCH 11/20] smbios: add smbios_add_usr_blob_size() helper + +RH-Author: Igor Mammedov +RH-MergeRequest: 230: Workaround Windows failing to find 64bit SMBIOS entry point with SeaBIOS +RH-Jira: RHEL-21705 +RH-Acked-by: MST +RH-Acked-by: Ani Sinha +RH-Commit: [9/18] 8c698fb9e186d2b1d2b7f75a74305f356450ad68 + +JIRA: https://issues.redhat.com/browse/RHEL-21705 + +it will be used by follow up patch when legacy handling +is moved out into a separate file. + +Signed-off-by: Igor Mammedov +Reviewed-by: Ani Sinha +--- + hw/smbios/smbios.c | 18 ++++++++++++++---- + 1 file changed, 14 insertions(+), 4 deletions(-) + +diff --git a/hw/smbios/smbios.c b/hw/smbios/smbios.c +index 441517cf24..c48a290478 100644 +--- a/hw/smbios/smbios.c ++++ b/hw/smbios/smbios.c +@@ -1426,6 +1426,14 @@ static bool save_opt_list(size_t *ndest, char ***dest, QemuOpts *opts, + return true; + } + ++static void smbios_add_usr_blob_size(size_t size) ++{ ++ if (!usr_blobs_sizes) { ++ usr_blobs_sizes = g_array_new(false, false, sizeof(size_t)); ++ } ++ g_array_append_val(usr_blobs_sizes, size); ++} ++ + void smbios_entry_add(QemuOpts *opts, Error **errp) + { + const char *val; +@@ -1473,10 +1481,12 @@ void smbios_entry_add(QemuOpts *opts, Error **errp) + smbios_type4_count++; + } + +- if (!usr_blobs_sizes) { +- usr_blobs_sizes = g_array_new(false, false, sizeof(size_t)); +- } +- g_array_append_val(usr_blobs_sizes, size); ++ /* ++ * preserve blob size for legacy mode so it could build its ++ * blobs flavor from 'usr_blobs' ++ */ ++ smbios_add_usr_blob_size(size); ++ + usr_blobs_len += size; + if (size > usr_table_max) { + usr_table_max = size; +-- +2.39.3 + diff --git a/kvm-smbios-avoid-mangling-user-provided-tables.patch b/kvm-smbios-avoid-mangling-user-provided-tables.patch new file mode 100644 index 0000000..b8e4d92 --- /dev/null +++ b/kvm-smbios-avoid-mangling-user-provided-tables.patch @@ -0,0 +1,309 @@ +From 15d293b706ca6c9e6ad569becda8da5f70461c30 Mon Sep 17 00:00:00 2001 +From: Igor Mammedov +Date: Tue, 13 Feb 2024 09:25:11 +0100 +Subject: [PATCH 09/20] smbios: avoid mangling user provided tables + +RH-Author: Igor Mammedov +RH-MergeRequest: 230: Workaround Windows failing to find 64bit SMBIOS entry point with SeaBIOS +RH-Jira: RHEL-21705 +RH-Acked-by: MST +RH-Acked-by: Ani Sinha +RH-Commit: [7/18] fa2c7372f55f29e5834eee94ba98f19ea02e7a82 + +JIRA: https://issues.redhat.com/browse/RHEL-21705 + + currently smbios_entry_add() preserves internally '-smbios type=' + options but tables provided with '-smbios file=' are stored directly + into blob that eventually will be exposed to VM. And then later + QEMU adds default/'-smbios type' entries on top into the same blob. + + It makes impossible to generate tables more than once, hence + 'immutable' guard was used. + Make it possible to regenerate final blob by storing user provided + blobs into a dedicated area (usr_blobs) and then copy it when + composing final blob. Which also makes handling of -smbios + options consistent. + + As side effect of this and previous commits there is no need to + generate legacy smbios_entries at the time options are parsed. + Instead compose smbios_entries on demand from usr_blobs like + it is done for non-legacy SMBIOS tables. + + Signed-off-by: Igor Mammedov + Tested-by: Fiona Ebner + Reviewed-by: Ani Sinha + +Conflicts: hw/smbios/smbios.c + caused by downstream smbios_type2_required + +Signed-off-by: Igor Mammedov +--- + hw/smbios/smbios.c | 181 +++++++++++++++++++++++---------------------- + 1 file changed, 93 insertions(+), 88 deletions(-) + +diff --git a/hw/smbios/smbios.c b/hw/smbios/smbios.c +index 0c8c439859..d8d68716d4 100644 +--- a/hw/smbios/smbios.c ++++ b/hw/smbios/smbios.c +@@ -60,6 +60,14 @@ static bool smbios_uuid_encoded = true; + /* Set to true for modern Windows 10 HardwareID-6 compat */ + static bool smbios_type2_required; + ++/* ++ * SMBIOS tables provided by user with '-smbios file=' option ++ */ ++uint8_t *usr_blobs; ++size_t usr_blobs_len; ++static GArray *usr_blobs_sizes; ++static unsigned usr_table_max; ++static unsigned usr_table_cnt; + + uint8_t *smbios_tables; + size_t smbios_tables_len; +@@ -70,7 +78,6 @@ static SmbiosEntryPointType smbios_ep_type = SMBIOS_ENTRY_POINT_TYPE_32; + static SmbiosEntryPoint 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; + +@@ -617,9 +624,8 @@ static void smbios_build_type_1_fields(void) + + uint8_t *smbios_get_table_legacy(uint32_t expected_t4_count, size_t *length) + { +- /* drop unwanted version of command-line file blob(s) */ +- g_free(smbios_tables); +- smbios_tables = NULL; ++ int i; ++ size_t usr_offset; + + /* also complain if fields were given for types > 1 */ + if (find_next_bit(have_fields_bitmap, +@@ -629,12 +635,33 @@ uint8_t *smbios_get_table_legacy(uint32_t expected_t4_count, size_t *length) + exit(1); + } + +- if (!smbios_immutable) { +- smbios_build_type_0_fields(); +- smbios_build_type_1_fields(); +- smbios_validate_table(expected_t4_count); +- smbios_immutable = true; ++ g_free(smbios_entries); ++ smbios_entries_len = sizeof(uint16_t); ++ smbios_entries = g_malloc0(smbios_entries_len); ++ ++ for (i = 0, usr_offset = 0; usr_blobs_sizes && i < usr_blobs_sizes->len; ++ i++) ++ { ++ struct smbios_table *table; ++ struct smbios_structure_header *header; ++ size_t size = g_array_index(usr_blobs_sizes, size_t, i); ++ ++ header = (struct smbios_structure_header *)(usr_blobs + usr_offset); ++ 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); ++ usr_offset += size; + } ++ ++ smbios_build_type_0_fields(); ++ smbios_build_type_1_fields(); ++ smbios_validate_table(expected_t4_count); + *length = smbios_entries_len; + return smbios_entries; + } +@@ -1232,68 +1259,68 @@ void smbios_get_tables(MachineState *ms, + { + unsigned i, dimm_cnt, offset; + +- /* drop unwanted (legacy) version of command-line file blob(s) */ +- g_free(smbios_entries); +- smbios_entries = NULL; ++ g_free(smbios_tables); ++ smbios_tables = g_memdup2(usr_blobs, usr_blobs_len); ++ smbios_tables_len = usr_blobs_len; ++ smbios_table_max = usr_table_max; ++ smbios_table_cnt = usr_table_cnt; + +- if (!smbios_immutable) { +- smbios_build_type_0_table(); +- smbios_build_type_1_table(); +- smbios_build_type_2_table(); +- smbios_build_type_3_table(); ++ smbios_build_type_0_table(); ++ smbios_build_type_1_table(); ++ smbios_build_type_2_table(); ++ smbios_build_type_3_table(); + +- assert(ms->smp.sockets >= 1); ++ assert(ms->smp.sockets >= 1); + +- for (i = 0; i < ms->smp.sockets; i++) { +- smbios_build_type_4_table(ms, i); +- } ++ for (i = 0; i < ms->smp.sockets; i++) { ++ smbios_build_type_4_table(ms, i); ++ } + +- smbios_build_type_8_table(); +- smbios_build_type_9_table(errp); +- smbios_build_type_11_table(); ++ smbios_build_type_8_table(); ++ smbios_build_type_9_table(errp); ++ smbios_build_type_11_table(); + + #define MAX_DIMM_SZ (16 * GiB) + #define GET_DIMM_SZ ((i < dimm_cnt - 1) ? MAX_DIMM_SZ \ + : ((current_machine->ram_size - 1) % MAX_DIMM_SZ) + 1) + +- dimm_cnt = QEMU_ALIGN_UP(current_machine->ram_size, MAX_DIMM_SZ) / MAX_DIMM_SZ; ++ dimm_cnt = QEMU_ALIGN_UP(current_machine->ram_size, MAX_DIMM_SZ) / ++ MAX_DIMM_SZ; + +- /* +- * The offset determines if we need to keep additional space between +- * table 17 and table 19 header handle numbers so that they do +- * not overlap. For example, for a VM with larger than 8 TB guest +- * memory and DIMM like chunks of 16 GiB, the default space between +- * the two tables (T19_BASE - T17_BASE = 512) is not enough. +- */ +- offset = (dimm_cnt > (T19_BASE - T17_BASE)) ? \ +- dimm_cnt - (T19_BASE - T17_BASE) : 0; ++ /* ++ * The offset determines if we need to keep additional space between ++ * table 17 and table 19 header handle numbers so that they do ++ * not overlap. For example, for a VM with larger than 8 TB guest ++ * memory and DIMM like chunks of 16 GiB, the default space between ++ * the two tables (T19_BASE - T17_BASE = 512) is not enough. ++ */ ++ offset = (dimm_cnt > (T19_BASE - T17_BASE)) ? \ ++ dimm_cnt - (T19_BASE - T17_BASE) : 0; + +- smbios_build_type_16_table(dimm_cnt); ++ 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; i < dimm_cnt; i++) { ++ smbios_build_type_17_table(i, GET_DIMM_SZ); ++ } + +- for (i = 0; i < mem_array_size; i++) { +- smbios_build_type_19_table(i, offset, mem_array[i].address, +- mem_array[i].length); +- } ++ for (i = 0; i < mem_array_size; i++) { ++ smbios_build_type_19_table(i, offset, mem_array[i].address, ++ mem_array[i].length); ++ } + +- /* +- * make sure 16 bit handle numbers in the headers of tables 19 +- * and 32 do not overlap. +- */ +- assert((mem_array_size + offset) < (T32_BASE - T19_BASE)); ++ /* ++ * make sure 16 bit handle numbers in the headers of tables 19 ++ * and 32 do not overlap. ++ */ ++ assert((mem_array_size + offset) < (T32_BASE - T19_BASE)); + +- smbios_build_type_32_table(); +- smbios_build_type_38_table(); +- smbios_build_type_41_table(errp); +- smbios_build_type_127_table(); ++ smbios_build_type_32_table(); ++ smbios_build_type_38_table(); ++ smbios_build_type_41_table(errp); ++ smbios_build_type_127_table(); + +- smbios_validate_table(ms->smp.sockets); +- smbios_entry_point_setup(); +- smbios_immutable = true; +- } ++ smbios_validate_table(ms->smp.sockets); ++ smbios_entry_point_setup(); + + /* return tables blob and entry point (anchor), and their sizes */ + *tables = smbios_tables; +@@ -1393,13 +1420,10 @@ void smbios_entry_add(QemuOpts *opts, Error **errp) + { + 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 */ ++ size_t size; + + if (!qemu_opts_validate(opts, qemu_smbios_file_opts, errp)) { + return; +@@ -1416,9 +1440,9 @@ void smbios_entry_add(QemuOpts *opts, Error **errp) + * (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); ++ usr_blobs = g_realloc(usr_blobs, usr_blobs_len + size); ++ header = (struct smbios_structure_header *)(usr_blobs + ++ usr_blobs_len); + + if (load_image_size(val, (uint8_t *)header, size) != size) { + error_setg(errp, "Failed to load SMBIOS file %s", val); +@@ -1439,34 +1463,15 @@ void smbios_entry_add(QemuOpts *opts, Error **errp) + smbios_type4_count++; + } + +- smbios_tables_len += size; +- if (size > smbios_table_max) { +- smbios_table_max = size; ++ if (!usr_blobs_sizes) { ++ usr_blobs_sizes = g_array_new(false, false, sizeof(size_t)); + } +- 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); ++ g_array_append_val(usr_blobs_sizes, size); ++ usr_blobs_len += size; ++ if (size > usr_table_max) { ++ usr_table_max = size; + } +- 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 */ ++ usr_table_cnt++; + + return; + } +-- +2.39.3 + diff --git a/kvm-smbios-build-legacy-mode-code-only-for-pc-machine.patch b/kvm-smbios-build-legacy-mode-code-only-for-pc-machine.patch new file mode 100644 index 0000000..1dc4d22 --- /dev/null +++ b/kvm-smbios-build-legacy-mode-code-only-for-pc-machine.patch @@ -0,0 +1,517 @@ +From 7ebb314a4f81d6d1a7dd4980b757fb5e556f5837 Mon Sep 17 00:00:00 2001 +From: Igor Mammedov +Date: Tue, 13 Feb 2024 16:45:18 +0100 +Subject: [PATCH 13/20] smbios: build legacy mode code only for 'pc' machine + +RH-Author: Igor Mammedov +RH-MergeRequest: 230: Workaround Windows failing to find 64bit SMBIOS entry point with SeaBIOS +RH-Jira: RHEL-21705 +RH-Acked-by: MST +RH-Acked-by: Ani Sinha +RH-Commit: [11/18] 06e639be03e0d151fb9bcf5f728388edcb84219a + +JIRA: https://issues.redhat.com/browse/RHEL-21705 + + basically moving code around without functional change. + And exposing some symbols so that they could be shared + between smbbios.c and new smbios_legacy.c + + plus some meson magic to build smbios_legacy.c only + for 'pc' machine and otherwise replace it with stub + if not selected. + + Signed-off-by: Igor Mammedov + Reviewed-by: Ani Sinha + +Conflicts: hw/smbios/smbios.c + context change due to downstream smbios_type2_required + +Signed-off-by: Igor Mammedov +--- + hw/i386/Kconfig | 1 + + hw/smbios/Kconfig | 2 + + hw/smbios/meson.build | 5 + + hw/smbios/smbios.c | 163 +----------------------------- + hw/smbios/smbios_legacy.c | 179 +++++++++++++++++++++++++++++++++ + hw/smbios/smbios_legacy_stub.c | 15 +++ + include/hw/firmware/smbios.h | 5 + + 7 files changed, 208 insertions(+), 162 deletions(-) + create mode 100644 hw/smbios/smbios_legacy.c + create mode 100644 hw/smbios/smbios_legacy_stub.c + +diff --git a/hw/i386/Kconfig b/hw/i386/Kconfig +index a1846be6f7..a6ee052f9a 100644 +--- a/hw/i386/Kconfig ++++ b/hw/i386/Kconfig +@@ -76,6 +76,7 @@ config I440FX + select PIIX + select DIMM + select SMBIOS ++ select SMBIOS_LEGACY + select FW_CFG_DMA + + config ISAPC +diff --git a/hw/smbios/Kconfig b/hw/smbios/Kconfig +index 553adf4bfc..8d989a2f1b 100644 +--- a/hw/smbios/Kconfig ++++ b/hw/smbios/Kconfig +@@ -1,2 +1,4 @@ + config SMBIOS + bool ++config SMBIOS_LEGACY ++ bool +diff --git a/hw/smbios/meson.build b/hw/smbios/meson.build +index 6eeae4b35c..fcac1d7490 100644 +--- a/hw/smbios/meson.build ++++ b/hw/smbios/meson.build +@@ -4,10 +4,15 @@ smbios_ss.add(when: 'CONFIG_IPMI', + if_true: files('smbios_type_38.c'), + if_false: files('smbios_type_38-stub.c')) + ++smbios_ss.add(when: 'CONFIG_SMBIOS_LEGACY', ++ if_true: files('smbios_legacy.c'), ++ if_false: files('smbios_legacy_stub.c')) ++ + system_ss.add_all(when: 'CONFIG_SMBIOS', if_true: smbios_ss) + system_ss.add(when: 'CONFIG_SMBIOS', if_false: files('smbios-stub.c')) + + system_ss.add(when: 'CONFIG_ALL', if_true: files( + 'smbios-stub.c', + 'smbios_type_38-stub.c', ++ 'smbios_legacy_stub.c', + )) +diff --git a/hw/smbios/smbios.c b/hw/smbios/smbios.c +index eb9927335d..e40204550e 100644 +--- a/hw/smbios/smbios.c ++++ b/hw/smbios/smbios.c +@@ -31,31 +31,7 @@ + #include "hw/pci/pci_device.h" + #include "smbios_build.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_uuid_encoded = true; +-/* end: legacy structures & constants for <= 2.0 machines */ + + /* Set to true for modern Windows 10 HardwareID-6 compat */ + static bool smbios_type2_required; +@@ -65,7 +41,6 @@ static bool smbios_type2_required; + */ + uint8_t *usr_blobs; + size_t usr_blobs_len; +-static GArray *usr_blobs_sizes; + static unsigned usr_table_max; + static unsigned usr_table_cnt; + +@@ -531,7 +506,7 @@ static void smbios_check_type4_count(uint32_t expected_t4_count) + } + } + +-static void smbios_validate_table(void) ++void smbios_validate_table(void) + { + if (smbios_ep_type == SMBIOS_ENTRY_POINT_TYPE_32 && + smbios_tables_len > SMBIOS_21_MAX_TABLES_LEN) { +@@ -541,134 +516,6 @@ static void smbios_validate_table(void) + } + } + +- +-/* 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), +- smbios_type0.vendor); +- smbios_maybe_add_str(0, offsetof(struct smbios_type_0, bios_version_str), +- smbios_type0.version); +- smbios_maybe_add_str(0, offsetof(struct smbios_type_0, +- bios_release_date_str), +- smbios_type0.date); +- if (smbios_type0.have_major_minor) { +- smbios_add_field(0, offsetof(struct smbios_type_0, +- system_bios_major_release), +- &smbios_type0.major, 1); +- smbios_add_field(0, offsetof(struct smbios_type_0, +- system_bios_minor_release), +- &smbios_type0.minor, 1); +- } +-} +- +-static void smbios_build_type_1_fields(void) +-{ +- smbios_maybe_add_str(1, offsetof(struct smbios_type_1, manufacturer_str), +- smbios_type1.manufacturer); +- smbios_maybe_add_str(1, offsetof(struct smbios_type_1, product_name_str), +- smbios_type1.product); +- smbios_maybe_add_str(1, offsetof(struct smbios_type_1, version_str), +- smbios_type1.version); +- smbios_maybe_add_str(1, offsetof(struct smbios_type_1, serial_number_str), +- smbios_type1.serial); +- smbios_maybe_add_str(1, offsetof(struct smbios_type_1, sku_number_str), +- smbios_type1.sku); +- smbios_maybe_add_str(1, offsetof(struct smbios_type_1, family_str), +- smbios_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) +-{ +- int i; +- size_t usr_offset; +- +- /* also complain if fields were given for types > 1 */ +- if (find_next_bit(smbios_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); +- } +- +- if (test_bit(4, smbios_have_binfile_bitmap)) { +- error_report("can't process table for smbios " +- "type 4 on machine versions < 2.1!"); +- exit(1); +- } +- +- g_free(smbios_entries); +- smbios_entries_len = sizeof(uint16_t); +- smbios_entries = g_malloc0(smbios_entries_len); +- +- for (i = 0, usr_offset = 0; usr_blobs_sizes && i < usr_blobs_sizes->len; +- i++) +- { +- struct smbios_table *table; +- struct smbios_structure_header *header; +- size_t size = g_array_index(usr_blobs_sizes, size_t, i); +- +- header = (struct smbios_structure_header *)(usr_blobs + usr_offset); +- 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); +- usr_offset += size; +- } +- +- smbios_build_type_0_fields(); +- smbios_build_type_1_fields(); +- smbios_validate_table(); +- *length = smbios_entries_len; +- return smbios_entries; +-} +-/* end: legacy setup functions for <= 2.0 machines */ +- +- + bool smbios_skip_table(uint8_t type, bool required_table) + { + if (test_bit(type, smbios_have_binfile_bitmap)) { +@@ -1418,14 +1265,6 @@ static bool save_opt_list(size_t *ndest, char ***dest, QemuOpts *opts, + return true; + } + +-static void smbios_add_usr_blob_size(size_t size) +-{ +- if (!usr_blobs_sizes) { +- usr_blobs_sizes = g_array_new(false, false, sizeof(size_t)); +- } +- g_array_append_val(usr_blobs_sizes, size); +-} +- + void smbios_entry_add(QemuOpts *opts, Error **errp) + { + const char *val; +diff --git a/hw/smbios/smbios_legacy.c b/hw/smbios/smbios_legacy.c +new file mode 100644 +index 0000000000..21f143e738 +--- /dev/null ++++ b/hw/smbios/smbios_legacy.c +@@ -0,0 +1,179 @@ ++/* ++ * SMBIOS legacy support ++ * ++ * Copyright (C) 2009 Hewlett-Packard Development Company, L.P. ++ * Copyright (C) 2013 Red Hat, Inc. ++ * ++ * Authors: ++ * Alex Williamson ++ * Markus Armbruster ++ * ++ * 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/osdep.h" ++#include "qemu/bswap.h" ++#include "hw/firmware/smbios.h" ++#include "sysemu/sysemu.h" ++#include "qemu/error-report.h" ++ ++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; ++GArray *usr_blobs_sizes; ++ ++void smbios_add_usr_blob_size(size_t size) ++{ ++ if (!usr_blobs_sizes) { ++ usr_blobs_sizes = g_array_new(false, false, sizeof(size_t)); ++ } ++ g_array_append_val(usr_blobs_sizes, size); ++} ++ ++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), ++ smbios_type0.vendor); ++ smbios_maybe_add_str(0, offsetof(struct smbios_type_0, bios_version_str), ++ smbios_type0.version); ++ smbios_maybe_add_str(0, offsetof(struct smbios_type_0, ++ bios_release_date_str), ++ smbios_type0.date); ++ if (smbios_type0.have_major_minor) { ++ smbios_add_field(0, offsetof(struct smbios_type_0, ++ system_bios_major_release), ++ &smbios_type0.major, 1); ++ smbios_add_field(0, offsetof(struct smbios_type_0, ++ system_bios_minor_release), ++ &smbios_type0.minor, 1); ++ } ++} ++ ++static void smbios_build_type_1_fields(void) ++{ ++ smbios_maybe_add_str(1, offsetof(struct smbios_type_1, manufacturer_str), ++ smbios_type1.manufacturer); ++ smbios_maybe_add_str(1, offsetof(struct smbios_type_1, product_name_str), ++ smbios_type1.product); ++ smbios_maybe_add_str(1, offsetof(struct smbios_type_1, version_str), ++ smbios_type1.version); ++ smbios_maybe_add_str(1, offsetof(struct smbios_type_1, serial_number_str), ++ smbios_type1.serial); ++ smbios_maybe_add_str(1, offsetof(struct smbios_type_1, sku_number_str), ++ smbios_type1.sku); ++ smbios_maybe_add_str(1, offsetof(struct smbios_type_1, family_str), ++ smbios_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) ++{ ++ int i; ++ size_t usr_offset; ++ ++ /* complain if fields were given for types > 1 */ ++ if (find_next_bit(smbios_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); ++ } ++ ++ if (test_bit(4, smbios_have_binfile_bitmap)) { ++ error_report("can't process table for smbios " ++ "type 4 on machine versions < 2.1!"); ++ exit(1); ++ } ++ ++ g_free(smbios_entries); ++ smbios_entries_len = sizeof(uint16_t); ++ smbios_entries = g_malloc0(smbios_entries_len); ++ ++ for (i = 0, usr_offset = 0; usr_blobs_sizes && i < usr_blobs_sizes->len; ++ i++) ++ { ++ struct smbios_table *table; ++ struct smbios_structure_header *header; ++ size_t size = g_array_index(usr_blobs_sizes, size_t, i); ++ ++ header = (struct smbios_structure_header *)(usr_blobs + usr_offset); ++ 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); ++ usr_offset += size; ++ } ++ ++ smbios_build_type_0_fields(); ++ smbios_build_type_1_fields(); ++ smbios_validate_table(); ++ *length = smbios_entries_len; ++ return smbios_entries; ++} +diff --git a/hw/smbios/smbios_legacy_stub.c b/hw/smbios/smbios_legacy_stub.c +new file mode 100644 +index 0000000000..f29b15316c +--- /dev/null ++++ b/hw/smbios/smbios_legacy_stub.c +@@ -0,0 +1,15 @@ ++/* ++ * IPMI SMBIOS firmware handling ++ * ++ * Copyright (c) 2024 Igor Mammedov, Red Hat, Inc. ++ * ++ * This work is licensed under the terms of the GNU GPL, version 2 or later. ++ * See the COPYING file in the top-level directory. ++ */ ++ ++#include "qemu/osdep.h" ++#include "hw/firmware/smbios.h" ++ ++void smbios_add_usr_blob_size(size_t size) ++{ ++} +diff --git a/include/hw/firmware/smbios.h b/include/hw/firmware/smbios.h +index 333de0d5fc..92e9aba415 100644 +--- a/include/hw/firmware/smbios.h ++++ b/include/hw/firmware/smbios.h +@@ -17,6 +17,9 @@ + * + */ + ++extern uint8_t *usr_blobs; ++extern GArray *usr_blobs_sizes; ++ + typedef struct { + const char *vendor, *version, *date; + bool have_major_minor, uefi; +@@ -323,6 +326,8 @@ struct smbios_type_127 { + struct smbios_structure_header header; + } QEMU_PACKED; + ++void smbios_validate_table(void); ++void smbios_add_usr_blob_size(size_t size); + void smbios_entry_add(QemuOpts *opts, Error **errp); + void smbios_set_cpuid(uint32_t version, uint32_t features); + void smbios_set_defaults(const char *manufacturer, const char *product, +-- +2.39.3 + diff --git a/kvm-smbios-cleanup-smbios_get_tables-from-legacy-handlin.patch b/kvm-smbios-cleanup-smbios_get_tables-from-legacy-handlin.patch new file mode 100644 index 0000000..48a9e16 --- /dev/null +++ b/kvm-smbios-cleanup-smbios_get_tables-from-legacy-handlin.patch @@ -0,0 +1,65 @@ +From 07f6ef2d032cda3e746ac2477c0a9bc1ac636f45 Mon Sep 17 00:00:00 2001 +From: Igor Mammedov +Date: Fri, 29 Dec 2023 14:08:13 +0100 +Subject: [PATCH 06/20] smbios: cleanup smbios_get_tables() from legacy + handling + +RH-Author: Igor Mammedov +RH-MergeRequest: 230: Workaround Windows failing to find 64bit SMBIOS entry point with SeaBIOS +RH-Jira: RHEL-21705 +RH-Acked-by: MST +RH-Acked-by: Ani Sinha +RH-Commit: [4/18] a5e09ce1df72293fecad863edd146a8c4b1a734f + +JIRA: https://issues.redhat.com/browse/RHEL-21705 + +smbios_get_tables() bails out right away if leagacy mode is enabled +and won't generate any SMBIOS tables. At the same time x86 specific +fw_cfg_build_smbios() will genarate legacy tables and then proceed +to preparing temporary mem_array for useless call to +smbios_get_tables() and then discard it. + +Drop legacy related check in smbios_get_tables() and return from +fw_cfg_build_smbios() early if legacy tables where built without +proceeding to non legacy part of the function. + +Signed-off-by: Igor Mammedov +Reviewed-by: Ani Sinha +Tested-by: Fiona Ebner +--- + hw/i386/fw_cfg.c | 1 + + hw/smbios/smbios.c | 6 ------ + 2 files changed, 1 insertion(+), 6 deletions(-) + +diff --git a/hw/i386/fw_cfg.c b/hw/i386/fw_cfg.c +index 6a5466faf0..ed72b1442d 100644 +--- a/hw/i386/fw_cfg.c ++++ b/hw/i386/fw_cfg.c +@@ -76,6 +76,7 @@ void fw_cfg_build_smbios(PCMachineState *pcms, FWCfgState *fw_cfg) + if (smbios_tables) { + fw_cfg_add_bytes(fw_cfg, FW_CFG_SMBIOS_ENTRIES, + smbios_tables, smbios_tables_len); ++ return; + } + + /* build the array of physical mem area from e820 table */ +diff --git a/hw/smbios/smbios.c b/hw/smbios/smbios.c +index 074705fa4c..b13e40bae2 100644 +--- a/hw/smbios/smbios.c ++++ b/hw/smbios/smbios.c +@@ -1244,12 +1244,6 @@ void smbios_get_tables(MachineState *ms, + { + unsigned i, dimm_cnt, offset; + +- 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(); +-- +2.39.3 + diff --git a/kvm-smbios-clear-smbios_type4_count-before-building-tabl.patch b/kvm-smbios-clear-smbios_type4_count-before-building-tabl.patch new file mode 100644 index 0000000..38a7f95 --- /dev/null +++ b/kvm-smbios-clear-smbios_type4_count-before-building-tabl.patch @@ -0,0 +1,38 @@ +From c0282a842a912aacac28a6ae229de5854c3fb5df Mon Sep 17 00:00:00 2001 +From: Igor Mammedov +Date: Mon, 26 Feb 2024 13:20:22 +0100 +Subject: [PATCH 16/20] smbios: clear smbios_type4_count before building tables + +RH-Author: Igor Mammedov +RH-MergeRequest: 230: Workaround Windows failing to find 64bit SMBIOS entry point with SeaBIOS +RH-Jira: RHEL-21705 +RH-Acked-by: MST +RH-Acked-by: Ani Sinha +RH-Commit: [14/18] f809595d2934ae975c0b7d17a4a79645e062ba42 + +JIRA: https://issues.redhat.com/browse/RHEL-21705 + +it will help to keep type 4 tables accounting correct in case +SMBIOS tables are built multiple times. + +Signed-off-by: Igor Mammedov +Tested-by: Fiona Ebner +--- + hw/smbios/smbios.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/hw/smbios/smbios.c b/hw/smbios/smbios.c +index 7e32430b85..4521ea386c 100644 +--- a/hw/smbios/smbios.c ++++ b/hw/smbios/smbios.c +@@ -1111,6 +1111,7 @@ void smbios_get_tables(MachineState *ms, + ep_type == SMBIOS_ENTRY_POINT_TYPE_64); + + g_free(smbios_tables); ++ smbios_type4_count = 0; + smbios_tables = g_memdup2(usr_blobs, usr_blobs_len); + smbios_tables_len = usr_blobs_len; + smbios_table_max = usr_table_max; +-- +2.39.3 + diff --git a/kvm-smbios-don-t-check-type4-structures-in-legacy-mode.patch b/kvm-smbios-don-t-check-type4-structures-in-legacy-mode.patch new file mode 100644 index 0000000..a2c9532 --- /dev/null +++ b/kvm-smbios-don-t-check-type4-structures-in-legacy-mode.patch @@ -0,0 +1,133 @@ +From 2b76d95ec07aba6d96070ee90c5015c1676be091 Mon Sep 17 00:00:00 2001 +From: Igor Mammedov +Date: Tue, 13 Feb 2024 16:25:54 +0100 +Subject: [PATCH 10/20] smbios: don't check type4 structures in legacy mode + +RH-Author: Igor Mammedov +RH-MergeRequest: 230: Workaround Windows failing to find 64bit SMBIOS entry point with SeaBIOS +RH-Jira: RHEL-21705 +RH-Acked-by: MST +RH-Acked-by: Ani Sinha +RH-Commit: [8/18] c1f8409ea0d916f333c9373535bf21b521c62855 + +JIRA: https://issues.redhat.com/browse/RHEL-21705 + + legacy mode doesn't support structures of type 2 and more, + and CLI has a check for '-smbios type' option, however it's + still possible to sneak in type4 as a blob with '-smbios file' + option. However doing the later makes SMBIOS tables broken + since SeaBIOS doesn't expect that. + + Rather than trying to add support for type4 to legacy code + (both QEMU and SeaBIOS), simplify smbios_get_table_legacy() + by dropping not relevant check in legacy code and error out + on type4 blob. + + Signed-off-by: Igor Mammedov + Reviewed-by: Ani Sinha + Tested-by: Fiona Ebner + +Conflicts: include/hw/firmware/smbios.h +Signed-off-by: Igor Mammedov + + Please enter the commit message for your changes. Lines starting +--- + hw/i386/fw_cfg.c | 3 +-- + hw/smbios/smbios.c | 18 ++++++++++++++---- + include/hw/firmware/smbios.h | 2 +- + 3 files changed, 16 insertions(+), 7 deletions(-) + +diff --git a/hw/i386/fw_cfg.c b/hw/i386/fw_cfg.c +index bb7149c4c3..a25793a68f 100644 +--- a/hw/i386/fw_cfg.c ++++ b/hw/i386/fw_cfg.c +@@ -73,8 +73,7 @@ void fw_cfg_build_smbios(PCMachineState *pcms, FWCfgState *fw_cfg) + smbios_set_cpuid(cpu->env.cpuid_version, cpu->env.features[FEAT_1_EDX]); + + if (pcmc->smbios_legacy_mode) { +- smbios_tables = smbios_get_table_legacy(ms->smp.cpus, +- &smbios_tables_len); ++ smbios_tables = smbios_get_table_legacy(&smbios_tables_len); + fw_cfg_add_bytes(fw_cfg, FW_CFG_SMBIOS_ENTRIES, + smbios_tables, smbios_tables_len); + return; +diff --git a/hw/smbios/smbios.c b/hw/smbios/smbios.c +index d8d68716d4..441517cf24 100644 +--- a/hw/smbios/smbios.c ++++ b/hw/smbios/smbios.c +@@ -530,14 +530,17 @@ opts_init(smbios_register_config); + */ + #define SMBIOS_21_MAX_TABLES_LEN 0xffff + +-static void smbios_validate_table(uint32_t expected_t4_count) ++static void smbios_check_type4_count(uint32_t expected_t4_count) + { + if (smbios_type4_count && smbios_type4_count != expected_t4_count) { + error_report("Expected %d SMBIOS Type 4 tables, got %d instead", + expected_t4_count, smbios_type4_count); + exit(1); + } ++} + ++static void smbios_validate_table(void) ++{ + if (smbios_ep_type == SMBIOS_ENTRY_POINT_TYPE_32 && + smbios_tables_len > SMBIOS_21_MAX_TABLES_LEN) { + error_report("SMBIOS 2.1 table length %zu exceeds %d", +@@ -622,7 +625,7 @@ static void smbios_build_type_1_fields(void) + } + } + +-uint8_t *smbios_get_table_legacy(uint32_t expected_t4_count, size_t *length) ++uint8_t *smbios_get_table_legacy(size_t *length) + { + int i; + size_t usr_offset; +@@ -635,6 +638,12 @@ uint8_t *smbios_get_table_legacy(uint32_t expected_t4_count, size_t *length) + exit(1); + } + ++ if (test_bit(4, have_binfile_bitmap)) { ++ error_report("can't process table for smbios " ++ "type 4 on machine versions < 2.1!"); ++ exit(1); ++ } ++ + g_free(smbios_entries); + smbios_entries_len = sizeof(uint16_t); + smbios_entries = g_malloc0(smbios_entries_len); +@@ -661,7 +670,7 @@ uint8_t *smbios_get_table_legacy(uint32_t expected_t4_count, size_t *length) + + smbios_build_type_0_fields(); + smbios_build_type_1_fields(); +- smbios_validate_table(expected_t4_count); ++ smbios_validate_table(); + *length = smbios_entries_len; + return smbios_entries; + } +@@ -1319,7 +1328,8 @@ void smbios_get_tables(MachineState *ms, + smbios_build_type_41_table(errp); + smbios_build_type_127_table(); + +- smbios_validate_table(ms->smp.sockets); ++ smbios_check_type4_count(ms->smp.sockets); ++ smbios_validate_table(); + smbios_entry_point_setup(); + + /* return tables blob and entry point (anchor), and their sizes */ +diff --git a/include/hw/firmware/smbios.h b/include/hw/firmware/smbios.h +index b9fc9a0f42..d55018e5e3 100644 +--- a/include/hw/firmware/smbios.h ++++ b/include/hw/firmware/smbios.h +@@ -315,7 +315,7 @@ void smbios_set_defaults(const char *manufacturer, const char *product, + SmbiosEntryPointType ep_type, + const char *stream_product, + const char *stream_version); +-uint8_t *smbios_get_table_legacy(uint32_t expected_t4_count, size_t *length); ++uint8_t *smbios_get_table_legacy(size_t *length); + void smbios_get_tables(MachineState *ms, + const struct smbios_phys_mem_area *mem_array, + const unsigned int mem_array_size, +-- +2.39.3 + diff --git a/kvm-smbios-error-out-when-building-type-4-table-is-not-p.patch b/kvm-smbios-error-out-when-building-type-4-table-is-not-p.patch new file mode 100644 index 0000000..2afbe66 --- /dev/null +++ b/kvm-smbios-error-out-when-building-type-4-table-is-not-p.patch @@ -0,0 +1,72 @@ +From bbb2d260e6f33380b9df28c74421055bd8dccda5 Mon Sep 17 00:00:00 2001 +From: Igor Mammedov +Date: Mon, 26 Feb 2024 12:59:33 +0100 +Subject: [PATCH 19/20] smbios: error out when building type 4 table is not + possible + +RH-Author: Igor Mammedov +RH-MergeRequest: 230: Workaround Windows failing to find 64bit SMBIOS entry point with SeaBIOS +RH-Jira: RHEL-21705 +RH-Acked-by: MST +RH-Acked-by: Ani Sinha +RH-Commit: [17/18] 86b1c67bfbe9c0c14a190cd1204b6ccd1de1630f + +JIRA: https://issues.redhat.com/browse/RHEL-21705 + +If SMBIOS v2 version is requested but number of cores/threads +are more than it's possible to describe with v2, error out +instead of silently ignoring the fact and filling core/thread +count with bogus values. + +This will help caller to decide if it should fallback to +SMBIOSv3 when smbios-entry-point-type='auto' + +Signed-off-by: Igor Mammedov +Reviewed-by: Ani Sinha +Tested-by: Fiona Ebner +--- + hw/smbios/smbios.c | 14 ++++++++++++-- + 1 file changed, 12 insertions(+), 2 deletions(-) + +diff --git a/hw/smbios/smbios.c b/hw/smbios/smbios.c +index 3d9dcb0d31..637aa952f5 100644 +--- a/hw/smbios/smbios.c ++++ b/hw/smbios/smbios.c +@@ -655,7 +655,8 @@ static void smbios_build_type_3_table(void) + } + + static void smbios_build_type_4_table(MachineState *ms, unsigned instance, +- SmbiosEntryPointType ep_type) ++ SmbiosEntryPointType ep_type, ++ Error **errp) + { + char sock_str[128]; + size_t tbl_len = SMBIOS_TYPE_4_LEN_V28; +@@ -709,6 +710,12 @@ static void smbios_build_type_4_table(MachineState *ms, unsigned instance, + if (tbl_len == SMBIOS_TYPE_4_LEN_V30) { + t->core_count2 = t->core_enabled2 = cpu_to_le16(cores_per_socket); + t->thread_count2 = cpu_to_le16(threads_per_socket); ++ } else if (t->core_count == 0xFF || t->thread_count == 0xFF) { ++ error_setg(errp, "SMBIOS 2.0 doesn't support number of processor " ++ "cores/threads more than 255, use " ++ "-machine smbios-entry-point-type=64 option to enable " ++ "SMBIOS 3.0 support"); ++ return; + } + + SMBIOS_BUILD_TABLE_POST; +@@ -1126,7 +1133,10 @@ static bool smbios_get_tables_ep(MachineState *ms, + assert(ms->smp.sockets >= 1); + + for (i = 0; i < ms->smp.sockets; i++) { +- smbios_build_type_4_table(ms, i, ep_type); ++ smbios_build_type_4_table(ms, i, ep_type, errp); ++ if (*errp) { ++ goto err_exit; ++ } + } + + smbios_build_type_8_table(); +-- +2.39.3 + diff --git a/kvm-smbios-extend-smbios-entry-point-type-with-auto-valu.patch b/kvm-smbios-extend-smbios-entry-point-type-with-auto-valu.patch new file mode 100644 index 0000000..db012bd --- /dev/null +++ b/kvm-smbios-extend-smbios-entry-point-type-with-auto-valu.patch @@ -0,0 +1,48 @@ +From c083959c963fde33f4769fd4c6e122dd16ce6d3c Mon Sep 17 00:00:00 2001 +From: Igor Mammedov +Date: Wed, 21 Feb 2024 16:04:36 +0100 +Subject: [PATCH 17/20] smbios: extend smbios-entry-point-type with 'auto' + value + +RH-Author: Igor Mammedov +RH-MergeRequest: 230: Workaround Windows failing to find 64bit SMBIOS entry point with SeaBIOS +RH-Jira: RHEL-21705 +RH-Acked-by: MST +RH-Acked-by: Ani Sinha +RH-Commit: [15/18] 202563dcf77e062a238aa2a10ec14c25d3f5a7d0 + +JIRA: https://issues.redhat.com/browse/RHEL-21705 + +later patches will use it to pick SMBIOS version at runtime +depending on configuration. + +Signed-off-by: Igor Mammedov +Acked-by: Markus Armbruster +Reviewed-by: Ani Sinha +Tested-by: Fiona Ebner +--- + qapi/machine.json | 5 ++++- + 1 file changed, 4 insertions(+), 1 deletion(-) + +diff --git a/qapi/machine.json b/qapi/machine.json +index b6d634b30d..99f6368fa6 100644 +--- a/qapi/machine.json ++++ b/qapi/machine.json +@@ -1788,10 +1788,13 @@ + # + # @64: SMBIOS version 3.0 (64-bit) Entry Point + # ++# @auto: Either 2.x or 3.x SMBIOS version, 2.x if configuration can be ++# described by it and 3.x otherwise (since: 9.0) ++# + # Since: 7.0 + ## + { 'enum': 'SmbiosEntryPointType', +- 'data': [ '32', '64' ] } ++ 'data': [ '32', '64', 'auto' ] } + + ## + # @MemorySizeConfiguration: +-- +2.39.3 + diff --git a/kvm-smbios-get-rid-of-global-smbios_ep_type.patch b/kvm-smbios-get-rid-of-global-smbios_ep_type.patch new file mode 100644 index 0000000..1896f2b --- /dev/null +++ b/kvm-smbios-get-rid-of-global-smbios_ep_type.patch @@ -0,0 +1,281 @@ +From be0abbf3f7845847b46486704c46c5de5a2b2323 Mon Sep 17 00:00:00 2001 +From: Igor Mammedov +Date: Mon, 26 Feb 2024 13:49:14 +0100 +Subject: [PATCH 15/20] smbios: get rid of global smbios_ep_type + +RH-Author: Igor Mammedov +RH-MergeRequest: 230: Workaround Windows failing to find 64bit SMBIOS entry point with SeaBIOS +RH-Jira: RHEL-21705 +RH-Acked-by: MST +RH-Acked-by: Ani Sinha +RH-Commit: [13/18] 2e838ed0d03989e2e4ee08041b5ba64d5d7f5820 + +JIRA: https://issues.redhat.com/browse/RHEL-21705 + +Conflicts: hw/arm/virt.c, hw/i386/fw_cfg.c, hw/riscv/virt.c, hw/smbios/smbios.c, + include/hw/firmware/smbios.h + due to downstream specific smbios_set_defaults() + +Signed-off-by: Igor Mammedov +Acked-by: Daniel Henrique Barboza +Reviewed-by: Ani Sinha +Tested-by: Fiona Ebner +Signed-off-by: Igor Mammedov +--- + hw/arm/virt.c | 4 ++-- + hw/i386/fw_cfg.c | 6 +++--- + hw/i386/fw_cfg.h | 3 ++- + hw/i386/pc.c | 2 +- + hw/loongarch/virt.c | 7 ++++--- + hw/smbios/smbios.c | 26 ++++++++++++++------------ + hw/smbios/smbios_legacy.c | 2 +- + include/hw/firmware/smbios.h | 4 ++-- + 8 files changed, 29 insertions(+), 25 deletions(-) + +diff --git a/hw/arm/virt.c b/hw/arm/virt.c +index e5cfc19c08..e4a66affcb 100644 +--- a/hw/arm/virt.c ++++ b/hw/arm/virt.c +@@ -1695,14 +1695,14 @@ static void virt_build_smbios(VirtMachineState *vms) + + smbios_set_defaults("QEMU", product, + vmc->smbios_old_sys_ver ? "1.0" : mc->name, +- true, SMBIOS_ENTRY_POINT_TYPE_64, ++ true, + NULL, NULL); + + /* build the array of physical mem area from base_memmap */ + mem_array.address = vms->memmap[VIRT_MEM].base; + mem_array.length = ms->ram_size; + +- smbios_get_tables(ms, &mem_array, 1, ++ smbios_get_tables(ms, SMBIOS_ENTRY_POINT_TYPE_64, &mem_array, 1, + &smbios_tables, &smbios_tables_len, + &smbios_anchor, &smbios_anchor_len, + &error_fatal); +diff --git a/hw/i386/fw_cfg.c b/hw/i386/fw_cfg.c +index bdc3cc4556..58429bb78d 100644 +--- a/hw/i386/fw_cfg.c ++++ b/hw/i386/fw_cfg.c +@@ -48,7 +48,8 @@ const char *fw_cfg_arch_key_name(uint16_t key) + return NULL; + } + +-void fw_cfg_build_smbios(PCMachineState *pcms, FWCfgState *fw_cfg) ++void fw_cfg_build_smbios(PCMachineState *pcms, FWCfgState *fw_cfg, ++ SmbiosEntryPointType ep_type) + { + #ifdef CONFIG_SMBIOS + uint8_t *smbios_tables, *smbios_anchor; +@@ -64,7 +65,6 @@ void fw_cfg_build_smbios(PCMachineState *pcms, FWCfgState *fw_cfg) + /* These values are guest ABI, do not change */ + smbios_set_defaults("QEMU", mc->desc, mc->name, + pcmc->smbios_uuid_encoded, +- pcms->smbios_entry_point_type, + pcmc->smbios_stream_product, + pcmc->smbios_stream_version); + } +@@ -91,7 +91,7 @@ void fw_cfg_build_smbios(PCMachineState *pcms, FWCfgState *fw_cfg) + array_count++; + } + } +- smbios_get_tables(ms, mem_array, array_count, ++ smbios_get_tables(ms, ep_type, mem_array, array_count, + &smbios_tables, &smbios_tables_len, + &smbios_anchor, &smbios_anchor_len, + &error_fatal); +diff --git a/hw/i386/fw_cfg.h b/hw/i386/fw_cfg.h +index 1e1de6b4a3..92e310f5fd 100644 +--- a/hw/i386/fw_cfg.h ++++ b/hw/i386/fw_cfg.h +@@ -23,7 +23,8 @@ + FWCfgState *fw_cfg_arch_create(MachineState *ms, + uint16_t boot_cpus, + uint16_t apic_id_limit); +-void fw_cfg_build_smbios(PCMachineState *ms, FWCfgState *fw_cfg); ++void fw_cfg_build_smbios(PCMachineState *pcms, FWCfgState *fw_cfg, ++ SmbiosEntryPointType ep_type); + void fw_cfg_build_feature_control(MachineState *ms, FWCfgState *fw_cfg); + void fw_cfg_add_acpi_dsdt(Aml *scope, FWCfgState *fw_cfg); + +diff --git a/hw/i386/pc.c b/hw/i386/pc.c +index 16de2a59e8..ae6777fc1a 100644 +--- a/hw/i386/pc.c ++++ b/hw/i386/pc.c +@@ -847,7 +847,7 @@ void pc_machine_done(Notifier *notifier, void *data) + + acpi_setup(); + if (x86ms->fw_cfg) { +- fw_cfg_build_smbios(pcms, x86ms->fw_cfg); ++ fw_cfg_build_smbios(pcms, x86ms->fw_cfg, pcms->smbios_entry_point_type); + fw_cfg_build_feature_control(MACHINE(pcms), x86ms->fw_cfg); + /* update FW_CFG_NB_CPUS to account for -device added CPUs */ + fw_cfg_modify_i16(x86ms->fw_cfg, FW_CFG_NB_CPUS, x86ms->boot_cpus); +diff --git a/hw/loongarch/virt.c b/hw/loongarch/virt.c +index 7358a023d3..77956b5ada 100644 +--- a/hw/loongarch/virt.c ++++ b/hw/loongarch/virt.c +@@ -320,10 +320,11 @@ static void virt_build_smbios(LoongArchMachineState *lams) + return; + } + +- smbios_set_defaults("QEMU", product, mc->name, +- true, SMBIOS_ENTRY_POINT_TYPE_64); ++ smbios_set_defaults("QEMU", product, mc->name, true); + +- smbios_get_tables(ms, NULL, 0, &smbios_tables, &smbios_tables_len, ++ smbios_get_tables(ms, SMBIOS_ENTRY_POINT_TYPE_64, ++ NULL, 0, ++ &smbios_tables, &smbios_tables_len, + &smbios_anchor, &smbios_anchor_len, &error_fatal); + + if (smbios_anchor) { +diff --git a/hw/smbios/smbios.c b/hw/smbios/smbios.c +index b5745c6c2d..7e32430b85 100644 +--- a/hw/smbios/smbios.c ++++ b/hw/smbios/smbios.c +@@ -47,7 +47,6 @@ uint8_t *smbios_tables; + size_t smbios_tables_len; + unsigned smbios_table_max; + unsigned smbios_table_cnt; +-static SmbiosEntryPointType smbios_ep_type = SMBIOS_ENTRY_POINT_TYPE_32; + + static SmbiosEntryPoint ep; + +@@ -506,9 +505,9 @@ static bool smbios_check_type4_count(uint32_t expected_t4_count, Error **errp) + return true; + } + +-bool smbios_validate_table(Error **errp) ++bool smbios_validate_table(SmbiosEntryPointType ep_type, Error **errp) + { +- if (smbios_ep_type == SMBIOS_ENTRY_POINT_TYPE_32 && ++ if (ep_type == SMBIOS_ENTRY_POINT_TYPE_32 && + smbios_tables_len > SMBIOS_21_MAX_TABLES_LEN) { + error_setg(errp, "SMBIOS 2.1 table length %zu exceeds %d", + smbios_tables_len, SMBIOS_21_MAX_TABLES_LEN); +@@ -655,14 +654,15 @@ static void smbios_build_type_3_table(void) + SMBIOS_BUILD_TABLE_POST; + } + +-static void smbios_build_type_4_table(MachineState *ms, unsigned instance) ++static void smbios_build_type_4_table(MachineState *ms, unsigned instance, ++ SmbiosEntryPointType ep_type) + { + char sock_str[128]; + size_t tbl_len = SMBIOS_TYPE_4_LEN_V28; + unsigned threads_per_socket; + unsigned cores_per_socket; + +- if (smbios_ep_type == SMBIOS_ENTRY_POINT_TYPE_64) { ++ if (ep_type == SMBIOS_ENTRY_POINT_TYPE_64) { + tbl_len = SMBIOS_TYPE_4_LEN_V30; + } + +@@ -991,13 +991,11 @@ void smbios_set_cpuid(uint32_t version, uint32_t features) + void smbios_set_defaults(const char *manufacturer, const char *product, + const char *version, + bool uuid_encoded, +- SmbiosEntryPointType ep_type, + const char *stream_product, + const char *stream_version) + { + smbios_have_defaults = true; + smbios_uuid_encoded = uuid_encoded; +- smbios_ep_type = ep_type; + + /* + * If @stream_product & @stream_version are non-NULL, then +@@ -1048,9 +1046,9 @@ void smbios_set_defaults(const char *manufacturer, const char *product, + SMBIOS_SET_DEFAULT(type17.manufacturer, manufacturer); + } + +-static void smbios_entry_point_setup(void) ++static void smbios_entry_point_setup(SmbiosEntryPointType ep_type) + { +- switch (smbios_ep_type) { ++ switch (ep_type) { + case SMBIOS_ENTRY_POINT_TYPE_32: + memcpy(ep.ep21.anchor_string, "_SM_", 4); + memcpy(ep.ep21.intermediate_anchor_string, "_DMI_", 5); +@@ -1100,6 +1098,7 @@ static void smbios_entry_point_setup(void) + } + + void smbios_get_tables(MachineState *ms, ++ SmbiosEntryPointType ep_type, + const struct smbios_phys_mem_area *mem_array, + const unsigned int mem_array_size, + uint8_t **tables, size_t *tables_len, +@@ -1108,6 +1107,9 @@ void smbios_get_tables(MachineState *ms, + { + unsigned i, dimm_cnt, offset; + ++ assert(ep_type == SMBIOS_ENTRY_POINT_TYPE_32 || ++ ep_type == SMBIOS_ENTRY_POINT_TYPE_64); ++ + g_free(smbios_tables); + smbios_tables = g_memdup2(usr_blobs, usr_blobs_len); + smbios_tables_len = usr_blobs_len; +@@ -1122,7 +1124,7 @@ void smbios_get_tables(MachineState *ms, + assert(ms->smp.sockets >= 1); + + for (i = 0; i < ms->smp.sockets; i++) { +- smbios_build_type_4_table(ms, i); ++ smbios_build_type_4_table(ms, i, ep_type); + } + + smbios_build_type_8_table(); +@@ -1171,10 +1173,10 @@ void smbios_get_tables(MachineState *ms, + if (!smbios_check_type4_count(ms->smp.sockets, errp)) { + goto err_exit; + } +- if (!smbios_validate_table(errp)) { ++ if (!smbios_validate_table(ep_type, errp)) { + goto err_exit; + } +- smbios_entry_point_setup(); ++ smbios_entry_point_setup(ep_type); + + /* return tables blob and entry point (anchor), and their sizes */ + *tables = smbios_tables; +diff --git a/hw/smbios/smbios_legacy.c b/hw/smbios/smbios_legacy.c +index a6544bf55a..06907cd16c 100644 +--- a/hw/smbios/smbios_legacy.c ++++ b/hw/smbios/smbios_legacy.c +@@ -173,7 +173,7 @@ uint8_t *smbios_get_table_legacy(size_t *length, Error **errp) + + smbios_build_type_0_fields(); + smbios_build_type_1_fields(); +- if (!smbios_validate_table(errp)) { ++ if (!smbios_validate_table(SMBIOS_ENTRY_POINT_TYPE_32, errp)) { + goto err_exit; + } + +diff --git a/include/hw/firmware/smbios.h b/include/hw/firmware/smbios.h +index 44af3a0d82..781298f594 100644 +--- a/include/hw/firmware/smbios.h ++++ b/include/hw/firmware/smbios.h +@@ -326,18 +326,18 @@ struct smbios_type_127 { + struct smbios_structure_header header; + } QEMU_PACKED; + +-bool smbios_validate_table(Error **errp); ++bool smbios_validate_table(SmbiosEntryPointType ep_type, Error **errp); + void smbios_add_usr_blob_size(size_t size); + void smbios_entry_add(QemuOpts *opts, Error **errp); + void smbios_set_cpuid(uint32_t version, uint32_t features); + void smbios_set_defaults(const char *manufacturer, const char *product, + const char *version, + bool uuid_encoded, +- SmbiosEntryPointType ep_type, + const char *stream_product, + const char *stream_version); + uint8_t *smbios_get_table_legacy(size_t *length, Error **errp); + void smbios_get_tables(MachineState *ms, ++ SmbiosEntryPointType ep_type, + const struct smbios_phys_mem_area *mem_array, + const unsigned int mem_array_size, + uint8_t **tables, size_t *tables_len, +-- +2.39.3 + diff --git a/kvm-smbios-get-rid-of-smbios_legacy-global.patch b/kvm-smbios-get-rid-of-smbios_legacy-global.patch new file mode 100644 index 0000000..ecb730e --- /dev/null +++ b/kvm-smbios-get-rid-of-smbios_legacy-global.patch @@ -0,0 +1,198 @@ +From 0802fa7199c8085d018fc38dd4beaa5062d383d1 Mon Sep 17 00:00:00 2001 +From: Igor Mammedov +Date: Fri, 29 Dec 2023 15:37:29 +0100 +Subject: [PATCH 08/20] smbios: get rid of smbios_legacy global + +RH-Author: Igor Mammedov +RH-MergeRequest: 230: Workaround Windows failing to find 64bit SMBIOS entry point with SeaBIOS +RH-Jira: RHEL-21705 +RH-Acked-by: MST +RH-Acked-by: Ani Sinha +RH-Commit: [6/18] 684dd1dca8d611c6de97b26ef8c1cda6ca509d54 + +JIRA: https://issues.redhat.com/browse/RHEL-21705 + + clean up smbios_set_defaults() which is reused by legacy + and non legacy machines from being aware of 'legacy' notion + and need to turn it off. And push legacy handling up to + PC machine code where it's relevant. + + Signed-off-by: Igor Mammedov + Reviewed-by: Ani Sinha + Acked-by: Daniel Henrique Barboza + Tested-by: Fiona Ebner + +Conflicts: hw/arm/virt.c, hw/i386/fw_cfg.c, hw/loongarch/virt.c, + hw/smbios/smbios.c, include/hw/firmware/smbios.h + due to downstream specifc signature of smbios_set_defaults() +PS: + while fixing conflicts move RHEL specific + smbios_stream_product/smbios_stream_version + at the end of arguments list + +Signed-off-by: Igor Mammedov +--- + hw/arm/virt.c | 5 +++-- + hw/i386/fw_cfg.c | 11 +++++----- + hw/loongarch/virt.c | 2 +- + hw/smbios/smbios.c | 39 ++++++++++++++++-------------------- + include/hw/firmware/smbios.h | 6 +++--- + 5 files changed, 30 insertions(+), 33 deletions(-) + +diff --git a/hw/arm/virt.c b/hw/arm/virt.c +index 943c563391..e5cfc19c08 100644 +--- a/hw/arm/virt.c ++++ b/hw/arm/virt.c +@@ -1694,8 +1694,9 @@ static void virt_build_smbios(VirtMachineState *vms) + } + + smbios_set_defaults("QEMU", product, +- vmc->smbios_old_sys_ver ? "1.0" : mc->name, false, +- true, NULL, NULL, SMBIOS_ENTRY_POINT_TYPE_64); ++ vmc->smbios_old_sys_ver ? "1.0" : mc->name, ++ true, SMBIOS_ENTRY_POINT_TYPE_64, ++ NULL, NULL); + + /* build the array of physical mem area from base_memmap */ + mem_array.address = vms->memmap[VIRT_MEM].base; +diff --git a/hw/i386/fw_cfg.c b/hw/i386/fw_cfg.c +index 79ff7f7225..bb7149c4c3 100644 +--- a/hw/i386/fw_cfg.c ++++ b/hw/i386/fw_cfg.c +@@ -63,17 +63,18 @@ void fw_cfg_build_smbios(PCMachineState *pcms, FWCfgState *fw_cfg) + if (pcmc->smbios_defaults) { + /* These values are guest ABI, do not change */ + smbios_set_defaults("QEMU", mc->desc, mc->name, +- pcmc->smbios_legacy_mode, pcmc->smbios_uuid_encoded, ++ pcmc->smbios_uuid_encoded, ++ pcms->smbios_entry_point_type, + pcmc->smbios_stream_product, +- pcmc->smbios_stream_version, +- pcms->smbios_entry_point_type); ++ pcmc->smbios_stream_version); + } + + /* tell smbios about cpuid version and features */ + smbios_set_cpuid(cpu->env.cpuid_version, cpu->env.features[FEAT_1_EDX]); + +- smbios_tables = smbios_get_table_legacy(ms->smp.cpus, &smbios_tables_len); +- if (smbios_tables) { ++ if (pcmc->smbios_legacy_mode) { ++ smbios_tables = smbios_get_table_legacy(ms->smp.cpus, ++ &smbios_tables_len); + fw_cfg_add_bytes(fw_cfg, FW_CFG_SMBIOS_ENTRIES, + smbios_tables, smbios_tables_len); + return; +diff --git a/hw/loongarch/virt.c b/hw/loongarch/virt.c +index 4b7dc67a2d..7358a023d3 100644 +--- a/hw/loongarch/virt.c ++++ b/hw/loongarch/virt.c +@@ -320,7 +320,7 @@ static void virt_build_smbios(LoongArchMachineState *lams) + return; + } + +- smbios_set_defaults("QEMU", product, mc->name, false, ++ smbios_set_defaults("QEMU", product, mc->name, + true, SMBIOS_ENTRY_POINT_TYPE_64); + + smbios_get_tables(ms, NULL, 0, &smbios_tables, &smbios_tables_len, +diff --git a/hw/smbios/smbios.c b/hw/smbios/smbios.c +index 8129d396d1..0c8c439859 100644 +--- a/hw/smbios/smbios.c ++++ b/hw/smbios/smbios.c +@@ -54,7 +54,6 @@ struct smbios_table { + + 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 */ + +@@ -618,9 +617,16 @@ static void smbios_build_type_1_fields(void) + + uint8_t *smbios_get_table_legacy(uint32_t expected_t4_count, size_t *length) + { +- if (!smbios_legacy) { +- *length = 0; +- return NULL; ++ /* drop unwanted version of command-line file blob(s) */ ++ g_free(smbios_tables); ++ smbios_tables = NULL; ++ ++ /* 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); + } + + if (!smbios_immutable) { +@@ -1107,31 +1113,16 @@ void smbios_set_cpuid(uint32_t version, uint32_t features) + } + + void smbios_set_defaults(const char *manufacturer, const char *product, +- const char *version, bool legacy_mode, ++ const char *version, + bool uuid_encoded, ++ SmbiosEntryPointType ep_type, + const char *stream_product, +- const char *stream_version, +- SmbiosEntryPointType ep_type) ++ const char *stream_version) + { + smbios_have_defaults = true; +- smbios_legacy = legacy_mode; + smbios_uuid_encoded = uuid_encoded; + smbios_ep_type = ep_type; + +- /* 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); +- } +- + /* + * If @stream_product & @stream_version are non-NULL, then + * we're following rules for new Windows driver support. +@@ -1241,6 +1232,10 @@ void smbios_get_tables(MachineState *ms, + { + unsigned i, dimm_cnt, offset; + ++ /* drop unwanted (legacy) version of command-line file blob(s) */ ++ g_free(smbios_entries); ++ smbios_entries = NULL; ++ + if (!smbios_immutable) { + smbios_build_type_0_table(); + smbios_build_type_1_table(); +diff --git a/include/hw/firmware/smbios.h b/include/hw/firmware/smbios.h +index 95ec64ce2c..b9fc9a0f42 100644 +--- a/include/hw/firmware/smbios.h ++++ b/include/hw/firmware/smbios.h +@@ -310,11 +310,11 @@ struct smbios_type_127 { + void smbios_entry_add(QemuOpts *opts, Error **errp); + void smbios_set_cpuid(uint32_t version, uint32_t features); + void smbios_set_defaults(const char *manufacturer, const char *product, +- const char *version, bool legacy_mode, ++ const char *version, + bool uuid_encoded, ++ SmbiosEntryPointType ep_type, + const char *stream_product, +- const char *stream_version, +- SmbiosEntryPointType ep_type); ++ const char *stream_version); + uint8_t *smbios_get_table_legacy(uint32_t expected_t4_count, size_t *length); + void smbios_get_tables(MachineState *ms, + const struct smbios_phys_mem_area *mem_array, +-- +2.39.3 + diff --git a/kvm-smbios-get-rid-of-smbios_smp_sockets-global.patch b/kvm-smbios-get-rid-of-smbios_smp_sockets-global.patch new file mode 100644 index 0000000..fde17ac --- /dev/null +++ b/kvm-smbios-get-rid-of-smbios_smp_sockets-global.patch @@ -0,0 +1,134 @@ +From 1536f1ec00ddc1729854b381cc0d54814bb6c19f Mon Sep 17 00:00:00 2001 +From: Igor Mammedov +Date: Fri, 29 Dec 2023 15:04:55 +0100 +Subject: [PATCH 07/20] smbios: get rid of smbios_smp_sockets global + +RH-Author: Igor Mammedov +RH-MergeRequest: 230: Workaround Windows failing to find 64bit SMBIOS entry point with SeaBIOS +RH-Jira: RHEL-21705 +RH-Acked-by: MST +RH-Acked-by: Ani Sinha +RH-Commit: [5/18] f59bfeb547b7febcf1de2b6179af006e7fa0bccd + +JIRA: https://issues.redhat.com/browse/RHEL-21705 + + it makes smbios_validate_table() independent from + smbios_smp_sockets global, which in turn lets + smbios_get_tables() avoid using not related legacy code. + + Signed-off-by: Igor Mammedov + Reviewed-by: Ani Sinha + Tested-by: Fiona Ebner + +Conflicts: + include/hw/firmware/smbios.h due to down-stream + (d9ff466c980d Machine type related general changes) + adding custom stream_product/stream_version + +Signed-off-by: Igor Mammedov +--- + hw/i386/fw_cfg.c | 2 +- + hw/smbios/smbios.c | 22 +++++++++------------- + include/hw/firmware/smbios.h | 2 +- + 3 files changed, 11 insertions(+), 15 deletions(-) + +diff --git a/hw/i386/fw_cfg.c b/hw/i386/fw_cfg.c +index ed72b1442d..79ff7f7225 100644 +--- a/hw/i386/fw_cfg.c ++++ b/hw/i386/fw_cfg.c +@@ -72,7 +72,7 @@ void fw_cfg_build_smbios(PCMachineState *pcms, FWCfgState *fw_cfg) + /* tell smbios about cpuid version and features */ + smbios_set_cpuid(cpu->env.cpuid_version, cpu->env.features[FEAT_1_EDX]); + +- smbios_tables = smbios_get_table_legacy(ms, &smbios_tables_len); ++ smbios_tables = smbios_get_table_legacy(ms->smp.cpus, &smbios_tables_len); + if (smbios_tables) { + fw_cfg_add_bytes(fw_cfg, FW_CFG_SMBIOS_ENTRIES, + smbios_tables, smbios_tables_len); +diff --git a/hw/smbios/smbios.c b/hw/smbios/smbios.c +index b13e40bae2..8129d396d1 100644 +--- a/hw/smbios/smbios.c ++++ b/hw/smbios/smbios.c +@@ -73,7 +73,7 @@ static SmbiosEntryPoint 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 uint32_t smbios_cpuid_version, smbios_cpuid_features; + + static DECLARE_BITMAP(have_binfile_bitmap, SMBIOS_MAX_TYPE+1); + static DECLARE_BITMAP(have_fields_bitmap, SMBIOS_MAX_TYPE+1); +@@ -524,14 +524,11 @@ opts_init(smbios_register_config); + */ + #define SMBIOS_21_MAX_TABLES_LEN 0xffff + +-static void smbios_validate_table(MachineState *ms) ++static void smbios_validate_table(uint32_t expected_t4_count) + { +- uint32_t expect_t4_count = smbios_legacy ? +- ms->smp.cpus : smbios_smp_sockets; +- +- if (smbios_type4_count && smbios_type4_count != expect_t4_count) { ++ if (smbios_type4_count && smbios_type4_count != expected_t4_count) { + error_report("Expected %d SMBIOS Type 4 tables, got %d instead", +- expect_t4_count, smbios_type4_count); ++ expected_t4_count, smbios_type4_count); + exit(1); + } + +@@ -619,7 +616,7 @@ static void smbios_build_type_1_fields(void) + } + } + +-uint8_t *smbios_get_table_legacy(MachineState *ms, size_t *length) ++uint8_t *smbios_get_table_legacy(uint32_t expected_t4_count, size_t *length) + { + if (!smbios_legacy) { + *length = 0; +@@ -629,7 +626,7 @@ uint8_t *smbios_get_table_legacy(MachineState *ms, size_t *length) + if (!smbios_immutable) { + smbios_build_type_0_fields(); + smbios_build_type_1_fields(); +- smbios_validate_table(ms); ++ smbios_validate_table(expected_t4_count); + smbios_immutable = true; + } + *length = smbios_entries_len; +@@ -1250,10 +1247,9 @@ void smbios_get_tables(MachineState *ms, + smbios_build_type_2_table(); + smbios_build_type_3_table(); + +- smbios_smp_sockets = ms->smp.sockets; +- assert(smbios_smp_sockets >= 1); ++ assert(ms->smp.sockets >= 1); + +- for (i = 0; i < smbios_smp_sockets; i++) { ++ for (i = 0; i < ms->smp.sockets; i++) { + smbios_build_type_4_table(ms, i); + } + +@@ -1299,7 +1295,7 @@ void smbios_get_tables(MachineState *ms, + smbios_build_type_41_table(errp); + smbios_build_type_127_table(); + +- smbios_validate_table(ms); ++ smbios_validate_table(ms->smp.sockets); + smbios_entry_point_setup(); + smbios_immutable = true; + } +diff --git a/include/hw/firmware/smbios.h b/include/hw/firmware/smbios.h +index f8dd07fe4c..95ec64ce2c 100644 +--- a/include/hw/firmware/smbios.h ++++ b/include/hw/firmware/smbios.h +@@ -315,7 +315,7 @@ void smbios_set_defaults(const char *manufacturer, const char *product, + const char *stream_product, + const char *stream_version, + SmbiosEntryPointType ep_type); +-uint8_t *smbios_get_table_legacy(MachineState *ms, size_t *length); ++uint8_t *smbios_get_table_legacy(uint32_t expected_t4_count, size_t *length); + void smbios_get_tables(MachineState *ms, + const struct smbios_phys_mem_area *mem_array, + const unsigned int mem_array_size, +-- +2.39.3 + diff --git a/kvm-smbios-handle-errors-consistently.patch b/kvm-smbios-handle-errors-consistently.patch new file mode 100644 index 0000000..ac75c76 --- /dev/null +++ b/kvm-smbios-handle-errors-consistently.patch @@ -0,0 +1,217 @@ +From 7271c4424c6d90f0bb34f8090eb4e192eb2b2537 Mon Sep 17 00:00:00 2001 +From: Igor Mammedov +Date: Tue, 20 Feb 2024 10:30:28 +0100 +Subject: [PATCH 14/20] smbios: handle errors consistently + +RH-Author: Igor Mammedov +RH-MergeRequest: 230: Workaround Windows failing to find 64bit SMBIOS entry point with SeaBIOS +RH-Jira: RHEL-21705 +RH-Acked-by: MST +RH-Acked-by: Ani Sinha +RH-Commit: [12/18] d8a5a70602ae0665ce35e5bf87b2d8420f9189bc + +JIRA: https://issues.redhat.com/browse/RHEL-21705 + + Current code uses mix of error_report()+exit(1) + and error_setg() to handle errors. + Use newer error_setg() everywhere, beside consistency + it will allow to detect error condition without killing + QEMU and attempt switch-over to SMBIOS3.x tables/entrypoint + in follow up patch. + + while at it, clear smbios_tables pointer after freeing. + that will avoid double free if smbios_get_tables() is called + multiple times. + + Signed-off-by: Igor Mammedov + Reviewed-by: Ani Sinha + +Conflicts: include/hw/firmware/smbios.h + due to downstream specific smbios_set_defaults() + +Signed-off-by: Igor Mammedov +--- + hw/i386/fw_cfg.c | 3 ++- + hw/smbios/smbios.c | 34 ++++++++++++++++++++++------------ + hw/smbios/smbios_legacy.c | 22 ++++++++++++++-------- + include/hw/firmware/smbios.h | 4 ++-- + 4 files changed, 40 insertions(+), 23 deletions(-) + +diff --git a/hw/i386/fw_cfg.c b/hw/i386/fw_cfg.c +index a25793a68f..bdc3cc4556 100644 +--- a/hw/i386/fw_cfg.c ++++ b/hw/i386/fw_cfg.c +@@ -73,7 +73,8 @@ void fw_cfg_build_smbios(PCMachineState *pcms, FWCfgState *fw_cfg) + smbios_set_cpuid(cpu->env.cpuid_version, cpu->env.features[FEAT_1_EDX]); + + if (pcmc->smbios_legacy_mode) { +- smbios_tables = smbios_get_table_legacy(&smbios_tables_len); ++ smbios_tables = smbios_get_table_legacy(&smbios_tables_len, ++ &error_fatal); + fw_cfg_add_bytes(fw_cfg, FW_CFG_SMBIOS_ENTRIES, + smbios_tables, smbios_tables_len); + return; +diff --git a/hw/smbios/smbios.c b/hw/smbios/smbios.c +index e40204550e..b5745c6c2d 100644 +--- a/hw/smbios/smbios.c ++++ b/hw/smbios/smbios.c +@@ -19,7 +19,6 @@ + #include "qemu/units.h" + #include "qapi/error.h" + #include "qemu/config-file.h" +-#include "qemu/error-report.h" + #include "qemu/module.h" + #include "qemu/option.h" + #include "sysemu/sysemu.h" +@@ -497,23 +496,25 @@ opts_init(smbios_register_config); + */ + #define SMBIOS_21_MAX_TABLES_LEN 0xffff + +-static void smbios_check_type4_count(uint32_t expected_t4_count) ++static bool smbios_check_type4_count(uint32_t expected_t4_count, Error **errp) + { + if (smbios_type4_count && smbios_type4_count != expected_t4_count) { +- error_report("Expected %d SMBIOS Type 4 tables, got %d instead", +- expected_t4_count, smbios_type4_count); +- exit(1); ++ error_setg(errp, "Expected %d SMBIOS Type 4 tables, got %d instead", ++ expected_t4_count, smbios_type4_count); ++ return false; + } ++ return true; + } + +-void smbios_validate_table(void) ++bool smbios_validate_table(Error **errp) + { + if (smbios_ep_type == SMBIOS_ENTRY_POINT_TYPE_32 && + smbios_tables_len > SMBIOS_21_MAX_TABLES_LEN) { +- error_report("SMBIOS 2.1 table length %zu exceeds %d", +- smbios_tables_len, SMBIOS_21_MAX_TABLES_LEN); +- exit(1); ++ error_setg(errp, "SMBIOS 2.1 table length %zu exceeds %d", ++ smbios_tables_len, SMBIOS_21_MAX_TABLES_LEN); ++ return false; + } ++ return true; + } + + bool smbios_skip_table(uint8_t type, bool required_table) +@@ -1167,15 +1168,18 @@ void smbios_get_tables(MachineState *ms, + smbios_build_type_41_table(errp); + smbios_build_type_127_table(); + +- smbios_check_type4_count(ms->smp.sockets); +- smbios_validate_table(); ++ if (!smbios_check_type4_count(ms->smp.sockets, errp)) { ++ goto err_exit; ++ } ++ if (!smbios_validate_table(errp)) { ++ goto err_exit; ++ } + smbios_entry_point_setup(); + + /* return tables blob and entry point (anchor), and their sizes */ + *tables = smbios_tables; + *tables_len = smbios_tables_len; + *anchor = (uint8_t *)&ep; +- + /* calculate length based on anchor string */ + if (!strncmp((char *)&ep, "_SM_", 4)) { + *anchor_len = sizeof(struct smbios_21_entry_point); +@@ -1184,6 +1188,12 @@ void smbios_get_tables(MachineState *ms, + } else { + abort(); + } ++ ++ return; ++err_exit: ++ g_free(smbios_tables); ++ smbios_tables = NULL; ++ return; + } + + static void save_opt(const char **dest, QemuOpts *opts, const char *name) +diff --git a/hw/smbios/smbios_legacy.c b/hw/smbios/smbios_legacy.c +index 21f143e738..a6544bf55a 100644 +--- a/hw/smbios/smbios_legacy.c ++++ b/hw/smbios/smbios_legacy.c +@@ -19,7 +19,7 @@ + #include "qemu/bswap.h" + #include "hw/firmware/smbios.h" + #include "sysemu/sysemu.h" +-#include "qemu/error-report.h" ++#include "qapi/error.h" + + struct smbios_header { + uint16_t length; +@@ -128,7 +128,7 @@ static void smbios_build_type_1_fields(void) + } + } + +-uint8_t *smbios_get_table_legacy(size_t *length) ++uint8_t *smbios_get_table_legacy(size_t *length, Error **errp) + { + int i; + size_t usr_offset; +@@ -136,15 +136,15 @@ uint8_t *smbios_get_table_legacy(size_t *length) + /* complain if fields were given for types > 1 */ + if (find_next_bit(smbios_have_fields_bitmap, + SMBIOS_MAX_TYPE + 1, 2) < SMBIOS_MAX_TYPE + 1) { +- error_report("can't process fields for smbios " ++ error_setg(errp, "can't process fields for smbios " + "types > 1 on machine versions < 2.1!"); +- exit(1); ++ goto err_exit; + } + + if (test_bit(4, smbios_have_binfile_bitmap)) { +- error_report("can't process table for smbios " +- "type 4 on machine versions < 2.1!"); +- exit(1); ++ error_setg(errp, "can't process table for smbios " ++ "type 4 on machine versions < 2.1!"); ++ goto err_exit; + } + + g_free(smbios_entries); +@@ -173,7 +173,13 @@ uint8_t *smbios_get_table_legacy(size_t *length) + + smbios_build_type_0_fields(); + smbios_build_type_1_fields(); +- smbios_validate_table(); ++ if (!smbios_validate_table(errp)) { ++ goto err_exit; ++ } ++ + *length = smbios_entries_len; + return smbios_entries; ++err_exit: ++ g_free(smbios_entries); ++ return NULL; + } +diff --git a/include/hw/firmware/smbios.h b/include/hw/firmware/smbios.h +index 92e9aba415..44af3a0d82 100644 +--- a/include/hw/firmware/smbios.h ++++ b/include/hw/firmware/smbios.h +@@ -326,7 +326,7 @@ struct smbios_type_127 { + struct smbios_structure_header header; + } QEMU_PACKED; + +-void smbios_validate_table(void); ++bool smbios_validate_table(Error **errp); + void smbios_add_usr_blob_size(size_t size); + void smbios_entry_add(QemuOpts *opts, Error **errp); + void smbios_set_cpuid(uint32_t version, uint32_t features); +@@ -336,7 +336,7 @@ void smbios_set_defaults(const char *manufacturer, const char *product, + SmbiosEntryPointType ep_type, + const char *stream_product, + const char *stream_version); +-uint8_t *smbios_get_table_legacy(size_t *length); ++uint8_t *smbios_get_table_legacy(size_t *length, Error **errp); + void smbios_get_tables(MachineState *ms, + const struct smbios_phys_mem_area *mem_array, + const unsigned int mem_array_size, +-- +2.39.3 + diff --git a/kvm-smbios-in-case-of-entry-point-is-auto-try-to-build-v.patch b/kvm-smbios-in-case-of-entry-point-is-auto-try-to-build-v.patch new file mode 100644 index 0000000..fd1bc19 --- /dev/null +++ b/kvm-smbios-in-case-of-entry-point-is-auto-try-to-build-v.patch @@ -0,0 +1,131 @@ +From 38220bc61bdb1614f34a53481f7604720c9e9e5a Mon Sep 17 00:00:00 2001 +From: Igor Mammedov +Date: Tue, 20 Feb 2024 10:41:06 +0100 +Subject: [PATCH 18/20] smbios: in case of entry point is 'auto' try to build + v2 tables 1st + +RH-Author: Igor Mammedov +RH-MergeRequest: 230: Workaround Windows failing to find 64bit SMBIOS entry point with SeaBIOS +RH-Jira: RHEL-21705 +RH-Acked-by: MST +RH-Acked-by: Ani Sinha +RH-Commit: [16/18] becbcb3d8dad4842e5939bb75e21f4e737a4a325 + +JIRA: https://issues.redhat.com/browse/RHEL-21705 + +QEMU for some time now uses SMBIOS 3.0 for PC/Q35 machines by +default, however Windows has a bug in locating SMBIOS 3.0 +entrypoint and fails to find tables when booted on SeaBIOS +(on UEFI SMBIOS 3.0 tables work fine since firmware hands +over tables in another way) + +Missing SMBIOS tables may lead to some issues for guest +though (worst are: possible reactiveation, inability to +get virtio drivers from 'Windows Update') + +It's unclear at this point if MS will fix the issue on their +side. So instead of it (or rather in addition) this patch +will try to workaround the issue. + +aka, use smbios-entry-point-type=auto to make QEMU try +generating conservative SMBIOS 2.0 tables and if that +fails (due to limits/requested configuration) fallback +to SMBIOS 3.0 tables. + +With this in place majority of users will use SMBIOS 2.0 +tables which work fine with (Windows + legacy BIOS). +The configurations that is not to possible to describe +with SMBIOS 2.0 will switch automatically to SMBIOS 3.0 +(which will trigger Windows bug but there is nothing +QEMU can do here, so go and aks Microsoft to real fix). + +Signed-off-by: Igor Mammedov +Reviewed-by: Ani Sinha +Tested-by: Fiona Ebner +--- + hw/smbios/smbios.c | 52 +++++++++++++++++++++++++++++++++++++++++++--- + 1 file changed, 49 insertions(+), 3 deletions(-) + +diff --git a/hw/smbios/smbios.c b/hw/smbios/smbios.c +index 4521ea386c..3d9dcb0d31 100644 +--- a/hw/smbios/smbios.c ++++ b/hw/smbios/smbios.c +@@ -1097,7 +1097,7 @@ static void smbios_entry_point_setup(SmbiosEntryPointType ep_type) + } + } + +-void smbios_get_tables(MachineState *ms, ++static bool smbios_get_tables_ep(MachineState *ms, + SmbiosEntryPointType ep_type, + const struct smbios_phys_mem_area *mem_array, + const unsigned int mem_array_size, +@@ -1106,6 +1106,7 @@ void smbios_get_tables(MachineState *ms, + Error **errp) + { + unsigned i, dimm_cnt, offset; ++ ERRP_GUARD(); + + assert(ep_type == SMBIOS_ENTRY_POINT_TYPE_32 || + ep_type == SMBIOS_ENTRY_POINT_TYPE_64); +@@ -1192,11 +1193,56 @@ void smbios_get_tables(MachineState *ms, + abort(); + } + +- return; ++ return true; + err_exit: + g_free(smbios_tables); + smbios_tables = NULL; +- return; ++ return false; ++} ++ ++void smbios_get_tables(MachineState *ms, ++ SmbiosEntryPointType ep_type, ++ const struct smbios_phys_mem_area *mem_array, ++ const unsigned int mem_array_size, ++ uint8_t **tables, size_t *tables_len, ++ uint8_t **anchor, size_t *anchor_len, ++ Error **errp) ++{ ++ Error *local_err = NULL; ++ bool is_valid; ++ ERRP_GUARD(); ++ ++ switch (ep_type) { ++ case SMBIOS_ENTRY_POINT_TYPE_AUTO: ++ case SMBIOS_ENTRY_POINT_TYPE_32: ++ is_valid = smbios_get_tables_ep(ms, SMBIOS_ENTRY_POINT_TYPE_32, ++ mem_array, mem_array_size, ++ tables, tables_len, ++ anchor, anchor_len, ++ &local_err); ++ if (is_valid || ep_type != SMBIOS_ENTRY_POINT_TYPE_AUTO) { ++ break; ++ } ++ /* ++ * fall through in case AUTO endpoint is selected and ++ * SMBIOS 2.x tables can't be generated, to try if SMBIOS 3.x ++ * tables would work ++ */ ++ case SMBIOS_ENTRY_POINT_TYPE_64: ++ error_free(local_err); ++ local_err = NULL; ++ is_valid = smbios_get_tables_ep(ms, SMBIOS_ENTRY_POINT_TYPE_64, ++ mem_array, mem_array_size, ++ tables, tables_len, ++ anchor, anchor_len, ++ &local_err); ++ break; ++ default: ++ abort(); ++ } ++ if (!is_valid) { ++ error_propagate(errp, local_err); ++ } + } + + static void save_opt(const char **dest, QemuOpts *opts, const char *name) +-- +2.39.3 + diff --git a/kvm-smbios-rename-expose-structures-bitmaps-used-by-both.patch b/kvm-smbios-rename-expose-structures-bitmaps-used-by-both.patch new file mode 100644 index 0000000..cba6134 --- /dev/null +++ b/kvm-smbios-rename-expose-structures-bitmaps-used-by-both.patch @@ -0,0 +1,330 @@ +From 36b0256e27f9d5268c5413891b4a7322819ae9db Mon Sep 17 00:00:00 2001 +From: Igor Mammedov +Date: Mon, 4 Mar 2024 15:56:19 +0100 +Subject: [PATCH 12/20] smbios: rename/expose structures/bitmaps used by both + legacy and modern code + +RH-Author: Igor Mammedov +RH-MergeRequest: 230: Workaround Windows failing to find 64bit SMBIOS entry point with SeaBIOS +RH-Jira: RHEL-21705 +RH-Acked-by: MST +RH-Acked-by: Ani Sinha +RH-Commit: [10/18] 59fe438d5b7f6e584a6bb02597e4d4724fe2cece + +JIRA: https://issues.redhat.com/browse/RHEL-21705 + + As a preparation to move legacy handling into a separate file, + add prefix 'smbios_' to type0/type1/have_binfile_bitmap/have_fields_bitmap + and expose them in smbios.h so that they can be reused in + legacy and modern code. + + Doing it as a separate patch to avoid rename cluttering follow-up + patch which will move legacy code into a separate file. + + Signed-off-by: Igor Mammedov + Reviewed-by: Ani Sinha + +Conflicts: hw/smbios/smbios.c + due to setting downstream type1.family/type1.sku defaults + +Signed-off-by: Igor Mammedov +--- + hw/smbios/smbios.c | 117 ++++++++++++++++------------------- + include/hw/firmware/smbios.h | 16 +++++ + 2 files changed, 71 insertions(+), 62 deletions(-) + +diff --git a/hw/smbios/smbios.c b/hw/smbios/smbios.c +index c48a290478..eb9927335d 100644 +--- a/hw/smbios/smbios.c ++++ b/hw/smbios/smbios.c +@@ -81,19 +81,11 @@ static int smbios_type4_count = 0; + static bool smbios_have_defaults; + static uint32_t smbios_cpuid_version, smbios_cpuid_features; + +-static DECLARE_BITMAP(have_binfile_bitmap, SMBIOS_MAX_TYPE+1); +-static DECLARE_BITMAP(have_fields_bitmap, SMBIOS_MAX_TYPE+1); ++DECLARE_BITMAP(smbios_have_binfile_bitmap, SMBIOS_MAX_TYPE + 1); ++DECLARE_BITMAP(smbios_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; ++smbios_type0_t smbios_type0; ++smbios_type1_t smbios_type1; + + static struct { + const char *manufacturer, *product, *version, *serial, *asset, *location; +@@ -584,36 +576,36 @@ static void smbios_maybe_add_str(int type, int offset, const char *data) + static void smbios_build_type_0_fields(void) + { + smbios_maybe_add_str(0, offsetof(struct smbios_type_0, vendor_str), +- type0.vendor); ++ smbios_type0.vendor); + smbios_maybe_add_str(0, offsetof(struct smbios_type_0, bios_version_str), +- type0.version); ++ smbios_type0.version); + smbios_maybe_add_str(0, offsetof(struct smbios_type_0, + bios_release_date_str), +- type0.date); +- if (type0.have_major_minor) { ++ smbios_type0.date); ++ if (smbios_type0.have_major_minor) { + smbios_add_field(0, offsetof(struct smbios_type_0, + system_bios_major_release), +- &type0.major, 1); ++ &smbios_type0.major, 1); + smbios_add_field(0, offsetof(struct smbios_type_0, + system_bios_minor_release), +- &type0.minor, 1); ++ &smbios_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_type1.manufacturer); + smbios_maybe_add_str(1, offsetof(struct smbios_type_1, product_name_str), +- type1.product); ++ smbios_type1.product); + smbios_maybe_add_str(1, offsetof(struct smbios_type_1, version_str), +- type1.version); ++ smbios_type1.version); + smbios_maybe_add_str(1, offsetof(struct smbios_type_1, serial_number_str), +- type1.serial); ++ smbios_type1.serial); + smbios_maybe_add_str(1, offsetof(struct smbios_type_1, sku_number_str), +- type1.sku); ++ smbios_type1.sku); + smbios_maybe_add_str(1, offsetof(struct smbios_type_1, family_str), +- type1.family); ++ smbios_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 +@@ -631,14 +623,14 @@ uint8_t *smbios_get_table_legacy(size_t *length) + size_t usr_offset; + + /* also complain if fields were given for types > 1 */ +- if (find_next_bit(have_fields_bitmap, ++ if (find_next_bit(smbios_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); + } + +- if (test_bit(4, have_binfile_bitmap)) { ++ if (test_bit(4, smbios_have_binfile_bitmap)) { + error_report("can't process table for smbios " + "type 4 on machine versions < 2.1!"); + exit(1); +@@ -679,10 +671,10 @@ uint8_t *smbios_get_table_legacy(size_t *length) + + bool smbios_skip_table(uint8_t type, bool required_table) + { +- if (test_bit(type, have_binfile_bitmap)) { ++ if (test_bit(type, smbios_have_binfile_bitmap)) { + return true; /* user provided their own binary blob(s) */ + } +- if (test_bit(type, have_fields_bitmap)) { ++ if (test_bit(type, smbios_have_fields_bitmap)) { + return false; /* user provided fields via command line */ + } + if (smbios_have_defaults && required_table) { +@@ -710,25 +702,25 @@ static void smbios_build_type_0_table(void) + { + SMBIOS_BUILD_TABLE_PRE(0, T0_BASE, 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); ++ SMBIOS_TABLE_SET_STR(0, vendor_str, smbios_type0.vendor); ++ SMBIOS_TABLE_SET_STR(0, bios_version_str, smbios_type0.version); + + t->bios_starting_address_segment = cpu_to_le16(0xE800); /* from SeaBIOS */ + +- SMBIOS_TABLE_SET_STR(0, bios_release_date_str, type0.date); ++ SMBIOS_TABLE_SET_STR(0, bios_release_date_str, smbios_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) { ++ if (smbios_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; ++ if (smbios_type0.have_major_minor) { ++ t->system_bios_major_release = smbios_type0.major; ++ t->system_bios_minor_release = smbios_type0.minor; + } else { + t->system_bios_major_release = 0; + t->system_bios_minor_release = 0; +@@ -758,18 +750,18 @@ static void smbios_build_type_1_table(void) + { + SMBIOS_BUILD_TABLE_PRE(1, T1_BASE, 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); ++ SMBIOS_TABLE_SET_STR(1, manufacturer_str, smbios_type1.manufacturer); ++ SMBIOS_TABLE_SET_STR(1, product_name_str, smbios_type1.product); ++ SMBIOS_TABLE_SET_STR(1, version_str, smbios_type1.version); ++ SMBIOS_TABLE_SET_STR(1, serial_number_str, smbios_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_TABLE_SET_STR(1, sku_number_str, smbios_type1.sku); ++ SMBIOS_TABLE_SET_STR(1, family_str, smbios_type1.family); + + SMBIOS_BUILD_TABLE_POST; + } +@@ -1184,12 +1176,12 @@ void smbios_set_defaults(const char *manufacturer, const char *product, + * + * We get 'System Manufacturer' and 'Baseboard Manufacturer' + */ +- SMBIOS_SET_DEFAULT(type1.manufacturer, manufacturer); +- SMBIOS_SET_DEFAULT(type1.product, product); +- SMBIOS_SET_DEFAULT(type1.version, version); +- SMBIOS_SET_DEFAULT(type1.family, "Red Hat Enterprise Linux"); ++ SMBIOS_SET_DEFAULT(smbios_type1.manufacturer, manufacturer); ++ SMBIOS_SET_DEFAULT(smbios_type1.product, product); ++ SMBIOS_SET_DEFAULT(smbios_type1.version, version); ++ SMBIOS_SET_DEFAULT(smbios_type1.family, "Red Hat Enterprise Linux"); + if (stream_version != NULL) { +- SMBIOS_SET_DEFAULT(type1.sku, stream_version); ++ SMBIOS_SET_DEFAULT(smbios_type1.sku, stream_version); + } + SMBIOS_SET_DEFAULT(type2.manufacturer, manufacturer); + if (stream_product != NULL) { +@@ -1468,13 +1460,13 @@ void smbios_entry_add(QemuOpts *opts, Error **errp) + } + + if (header->type <= SMBIOS_MAX_TYPE) { +- if (test_bit(header->type, have_fields_bitmap)) { ++ if (test_bit(header->type, smbios_have_fields_bitmap)) { + error_setg(errp, + "can't load type %d struct, fields already specified!", + header->type); + return; + } +- set_bit(header->type, have_binfile_bitmap); ++ set_bit(header->type, smbios_have_binfile_bitmap); + } + + if (header->type == 4) { +@@ -1505,41 +1497,42 @@ void smbios_entry_add(QemuOpts *opts, Error **errp) + return; + } + +- if (test_bit(type, have_binfile_bitmap)) { ++ if (test_bit(type, smbios_have_binfile_bitmap)) { + error_setg(errp, "can't add fields, binary file already loaded!"); + return; + } +- set_bit(type, have_fields_bitmap); ++ set_bit(type, smbios_have_fields_bitmap); + + switch (type) { + case 0: + if (!qemu_opts_validate(opts, qemu_smbios_type0_opts, errp)) { + return; + } +- 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); ++ save_opt(&smbios_type0.vendor, opts, "vendor"); ++ save_opt(&smbios_type0.version, opts, "version"); ++ save_opt(&smbios_type0.date, opts, "date"); ++ smbios_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) { ++ if (sscanf(val, "%hhu.%hhu", &smbios_type0.major, ++ &smbios_type0.minor) != 2) { + error_setg(errp, "Invalid release"); + return; + } +- type0.have_major_minor = true; ++ smbios_type0.have_major_minor = true; + } + return; + case 1: + if (!qemu_opts_validate(opts, qemu_smbios_type1_opts, errp)) { + return; + } +- 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"); ++ save_opt(&smbios_type1.manufacturer, opts, "manufacturer"); ++ save_opt(&smbios_type1.product, opts, "product"); ++ save_opt(&smbios_type1.version, opts, "version"); ++ save_opt(&smbios_type1.serial, opts, "serial"); ++ save_opt(&smbios_type1.sku, opts, "sku"); ++ save_opt(&smbios_type1.family, opts, "family"); + + val = qemu_opt_get(opts, "uuid"); + if (val) { +diff --git a/include/hw/firmware/smbios.h b/include/hw/firmware/smbios.h +index d55018e5e3..333de0d5fc 100644 +--- a/include/hw/firmware/smbios.h ++++ b/include/hw/firmware/smbios.h +@@ -2,6 +2,7 @@ + #define QEMU_SMBIOS_H + + #include "qapi/qapi-types-machine.h" ++#include "qemu/bitmap.h" + + /* + * SMBIOS Support +@@ -16,8 +17,23 @@ + * + */ + ++typedef struct { ++ const char *vendor, *version, *date; ++ bool have_major_minor, uefi; ++ uint8_t major, minor; ++} smbios_type0_t; ++extern smbios_type0_t smbios_type0; ++ ++typedef struct { ++ const char *manufacturer, *product, *version, *serial, *sku, *family; ++ /* uuid is in qemu_uuid */ ++} smbios_type1_t; ++extern smbios_type1_t smbios_type1; + + #define SMBIOS_MAX_TYPE 127 ++extern DECLARE_BITMAP(smbios_have_binfile_bitmap, SMBIOS_MAX_TYPE + 1); ++extern DECLARE_BITMAP(smbios_have_fields_bitmap, SMBIOS_MAX_TYPE + 1); ++ + #define offsetofend(TYPE, MEMBER) \ + (offsetof(TYPE, MEMBER) + sizeof_field(TYPE, MEMBER)) + +-- +2.39.3 + diff --git a/kvm-ui-clipboard-add-asserts-for-update-and-request.patch b/kvm-ui-clipboard-add-asserts-for-update-and-request.patch new file mode 100644 index 0000000..b51961c --- /dev/null +++ b/kvm-ui-clipboard-add-asserts-for-update-and-request.patch @@ -0,0 +1,81 @@ +From 6e4f68e9ba3fe75ca6f200f189f96bb402f0ee8e Mon Sep 17 00:00:00 2001 +From: Fiona Ebner +Date: Wed, 24 Jan 2024 11:57:49 +0100 +Subject: [PATCH 02/20] ui/clipboard: add asserts for update and request +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +RH-Author: Jon Maloy +RH-MergeRequest: 228: ui/clipboard: mark type as not available when there is no data +RH-Jira: RHEL-19629 +RH-Acked-by: Marc-André Lureau +RH-Acked-by: Gerd Hoffmann +RH-Commit: [2/2] 176b4b835fd8aa226f2fa93fd334b9384080cf21 (jmaloy/jmaloy-qemu-kvm-2) + +JIRA: https://issues.redhat.com/browse/RHEL-19629 +CVE: CVE-2023-6683 +Upstream: Merged + +ui/clipboard: add asserts for update and request + +commit 9c416582611b7495bdddb4c5456c7acb64b78938 +Author: Fiona Ebner +Date: Wed Jan 24 11:57:49 2024 +0100 + + ui/clipboard: add asserts for update and request + + Should an issue like CVE-2023-6683 ever appear again in the future, + it will be more obvious which assumption was violated. + + Suggested-by: Marc-André Lureau + Signed-off-by: Fiona Ebner + Reviewed-by: Marc-André Lureau + Message-ID: <20240124105749.204610-2-f.ebner@proxmox.com> + +Signed-off-by: Jon Maloy +--- + ui/clipboard.c | 14 ++++++++++++++ + 1 file changed, 14 insertions(+) + +diff --git a/ui/clipboard.c b/ui/clipboard.c +index b3f6fa3c9e..4264884a6c 100644 +--- a/ui/clipboard.c ++++ b/ui/clipboard.c +@@ -65,12 +65,24 @@ bool qemu_clipboard_check_serial(QemuClipboardInfo *info, bool client) + + void qemu_clipboard_update(QemuClipboardInfo *info) + { ++ uint32_t type; + QemuClipboardNotify notify = { + .type = QEMU_CLIPBOARD_UPDATE_INFO, + .info = info, + }; + assert(info->selection < QEMU_CLIPBOARD_SELECTION__COUNT); + ++ for (type = 0; type < QEMU_CLIPBOARD_TYPE__COUNT; type++) { ++ /* ++ * If data is missing, the clipboard owner's 'request' callback needs to ++ * be set. Otherwise, there is no way to get the clipboard data and ++ * qemu_clipboard_request() cannot be called. ++ */ ++ if (info->types[type].available && !info->types[type].data) { ++ assert(info->owner && info->owner->request); ++ } ++ } ++ + notifier_list_notify(&clipboard_notifiers, ¬ify); + + if (cbinfo[info->selection] != info) { +@@ -132,6 +144,8 @@ void qemu_clipboard_request(QemuClipboardInfo *info, + !info->owner) + return; + ++ assert(info->owner->request); ++ + info->types[type].requested = true; + info->owner->request(info, type); + } +-- +2.39.3 + diff --git a/kvm-ui-clipboard-mark-type-as-not-available-when-there-i.patch b/kvm-ui-clipboard-mark-type-as-not-available-when-there-i.patch new file mode 100644 index 0000000..00c9369 --- /dev/null +++ b/kvm-ui-clipboard-mark-type-as-not-available-when-there-i.patch @@ -0,0 +1,107 @@ +From 097516bef2993d917e76d92066ca2eb067e45394 Mon Sep 17 00:00:00 2001 +From: Fiona Ebner +Date: Wed, 24 Jan 2024 11:57:48 +0100 +Subject: [PATCH 01/20] ui/clipboard: mark type as not available when there is + no data +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +RH-Author: Jon Maloy +RH-MergeRequest: 228: ui/clipboard: mark type as not available when there is no data +RH-Jira: RHEL-19629 +RH-Acked-by: Marc-André Lureau +RH-Acked-by: Gerd Hoffmann +RH-Commit: [1/2] 74ded03d6376f9693733d673502219f76eab7099 (jmaloy/jmaloy-qemu-kvm-2) + +JIRA: https://issues.redhat.com/browse/RHEL-19629 +CVE: CVE-2023-6683 +Upstream: Merged + +commit 405484b29f6548c7b86549b0f961b906337aa68a +Author: Fiona Ebner +Date: Wed Jan 24 11:57:48 2024 +0100 + + ui/clipboard: mark type as not available when there is no data + + With VNC, a client can send a non-extended VNC_MSG_CLIENT_CUT_TEXT + message with len=0. In qemu_clipboard_set_data(), the clipboard info + will be updated setting data to NULL (because g_memdup(data, size) + returns NULL when size is 0). If the client does not set the + VNC_ENCODING_CLIPBOARD_EXT feature when setting up the encodings, then + the 'request' callback for the clipboard peer is not initialized. + Later, because data is NULL, qemu_clipboard_request() can be reached + via vdagent_chr_write() and vdagent_clipboard_recv_request() and + there, the clipboard owner's 'request' callback will be attempted to + be called, but that is a NULL pointer. + + In particular, this can happen when using the KRDC (22.12.3) VNC + client. + + Another scenario leading to the same issue is with two clients (say + noVNC and KRDC): + + The noVNC client sets the extension VNC_FEATURE_CLIPBOARD_EXT and + initializes its cbpeer. + + The KRDC client does not, but triggers a vnc_client_cut_text() (note + it's not the _ext variant)). There, a new clipboard info with it as + the 'owner' is created and via qemu_clipboard_set_data() is called, + which in turn calls qemu_clipboard_update() with that info. + + In qemu_clipboard_update(), the notifier for the noVNC client will be + called, i.e. vnc_clipboard_notify() and also set vs->cbinfo for the + noVNC client. The 'owner' in that clipboard info is the clipboard peer + for the KRDC client, which did not initialize the 'request' function. + That sounds correct to me, it is the owner of that clipboard info. + + Then when noVNC sends a VNC_MSG_CLIENT_CUT_TEXT message (it did set + the VNC_FEATURE_CLIPBOARD_EXT feature correctly, so a check for it + passes), that clipboard info is passed to qemu_clipboard_request() and + the original segfault still happens. + + Fix the issue by handling updates with size 0 differently. In + particular, mark in the clipboard info that the type is not available. + + While at it, switch to g_memdup2(), because g_memdup() is deprecated. + + Cc: qemu-stable@nongnu.org + Fixes: CVE-2023-6683 + Reported-by: Markus Frank + Suggested-by: Marc-André Lureau + Signed-off-by: Fiona Ebner + Reviewed-by: Marc-André Lureau + Tested-by: Markus Frank + Message-ID: <20240124105749.204610-1-f.ebner@proxmox.com> + +Signed-off-by: Jon Maloy +--- + ui/clipboard.c | 12 +++++++++--- + 1 file changed, 9 insertions(+), 3 deletions(-) + +diff --git a/ui/clipboard.c b/ui/clipboard.c +index 3d14bffaf8..b3f6fa3c9e 100644 +--- a/ui/clipboard.c ++++ b/ui/clipboard.c +@@ -163,9 +163,15 @@ void qemu_clipboard_set_data(QemuClipboardPeer *peer, + } + + g_free(info->types[type].data); +- info->types[type].data = g_memdup(data, size); +- info->types[type].size = size; +- info->types[type].available = true; ++ if (size) { ++ info->types[type].data = g_memdup2(data, size); ++ info->types[type].size = size; ++ info->types[type].available = true; ++ } else { ++ info->types[type].data = NULL; ++ info->types[type].size = 0; ++ info->types[type].available = false; ++ } + + if (update) { + qemu_clipboard_update(info); +-- +2.39.3 + diff --git a/qemu-kvm.spec b/qemu-kvm.spec index 6d0c797..1e8ed3f 100644 --- a/qemu-kvm.spec +++ b/qemu-kvm.spec @@ -149,7 +149,7 @@ Obsoletes: %{name}-block-ssh <= %{epoch}:%{version} \ Summary: QEMU is a machine emulator and virtualizer Name: qemu-kvm Version: 8.2.0 -Release: 7%{?rcrel}%{?dist}%{?cc_suffix} +Release: 8%{?rcrel}%{?dist}%{?cc_suffix} # Epoch because we pushed a qemu-1.0 package. AIUI this can't ever be dropped # Epoch 15 used for RHEL 8 # Epoch 17 used for RHEL 9 (due to release versioning offset in RHEL 8.5) @@ -552,6 +552,46 @@ Patch146: kvm-x86-rhel-9.2.0-machine-type-compat-fix.patch Patch147: kvm-qemu_init-increase-NOFILE-soft-limit-on-POSIX.patch # For RHEL-24614 - [RHEL9][chardev][s390x] qemu hit core dump while using TLS server from host to guest Patch148: kvm-chardev-char-socket-Fix-TLS-io-channels-sending-too-.patch +# For RHEL-19629 - CVE-2023-6683 qemu-kvm: QEMU: VNC: NULL pointer dereference in qemu_clipboard_request() [rhel-9] +Patch149: kvm-ui-clipboard-mark-type-as-not-available-when-there-i.patch +# For RHEL-19629 - CVE-2023-6683 qemu-kvm: QEMU: VNC: NULL pointer dereference in qemu_clipboard_request() [rhel-9] +Patch150: kvm-ui-clipboard-add-asserts-for-update-and-request.patch +# For RHEL-21705 - pc-q35-rhel9.4.0 does not provide proper computer information +Patch151: kvm-hw-i386-pc-Defer-smbios_set_defaults-to-machine_done.patch +# For RHEL-21705 - pc-q35-rhel9.4.0 does not provide proper computer information +Patch152: kvm-Implement-base-of-SMBIOS-type-9-descriptor.patch +# For RHEL-21705 - pc-q35-rhel9.4.0 does not provide proper computer information +Patch153: kvm-Implement-SMBIOS-type-9-v2.6.patch +# For RHEL-21705 - pc-q35-rhel9.4.0 does not provide proper computer information +Patch154: kvm-smbios-cleanup-smbios_get_tables-from-legacy-handlin.patch +# For RHEL-21705 - pc-q35-rhel9.4.0 does not provide proper computer information +Patch155: kvm-smbios-get-rid-of-smbios_smp_sockets-global.patch +# For RHEL-21705 - pc-q35-rhel9.4.0 does not provide proper computer information +Patch156: kvm-smbios-get-rid-of-smbios_legacy-global.patch +# For RHEL-21705 - pc-q35-rhel9.4.0 does not provide proper computer information +Patch157: kvm-smbios-avoid-mangling-user-provided-tables.patch +# For RHEL-21705 - pc-q35-rhel9.4.0 does not provide proper computer information +Patch158: kvm-smbios-don-t-check-type4-structures-in-legacy-mode.patch +# For RHEL-21705 - pc-q35-rhel9.4.0 does not provide proper computer information +Patch159: kvm-smbios-add-smbios_add_usr_blob_size-helper.patch +# For RHEL-21705 - pc-q35-rhel9.4.0 does not provide proper computer information +Patch160: kvm-smbios-rename-expose-structures-bitmaps-used-by-both.patch +# For RHEL-21705 - pc-q35-rhel9.4.0 does not provide proper computer information +Patch161: kvm-smbios-build-legacy-mode-code-only-for-pc-machine.patch +# For RHEL-21705 - pc-q35-rhel9.4.0 does not provide proper computer information +Patch162: kvm-smbios-handle-errors-consistently.patch +# For RHEL-21705 - pc-q35-rhel9.4.0 does not provide proper computer information +Patch163: kvm-smbios-get-rid-of-global-smbios_ep_type.patch +# For RHEL-21705 - pc-q35-rhel9.4.0 does not provide proper computer information +Patch164: kvm-smbios-clear-smbios_type4_count-before-building-tabl.patch +# For RHEL-21705 - pc-q35-rhel9.4.0 does not provide proper computer information +Patch165: kvm-smbios-extend-smbios-entry-point-type-with-auto-valu.patch +# For RHEL-21705 - pc-q35-rhel9.4.0 does not provide proper computer information +Patch166: kvm-smbios-in-case-of-entry-point-is-auto-try-to-build-v.patch +# For RHEL-21705 - pc-q35-rhel9.4.0 does not provide proper computer information +Patch167: kvm-smbios-error-out-when-building-type-4-table-is-not-p.patch +# For RHEL-21705 - pc-q35-rhel9.4.0 does not provide proper computer information +Patch168: kvm-pc-q35-set-SMBIOS-entry-point-type-to-auto-by-defaul.patch %if %{have_clang} BuildRequires: clang @@ -1613,6 +1653,32 @@ useradd -r -u 107 -g qemu -G kvm -d / -s /sbin/nologin \ %endif %changelog +* Mon Mar 18 2024 Miroslav Rezanina - 8.2.0-8 +- kvm-ui-clipboard-mark-type-as-not-available-when-there-i.patch [RHEL-19629] +- kvm-ui-clipboard-add-asserts-for-update-and-request.patch [RHEL-19629] +- kvm-hw-i386-pc-Defer-smbios_set_defaults-to-machine_done.patch [RHEL-21705] +- kvm-Implement-base-of-SMBIOS-type-9-descriptor.patch [RHEL-21705] +- kvm-Implement-SMBIOS-type-9-v2.6.patch [RHEL-21705] +- kvm-smbios-cleanup-smbios_get_tables-from-legacy-handlin.patch [RHEL-21705] +- kvm-smbios-get-rid-of-smbios_smp_sockets-global.patch [RHEL-21705] +- kvm-smbios-get-rid-of-smbios_legacy-global.patch [RHEL-21705] +- kvm-smbios-avoid-mangling-user-provided-tables.patch [RHEL-21705] +- kvm-smbios-don-t-check-type4-structures-in-legacy-mode.patch [RHEL-21705] +- kvm-smbios-add-smbios_add_usr_blob_size-helper.patch [RHEL-21705] +- kvm-smbios-rename-expose-structures-bitmaps-used-by-both.patch [RHEL-21705] +- kvm-smbios-build-legacy-mode-code-only-for-pc-machine.patch [RHEL-21705] +- kvm-smbios-handle-errors-consistently.patch [RHEL-21705] +- kvm-smbios-get-rid-of-global-smbios_ep_type.patch [RHEL-21705] +- kvm-smbios-clear-smbios_type4_count-before-building-tabl.patch [RHEL-21705] +- kvm-smbios-extend-smbios-entry-point-type-with-auto-valu.patch [RHEL-21705] +- kvm-smbios-in-case-of-entry-point-is-auto-try-to-build-v.patch [RHEL-21705] +- kvm-smbios-error-out-when-building-type-4-table-is-not-p.patch [RHEL-21705] +- kvm-pc-q35-set-SMBIOS-entry-point-type-to-auto-by-defaul.patch [RHEL-21705] +- Resolves: RHEL-19629 + (CVE-2023-6683 qemu-kvm: QEMU: VNC: NULL pointer dereference in qemu_clipboard_request() [rhel-9]) +- Resolves: RHEL-21705 + (pc-q35-rhel9.4.0 does not provide proper computer information) + * Fri Mar 08 2024 Miroslav Rezanina - 8.2.0-7 - kvm-qemu_init-increase-NOFILE-soft-limit-on-POSIX.patch [RHEL-26049] - kvm-chardev-char-socket-Fix-TLS-io-channels-sending-too-.patch [RHEL-24614]