diff mbox

[15/20] acpi: Add a way to extend tables

Message ID 1369865296-19584-16-git-send-email-minyard@acm.org
State New
Headers show

Commit Message

Corey Minyard May 29, 2013, 10:08 p.m. UTC
From: Corey Minyard <cminyard@mvista.com>

Add a function that can extend the contents of a given
ACPI table to add on new entries.  This way devices that
have ACPI entries can add them.

Signed-off-by: Corey Minyard <cminyard@mvista.com>
---
 hw/acpi/core.c         |   47 +++++++++++++++++++++++++++++++++++++++++++++++
 include/hw/acpi/acpi.h |    2 ++
 2 files changed, 49 insertions(+)
diff mbox

Patch

diff --git a/hw/acpi/core.c b/hw/acpi/core.c
index 42eeace..4bd006c 100644
--- a/hw/acpi/core.c
+++ b/hw/acpi/core.c
@@ -229,6 +229,53 @@  static void acpi_table_install(const char unsigned *blob, size_t bloblen,
                                       ACPI_TABLE_PFX_SIZE, acpi_payload_size);
 }
 
+void acpi_append_to_table(const char *sig, void *blob, size_t bloblen,
+                          Error **errp)
+{
+    struct acpi_table_header *ext_hdr;
+    unsigned int ntables, i;
+    size_t acpi_payload_size;
+    size_t pos, pos2;
+
+    if (!acpi_tables)
+        return;
+
+    ntables = le16_to_cpupu((uint16_t *)acpi_tables);
+    pos = sizeof(uint16_t);
+    for (i = 0; i < ntables; i++) {
+        ext_hdr = (void *) (((char *) acpi_tables) + pos);
+        if (memcmp(sig, ext_hdr->sig, 4) == 0)
+            break;
+        pos += le16_to_cpupu(&ext_hdr->_length) + ACPI_TABLE_PFX_SIZE;
+    }
+    if (i == ntables)
+        return;
+
+    acpi_payload_size = le16_to_cpupu(&ext_hdr->_length);
+    if (acpi_payload_size + bloblen > UINT16_MAX) {
+        error_setg(errp, "ACPI table overflow adding field");
+        return;
+    }
+
+    acpi_tables = g_realloc(acpi_tables, acpi_tables_len + bloblen);
+
+    pos2 = pos + acpi_payload_size + ACPI_TABLE_PFX_SIZE;
+    memcpy(acpi_tables + pos2 + bloblen, acpi_tables + pos2,
+           acpi_tables_len - pos2);
+    memcpy(acpi_tables + pos2, blob, bloblen);
+
+    acpi_payload_size += bloblen;
+
+    ext_hdr = (void *) (((char *) acpi_tables) + pos);
+    ext_hdr->_length = cpu_to_le16(acpi_payload_size);
+    ext_hdr->length = cpu_to_le32(acpi_payload_size);
+
+    ext_hdr->checksum = 0;
+    ext_hdr->checksum = acpi_checksum((const char unsigned *)ext_hdr +
+                                      ACPI_TABLE_PFX_SIZE, acpi_payload_size);
+    acpi_tables_len += bloblen;
+}
+
 void acpi_table_add(const QemuOpts *opts, Error **errp)
 {
     AcpiTableOptions *hdrs = NULL;
diff --git a/include/hw/acpi/acpi.h b/include/hw/acpi/acpi.h
index 635be7b..01d3a1b 100644
--- a/include/hw/acpi/acpi.h
+++ b/include/hw/acpi/acpi.h
@@ -166,5 +166,7 @@  extern char unsigned *acpi_tables;
 extern size_t acpi_tables_len;
 
 void acpi_table_add(const QemuOpts *opts, Error **errp);
+void acpi_append_to_table(const char *sig, void *blob, size_t bloblen,
+                          Error **errp);
 
 #endif /* !QEMU_HW_ACPI_H */