Improve and fix scanning for ACPI tables.
This commit is contained in:
parent
27c5fe363f
commit
1d2bf57403
71
system/smp.c
71
system/smp.c
|
@ -89,7 +89,8 @@
|
||||||
|
|
||||||
#define MPCSignature ('P' | ('C' << 8) | ('M' << 16) | ('P' << 24))
|
#define MPCSignature ('P' | ('C' << 8) | ('M' << 16) | ('P' << 24))
|
||||||
|
|
||||||
#define RSDPSignature ('R' | ('S' << 8) | ('D' << 16) | (' ' << 24))
|
#define RSDPSignature1 ('R' | ('S' << 8) | ('D' << 16) | (' ' << 24))
|
||||||
|
#define RSDPSignature2 ('P' | ('T' << 8) | ('R' << 16) | (' ' << 24))
|
||||||
|
|
||||||
#define RSDTSignature ('R' | ('S' << 8) | ('D' << 16) | ('T' << 24))
|
#define RSDTSignature ('R' | ('S' << 8) | ('D' << 16) | ('T' << 24))
|
||||||
|
|
||||||
|
@ -207,7 +208,7 @@ typedef struct {
|
||||||
} rsdp_t;
|
} rsdp_t;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
char signature[4]; // "RSDT"
|
char signature[4]; // "RSDT" or "XSDT"
|
||||||
uint32_t length;
|
uint32_t length;
|
||||||
uint8_t revision;
|
uint8_t revision;
|
||||||
uint8_t checksum;
|
uint8_t checksum;
|
||||||
|
@ -216,7 +217,7 @@ typedef struct {
|
||||||
char oem_revision[4];
|
char oem_revision[4];
|
||||||
char creator_id[4];
|
char creator_id[4];
|
||||||
char creator_revision[4];
|
char creator_revision[4];
|
||||||
} rsdt_t;
|
} rsdt_header_t;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
uint8_t type;
|
uint8_t type;
|
||||||
|
@ -382,7 +383,7 @@ static bool find_cpus_in_floating_mp_struct(void)
|
||||||
fp = scan_for_floating_ptr_struct(0xf0000, 0x10000);
|
fp = scan_for_floating_ptr_struct(0xf0000, 0x10000);
|
||||||
}
|
}
|
||||||
if (fp == NULL) {
|
if (fp == NULL) {
|
||||||
// Search the BIOS ESDS area.
|
// Search the BIOS EBDA area.
|
||||||
uintptr_t address = *(uint16_t *)0x40E << 4;
|
uintptr_t address = *(uint16_t *)0x40E << 4;
|
||||||
if (address) {
|
if (address) {
|
||||||
fp = scan_for_floating_ptr_struct(address, 0x400);
|
fp = scan_for_floating_ptr_struct(address, 0x400);
|
||||||
|
@ -420,10 +421,12 @@ static rsdp_t *scan_for_rsdp(uintptr_t addr, int length)
|
||||||
|
|
||||||
while (ptr < end) {
|
while (ptr < end) {
|
||||||
rsdp_t *rp = (rsdp_t *)ptr;
|
rsdp_t *rp = (rsdp_t *)ptr;
|
||||||
if (*ptr == RSDPSignature && checksum(ptr, rp->length) == 0) {
|
if (*ptr == RSDPSignature1 && *(ptr+1) == RSDPSignature2 && checksum(ptr, 20) == 0) {
|
||||||
return rp;
|
if (rp->revision < 2 || (rp->length < 1024 && checksum(ptr, rp->length) == 0)) {
|
||||||
|
return rp;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
ptr++;
|
ptr += 4;
|
||||||
}
|
}
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
@ -516,25 +519,25 @@ static bool find_cpus_in_rsdp(void)
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
if (rp == NULL) {
|
if (rp == NULL) {
|
||||||
// Search the BIOS reserved area.
|
// Search the BIOS EBDA area.
|
||||||
rp = scan_for_rsdp(0xE0000, 0x20000);
|
|
||||||
}
|
|
||||||
if (rp == NULL) {
|
|
||||||
// Search the BIOS ESDS area.
|
|
||||||
uintptr_t address = *(uint16_t *)0x40E << 4;
|
uintptr_t address = *(uint16_t *)0x40E << 4;
|
||||||
if (address) {
|
if (address) {
|
||||||
rp = scan_for_rsdp(address, 0x400);
|
rp = scan_for_rsdp(address, 0x400);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (rp == NULL) {
|
||||||
|
// Search the BIOS reserved area.
|
||||||
|
rp = scan_for_rsdp(0xE0000, 0x20000);
|
||||||
|
}
|
||||||
if (rp == NULL) {
|
if (rp == NULL) {
|
||||||
// RSDP not found, give up.
|
// RSDP not found, give up.
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Found the RSDP, now get either the RSDT or XSDT.
|
// Found the RSDP, now get either the RSDT or XSDT and scan it for a pointer to the MADT.
|
||||||
rsdt_t *rt;
|
rsdt_header_t *rt;
|
||||||
if (rp->revision >= 2) {
|
if (rp->revision >= 2) {
|
||||||
rt = (rsdt_t *)((uintptr_t)rp->xsdt_addr);
|
rt = (rsdt_header_t *)((uintptr_t)rp->xsdt_addr);
|
||||||
if (rt == 0) {
|
if (rt == 0) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -542,11 +545,24 @@ static bool find_cpus_in_rsdp(void)
|
||||||
if (*(uint32_t *)rt != XSDTSignature) {
|
if (*(uint32_t *)rt != XSDTSignature) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if (checksum((uint8_t *)rt, rt->length) != 0) {
|
if (checksum(rt, rt->length) != 0) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
// Scan the XSDT for a pointer to the MADT.
|
||||||
|
uint64_t *tab_ptr = (uint64_t *)((uint8_t *)rt + sizeof(rsdt_header_t));
|
||||||
|
uint64_t *tab_end = (uint64_t *)((uint8_t *)rt + rt->length);
|
||||||
|
|
||||||
|
while (tab_ptr < tab_end) {
|
||||||
|
uint32_t *ptr = (uint32_t *)((uintptr_t)(*tab_ptr++)); // read the next table entry
|
||||||
|
|
||||||
|
if (ptr && *ptr == MADTSignature) {
|
||||||
|
if (parse_madt(ptr)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
rt = (rsdt_t *)((uintptr_t)rp->rsdt_addr);
|
rt = (rsdt_header_t *)((uintptr_t)rp->rsdt_addr);
|
||||||
if (rt == 0) {
|
if (rt == 0) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -554,21 +570,20 @@ static bool find_cpus_in_rsdp(void)
|
||||||
if (*(uint32_t *)rt != RSDTSignature) {
|
if (*(uint32_t *)rt != RSDTSignature) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if (checksum((uint8_t *)rt, rt->length) != 0) {
|
if (checksum(rt, rt->length) != 0) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
// Scan the RSDT for a pointer to the MADT.
|
||||||
|
uint32_t *tab_ptr = (uint32_t *)((uint8_t *)rt + sizeof(rsdt_header_t));
|
||||||
|
uint32_t *tab_end = (uint32_t *)((uint8_t *)rt + rt->length);
|
||||||
|
|
||||||
// Scan the RSDT or XSDT for a pointer to the MADT.
|
while (tab_ptr < tab_end) {
|
||||||
uint32_t *tab_ptr = (uint32_t *)(rt + 1); // immediately follows the RSDT/XSDT
|
uint32_t *ptr = (uint32_t *)((uintptr_t)(*tab_ptr++)); // read the next table entry
|
||||||
uint32_t *tab_end = tab_ptr + (rt->length / sizeof(uint32_t));
|
|
||||||
|
|
||||||
while (tab_ptr < tab_end) {
|
if (ptr && *ptr == MADTSignature) {
|
||||||
uint32_t *ptr = (uint32_t *)((uintptr_t)(*tab_ptr++)); // read the next table entry
|
if (parse_madt(ptr)) {
|
||||||
|
return true;
|
||||||
if (ptr && *ptr == MADTSignature) {
|
}
|
||||||
if (parse_madt(ptr)) {
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue