Patchwork [RFC,2/7] acpi: split and rename acpi_table_add()

login
register
mail settings
Submitter Eduard - Gabriel Munteanu
Date March 30, 2010, 8:20 a.m.
Message ID <972d931f99c27de91d043b1332eb564e6b4260db.1269936879.git.eduard.munteanu@linux360.ro>
Download mbox | patch
Permalink /patch/48968/
State New
Headers show

Comments

Eduard - Gabriel Munteanu - March 30, 2010, 8:20 a.m.
We'd like to let emulation code build and insert ACPI tables at bootup,
without depending on hacking the BIOS code. This will be used to provide
an IVRS table for emulating the AMD IOMMU, for instance.

This splits acpi_table_add(), retaining the old behavior of inserting
cmdline-supplied tables under the name of acpi_table_cmdline_add(). The
other two resulting functions can be used for the aforementioned
purpose.

Signed-off-by: Eduard - Gabriel Munteanu <eduard.munteanu@linux360.ro>
---
 hw/acpi.c |   64 ++++++++++++++++++++++++++++++++++++++++---------------------
 hw/pc.h   |    4 ++-
 vl.c      |    2 +-
 3 files changed, 46 insertions(+), 24 deletions(-)

Patch

diff --git a/hw/acpi.c b/hw/acpi.c
index 7c4e8d3..8eb53da 100644
--- a/hw/acpi.c
+++ b/hw/acpi.c
@@ -840,7 +840,7 @@  struct acpi_table_header
 } __attribute__((packed));
 
 char *acpi_tables;
-size_t acpi_tables_len;
+size_t acpi_tables_len, acpi_tables_prev_len;
 
 static int acpi_checksum(const uint8_t *data, int len)
 {
@@ -851,13 +851,44 @@  static int acpi_checksum(const uint8_t *data, int len)
     return (-sum) & 0xff;
 }
 
-int acpi_table_add(const char *t)
+void *acpi_alloc_table(size_t size)
+{
+    void *ptr;
+
+    if (!acpi_tables) {
+        acpi_tables_len = sizeof(uint16_t);
+        acpi_tables = qemu_mallocz(acpi_tables_len);
+    }
+    acpi_tables_prev_len = acpi_tables_len;
+    acpi_tables_len += sizeof(uint16_t) + size;
+    acpi_tables = qemu_realloc(acpi_tables, acpi_tables_len);
+    ptr = acpi_tables + acpi_tables_prev_len;
+
+    *(uint16_t *) ptr = size;
+
+    return ptr + sizeof(uint16_t);
+}
+
+void acpi_commit_table(void *buf)
+{
+    struct acpi_table_header *acpi_hdr = buf;
+    size_t size = acpi_tables_len - acpi_tables_prev_len - sizeof(uint16_t);
+
+    acpi_hdr->length = cpu_to_le32(size);
+    acpi_hdr->checksum = acpi_checksum(buf, size);
+
+    /* increase number of tables */
+    (*(uint16_t *) acpi_tables) =
+	    cpu_to_le32(le32_to_cpu(*(uint16_t *) acpi_tables) + 1);
+}
+
+int acpi_table_cmdline_add(const char *t)
 {
     static const char *dfl_id = "QEMUQEMU";
     char buf[1024], *p, *f;
     struct acpi_table_header acpi_hdr;
     unsigned long val;
-    size_t newlen, off;
+    size_t size, off;
 
     memset(&acpi_hdr, 0, sizeof(acpi_hdr));
   
@@ -915,7 +946,7 @@  int acpi_table_add(const char *t)
          buf[0] = '\0';
     }
 
-    acpi_hdr.length = sizeof(acpi_hdr);
+    size = sizeof(acpi_hdr);
 
     f = buf;
     while (buf[0]) {
@@ -927,27 +958,17 @@  int acpi_table_add(const char *t)
             fprintf(stderr, "Can't stat file '%s': %s\n", f, strerror(errno));
             goto out;
         }
-        acpi_hdr.length += s.st_size;
+        size += s.st_size;
         if (!n)
             break;
         *n = ':';
         f = n + 1;
     }
 
-    if (!acpi_tables) {
-        acpi_tables_len = sizeof(uint16_t);
-        acpi_tables = qemu_mallocz(acpi_tables_len);
-    }
-    newlen = acpi_tables_len + sizeof(uint16_t) + acpi_hdr.length;
-    acpi_tables = qemu_realloc(acpi_tables, newlen);
-    p = acpi_tables + acpi_tables_len;
-    acpi_tables_len = newlen;
+    p = acpi_alloc_table(size);
+    off = sizeof(struct acpi_table_header);
 
-    acpi_hdr.length = cpu_to_le32(acpi_hdr.length);
-    *(uint16_t*)p = acpi_hdr.length;
-    p += sizeof(uint16_t);
-    memcpy(p, &acpi_hdr, sizeof(acpi_hdr));
-    off = sizeof(acpi_hdr);
+    memcpy(p, &acpi_hdr, off);
 
     f = buf;
     while (buf[0]) {
@@ -983,10 +1004,8 @@  int acpi_table_add(const char *t)
         f = n + 1;
     }
 
-    ((struct acpi_table_header*)p)->checksum = acpi_checksum((uint8_t*)p, off);
-    /* increase number of tables */
-    (*(uint16_t*)acpi_tables) =
-	    cpu_to_le32(le32_to_cpu(*(uint16_t*)acpi_tables) + 1);
+    acpi_commit_table(p);
+
     return 0;
 out:
     if (acpi_tables) {
@@ -995,3 +1014,4 @@  out:
     }
     return -1;
 }
+
diff --git a/hw/pc.h b/hw/pc.h
index b599564..0cef140 100644
--- a/hw/pc.h
+++ b/hw/pc.h
@@ -108,7 +108,9 @@  extern char *acpi_tables;
 extern size_t acpi_tables_len;
 
 void acpi_bios_init(void);
-int acpi_table_add(const char *table_desc);
+void *acpi_alloc_table(size_t size);
+void acpi_commit_table(void *buf);
+int acpi_table_cmdline_add(const char *table_desc);
 
 /* acpi_piix.c */
 i2c_bus *piix4_pm_init(PCIBus *bus, int devfn, uint32_t smb_io_base,
diff --git a/vl.c b/vl.c
index d959fdb..0efba90 100644
--- a/vl.c
+++ b/vl.c
@@ -5492,7 +5492,7 @@  int main(int argc, char **argv, char **envp)
                 rtc_td_hack = 1;
                 break;
             case QEMU_OPTION_acpitable:
-                if(acpi_table_add(optarg) < 0) {
+                if(acpi_table_cmdline_add(optarg) < 0) {
                     fprintf(stderr, "Wrong acpi table provided\n");
                     exit(1);
                 }