[SeaBIOS] [PATCH 3/4] acpi: EJ0 method name patching

Michael S. Tsirkin mst at redhat.com
Wed Sep 21 14:44:37 CEST 2011


Modify ACPI to only supply _EJ0 methods for PCI
slots that support hotplug.

This is done by runtime patching:
- Rename _EJ0 methods for PCI slots in DSDT to EJ0_:
  note that this has the same checksum, but
  is ignored by OSPM.
- At compile time, look for these methods in ASL source,
  find the matching AML,  and store the offsets of these methods
  in a table named aml_ej0_data.
  Note that we are looking for EJ0_ in source code,
  so we'll be able to write EJ0 if we want to and the script
  will not match it.
- At run time, go over aml_ej0_data, check which slots
  support hotplug and patch the ACPI table, replacing EJ0_ with _EJ0.

Note: the method used is robust in that we don't need
to change any offsets manually in case of ASL code changes.
As all parsing is done at compile time, any unexpected input causes
build failure, not a runtime failure.

Signed-off-by: Michael S. Tsirkin <mst at redhat.com>
---
 Makefile          |    3 ++-
 src/acpi-dsdt.dsl |    9 +++++++--
 src/acpi.c        |   11 +++++++++++
 3 files changed, 20 insertions(+), 3 deletions(-)

diff --git a/Makefile b/Makefile
index 5c011bb..dee93d6 100644
--- a/Makefile
+++ b/Makefile
@@ -197,7 +197,8 @@ src/%.hex: src/%.dsl src/splitdsl.pl src/find_ej0.pl
 	$(Q)cpp -P $< > $(OUT)$*.dsl.i.orig
 	$(Q)./src/splitdsl.pl $(OUT)$*.dsl.i.orig > $(OUT)$*.dsl.i
 	$(Q)iasl -l -tc -p $(OUT)$* $(OUT)$*.dsl.i
-	$(Q)cp $(OUT)$*.hex $@
+	$(Q)./src/find_ej0.pl $(OUT)$*.lst > $(OUT)$*.off
+	$(Q)cat $(OUT)$*.hex $(OUT)$*.off > $@
 
 $(OUT)ccode32flat.o: src/acpi-dsdt.hex
 
diff --git a/src/acpi-dsdt.dsl b/src/acpi-dsdt.dsl
index 08412e2..3d43e4b 100644
--- a/src/acpi-dsdt.dsl
+++ b/src/acpi-dsdt.dsl
@@ -127,11 +127,16 @@ DefinitionBlock (
             {
                 PCRM, 32,
             }
-
+            // Method EJ0_ will be patched by BIOS to _EJ0
+            // at runtime, if the slot is detected to support hotplug.
+            // Must be immediately preceded by _ADR for this to work.
+            // EJ0_ is not allowed anywhere else in this file,
+            // if you really want to use it, write EJ0 which
+            // creates the same AML but isn't patched.
 #define hotplug_slot(name, nr) \
             Device (S##name) {                    \
                Name (_ADR, nr##0000)              \
-               Method (_EJ0,1) {                  \
+               Method (EJ0_,1) {                  \
                     Store(ShiftLeft(1, nr), B0EJ) \
                     Return (0x0)                  \
                }                                  \
diff --git a/src/acpi.c b/src/acpi.c
index 6bb6ff6..cbb5143 100644
--- a/src/acpi.c
+++ b/src/acpi.c
@@ -198,6 +198,8 @@ struct srat_memory_affinity
     u32    reserved3[2];
 } PACKED;
 
+#define PCI_RMV_BASE 0xae0c
+
 #include "acpi-dsdt.hex"
 
 static void
@@ -243,6 +245,8 @@ build_fadt(struct pci_device *pci)
     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));
+    u32 rmvc_pcrm;
+    int i;
 
     if (!fadt || !facs || !dsdt) {
         warn_noalloc();
@@ -255,7 +259,13 @@ build_fadt(struct pci_device *pci)
     facs->length = cpu_to_le32(sizeof(*facs));
 
     /* DSDT */
     memcpy(dsdt, AmlCode, sizeof(AmlCode));
+    rmvc_pcrm = inl(PCI_RMV_BASE);
+    for (i = 0; i < sizeof(aml_ej0_data) / sizeof(*aml_ej0_data); ++i) {
+        if (rmvc_pcrm & aml_ej0_data[i].slot_mask) {
+            memcpy(dsdt + aml_ej0_data[i].offset, "_EJ0", 4);
+        }
+    }
 
     /* FADT */
     memset(fadt, 0, sizeof(*fadt));
-- 
1.7.5.53.gc233e




More information about the SeaBIOS mailing list