Patchwork [v2] seabios: acpi: allow qemu to load dsdt as external acpi table.

login
register
mail settings
Submitter Isaku Yamahata
Date June 22, 2010, 8:53 a.m.
Message ID <20100622085326.GA28468@valinux.co.jp>
Download mbox | patch
Permalink /patch/56441/
State New
Headers show

Comments

Isaku Yamahata - June 22, 2010, 8:53 a.m.
allow qemu to load dsdt as external acpi table.

Signed-off-by: Isaku Yamahata <yamahata@valinux.co.jp>

---
changes v1 -> v2.
- load qemu table first and they try default dsdt table if
  qemu doesn't supply dsdt.
  Thus unnecessary malloc_high()/free() is avoided.
---
 src/acpi.c |   49 +++++++++++++++++++++++++++++++++++++++++--------
 1 files changed, 41 insertions(+), 8 deletions(-)

Patch

diff --git a/src/acpi.c b/src/acpi.c
index 0559443..b75f9af 100644
--- a/src/acpi.c
+++ b/src/acpi.c
@@ -126,6 +126,11 @@  struct fadt_descriptor_rev1
 } PACKED;
 
 /*
+ * Differentiated System Descrition Table (DSDT)
+ */
+#define DSDT_SIGNATURE 0x54445344 // DSDT
+
+/*
  * MADT values and structures
  */
 
@@ -280,6 +285,11 @@  static inline u32 cpu_to_le32(u32 x)
     return x;
 }
 
+static inline u32 le32_to_cpu(u32 x)
+{
+    return x;
+}
+
 static void
 build_header(struct acpi_table_header *h, u32 sig, int len, u8 rev)
 {
@@ -295,14 +305,20 @@  build_header(struct acpi_table_header *h, u32 sig, int len, u8 rev)
     h->checksum -= checksum(h, len);
 }
 
+static void fill_dsdt(struct fadt_descriptor_rev1 *fadt, void *dsdt)
+{
+    fadt->dsdt = cpu_to_le32((u32)dsdt);
+    fadt->checksum -= checksum(fadt, sizeof(*fadt));
+    dprintf(1, "ACPI DSDT=%p\n", dsdt);
+}
+
 static void*
 build_fadt(int bdf)
 {
     struct fadt_descriptor_rev1 *fadt = malloc_high(sizeof(*fadt));
     struct facs_descriptor_rev1 *facs = memalign_high(64, sizeof(*facs));
-    void *dsdt = malloc_high(sizeof(AmlCode));
 
-    if (!fadt || !facs || !dsdt) {
+    if (!fadt || !facs) {
         warn_noalloc();
         return NULL;
     }
@@ -312,13 +328,11 @@  build_fadt(int bdf)
     facs->signature = FACS_SIGNATURE;
     facs->length = cpu_to_le32(sizeof(*facs));
 
-    /* DSDT */
-    memcpy(dsdt, AmlCode, sizeof(AmlCode));
-
     /* FADT */
     memset(fadt, 0, sizeof(*fadt));
     fadt->firmware_ctrl = cpu_to_le32((u32)facs);
-    fadt->dsdt = cpu_to_le32((u32)dsdt);
+    fadt->dsdt = 0;  /* dsdt will be filled later in acpi_bios_init()
+                        by fill_dsdt() */
     fadt->model = 1;
     fadt->reserved1 = 0;
     int pm_sci_int = pci_config_readb(bdf, PCI_INTERRUPT_LINE);
@@ -634,7 +648,8 @@  acpi_bios_init(void)
     } while(0)
 
     // Add tables
-    ACPI_INIT_TABLE(build_fadt(bdf));
+    struct fadt_descriptor_rev1 *fadt = build_fadt(bdf);
+    ACPI_INIT_TABLE(fadt);
     ACPI_INIT_TABLE(build_ssdt());
     ACPI_INIT_TABLE(build_madt());
     ACPI_INIT_TABLE(build_hpet());
@@ -649,12 +664,30 @@  acpi_bios_init(void)
             warn_noalloc();
             continue;
         }
-        ACPI_INIT_TABLE(qemu_cfg_next_acpi_table_load(addr, len));
+        struct acpi_table_header *header =
+            qemu_cfg_next_acpi_table_load(addr, len);
+        if (header->signature == DSDT_SIGNATURE) {
+            if (fadt) {
+                fill_dsdt(fadt, addr);
+            }
+        } else {
+            ACPI_INIT_TABLE(header);
+        }
         if (tbl_idx == MAX_ACPI_TABLES) {
             warn_noalloc();
             break;
         }
     }
+    if (fadt && !fadt->dsdt) {
+        /* default DSDT */
+        void *dsdt = malloc_high(sizeof(AmlCode));
+        if (!dsdt) {
+            warn_noalloc();
+            return;
+        }
+        memcpy(dsdt, AmlCode, sizeof(AmlCode));
+        fill_dsdt(fadt, dsdt);
+    }
 
     struct rsdt_descriptor_rev1 *rsdt;
     size_t rsdt_len = sizeof(*rsdt) + sizeof(u32) * tbl_idx;