From: minyard@acm.org
To: qemu-devel@nongnu.org
Cc: Corey Minyard <cminyard@mvista.com>
Subject: [Qemu-devel] [PATCH 10/15] smbios: Add a function to directly add an entry
Date: Tue, 7 Apr 2015 14:51:39 -0500 [thread overview]
Message-ID: <1428436304-24044-11-git-send-email-minyard@acm.org> (raw)
In-Reply-To: <1428436304-24044-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 | 149 ++++++++++++++++++++++++++++++-----------------
include/hw/i386/smbios.h | 13 +++++
2 files changed, 110 insertions(+), 52 deletions(-)
diff --git a/hw/i386/smbios.c b/hw/i386/smbios.c
index 1341e02..fe15325 100644
--- a/hw/i386/smbios.c
+++ b/hw/i386/smbios.c
@@ -831,6 +831,25 @@ static void smbios_entry_point_setup(void)
ep.structure_table_address = cpu_to_le32(0);
}
+struct smbios_device_handler {
+ void (*handle_device_table)(void *opaque);
+ void *opaque;
+ struct smbios_device_handler *prev;
+};
+static struct smbios_device_handler *device_handlers;
+
+void smbios_register_device_table_handler(void (*handle_device_table)
+ (void *opaque),
+ void *opaque)
+{
+ struct smbios_device_handler *handler = g_malloc(sizeof(*handler));
+
+ handler->handle_device_table = handle_device_table;
+ handler->opaque = opaque;
+ handler->prev = device_handlers;
+ device_handlers = handler;
+}
+
void smbios_get_tables(uint8_t **tables, size_t *tables_len,
uint8_t **anchor, size_t *anchor_len)
{
@@ -875,6 +894,14 @@ void smbios_get_tables(uint8_t **tables, size_t *tables_len,
}
smbios_build_type_32_table();
+
+ while (device_handlers) {
+ struct smbios_device_handler *handler = device_handlers;
+ device_handlers = handler->prev;
+ handler->handle_device_table(handler->opaque);
+ g_free(handler);
+ }
+
smbios_build_type_127_table();
smbios_validate_table();
@@ -898,6 +925,71 @@ static void save_opt(const char **dest, QemuOpts *opts, const char *name)
}
}
+int smbios_table_entry_add(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 (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 */
+
+ return 0;
+}
+
void smbios_entry_add(QemuOpts *opts)
{
Error *local_err = NULL;
@@ -907,9 +999,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 +1014,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_add(data, size, false);
+ g_free(data);
return;
}
diff --git a/include/hw/i386/smbios.h b/include/hw/i386/smbios.h
index d2850be..656327d 100644
--- a/include/hw/i386/smbios.h
+++ b/include/hw/i386/smbios.h
@@ -27,6 +27,19 @@ 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.
+ */
+int smbios_table_entry_add(void *data, int size, bool append_zeros);
+
+/*
+ * When constructing SMBIOS tables, call a function at the end of the
+ * add process to allow devices to add their own SMBIOS table entries.
+ */
+void smbios_register_device_table_handler(void (*handle_device_table)
+ (void *opaque),
+ void *opaque);
+/*
* SMBIOS spec defined tables
*/
--
1.8.3.1
next prev parent reply other threads:[~2015-04-07 19:52 UTC|newest]
Thread overview: 36+ messages / expand[flat|nested] mbox.gz Atom feed top
2015-04-07 19:51 [Qemu-devel] [PATCH 00/15] IPMI device for qemu minyard
2015-04-07 19:51 ` [Qemu-devel] [PATCH 01/15] Add a base IPMI interface minyard
2015-04-07 19:51 ` [Qemu-devel] [PATCH 02/15] ipmi: Add a PC ISA type structure minyard
2015-04-07 19:51 ` [Qemu-devel] [PATCH 03/15] ipmi: Add a KCS low-level interface minyard
2015-04-07 19:51 ` [Qemu-devel] [PATCH 04/15] ipmi: Add a BT " minyard
2015-04-07 19:51 ` [Qemu-devel] [PATCH 05/15] ipmi: Add a local BMC simulation minyard
2015-04-07 19:51 ` [Qemu-devel] [PATCH 06/15] ipmi: Add an external connection simulation interface minyard
2015-04-07 19:51 ` [Qemu-devel] [PATCH 07/15] ipmi: Add tests minyard
2015-04-07 19:51 ` [Qemu-devel] [PATCH 08/15] ipmi: Add documentation minyard
2015-04-07 19:51 ` [Qemu-devel] [PATCH 09/15] ipmi: Add migration capability to the IPMI device minyard
2015-04-07 19:51 ` minyard [this message]
2015-04-12 16:05 ` [Qemu-devel] [PATCH 10/15] smbios: Add a function to directly add an entry Michael S. Tsirkin
2015-04-13 1:26 ` Corey Minyard
2015-04-13 7:00 ` Michael S. Tsirkin
2015-04-13 16:34 ` Corey Minyard
2015-04-13 16:40 ` Paolo Bonzini
2015-04-14 6:31 ` Michael S. Tsirkin
2015-04-14 15:30 ` Corey Minyard
2015-04-14 16:31 ` Paolo Bonzini
2015-04-14 6:41 ` Michael S. Tsirkin
2015-04-07 19:51 ` [Qemu-devel] [PATCH 11/15] pc: Postpone SMBIOS table installation to post machine init minyard
2015-04-07 19:51 ` [Qemu-devel] [PATCH 12/15] ipmi: Add SMBIOS table entry minyard
2015-04-07 19:51 ` [Qemu-devel] [PATCH 13/15] configure: Copy some items from default configs to target configs minyard
2015-04-10 11:47 ` Paolo Bonzini
2015-04-07 19:51 ` [Qemu-devel] [PATCH 14/15] acpi: Add hooks for adding things to the SSDT table minyard
2015-04-10 11:29 ` Paolo Bonzini
2015-04-12 16:17 ` Michael S. Tsirkin
2015-04-13 1:30 ` Corey Minyard
2015-04-13 6:36 ` Michael S. Tsirkin
2015-04-13 8:39 ` Paolo Bonzini
2015-04-13 11:32 ` Michael S. Tsirkin
2015-04-13 13:47 ` Paolo Bonzini
2015-04-13 13:44 ` Paolo Bonzini
2015-04-13 16:00 ` Corey Minyard
2015-04-13 16:41 ` Paolo Bonzini
2015-04-10 11:48 ` [Qemu-devel] [PATCH 00/15] IPMI device for qemu Paolo Bonzini
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=1428436304-24044-11-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).