[SeaBIOS] [PATCH 3/4] Add acpi_reboot() reset method using RESET_REG

David Woodhouse dwmw2 at infradead.org
Sat Feb 23 01:24:49 CET 2013


From: David Woodhouse <David.Woodhouse at intel.com>

Signed-off-by: David Woodhouse <David.Woodhouse at intel.com>
---
 src/acpi.c   | 58 +++++++++++++++++++++++++++++++++++++++++++++++-----------
 src/acpi.h   | 14 ++++++++++++++
 src/resume.c |  3 +++
 3 files changed, 64 insertions(+), 11 deletions(-)

diff --git a/src/acpi.c b/src/acpi.c
index 36bd39a..195dc88 100644
--- a/src/acpi.c
+++ b/src/acpi.c
@@ -151,17 +151,6 @@ struct madt_local_nmi {
 
 
 /*
- * ACPI 2.0 Generic Address Space definition.
- */
-struct acpi_20_generic_address {
-    u8  address_space_id;
-    u8  register_bit_width;
-    u8  register_bit_offset;
-    u8  reserved;
-    u64 address;
-} PACKED;
-
-/*
  * HPET Description Table
  */
 struct acpi_20_hpet {
@@ -934,4 +923,51 @@ find_acpi_features(void)
     dprintf(4, "pm_tmr_blk=%x\n", pm_tmr);
     if (pm_tmr)
         pmtimer_setup(pm_tmr, 3579);
+
+    // Theoretically we should check the 'reset_reg_sup' flag, but Windows
+    // doesn't and thus nobody seems to *set* it. If the table is large enough
+    // to include it, let the sanity checks in acpi_set_reset_reg() suffice.
+    if (fadt->length >= 129) {
+        void *p = fadt;
+        acpi_set_reset_reg(p + 116, *(u8 *)(p + 128));
+    }
+}
+
+static struct acpi_20_generic_address acpi_reset_reg;
+static u8 acpi_reset_val;
+
+void
+acpi_reboot(void)
+{
+    // Check it passed the sanity checks in acpi_set_reset_reg() and was set
+    if (acpi_reset_reg.register_bit_width != 8)
+        return;
+
+    u64 addr = le64_to_cpu(acpi_reset_reg.address);
+
+    dprintf(1, "ACPI hard reset %d:%llx (%x)\n",
+            acpi_reset_reg.address_space_id, addr, acpi_reset_val);
+
+    switch (acpi_reset_reg.address_space_id) {
+    case 0: // System Memory
+	writeb((void *)(u32)addr, acpi_reset_val);
+        break;
+    case 1: // System I/O
+        outb(acpi_reset_val, addr);
+        break;
+    case 2: // PCI config space
+        pci_config_writeb(acpi_ga_to_bdf(addr), addr & 0xffff, acpi_reset_val);
+        break;
+    }
+}
+
+void
+acpi_set_reset_reg(struct acpi_20_generic_address *reg, u8 val)
+{
+    if (!reg || reg->address_space_id > 2 ||
+        reg->register_bit_width != 8 || reg->register_bit_offset)
+        return;
+
+    acpi_reset_reg = *reg;
+    acpi_reset_val = val;
 }
diff --git a/src/acpi.h b/src/acpi.h
index b23717a..6289953 100644
--- a/src/acpi.h
+++ b/src/acpi.h
@@ -3,9 +3,23 @@
 
 #include "types.h" // u32
 
+/*
+ * ACPI 2.0 Generic Address Space definition.
+ */
+struct acpi_20_generic_address {
+    u8  address_space_id;
+    u8  register_bit_width;
+    u8  register_bit_offset;
+    u8  reserved;
+    u64 address;
+} PACKED;
+#define acpi_ga_to_bdf(addr) pci_to_bdf(0, (addr >> 32) & 0xffff, (addr >> 16) & 0xffff)
+
 void acpi_setup(void);
 u32 find_resume_vector(void);
 void find_acpi_features(void);
+void acpi_set_reset_reg(struct acpi_20_generic_address *reg, u8 val);
+void acpi_reboot(void);
 
 #define RSDP_SIGNATURE 0x2052545020445352LL // "RSD PTR "
 
diff --git a/src/resume.c b/src/resume.c
index b30d62e..784abac 100644
--- a/src/resume.c
+++ b/src/resume.c
@@ -132,6 +132,9 @@ tryReboot(void)
     // Setup for reset on qemu.
     qemu_prep_reset();
 
+    // Reboot using ACPI RESET_REG
+    acpi_reboot();
+
     // Try keyboard controller reboot.
     i8042_reboot();
 
-- 
1.8.1.2




More information about the SeaBIOS mailing list