From: Michael Kelly <[email protected]>
acpi now has to be initialised by calling acpi_initialise().
---
i386/i386at/acpi_parse_apic.c | 102 ++++++++++++++++++++++++----------
i386/i386at/acpi_parse_apic.h | 3 +
i386/i386at/model_dep.c | 1 +
3 files changed, 77 insertions(+), 29 deletions(-)
diff --git a/i386/i386at/acpi_parse_apic.c b/i386/i386at/acpi_parse_apic.c
index 848585c2..9edb524c 100644
--- a/i386/i386at/acpi_parse_apic.c
+++ b/i386/i386at/acpi_parse_apic.c
@@ -36,6 +36,12 @@ static struct acpi_apic *apic_madt = NULL;
unsigned lapic_addr;
uint32_t *hpet_addr;
+/* Retains a copy of the detected and validated system RSDP. */
+static struct acpi_rsdp2 acpi_rsdp_store;
+
+/* This is NULL in the case where the RSDP cannot be found. */
+static const struct acpi_rsdp2 *acpi_rsdp_verified = NULL;
+
/*
* acpi_print_info: shows by screen the ACPI's rsdp and rsdt virtual address
* and the number of entries stored in RSDT table.
@@ -90,7 +96,7 @@ acpi_check_signature(const uint8_t table_signature[], const
char *real_signature
/*
* acpi_check_rsdp:
- * check if the RDSP "candidate" table is the real RSDP table.
+ * check if the RSDP "candidate" table is the real RSDP table.
*
* Compare the table signature with the ACPI signature for this table
* and check is the checksum is correct.
@@ -99,11 +105,11 @@ acpi_check_signature(const uint8_t table_signature[],
const char *real_signature
*
* Preconditions: RSDP pointer must not be NULL.
*
- * Returns 1 if ACPI 1.0 and sets sdt_base
- * Returns 2 if ACPI >= 2.0 and sets sdt_base
+ * Returns 1 if ACPI 1.0
+ * Returns 2 if ACPI >= 2.0
*/
static int8_t
-acpi_check_rsdp(struct acpi_rsdp2 *rsdp, phys_addr_t *sdt_base)
+acpi_check_rsdp(const struct acpi_rsdp2 *rsdp)
{
int is_rsdp;
uint8_t cksum;
@@ -116,7 +122,6 @@ acpi_check_rsdp(struct acpi_rsdp2 *rsdp, phys_addr_t
*sdt_base)
if (rsdp->v1.revision == 0) {
// ACPI 1.0
- *sdt_base = rsdp->v1.rsdt_addr;
printf("ACPI v1.0\n");
cksum = acpi_checksum((void *)(&rsdp->v1), sizeof(struct acpi_rsdp));
@@ -127,7 +132,6 @@ acpi_check_rsdp(struct acpi_rsdp2 *rsdp, phys_addr_t
*sdt_base)
} else if (rsdp->v1.revision == 2) {
// ACPI >= 2.0
- *sdt_base = rsdp->xsdt_addr;
printf("ACPI >= v2.0\n");
cksum = acpi_checksum((void *)rsdp, sizeof(struct acpi_rsdp2));
@@ -160,46 +164,43 @@ acpi_check_rsdp_align(void *addr)
/*
* acpi_search_rsdp: search the rsdp table in a memory range.
*
- * Receives as input the initial virtual address, and the lenght
+ * Receives as input the initial virtual address, and the length
* of memory range.
*
* Preconditions: The start address (addr) must be aligned.
*
- * Returns the physical address of rsdp structure if success, 0 if failure.
+ * Returns the virtual address of rsdp structure if success, NULL if failure.
*/
-static phys_addr_t
-acpi_search_rsdp(void *addr, uint32_t length, int *is_64bit)
+static const struct acpi_rsdp2 *
+acpi_search_rsdp(const void *addr, uint32_t length)
{
- void *end;
- int version = 0;
- phys_addr_t sdt_base = 0;
+ const void *end;
- /* Search RDSP in memory space between addr and addr+lenght. */
+ /* Search RSDP in memory space between addr and addr+length. */
for (end = addr+length; addr < end; addr += ACPI_RSDP_ALIGN) {
- /* Check if the current memory block stores the RDSP. */
- if ((addr != NULL) && ((version = acpi_check_rsdp(addr, &sdt_base)) >
0)) {
- /* If yes, return RSDT/XSDT address */
- *is_64bit = (version == 2);
- return sdt_base;
+ /* Check if the current memory block stores the RSDP. */
+ if ((addr != NULL) && (acpi_check_rsdp(addr) > 0)) {
+ return (const struct acpi_rsdp2 *)addr;
}
}
- return 0;
+ return NULL;
}
/*
- * acpi_get_rsdp: tries to find the RSDP table,
+ * acpi_rsdp_from_bios: tries to find the RSDP table,
* searching It in many memory ranges, as It's written in ACPI Specification.
*
- * Returns the reference to RDSP structure if success, 0 if failure.
+ * Returns the virtual pointer to the RSDP structure if success, NULL
+ * if failure.
*/
-static phys_addr_t
-acpi_get_rsdp(int *is_64bit)
+static const struct acpi_rsdp2 *
+acpi_rsdp_from_bios (void)
{
uint16_t *start = 0;
phys_addr_t base = 0;
- phys_addr_t rsdp = 0;
+ const struct acpi_rsdp2 *rsdp = NULL;
/* EDBA start address. */
start = (uint16_t*) phystokv(0x040e);
@@ -208,16 +209,38 @@ acpi_get_rsdp(int *is_64bit)
/* check alignment. */
if (acpi_check_rsdp_align((void *)base) == ACPI_BAD_ALIGN)
return 0;
- rsdp = acpi_search_rsdp((void *)base, 1024, is_64bit);
+ rsdp = acpi_search_rsdp((void *)base, 1024);
- if (rsdp == 0) {
+ if (rsdp == NULL) {
/* If RSDP isn't in EDBA, search in the BIOS read-only memory space
between 0E0000h and 0FFFFFh */
- rsdp = acpi_search_rsdp((void *)phystokv(0xe0000), 0x100000 -
0x0e0000, is_64bit);
+ rsdp = acpi_search_rsdp((void *)phystokv(0xe0000), 0x100000 -
0x0e0000);
}
return rsdp;
}
+/*
+ * acpi_get_sdt_base:
+ *
+ * acpi_initialise() should be called before use.
+ * Returns the reference to RSDP structure if success, 0 if failure.
+ */
+static phys_addr_t
+acpi_get_sdt_base (int *is_64bit)
+{
+ phys_addr_t sdt_base = 0;
+
+ if (acpi_rsdp_verified != NULL)
+ {
+ *is_64bit = (acpi_rsdp_verified->v1.revision == 2);
+ sdt_base = (*is_64bit
+ ? acpi_rsdp_verified->xsdt_addr
+ : acpi_rsdp_verified->v1.rsdt_addr);
+ }
+
+ return sdt_base;
+}
+
/*
* acpi_get_rsdt: Get RSDT table reference from RSDP entries.
*
@@ -585,7 +608,7 @@ acpi_apic_init(void)
uint8_t checksum;
/* Try to get the RSDP physical address. */
- rsdp = acpi_get_rsdp(&is_64bit);
+ rsdp = acpi_get_sdt_base (&is_64bit);
if (rsdp == 0)
return ACPI_NO_RSDP;
@@ -651,3 +674,24 @@ acpi_apic_init(void)
return ACPI_SUCCESS;
}
+
+void
+acpi_initialise (const struct multiboot2_raw_info *bi)
+{
+ const struct acpi_rsdp2 *rsdp;
+
+ rsdp = acpi_rsdp_from_bios ();
+
+ if (rsdp != NULL)
+ {
+ memcpy (&acpi_rsdp_store,
+ rsdp,
+ rsdp->v1.revision == 2
+ ? sizeof (struct acpi_rsdp2)
+ : sizeof (struct acpi_rsdp));
+
+ acpi_rsdp_verified = &acpi_rsdp_store;
+ }
+ else
+ acpi_rsdp_verified = NULL;
+}
diff --git a/i386/i386at/acpi_parse_apic.h b/i386/i386at/acpi_parse_apic.h
index df8d4bae..bb4489d9 100644
--- a/i386/i386at/acpi_parse_apic.h
+++ b/i386/i386at/acpi_parse_apic.h
@@ -200,4 +200,7 @@ void acpi_print_info(phys_addr_t rsdp, void *rsdt, int
acpi_rsdt_n);
extern unsigned lapic_addr;
+struct multiboot2_raw_info;
+void acpi_initialise (const struct multiboot2_raw_info *bi);
+
#endif /* __ACPI_H__ */
diff --git a/i386/i386at/model_dep.c b/i386/i386at/model_dep.c
index 6b14e908..be4f737b 100644
--- a/i386/i386at/model_dep.c
+++ b/i386/i386at/model_dep.c
@@ -680,6 +680,7 @@ i386at_init(const struct multiboot2_raw_info *mb2_info)
# else
picinit();
# endif
+ acpi_initialise (mb2_info);
#else /* MACH_HYP */
hyp_intrinit();
#endif /* MACH_HYP */
--
2.47.3