mirror of
https://github.com/memtest86plus/memtest86plus.git
synced 2025-02-25 18:55:23 -06:00
Parse FADT to find ACPI Timer Base Address and specs
This commit is contained in:
parent
cee2d32766
commit
eac4d03462
@ -35,7 +35,7 @@
|
||||
#define EINJSignature ('E' | ('I' << 8) | ('N' << 16) | ('J' << 24)) // Error Injection Table
|
||||
#define ERSTSignature ('E' | ('R' << 8) | ('S' << 16) | ('T' << 24)) // Error Record Serialization Table
|
||||
#define CPEPSignature ('C' | ('P' << 8) | ('E' << 16) | ('P' << 24)) // Corrected Platform Error Polling Table
|
||||
#define HESTSignature ('H' | ('E' << 8) | ('S' << 16) | ('T' << 24)) // Hardware Error Source Table
|
||||
#define HESTSignature ('H' | ('E' << 8) | ('S' << 16) | ('T' << 24)) // Hardware Error Source Table
|
||||
|
||||
#define SLITSignature ('S' | ('L' << 8) | ('I' << 16) | ('T' << 24)) // System Locality System Information Table (NUMA)
|
||||
#define SRATSignature ('S' | ('R' << 8) | ('A' << 16) | ('T' << 24)) // System Resource Affinity Table (NUMA)
|
||||
@ -44,6 +44,14 @@
|
||||
// Types
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
typedef struct __attribute__ ((packed)) {
|
||||
uint8_t address_space;
|
||||
uint8_t bit_width;
|
||||
uint8_t bit_offset;
|
||||
uint8_t access_size;
|
||||
uint64_t address;
|
||||
} acpi_gen_addr_struct;
|
||||
|
||||
typedef struct {
|
||||
char signature[8]; // "RSD PTR "
|
||||
uint8_t checksum;
|
||||
@ -81,10 +89,7 @@ static const efi_guid_t EFI_ACPI_2_RDSP_GUID = { 0x8868e871, 0xe4f1, 0x11d3, {0x
|
||||
|
||||
const char *rsdp_source = "";
|
||||
|
||||
uintptr_t rsdp_addr = 0;
|
||||
uintptr_t madt_addr = 0;
|
||||
uintptr_t fadt_addr = 0;
|
||||
uintptr_t hpet_addr = 0;
|
||||
acpi_t acpi_config = {0, 0, 0, 0, 0, 0, 0, 0, false};
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Private Functions
|
||||
@ -197,11 +202,16 @@ static uintptr_t find_rsdp(void)
|
||||
|
||||
static uintptr_t find_acpi_table(uint32_t table_signature)
|
||||
{
|
||||
rsdp_t *rp = (rsdp_t *)rsdp_addr;;
|
||||
rsdp_t *rp = (rsdp_t *)acpi_config.rsdp_addr;
|
||||
|
||||
// Found the RSDP, now get either the RSDT or XSDT and scan it for a pointer to the MADT.
|
||||
// Found the RSDP, now get either the RSDT or XSDT
|
||||
// and scan it for a pointer to the table we're looking for
|
||||
rsdt_header_t *rt;
|
||||
|
||||
if (acpi_config.ver_maj < rp->revision) {
|
||||
acpi_config.ver_maj = rp->revision;
|
||||
}
|
||||
|
||||
if (rp->revision >= 2) {
|
||||
rt = (rsdt_header_t *)map_region(rp->xsdt_addr, sizeof(rsdt_header_t), true);
|
||||
if (rt == NULL) {
|
||||
@ -215,7 +225,7 @@ static uintptr_t find_acpi_table(uint32_t table_signature)
|
||||
if (rt == NULL || acpi_checksum(rt, rt->length) != 0) {
|
||||
return 0;
|
||||
}
|
||||
// Scan the XSDT for a pointer to the MADT.
|
||||
// Scan the XSDT for a pointer to the table we're looking for.
|
||||
uint64_t *tab_ptr = (uint64_t *)((uint8_t *)rt + sizeof(rsdt_header_t));
|
||||
uint64_t *tab_end = (uint64_t *)((uint8_t *)rt + rt->length);
|
||||
|
||||
@ -240,7 +250,7 @@ static uintptr_t find_acpi_table(uint32_t table_signature)
|
||||
if (rt == NULL || acpi_checksum(rt, rt->length) != 0) {
|
||||
return 0;
|
||||
}
|
||||
// Scan the RSDT for a pointer to the MADT.
|
||||
// Scan the RSDT for a pointer to the table we're looking for.
|
||||
uint32_t *tab_ptr = (uint32_t *)((uint8_t *)rt + sizeof(rsdt_header_t));
|
||||
uint32_t *tab_end = (uint32_t *)((uint8_t *)rt + rt->length);
|
||||
|
||||
@ -257,6 +267,48 @@ static uintptr_t find_acpi_table(uint32_t table_signature)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static bool parse_fadt(uintptr_t fadt_addr)
|
||||
{
|
||||
// FADT is a very big & complex table and we only need a few data.
|
||||
// We use byte offset instead of a complete struct.
|
||||
|
||||
// FADT Header is identical to RSDP Header
|
||||
rsdt_header_t *fadt = (rsdt_header_t *)fadt_addr;
|
||||
|
||||
// Validate FADT
|
||||
if (fadt == NULL || acpi_checksum(fadt, fadt->length) != 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Get ACPI Version
|
||||
acpi_config.ver_maj = fadt->revision;
|
||||
|
||||
if (fadt->length > FADT_MINOR_REV_OFFSET) {
|
||||
acpi_config.ver_min = *(uint8_t *)(fadt_addr+FADT_MINOR_REV_OFFSET) & 0xF;
|
||||
}
|
||||
|
||||
// Get Old PM Base Address (32bit IO)
|
||||
acpi_config.pm_addr = *(uint32_t *)(fadt_addr+FADT_PM_TMR_BLK_OFFSET);
|
||||
acpi_config.pm_is_io = true;
|
||||
|
||||
#ifdef __x86_64__
|
||||
acpi_gen_addr_struct *rt;
|
||||
|
||||
// Get APIC Timer Address
|
||||
if (fadt->length > FADT_X_PM_TMR_BLK_OFFSET) {
|
||||
rt = (acpi_gen_addr_struct *)map_region(fadt_addr+FADT_X_PM_TMR_BLK_OFFSET, sizeof(acpi_gen_addr_struct), true);
|
||||
|
||||
acpi_config.pm_is_io = (rt->address_space == 1) ? true : false;
|
||||
|
||||
if (rt->address != 0) {
|
||||
acpi_config.pm_addr = rt->address;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Public Functions
|
||||
//------------------------------------------------------------------------------
|
||||
@ -275,14 +327,19 @@ int acpi_checksum(const void *data, int length)
|
||||
void acpi_init(void)
|
||||
{
|
||||
// Find ACPI RDST Table Address
|
||||
rsdp_addr = find_rsdp();
|
||||
acpi_config.rsdp_addr = find_rsdp();
|
||||
|
||||
// Find ACPI MADT Table Address
|
||||
madt_addr = find_acpi_table(MADTSignature);
|
||||
acpi_config.madt_addr = find_acpi_table(MADTSignature);
|
||||
|
||||
// Find ACPI FADT Table Address
|
||||
fadt_addr = find_acpi_table(FADTSignature);
|
||||
acpi_config.fadt_addr = find_acpi_table(FADTSignature);
|
||||
|
||||
// Parse FADT
|
||||
if (acpi_config.fadt_addr) {
|
||||
parse_fadt(acpi_config.fadt_addr);
|
||||
}
|
||||
|
||||
// Find ACPI HPET Table Address
|
||||
hpet_addr = find_acpi_table(HPETSignature);
|
||||
acpi_config.hpet_addr = find_acpi_table(HPETSignature);
|
||||
}
|
||||
|
@ -14,30 +14,35 @@
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#define FADT_PM_TMR_BLK_OFFSET 76
|
||||
#define FADT_MINOR_REV_OFFSET 131
|
||||
#define FADT_X_PM_TMR_BLK_OFFSET 208
|
||||
|
||||
/**
|
||||
* A struct containing various ACPI-related infos for later uses.
|
||||
*/
|
||||
|
||||
typedef struct {
|
||||
uint8_t ver_maj;
|
||||
uint8_t ver_min;
|
||||
uint64_t test;
|
||||
uintptr_t rsdp_addr;
|
||||
uintptr_t madt_addr;
|
||||
uintptr_t fadt_addr;
|
||||
uintptr_t hpet_addr;
|
||||
uintptr_t pm_addr;
|
||||
bool pm_is_io;
|
||||
} acpi_t;
|
||||
|
||||
/**
|
||||
* The search step that located the ACPI RSDP (for debug).
|
||||
*/
|
||||
extern const char *rsdp_source;
|
||||
|
||||
/**
|
||||
* The address of the ACPI RSDP
|
||||
* Global ACPI config struct
|
||||
*/
|
||||
extern uintptr_t rsdp_addr;
|
||||
|
||||
/**
|
||||
* The address of the ACPI MADT
|
||||
*/
|
||||
extern uintptr_t madt_addr;
|
||||
|
||||
/**
|
||||
* The address of the ACPI FADT
|
||||
*/
|
||||
extern uintptr_t fadt_addr;
|
||||
|
||||
/**
|
||||
* The address of the ACPI HPET
|
||||
*/
|
||||
extern uintptr_t hpet_addr;
|
||||
extern acpi_t acpi_config;
|
||||
|
||||
/**
|
||||
* ACPI Table Checksum Function
|
||||
|
@ -376,12 +376,12 @@ static bool find_cpus_in_floating_mp_struct(void)
|
||||
|
||||
static bool find_cpus_in_madt(void)
|
||||
{
|
||||
if(madt_addr == 0) return false;
|
||||
if(acpi_config.madt_addr == 0) return false;
|
||||
|
||||
madt_table_header_t *mpc = (madt_table_header_t *)map_region(madt_addr, sizeof(madt_table_header_t), true);
|
||||
madt_table_header_t *mpc = (madt_table_header_t *)map_region(acpi_config.madt_addr, sizeof(madt_table_header_t), true);
|
||||
if (mpc == NULL) return false;
|
||||
|
||||
mpc = (madt_table_header_t *)map_region(madt_addr, mpc->length, true);
|
||||
mpc = (madt_table_header_t *)map_region(acpi_config.madt_addr, mpc->length, true);
|
||||
if (mpc == NULL) return false;
|
||||
|
||||
if (acpi_checksum(mpc, mpc->length) != 0) {
|
||||
|
Loading…
Reference in New Issue
Block a user