summary refs log tree commit diff stats
path: root/hw/smbios/smbios.c
diff options
context:
space:
mode:
authorPeter Maydell <peter.maydell@linaro.org>2020-09-29 11:10:29 +0100
committerPeter Maydell <peter.maydell@linaro.org>2020-09-29 11:10:29 +0100
commit213057383c9f73a17cfe635b204d88e11f918df1 (patch)
treef3a1da40a8e48e3b8aaff8d355610e219c0de1cf /hw/smbios/smbios.c
parent23290e8070fa18dd8ff930515326e76eeee5810a (diff)
parent8138405528c29af2a850cd672a8f8a0b33b7ab40 (diff)
downloadfocaccia-qemu-213057383c9f73a17cfe635b204d88e11f918df1.tar.gz
focaccia-qemu-213057383c9f73a17cfe635b204d88e11f918df1.zip
Merge remote-tracking branch 'remotes/mst/tags/for_upstream' into staging
virtio,pc,acpi: fixes, tests

Fixes and tests all over the place.
Batch iommu updates for vdpa.
Removal of deprecated cpu hotplug commands.
SMBIOS OEM string support.

Signed-off-by: Michael S. Tsirkin <mst@redhat.com>

# gpg: Signature made Tue 29 Sep 2020 08:09:21 BST
# gpg:                using RSA key 5D09FD0871C8F85B94CA8A0D281F0DB8D28D5469
# gpg:                issuer "mst@redhat.com"
# gpg: Good signature from "Michael S. Tsirkin <mst@kernel.org>" [full]
# gpg:                 aka "Michael S. Tsirkin <mst@redhat.com>" [full]
# Primary key fingerprint: 0270 606B 6F3C DF3D 0B17  0970 C350 3912 AFBE 8E67
#      Subkey fingerprint: 5D09 FD08 71C8 F85B 94CA  8A0D 281F 0DB8 D28D 5469

* remotes/mst/tags/for_upstream: (48 commits)
  libvhost-user: return on error in vu_log_queue_fill()
  libvhost-user: return early on virtqueue errors
  hw: virtio-pmem: detach the element fromt the virtqueue when error occurs
  tests/acpi: update golden master DSDT binary table blobs for q35
  piix4: don't reserve hw resources when hotplug is off globally
  Add ACPI DSDT tables for q35 that are being updated by the next patch
  tests/acpi: add newly added acpi DSDT table blob for pci bridge hotplug flag
  tests/acpi: unit test for 'acpi-pci-hotplug-with-bridge-support' bridge flag
  tests/acpi: list added acpi table binary file for pci bridge hotplug test
  i440fx/acpi: do not add hotplug related amls for cold plugged bridges
  Fix a gap where acpi_pcihp_find_hotplug_bus() returns a non-hotpluggable bus
  tests/acpi: add a new ACPI table in order to test root pci hotplug on/off
  tests/acpi: add new unit test to test hotplug off/on feature on the root pci bus
  tests/acpi: mark addition of table DSDT.roothp for unit testing root pci hotplug
  vhost-user: save features of multiqueues if chardev is closed
  qemu-options: document SMBIOS type 11 settings
  hw/smbios: report error if table size is too large
  hw/smbios: support loading OEM strings values from a file
  tests: acpi: update acpi blobs with new AML
  x68: acpi: trigger SMI before sending hotplug Notify event to OSPM
  ...

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Diffstat (limited to 'hw/smbios/smbios.c')
-rw-r--r--hw/smbios/smbios.c85
1 files changed, 72 insertions, 13 deletions
diff --git a/hw/smbios/smbios.c b/hw/smbios/smbios.c
index 7cc950b41c..8b30906e50 100644
--- a/hw/smbios/smbios.c
+++ b/hw/smbios/smbios.c
@@ -110,7 +110,7 @@ static struct {
 
 static struct {
     size_t nvalues;
-    const char **values;
+    char **values;
 } type11;
 
 static struct {
@@ -314,6 +314,11 @@ static const QemuOptDesc qemu_smbios_type11_opts[] = {
         .type = QEMU_OPT_STRING,
         .help = "OEM string data",
     },
+    {
+        .name = "path",
+        .type = QEMU_OPT_STRING,
+        .help = "OEM string data from file",
+    },
 };
 
 static const QemuOptDesc qemu_smbios_type17_opts[] = {
@@ -360,6 +365,13 @@ static void smbios_register_config(void)
 
 opts_init(smbios_register_config);
 
+/*
+ * The SMBIOS 2.1 "structure table length" field in the
+ * entry point uses a 16-bit integer, so we're limited
+ * in total table size
+ */
+#define SMBIOS_21_MAX_TABLES_LEN 0xffff
+
 static void smbios_validate_table(MachineState *ms)
 {
     uint32_t expect_t4_count = smbios_legacy ?
@@ -370,6 +382,13 @@ static void smbios_validate_table(MachineState *ms)
                      expect_t4_count, smbios_type4_count);
         exit(1);
     }
+
+    if (smbios_ep_type == SMBIOS_ENTRY_POINT_21 &&
+        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);
+    }
 }
 
 
@@ -641,6 +660,8 @@ static void smbios_build_type_11_table(void)
 
     for (i = 0; i < type11.nvalues; i++) {
         SMBIOS_TABLE_SET_STR_LIST(11, type11.values[i]);
+        g_free(type11.values[i]);
+        type11.values[i] = NULL;
     }
 
     SMBIOS_BUILD_TABLE_POST;
@@ -940,9 +961,8 @@ static void save_opt(const char **dest, QemuOpts *opts, const char *name)
 
 
 struct opt_list {
-    const char *name;
     size_t *ndest;
-    const char ***dest;
+    char ***dest;
 };
 
 static int save_opt_one(void *opaque,
@@ -951,23 +971,60 @@ static int save_opt_one(void *opaque,
 {
     struct opt_list *opt = opaque;
 
-    if (!g_str_equal(name, opt->name)) {
-        return 0;
+    if (g_str_equal(name, "path")) {
+        g_autoptr(GByteArray) data = g_byte_array_new();
+        g_autofree char *buf = g_new(char, 4096);
+        ssize_t ret;
+        int fd = qemu_open(value, O_RDONLY, errp);
+        if (fd < 0) {
+            return -1;
+        }
+
+        while (1) {
+            ret = read(fd, buf, 4096);
+            if (ret == 0) {
+                break;
+            }
+            if (ret < 0) {
+                error_setg(errp, "Unable to read from %s: %s",
+                           value, strerror(errno));
+                return -1;
+            }
+            if (memchr(buf, '\0', ret)) {
+                error_setg(errp, "NUL in OEM strings value in %s", value);
+                return -1;
+            }
+            g_byte_array_append(data, (guint8 *)buf, ret);
+        }
+
+        close(fd);
+
+        *opt->dest = g_renew(char *, *opt->dest, (*opt->ndest) + 1);
+        (*opt->dest)[*opt->ndest] = (char *)g_byte_array_free(data,  FALSE);
+        (*opt->ndest)++;
+        data = NULL;
+   } else if (g_str_equal(name, "value")) {
+        *opt->dest = g_renew(char *, *opt->dest, (*opt->ndest) + 1);
+        (*opt->dest)[*opt->ndest] = g_strdup(value);
+        (*opt->ndest)++;
+    } else if (!g_str_equal(name, "type")) {
+        error_setg(errp, "Unexpected option %s", name);
+        return -1;
     }
 
-    *opt->dest = g_renew(const char *, *opt->dest, (*opt->ndest) + 1);
-    (*opt->dest)[*opt->ndest] = value;
-    (*opt->ndest)++;
     return 0;
 }
 
-static void save_opt_list(size_t *ndest, const char ***dest,
-                          QemuOpts *opts, const char *name)
+static bool save_opt_list(size_t *ndest, char ***dest, QemuOpts *opts,
+                          Error **errp)
 {
     struct opt_list opt = {
-        name, ndest, dest,
+        ndest, dest,
     };
-    qemu_opt_foreach(opts, save_opt_one, &opt, NULL);
+    if (!qemu_opt_foreach(opts, save_opt_one, &opt, errp)) {
+        return false;
+    }
+    return true;
 }
 
 void smbios_entry_add(QemuOpts *opts, Error **errp)
@@ -1149,7 +1206,9 @@ void smbios_entry_add(QemuOpts *opts, Error **errp)
             if (!qemu_opts_validate(opts, qemu_smbios_type11_opts, errp)) {
                 return;
             }
-            save_opt_list(&type11.nvalues, &type11.values, opts, "value");
+            if (!save_opt_list(&type11.nvalues, &type11.values, opts, errp)) {
+                return;
+            }
             return;
         case 17:
             if (!qemu_opts_validate(opts, qemu_smbios_type17_opts, errp)) {