58fc860e6d
A couple of fixes, including one which gives confidence we can submit to Factory finally. OBS-URL: https://build.opensuse.org/request/show/612290 OBS-URL: https://build.opensuse.org/package/show/Virtualization/qemu?expand=0&rev=410
193 lines
8.7 KiB
Diff
193 lines
8.7 KiB
Diff
From 82f73214b4bb024153408b121ccb78321093862f Mon Sep 17 00:00:00 2001
|
|
From: Lin Ma <lma@suse.com>
|
|
Date: Wed, 14 Mar 2018 14:31:26 +0800
|
|
Subject: [PATCH] smbios: Add 1 terminator if any string fields defined in
|
|
given table.
|
|
|
|
If user specifies smbios table files through qemu command line, Then will
|
|
get error messages while decoding those table content in guest.
|
|
|
|
Reproducer:
|
|
1. dump a smbios table(say table 1) to a binary file from a pc.
|
|
2. load the binary file through command line: 'qemu -smbios file=...'.
|
|
3. perform 'dmidecode' or 'dmidecode -t 1' in guest.
|
|
|
|
It reports 'Invalid entry length...' because qemu doesn't add terminator(s)
|
|
correctly for the table.
|
|
|
|
This patch fixed the issue by:
|
|
|
|
For smbios tables which have string fields provided, qemu should add 1 terminator.
|
|
For smbios tables which dont have string fields provided, qemu should add 2.
|
|
|
|
[LM: BSC#994082]
|
|
[LM: BSC#1084316]
|
|
Signed-off-by: Lin Ma <lma@suse.com>
|
|
---
|
|
hw/smbios/smbios.c | 90 ++++++++++++++++++++++++++++++++++++++
|
|
include/hw/smbios/smbios.h | 44 +++++++++++++++++++
|
|
2 files changed, 134 insertions(+)
|
|
|
|
diff --git a/hw/smbios/smbios.c b/hw/smbios/smbios.c
|
|
index 27a07e96f4..b4515ae787 100644
|
|
--- a/hw/smbios/smbios.c
|
|
+++ b/hw/smbios/smbios.c
|
|
@@ -955,6 +955,9 @@ void smbios_entry_add(QemuOpts *opts, Error **errp)
|
|
{
|
|
const char *val;
|
|
|
|
+ int i, terminator_count = 2, table_str_field_count = 0;
|
|
+ int *tables_str_field_offset = NULL;
|
|
+
|
|
assert(!smbios_immutable);
|
|
|
|
val = qemu_opt_get(opts, "file");
|
|
@@ -996,7 +999,94 @@ void smbios_entry_add(QemuOpts *opts, Error **errp)
|
|
smbios_type4_count++;
|
|
}
|
|
|
|
+ switch (header->type) {
|
|
+ case 0:
|
|
+ tables_str_field_offset = g_malloc0(sizeof(int) * \
|
|
+ TYPE_0_STR_FIELD_COUNT);
|
|
+ tables_str_field_offset = (int []){\
|
|
+ TYPE_0_STR_FIELD_OFFSET_VENDOR, \
|
|
+ TYPE_0_STR_FIELD_OFFSET_BIOS_VERSION, \
|
|
+ TYPE_0_STR_FIELD_OFFSET_BIOS_RELEASE_DATE};
|
|
+ table_str_field_count = sizeof(tables_str_field_offset) / \
|
|
+ sizeof(tables_str_field_offset[0]);
|
|
+ break;
|
|
+ case 1:
|
|
+ tables_str_field_offset = g_malloc0(sizeof(int) * \
|
|
+ TYPE_1_STR_FIELD_COUNT);
|
|
+ tables_str_field_offset = (int []){
|
|
+ TYPE_1_STR_FIELD_OFFSET_MANUFACTURER, \
|
|
+ TYPE_1_STR_FIELD_OFFSET_PRODUCT, \
|
|
+ TYPE_1_STR_FIELD_OFFSET_VERSION, \
|
|
+ TYPE_1_STR_FIELD_OFFSET_SERIAL, \
|
|
+ TYPE_1_STR_FIELD_OFFSET_SKU, \
|
|
+ TYPE_1_STR_FIELD_OFFSET_FAMILY};
|
|
+ table_str_field_count = sizeof(tables_str_field_offset) / \
|
|
+ sizeof(tables_str_field_offset[0]);
|
|
+ break;
|
|
+ case 2:
|
|
+ tables_str_field_offset = g_malloc0(sizeof(int) * \
|
|
+ TYPE_2_STR_FIELD_COUNT);
|
|
+ tables_str_field_offset = (int []){\
|
|
+ TYPE_2_STR_FIELD_OFFSET_MANUFACTURER, \
|
|
+ TYPE_2_STR_FIELD_OFFSET_PRODUCT, \
|
|
+ TYPE_2_STR_FIELD_OFFSET_VERSION, \
|
|
+ TYPE_2_STR_FIELD_OFFSET_SERIAL, \
|
|
+ TYPE_2_STR_FIELD_OFFSET_ASSET, \
|
|
+ TYPE_2_STR_FIELD_OFFSET_LOCATION};
|
|
+ table_str_field_count = sizeof(tables_str_field_offset) / \
|
|
+ sizeof(tables_str_field_offset[0]);
|
|
+ break;
|
|
+ case 3:
|
|
+ tables_str_field_offset = g_malloc0(sizeof(int) * \
|
|
+ TYPE_3_STR_FIELD_COUNT);
|
|
+ tables_str_field_offset = (int []){\
|
|
+ TYPE_3_STR_FIELD_OFFSET_MANUFACTURER, \
|
|
+ TYPE_3_STR_FIELD_OFFSET_VERSION, \
|
|
+ TYPE_3_STR_FIELD_OFFSET_SERIAL, \
|
|
+ TYPE_3_STR_FIELD_OFFSET_ASSET, \
|
|
+ TYPE_3_STR_FIELD_OFFSET_SKU};
|
|
+ table_str_field_count = sizeof(tables_str_field_offset) / \
|
|
+ sizeof(tables_str_field_offset[0]);
|
|
+ break;
|
|
+ case 4:
|
|
+ tables_str_field_offset = g_malloc0(sizeof(int) * \
|
|
+ TYPE_4_STR_FIELD_COUNT);
|
|
+ tables_str_field_offset = (int []){\
|
|
+ TYPE_4_STR_FIELD_OFFSET_SOCKET, \
|
|
+ TYPE_4_STR_FIELD_OFFSET_PROCESSOR_MANUFACTURER, \
|
|
+ TYPE_4_STR_FIELD_OFFSET_PROCESSOR_VERSION, \
|
|
+ TYPE_4_STR_FIELD_OFFSET_SERIAL, \
|
|
+ TYPE_4_STR_FIELD_OFFSET_ASSET, \
|
|
+ TYPE_4_STR_FIELD_OFFSET_PART};
|
|
+ table_str_field_count = sizeof(tables_str_field_offset) / \
|
|
+ sizeof(tables_str_field_offset[0]);
|
|
+ break;
|
|
+ case 17:
|
|
+ tables_str_field_offset = g_malloc0(sizeof(int) * \
|
|
+ TYPE_17_STR_FIELD_COUNT);
|
|
+ tables_str_field_offset = (int []){\
|
|
+ TYPE_17_STR_FIELD_OFFSET_DEVICE_LOCATOR, \
|
|
+ TYPE_17_STR_FIELD_OFFSET_BANK_LOCATOR, \
|
|
+ TYPE_17_STR_FIELD_OFFSET_MANUFACTURER, \
|
|
+ TYPE_17_STR_FIELD_OFFSET_SERIAL, \
|
|
+ TYPE_17_STR_FIELD_OFFSET_ASSET, \
|
|
+ TYPE_17_STR_FIELD_OFFSET_PART};
|
|
+ table_str_field_count = sizeof(tables_str_field_offset) / \
|
|
+ sizeof(tables_str_field_offset[0]);
|
|
+ break;
|
|
+ default:
|
|
+ break;
|
|
+ }
|
|
+
|
|
+ for (i = 0; i < table_str_field_count; i++) {
|
|
+ if (*(uint8_t *)(smbios_tables + tables_str_field_offset[i]) > 0) {
|
|
+ terminator_count = 1;
|
|
+ break;
|
|
+ }
|
|
+ }
|
|
+
|
|
smbios_tables_len += size;
|
|
+ smbios_tables_len += terminator_count;
|
|
if (size > smbios_table_max) {
|
|
smbios_table_max = size;
|
|
}
|
|
diff --git a/include/hw/smbios/smbios.h b/include/hw/smbios/smbios.h
|
|
index eeb5a4d7b6..2662df995a 100644
|
|
--- a/include/hw/smbios/smbios.h
|
|
+++ b/include/hw/smbios/smbios.h
|
|
@@ -272,4 +272,48 @@ void smbios_get_tables(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);
|
|
+
|
|
+#define TYPE_0_STR_FIELD_OFFSET_VENDOR 0x4
|
|
+#define TYPE_0_STR_FIELD_OFFSET_BIOS_VERSION 0x5
|
|
+#define TYPE_0_STR_FIELD_OFFSET_BIOS_RELEASE_DATE 0x8
|
|
+#define TYPE_0_STR_FIELD_COUNT 3
|
|
+
|
|
+#define TYPE_1_STR_FIELD_OFFSET_MANUFACTURER 0x4
|
|
+#define TYPE_1_STR_FIELD_OFFSET_PRODUCT 0x5
|
|
+#define TYPE_1_STR_FIELD_OFFSET_VERSION 0x6
|
|
+#define TYPE_1_STR_FIELD_OFFSET_SERIAL 0x7
|
|
+#define TYPE_1_STR_FIELD_OFFSET_SKU 0x19
|
|
+#define TYPE_1_STR_FIELD_OFFSET_FAMILY 0x1a
|
|
+#define TYPE_1_STR_FIELD_COUNT 6
|
|
+
|
|
+#define TYPE_2_STR_FIELD_OFFSET_MANUFACTURER 0x4
|
|
+#define TYPE_2_STR_FIELD_OFFSET_PRODUCT 0x5
|
|
+#define TYPE_2_STR_FIELD_OFFSET_VERSION 0x6
|
|
+#define TYPE_2_STR_FIELD_OFFSET_SERIAL 0x7
|
|
+#define TYPE_2_STR_FIELD_OFFSET_ASSET 0x8
|
|
+#define TYPE_2_STR_FIELD_OFFSET_LOCATION 0xa
|
|
+#define TYPE_2_STR_FIELD_COUNT 6
|
|
+
|
|
+#define TYPE_3_STR_FIELD_OFFSET_MANUFACTURER 0x4
|
|
+#define TYPE_3_STR_FIELD_OFFSET_VERSION 0x6
|
|
+#define TYPE_3_STR_FIELD_OFFSET_SERIAL 0x7
|
|
+#define TYPE_3_STR_FIELD_OFFSET_ASSET 0x8
|
|
+#define TYPE_3_STR_FIELD_OFFSET_SKU 0x14
|
|
+#define TYPE_3_STR_FIELD_COUNT 5
|
|
+
|
|
+#define TYPE_4_STR_FIELD_OFFSET_SOCKET 0x4
|
|
+#define TYPE_4_STR_FIELD_OFFSET_PROCESSOR_MANUFACTURER 0x7
|
|
+#define TYPE_4_STR_FIELD_OFFSET_PROCESSOR_VERSION 0x10
|
|
+#define TYPE_4_STR_FIELD_OFFSET_SERIAL 0x20
|
|
+#define TYPE_4_STR_FIELD_OFFSET_ASSET 0x21
|
|
+#define TYPE_4_STR_FIELD_OFFSET_PART 0x22
|
|
+#define TYPE_4_STR_FIELD_COUNT 6
|
|
+
|
|
+#define TYPE_17_STR_FIELD_OFFSET_DEVICE_LOCATOR 0x10
|
|
+#define TYPE_17_STR_FIELD_OFFSET_BANK_LOCATOR 0x11
|
|
+#define TYPE_17_STR_FIELD_OFFSET_MANUFACTURER 0x17
|
|
+#define TYPE_17_STR_FIELD_OFFSET_SERIAL 0x18
|
|
+#define TYPE_17_STR_FIELD_OFFSET_ASSET 0x19
|
|
+#define TYPE_17_STR_FIELD_OFFSET_PART 0x1a
|
|
+#define TYPE_17_STR_FIELD_COUNT 6
|
|
#endif /* QEMU_SMBIOS_H */
|