qemu-devel.nongnu.org archive mirror
 help / color / mirror / Atom feed
From: minyard@acm.org
To: qemu-devel@nongnu.org
Cc: Corey Minyard <cminyard@mvista.com>
Subject: [Qemu-devel] [PATCH v3 11/16] smbios: Add a function to directly add an entry
Date: Mon,  8 Jun 2015 20:12:06 -0500	[thread overview]
Message-ID: <1433812331-18993-12-git-send-email-minyard@acm.org> (raw)
In-Reply-To: <1433812331-18993-1-git-send-email-minyard@acm.org>

From: Corey Minyard <cminyard@mvista.com>

There was no way to directly add a table entry to the SMBIOS table,
even though the BIOS supports this.  So add a function to do this.
This is in preparation for the IPMI handler adding it's SMBIOS table
entry.

Signed-off-by: Corey Minyard <cminyard@mvista.com>
---
 hw/i386/smbios.c         | 153 +++++++++++++++++++++++++++++++----------------
 include/hw/i386/smbios.h |   8 +++
 2 files changed, 109 insertions(+), 52 deletions(-)

diff --git a/hw/i386/smbios.c b/hw/i386/smbios.c
index 1341e02..68ad0be 100644
--- a/hw/i386/smbios.c
+++ b/hw/i386/smbios.c
@@ -831,6 +831,92 @@ static void smbios_entry_point_setup(void)
     ep.structure_table_address = cpu_to_le32(0);
 }
 
+struct smbios_table_entry {
+    void *data;
+    int size;
+    bool append_zeros;
+    QSLIST_ENTRY(smbios_table_entry) next;
+};
+
+static QSLIST_HEAD(, smbios_table_entry) table_entries;
+
+void smbios_add_table_entry(void *data, int size, bool append_zeros)
+{
+    struct smbios_table_entry *e = g_malloc(sizeof(*e));
+
+    e->data = g_malloc(size);
+    memcpy(e->data, data, size);
+    e->size = size;
+    e->append_zeros = append_zeros;
+    QSLIST_INSERT_HEAD(&table_entries, e, next);
+}
+
+static void smbios_table_entry_append(void *data, int size, bool append_zeros)
+{
+    struct smbios_structure_header *header;
+    struct smbios_table *table; /* legacy mode only */
+
+    /*
+     * NOTE: standard double '\0' terminator expected, per smbios spec.
+     * (except in legacy mode, where the second '\0' is implicit and
+     *  will be inserted by the BIOS).
+     */
+    if (append_zeros) {
+        size += 2;
+    }
+    smbios_tables = g_realloc(smbios_tables, smbios_tables_len + size);
+    header = (struct smbios_structure_header *)(smbios_tables +
+                                                smbios_tables_len);
+
+    memcpy(header, data, size);
+    if (append_zeros) {
+        memset(smbios_tables + smbios_tables_len + size - 2, 0, 2);
+    }
+
+    if (test_bit(header->type, have_fields_bitmap)) {
+        error_report("can't load type %d struct, fields already specified!",
+                     header->type);
+        exit(1);
+    }
+    set_bit(header->type, have_binfile_bitmap);
+
+    if (header->type == 4) {
+        smbios_type4_count++;
+    }
+
+    smbios_tables_len += size;
+    if (size > smbios_table_max) {
+        smbios_table_max = size;
+    }
+    smbios_table_cnt++;
+
+    /* add a copy of the newly loaded blob to legacy smbios_entries */
+    /* NOTE: This code runs before smbios_set_defaults(), so we don't
+     *       yet know which mode (legacy vs. aggregate-table) will be
+     *       required. We therefore add the binary blob to both legacy
+     *       (smbios_entries) and aggregate (smbios_tables) tables, and
+     *       delete the one we don't need from smbios_set_defaults(),
+     *       once we know which machine version has been requested.
+     */
+    if (!smbios_entries) {
+        smbios_entries_len = sizeof(uint16_t);
+        smbios_entries = g_malloc0(smbios_entries_len);
+    }
+    if (append_zeros) {
+        size -= 1; /* The BIOS adds the second zero in legacy mode. */
+    }
+    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 */
+}
+
 void smbios_get_tables(uint8_t **tables, size_t *tables_len,
                        uint8_t **anchor, size_t *anchor_len)
 {
@@ -875,6 +961,16 @@ void smbios_get_tables(uint8_t **tables, size_t *tables_len,
         }
 
         smbios_build_type_32_table();
+
+        while (!QSLIST_EMPTY(&table_entries)) {
+            struct smbios_table_entry *e = QSLIST_FIRST(&table_entries);
+
+            QSLIST_REMOVE_HEAD(&table_entries, next);
+            smbios_table_entry_append(e->data, e->size, e->append_zeros);
+            g_free(e->data);
+            g_free(e);
+        }
+
         smbios_build_type_127_table();
 
         smbios_validate_table();
@@ -907,9 +1003,8 @@ void smbios_entry_add(QemuOpts *opts)
 
     val = qemu_opt_get(opts, "file");
     if (val) {
-        struct smbios_structure_header *header;
         int size;
-        struct smbios_table *table; /* legacy mode only */
+        uint8_t *data;
 
         qemu_opts_validate(opts, qemu_smbios_file_opts, &local_err);
         if (local_err) {
@@ -923,60 +1018,14 @@ void smbios_entry_add(QemuOpts *opts)
             exit(1);
         }
 
-        /*
-         * NOTE: standard double '\0' terminator expected, per smbios spec.
-         * (except in legacy mode, where the second '\0' is implicit and
-         *  will be inserted by the BIOS).
-         */
-        smbios_tables = g_realloc(smbios_tables, smbios_tables_len + size);
-        header = (struct smbios_structure_header *)(smbios_tables +
-                                                    smbios_tables_len);
-
-        if (load_image(val, (uint8_t *)header) != size) {
+        data = g_malloc(size);
+        if (load_image(val, data) != size) {
             error_report("Failed to load SMBIOS file %s", val);
             exit(1);
         }
 
-        if (test_bit(header->type, have_fields_bitmap)) {
-            error_report("can't load type %d struct, fields already specified!",
-                         header->type);
-            exit(1);
-        }
-        set_bit(header->type, have_binfile_bitmap);
-
-        if (header->type == 4) {
-            smbios_type4_count++;
-        }
-
-        smbios_tables_len += size;
-        if (size > smbios_table_max) {
-            smbios_table_max = size;
-        }
-        smbios_table_cnt++;
-
-        /* add a copy of the newly loaded blob to legacy smbios_entries */
-        /* NOTE: This code runs before smbios_set_defaults(), so we don't
-         *       yet know which mode (legacy vs. aggregate-table) will be
-         *       required. We therefore add the binary blob to both legacy
-         *       (smbios_entries) and aggregate (smbios_tables) tables, and
-         *       delete the one we don't need from smbios_set_defaults(),
-         *       once we know which machine version has been requested.
-         */
-        if (!smbios_entries) {
-            smbios_entries_len = sizeof(uint16_t);
-            smbios_entries = g_malloc0(smbios_entries_len);
-        }
-        smbios_entries = g_realloc(smbios_entries, smbios_entries_len +
-                                                   size + sizeof(*table));
-        table = (struct smbios_table *)(smbios_entries + smbios_entries_len);
-        table->header.type = SMBIOS_TABLE_ENTRY;
-        table->header.length = cpu_to_le16(sizeof(*table) + size);
-        memcpy(table->data, header, size);
-        smbios_entries_len += sizeof(*table) + size;
-        (*(uint16_t *)smbios_entries) =
-                cpu_to_le16(le16_to_cpu(*(uint16_t *)smbios_entries) + 1);
-        /* end: add a copy of the newly loaded blob to legacy smbios_entries */
-
+        smbios_table_entry_append(data, size, false);
+        g_free(data);
         return;
     }
 
diff --git a/include/hw/i386/smbios.h b/include/hw/i386/smbios.h
index d2850be..9f3e920 100644
--- a/include/hw/i386/smbios.h
+++ b/include/hw/i386/smbios.h
@@ -27,6 +27,14 @@ void smbios_get_tables(uint8_t **tables, size_t *tables_len,
                        uint8_t **anchor, size_t *anchor_len);
 
 /*
+ * Add an external entry to the SMBIOS table.  Can only be called
+ * from a registered device table handler.  This will store the
+ * given data in a queue and append it when the SMBIOS table is
+ * built.
+ */
+void smbios_add_table_entry(void *data, int size, bool append_zeros);
+
+/*
  * SMBIOS spec defined tables
  */
 
-- 
1.8.3.1

  parent reply	other threads:[~2015-06-09  1:12 UTC|newest]

Thread overview: 31+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2015-06-09  1:11 [Qemu-devel] [PATCH v3 00/16] Add an IPMI device to QEMU minyard
2015-06-09  1:11 ` [Qemu-devel] [PATCH v3 01/16] Add a base IPMI interface minyard
2015-06-09  1:11 ` [Qemu-devel] [PATCH v3 02/16] ipmi: Add a local BMC simulation minyard
2015-06-09  1:11 ` [Qemu-devel] [PATCH v3 03/16] ipmi: Add an external connection simulation interface minyard
2015-06-09  1:11 ` [Qemu-devel] [PATCH v3 04/16] ipmi: Add an ISA KCS low-level interface minyard
2015-06-09  1:12 ` [Qemu-devel] [PATCH v3 05/16] ipmi: Add a BT " minyard
2015-06-09  1:12 ` [Qemu-devel] [PATCH v3 06/16] ipmi: Add tests minyard
2015-06-09  1:12 ` [Qemu-devel] [PATCH v3 07/16] ipmi: Add documentation minyard
2015-06-09  1:12 ` [Qemu-devel] [PATCH v3 08/16] ipmi: Add migration capability to the IPMI devices minyard
2015-06-09  1:12 ` [Qemu-devel] [PATCH v3 09/16] ipmi: Add a firmware configuration repository minyard
2015-06-09  1:12 ` [Qemu-devel] [PATCH v3 10/16] ipmi: Add firmware registration to the ISA interface minyard
2015-06-09  1:12 ` minyard [this message]
2015-06-09  1:12 ` [Qemu-devel] [PATCH v3 12/16] pc: Postpone SMBIOS table installation to post machine init minyard
2015-07-03  8:17   ` Michael S. Tsirkin
2015-06-09  1:12 ` [Qemu-devel] [PATCH v3 13/16] ipmi: Add SMBIOS table entry minyard
2015-06-09  1:12 ` [Qemu-devel] [PATCH v3 14/16] acpi: Add a way for devices to add ACPI tables minyard
2015-07-03  8:21   ` Michael S. Tsirkin
2015-07-03  8:27   ` Michael S. Tsirkin
2015-07-07  8:08   ` Igor Mammedov
2015-07-08 17:44     ` Paolo Bonzini
2015-07-08 19:26       ` Igor Mammedov
2015-07-08 20:39         ` Paolo Bonzini
2015-07-09  8:25           ` Igor Mammedov
2015-07-13 21:55             ` Corey Minyard
2015-07-14  7:36               ` Igor Mammedov
2015-06-09  1:12 ` [Qemu-devel] [PATCH v3 15/16] ipmi: Add ACPI table entries minyard
2015-07-07  9:47   ` Igor Mammedov
2015-06-09  1:12 ` [Qemu-devel] [PATCH v3 16/16] bios: Add tests for the IPMI ACPI and SMBIOS entries minyard
2015-07-03  0:30 ` [Qemu-devel] [PATCH v3 00/16] Add an IPMI device to QEMU Benjamin Herrenschmidt
2015-07-03  6:50 ` Paolo Bonzini
2015-07-03  8:23 ` Michael S. Tsirkin

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=1433812331-18993-12-git-send-email-minyard@acm.org \
    --to=minyard@acm.org \
    --cc=cminyard@mvista.com \
    --cc=qemu-devel@nongnu.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).