diff mbox

[kvm-unit-tests,1/2] x86: add small library to find ACPI tables

Message ID 1440186882-27262-2-git-send-email-pbonzini@redhat.com (mailing list archive)
State New, archived
Headers show

Commit Message

Paolo Bonzini Aug. 21, 2015, 7:54 p.m. UTC
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
---
 config/config-x86-common.mak |   1 +
 lib/x86/acpi.c               |  52 ++++++++++++++++++
 lib/x86/acpi.h               | 104 +++++++++++++++++++++++++++++++++++
 x86/s3.c                     | 127 ++-----------------------------------------
 4 files changed, 162 insertions(+), 122 deletions(-)
 create mode 100644 lib/x86/acpi.c
 create mode 100644 lib/x86/acpi.h
diff mbox

Patch

diff --git a/config/config-x86-common.mak b/config/config-x86-common.mak
index d45c9a8..869b5c7 100644
--- a/config/config-x86-common.mak
+++ b/config/config-x86-common.mak
@@ -11,6 +11,7 @@  cflatobjs += lib/x86/atomic.o
 cflatobjs += lib/x86/desc.o
 cflatobjs += lib/x86/isr.o
 cflatobjs += lib/x86/pci.o
+cflatobjs += lib/x86/acpi.o
 
 $(libcflat): LDFLAGS += -nostdlib
 $(libcflat): CFLAGS += -ffreestanding -I lib
diff --git a/lib/x86/acpi.c b/lib/x86/acpi.c
new file mode 100644
index 0000000..4373106
--- /dev/null
+++ b/lib/x86/acpi.c
@@ -0,0 +1,52 @@ 
+#include "libcflat.h"
+#include "acpi.h"
+
+void* find_acpi_table_addr(u32 sig)
+{
+    unsigned long addr;
+    struct rsdp_descriptor *rsdp;
+    struct rsdt_descriptor_rev1 *rsdt;
+    void *end;
+    int i;
+
+    /* FACS is special... */
+    if (sig == FACS_SIGNATURE) {
+        struct fadt_descriptor_rev1 *fadt;
+        fadt = find_acpi_table_addr(FACP_SIGNATURE);
+        if (!fadt) {
+            return NULL;
+        }
+        return (void*)(ulong)fadt->firmware_ctrl;
+    }
+
+    for(addr = 0xf0000; addr < 0x100000; addr += 16) {
+	rsdp = (void*)addr;
+	if (rsdp->signature == 0x2052545020445352LL)
+          break;
+    }
+    if (addr == 0x100000) {
+        printf("Can't find RSDP\n");
+        return 0;
+    }
+
+    if (sig == RSDP_SIGNATURE) {
+        return rsdp;
+    }
+
+    rsdt = (void*)(ulong)rsdp->rsdt_physical_address;
+    if (!rsdt || rsdt->signature != RSDT_SIGNATURE)
+        return 0;
+
+    if (sig == RSDT_SIGNATURE) {
+        return rsdt;
+    }
+
+    end = (void*)rsdt + rsdt->length;
+    for (i=0; (void*)&rsdt->table_offset_entry[i] < end; i++) {
+        struct acpi_table *t = (void*)(ulong)rsdt->table_offset_entry[i];
+        if (t && t->signature == sig) {
+            return t;
+        }
+    }
+   return NULL;
+}
diff --git a/lib/x86/acpi.h b/lib/x86/acpi.h
new file mode 100644
index 0000000..08aaf57
--- /dev/null
+++ b/lib/x86/acpi.h
@@ -0,0 +1,104 @@ 
+#ifndef KVM_ACPI_H
+#define KVM_ACPI_H 1
+
+#include "libcflat.h"
+
+#define ACPI_SIGNATURE(c1, c2, c3, c4) \
+	((c1) | ((c2) << 8) | ((c3) << 16) | ((c4) << 24))
+
+#define RSDP_SIGNATURE ACPI_SIGNATURE('R','S','D','P')
+#define RSDT_SIGNATURE ACPI_SIGNATURE('R','S','D','T')
+#define FACP_SIGNATURE ACPI_SIGNATURE('F','A','C','P')
+#define FACS_SIGNATURE ACPI_SIGNATURE('F','A','C','S')
+
+struct rsdp_descriptor {        /* Root System Descriptor Pointer */
+    u64 signature;              /* ACPI signature, contains "RSD PTR " */
+    u8  checksum;               /* To make sum of struct == 0 */
+    u8  oem_id [6];             /* OEM identification */
+    u8  revision;               /* Must be 0 for 1.0, 2 for 2.0 */
+    u32 rsdt_physical_address;  /* 32-bit physical address of RSDT */
+    u32 length;                 /* XSDT Length in bytes including hdr */
+    u64 xsdt_physical_address;  /* 64-bit physical address of XSDT */
+    u8  extended_checksum;      /* Checksum of entire table */
+    u8  reserved [3];           /* Reserved field must be 0 */
+};
+
+#define ACPI_TABLE_HEADER_DEF   /* ACPI common table header */ \
+    u32 signature;          /* ACPI signature (4 ASCII characters) */ \
+    u32 length;                 /* Length of table, in bytes, including header */ \
+    u8  revision;               /* ACPI Specification minor version # */ \
+    u8  checksum;               /* To make sum of entire table == 0 */ \
+    u8  oem_id [6];             /* OEM identification */ \
+    u8  oem_table_id [8];       /* OEM table identification */ \
+    u32 oem_revision;           /* OEM revision number */ \
+    u8  asl_compiler_id [4];    /* ASL compiler vendor ID */ \
+    u32 asl_compiler_revision;  /* ASL compiler revision number */
+
+struct acpi_table {
+    ACPI_TABLE_HEADER_DEF
+    char data[0];
+};
+
+struct rsdt_descriptor_rev1 {
+    ACPI_TABLE_HEADER_DEF
+    u32 table_offset_entry[0];
+};
+
+struct fadt_descriptor_rev1
+{
+    ACPI_TABLE_HEADER_DEF     /* ACPI common table header */
+    u32 firmware_ctrl;          /* Physical address of FACS */
+    u32 dsdt;                   /* Physical address of DSDT */
+    u8  model;                  /* System Interrupt Model */
+    u8  reserved1;              /* Reserved */
+    u16 sci_int;                /* System vector of SCI interrupt */
+    u32 smi_cmd;                /* Port address of SMI command port */
+    u8  acpi_enable;            /* Value to write to smi_cmd to enable ACPI */
+    u8  acpi_disable;           /* Value to write to smi_cmd to disable ACPI */
+    u8  S4bios_req;             /* Value to write to SMI CMD to enter S4BIOS state */
+    u8  reserved2;              /* Reserved - must be zero */
+    u32 pm1a_evt_blk;           /* Port address of Power Mgt 1a acpi_event Reg Blk */
+    u32 pm1b_evt_blk;           /* Port address of Power Mgt 1b acpi_event Reg Blk */
+    u32 pm1a_cnt_blk;           /* Port address of Power Mgt 1a Control Reg Blk */
+    u32 pm1b_cnt_blk;           /* Port address of Power Mgt 1b Control Reg Blk */
+    u32 pm2_cnt_blk;            /* Port address of Power Mgt 2 Control Reg Blk */
+    u32 pm_tmr_blk;             /* Port address of Power Mgt Timer Ctrl Reg Blk */
+    u32 gpe0_blk;               /* Port addr of General Purpose acpi_event 0 Reg Blk */
+    u32 gpe1_blk;               /* Port addr of General Purpose acpi_event 1 Reg Blk */
+    u8  pm1_evt_len;            /* Byte length of ports at pm1_x_evt_blk */
+    u8  pm1_cnt_len;            /* Byte length of ports at pm1_x_cnt_blk */
+    u8  pm2_cnt_len;            /* Byte Length of ports at pm2_cnt_blk */
+    u8  pm_tmr_len;             /* Byte Length of ports at pm_tm_blk */
+    u8  gpe0_blk_len;           /* Byte Length of ports at gpe0_blk */
+    u8  gpe1_blk_len;           /* Byte Length of ports at gpe1_blk */
+    u8  gpe1_base;              /* Offset in gpe model where gpe1 events start */
+    u8  reserved3;              /* Reserved */
+    u16 plvl2_lat;              /* Worst case HW latency to enter/exit C2 state */
+    u16 plvl3_lat;              /* Worst case HW latency to enter/exit C3 state */
+    u16 flush_size;             /* Size of area read to flush caches */
+    u16 flush_stride;           /* Stride used in flushing caches */
+    u8  duty_offset;            /* Bit location of duty cycle field in p_cnt reg */
+    u8  duty_width;             /* Bit width of duty cycle field in p_cnt reg */
+    u8  day_alrm;               /* Index to day-of-month alarm in RTC CMOS RAM */
+    u8  mon_alrm;               /* Index to month-of-year alarm in RTC CMOS RAM */
+    u8  century;                /* Index to century in RTC CMOS RAM */
+    u8  reserved4;              /* Reserved */
+    u8  reserved4a;             /* Reserved */
+    u8  reserved4b;             /* Reserved */
+};
+
+struct facs_descriptor_rev1
+{
+    u32 signature;           /* ACPI Signature */
+    u32 length;                 /* Length of structure, in bytes */
+    u32 hardware_signature;     /* Hardware configuration signature */
+    u32 firmware_waking_vector; /* ACPI OS waking vector */
+    u32 global_lock;            /* Global Lock */
+    u32 S4bios_f        : 1;    /* Indicates if S4BIOS support is present */
+    u32 reserved1       : 31;   /* Must be 0 */
+    u8  reserved3 [40];         /* Reserved - must be zero */
+};
+
+void* find_acpi_table_addr(u32 sig);
+
+#endif
diff --git a/x86/s3.c b/x86/s3.c
index d568aa7..72467a2 100644
--- a/x86/s3.c
+++ b/x86/s3.c
@@ -1,130 +1,13 @@ 
 #include "libcflat.h"
-
-struct rsdp_descriptor {        /* Root System Descriptor Pointer */
-    u64 signature;              /* ACPI signature, contains "RSD PTR " */
-    u8  checksum;               /* To make sum of struct == 0 */
-    u8  oem_id [6];             /* OEM identification */
-    u8  revision;               /* Must be 0 for 1.0, 2 for 2.0 */
-    u32 rsdt_physical_address;  /* 32-bit physical address of RSDT */
-    u32 length;                 /* XSDT Length in bytes including hdr */
-    u64 xsdt_physical_address;  /* 64-bit physical address of XSDT */
-    u8  extended_checksum;      /* Checksum of entire table */
-    u8  reserved [3];           /* Reserved field must be 0 */
-};
-
-#define ACPI_TABLE_HEADER_DEF   /* ACPI common table header */ \
-    u32 signature;          /* ACPI signature (4 ASCII characters) */ \
-    u32 length;                 /* Length of table, in bytes, including header */ \
-    u8  revision;               /* ACPI Specification minor version # */ \
-    u8  checksum;               /* To make sum of entire table == 0 */ \
-    u8  oem_id [6];             /* OEM identification */ \
-    u8  oem_table_id [8];       /* OEM table identification */ \
-    u32 oem_revision;           /* OEM revision number */ \
-    u8  asl_compiler_id [4];    /* ASL compiler vendor ID */ \
-    u32 asl_compiler_revision;  /* ASL compiler revision number */
-
-#define RSDT_SIGNATURE 0x54445352
-struct rsdt_descriptor_rev1 {
-    ACPI_TABLE_HEADER_DEF
-    u32 table_offset_entry[0];
-};
-
-#define FACP_SIGNATURE 0x50434146 // FACP
-struct fadt_descriptor_rev1
-{
-    ACPI_TABLE_HEADER_DEF     /* ACPI common table header */
-    u32 firmware_ctrl;          /* Physical address of FACS */
-    u32 dsdt;                   /* Physical address of DSDT */
-    u8  model;                  /* System Interrupt Model */
-    u8  reserved1;              /* Reserved */
-    u16 sci_int;                /* System vector of SCI interrupt */
-    u32 smi_cmd;                /* Port address of SMI command port */
-    u8  acpi_enable;            /* Value to write to smi_cmd to enable ACPI */
-    u8  acpi_disable;           /* Value to write to smi_cmd to disable ACPI */
-    u8  S4bios_req;             /* Value to write to SMI CMD to enter S4BIOS state */
-    u8  reserved2;              /* Reserved - must be zero */
-    u32 pm1a_evt_blk;           /* Port address of Power Mgt 1a acpi_event Reg Blk */
-    u32 pm1b_evt_blk;           /* Port address of Power Mgt 1b acpi_event Reg Blk */
-    u32 pm1a_cnt_blk;           /* Port address of Power Mgt 1a Control Reg Blk */
-    u32 pm1b_cnt_blk;           /* Port address of Power Mgt 1b Control Reg Blk */
-    u32 pm2_cnt_blk;            /* Port address of Power Mgt 2 Control Reg Blk */
-    u32 pm_tmr_blk;             /* Port address of Power Mgt Timer Ctrl Reg Blk */
-    u32 gpe0_blk;               /* Port addr of General Purpose acpi_event 0 Reg Blk */
-    u32 gpe1_blk;               /* Port addr of General Purpose acpi_event 1 Reg Blk */
-    u8  pm1_evt_len;            /* Byte length of ports at pm1_x_evt_blk */
-    u8  pm1_cnt_len;            /* Byte length of ports at pm1_x_cnt_blk */
-    u8  pm2_cnt_len;            /* Byte Length of ports at pm2_cnt_blk */
-    u8  pm_tmr_len;             /* Byte Length of ports at pm_tm_blk */
-    u8  gpe0_blk_len;           /* Byte Length of ports at gpe0_blk */
-    u8  gpe1_blk_len;           /* Byte Length of ports at gpe1_blk */
-    u8  gpe1_base;              /* Offset in gpe model where gpe1 events start */
-    u8  reserved3;              /* Reserved */
-    u16 plvl2_lat;              /* Worst case HW latency to enter/exit C2 state */
-    u16 plvl3_lat;              /* Worst case HW latency to enter/exit C3 state */
-    u16 flush_size;             /* Size of area read to flush caches */
-    u16 flush_stride;           /* Stride used in flushing caches */
-    u8  duty_offset;            /* Bit location of duty cycle field in p_cnt reg */
-    u8  duty_width;             /* Bit width of duty cycle field in p_cnt reg */
-    u8  day_alrm;               /* Index to day-of-month alarm in RTC CMOS RAM */
-    u8  mon_alrm;               /* Index to month-of-year alarm in RTC CMOS RAM */
-    u8  century;                /* Index to century in RTC CMOS RAM */
-    u8  reserved4;              /* Reserved */
-    u8  reserved4a;             /* Reserved */
-    u8  reserved4b;             /* Reserved */
-};
-
-#define FACS_SIGNATURE 0x53434146 // FACS
-struct facs_descriptor_rev1
-{
-    u32 signature;           /* ACPI Signature */
-    u32 length;                 /* Length of structure, in bytes */
-    u32 hardware_signature;     /* Hardware configuration signature */
-    u32 firmware_waking_vector; /* ACPI OS waking vector */
-    u32 global_lock;            /* Global Lock */
-    u32 S4bios_f        : 1;    /* Indicates if S4BIOS support is present */
-    u32 reserved1       : 31;   /* Must be 0 */
-    u8  resverved3 [40];        /* Reserved - must be zero */
-};
+#include "acpi.h"
 
 u32* find_resume_vector_addr(void)
 {
-    unsigned long addr;
-    struct rsdp_descriptor *rsdp;
-    struct rsdt_descriptor_rev1 *rsdt;
-    void *end;
-    int i;
-
-    for(addr = 0xf0000; addr < 0x100000; addr += 16) {
-	rsdp = (void*)addr;
-	if (rsdp->signature == 0x2052545020445352LL)
-          break;
-    }
-    if (addr == 0x100000) {
-        printf("Can't find RSDP\n");
-        return 0;
-    }
-
-    printf("RSDP is at %x\n", rsdp);
-    rsdt = (void*)(ulong)rsdp->rsdt_physical_address;
-    if (!rsdt || rsdt->signature != RSDT_SIGNATURE)
+    struct facs_descriptor_rev1 *facs = find_acpi_table_addr(FACS_SIGNATURE);
+    if (!facs)
         return 0;
-
-    printf("RSDT is at %x\n", rsdt);
-
-    end = (void*)rsdt + rsdt->length;
-    for (i=0; (void*)&rsdt->table_offset_entry[i] < end; i++) {
-        struct fadt_descriptor_rev1 *fadt = (void*)(ulong)rsdt->table_offset_entry[i];
-        struct facs_descriptor_rev1 *facs;
-        if (!fadt || fadt->signature != FACP_SIGNATURE)
-            continue;
-        printf("FADT is at %x\n", fadt);
-        facs = (void*)(ulong)fadt->firmware_ctrl;
-        if (!facs || facs->signature != FACS_SIGNATURE)
-            return 0;
-        printf("FACS is at %x\n", facs);
-        return &facs->firmware_waking_vector;
-    }
-   return 0;
+    printf("FACS is at %x\n", facs);
+    return &facs->firmware_waking_vector;
 }
 
 #define RTC_SECONDS_ALARM       1