qemu-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Qemu-devel] [PATCH 13/16] acpi: Add a way to extend tables


From: minyard
Subject: [Qemu-devel] [PATCH 13/16] acpi: Add a way to extend tables
Date: Fri, 12 Dec 2014 13:15:48 -0600

From: Corey Minyard <address@hidden>

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 <address@hidden>
---
 hw/acpi/core.c         | 106 +++++++++++++++++++++++++++++++++----------------
 include/hw/acpi/acpi.h |   2 +
 2 files changed, 74 insertions(+), 34 deletions(-)

diff --git a/hw/acpi/core.c b/hw/acpi/core.c
index 51913d6..a4cb485 100644
--- a/hw/acpi/core.c
+++ b/hw/acpi/core.c
@@ -78,33 +78,16 @@ static int acpi_checksum(const uint8_t *data, int len)
     return (-sum) & 0xff;
 }
 
-
-/* Install a copy of the ACPI table specified in @blob.
- *
- * If @has_header is set, @blob starts with the System Description Table Header
- * structure. Otherwise, "dfl_hdr" is prepended. In any case, each header field
- * is optionally overwritten from @hdrs.
- *
- * It is valid to call this function with
- * (@blob == NULL && bloblen == 0 && !has_header).
- *
- * @hdrs->file and @hdrs->data are ignored.
- *
- * SIZE_MAX is considered "infinity" in this function.
- *
- * The number of tables that can be installed is not limited, but the 16-bit
- * counter at the beginning of "acpi_tables" wraps around after UINT16_MAX.
- */
-static void acpi_table_install(const char unsigned *blob, size_t bloblen,
-                               bool has_header,
-                               const struct AcpiTableOptions *hdrs,
-                               Error **errp)
+static struct acpi_table_header *acpi_new_table(const unsigned char *blob,
+                                                size_t bloblen,
+                                                bool has_header,
+                                                size_t *rpayload_size,
+                                                Error **errp)
 {
     size_t body_start;
-    const char unsigned *hdr_src;
+    const unsigned char *hdr_src;
     size_t body_size, acpi_payload_size;
     struct acpi_table_header *ext_hdr;
-    unsigned changed_fields;
 
     /* Calculate where the ACPI table body starts within the blob, plus where
      * to copy the ACPI table header from.
@@ -124,7 +107,7 @@ static void acpi_table_install(const char unsigned *blob, 
size_t bloblen,
             error_setg(errp, "ACPI table claiming to have header is too "
                        "short, available: %zu, expected: %zu", bloblen,
                        body_start);
-            return;
+            return NULL;
         }
         hdr_src = blob;
     } else {
@@ -145,7 +128,7 @@ static void acpi_table_install(const char unsigned *blob, 
size_t bloblen,
     if (acpi_payload_size > UINT16_MAX) {
         error_setg(errp, "ACPI table too big, requested: %zu, max: %u",
                    acpi_payload_size, (unsigned)UINT16_MAX);
-        return;
+        return NULL;
     }
 
     /* We won't fail from here on. Initialize / extend the globals. */
@@ -173,29 +156,63 @@ static void acpi_table_install(const char unsigned *blob, 
size_t bloblen,
     stw_le_p(acpi_tables, lduw_le_p(acpi_tables) + 1u);
 
     /* Update the header fields. The strings need not be NUL-terminated. */
-    changed_fields = 0;
     ext_hdr->_length = cpu_to_le16(acpi_payload_size);
 
-    if (hdrs->has_sig) {
-        strncpy(ext_hdr->sig, hdrs->sig, sizeof ext_hdr->sig);
-        ++changed_fields;
-    }
-
     if (has_header && le32_to_cpu(ext_hdr->length) != acpi_payload_size) {
         fprintf(stderr,
                 "warning: ACPI table has wrong length, header says "
                 "%" PRIu32 ", actual size %zu bytes\n",
                 le32_to_cpu(ext_hdr->length), acpi_payload_size);
     }
+
     ext_hdr->length = cpu_to_le32(acpi_payload_size);
+    *rpayload_size = acpi_payload_size;
+
+    return ext_hdr;
+}
+
+/* Install a copy of the ACPI table specified in @blob.
+ *
+ * If @has_header is set, @blob starts with the System Description Table Header
+ * structure. Otherwise, "dfl_hdr" is prepended. In any case, each header field
+ * is optionally overwritten from @hdrs.
+ *
+ * It is valid to call this function with
+ * (@blob == NULL && bloblen == 0 && !has_header).
+ *
+ * @hdrs->file and @hdrs->data are ignored.
+ *
+ * SIZE_MAX is considered "infinity" in this function.
+ *
+ * The number of tables that can be installed is not limited, but the 16-bit
+ * counter at the beginning of "acpi_tables" wraps around after UINT16_MAX.
+ */
+static void acpi_table_install(const char unsigned *blob, size_t bloblen,
+                               bool has_header,
+                               const struct AcpiTableOptions *hdrs,
+                               Error **errp)
+{
+    struct acpi_table_header *ext_hdr;
+    size_t payload_size = 0;
+    unsigned changed_fields = 0;
+
+    ext_hdr = acpi_new_table(blob, bloblen, has_header, &payload_size, errp);
+    if (errp && !*errp) {
+        return;
+    }
+
+    ext_hdr->checksum = 0;
+
+    if (hdrs->has_sig) {
+        strncpy(ext_hdr->sig, hdrs->sig, sizeof ext_hdr->sig);
+        ++changed_fields;
+    }
 
     if (hdrs->has_rev) {
         ext_hdr->revision = hdrs->rev;
         ++changed_fields;
     }
 
-    ext_hdr->checksum = 0;
-
     if (hdrs->has_oem_id) {
         strncpy(ext_hdr->oem_id, hdrs->oem_id, sizeof ext_hdr->oem_id);
         ++changed_fields;
@@ -225,7 +242,28 @@ static void acpi_table_install(const char unsigned *blob, 
size_t bloblen,
 
     /* recalculate checksum */
     ext_hdr->checksum = acpi_checksum((const char unsigned *)ext_hdr +
-                                      ACPI_TABLE_PFX_SIZE, acpi_payload_size);
+                                      ACPI_TABLE_PFX_SIZE, payload_size);
+}
+
+/*
+ * Add a table from an internal driver.
+ */
+void acpi_append_to_table(const char *sig, void *blob, size_t bloblen,
+                          Error **errp)
+{
+    struct acpi_table_header *ext_hdr;
+    size_t payload_size = 0;
+
+    ext_hdr = acpi_new_table(blob, bloblen, false, &payload_size, errp);
+    if (errp && *errp) {
+        return;
+    }
+
+    strncpy(ext_hdr->sig, sig, sizeof ext_hdr->sig);
+
+    /* recalculate checksum */
+    ext_hdr->checksum = acpi_checksum((const char unsigned *)ext_hdr +
+                                      ACPI_TABLE_PFX_SIZE, payload_size);
 }
 
 void acpi_table_add(const QemuOpts *opts, Error **errp)
diff --git a/include/hw/acpi/acpi.h b/include/hw/acpi/acpi.h
index 1f678b4..acdd432 100644
--- a/include/hw/acpi/acpi.h
+++ b/include/hw/acpi/acpi.h
@@ -184,5 +184,7 @@ uint8_t *acpi_table_next(uint8_t *current);
 unsigned acpi_table_len(void *current);
 void acpi_table_add(const QemuOpts *opts, Error **errp);
 void acpi_table_add_builtin(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 */
-- 
1.8.3.1




reply via email to

[Prev in Thread] Current Thread [Next in Thread]