Will be used when it's loaded from QEMU.
Signed-off-by: Michael S. Tsirkin mst@redhat.com --- src/util.h | 1 + src/fw/biostables.c | 40 +++++++++++++++++++++++++++++++++------- 2 files changed, 34 insertions(+), 7 deletions(-)
diff --git a/src/util.h b/src/util.h index 880c04a..bf983e5 100644 --- a/src/util.h +++ b/src/util.h @@ -72,6 +72,7 @@ void acpi_reboot(void); // fw/biostable.c void copy_smbios(void *pos); void copy_table(void *pos); +void *find_acpi_rsdp(void);
// fw/coreboot.c extern const char *CBvendor, *CBpart; diff --git a/src/fw/biostables.c b/src/fw/biostables.c index a3ee827..4c2f355 100644 --- a/src/fw/biostables.c +++ b/src/fw/biostables.c @@ -60,22 +60,34 @@ copy_mptable(void *pos) memcpy((void*)newpos + length, (void*)p->physaddr, mpclength); }
-static void -copy_acpi_rsdp(void *pos) +static bool +test_acpi_rsdp(void *pos, unsigned size) { - if (RsdpAddr) - return; struct rsdp_descriptor *p = pos; if (p->signature != RSDP_SIGNATURE) - return; + return false; u32 length = 20; + if (length > size) + return false; if (checksum(pos, length) != 0) - return; + return false; if (p->revision > 1) { length = p->length; + if (length > size) + return false; if (checksum(pos, length) != 0) - return; + return false; } + return true; +} + +static void +copy_acpi_rsdp(void *pos) +{ + if (RsdpAddr) + return; + if (!test_acpi_rsdp(pos, -1)) + return; void *newpos = malloc_fseg(length); if (!newpos) { warn_noalloc(); @@ -118,3 +130,17 @@ copy_table(void *pos) copy_acpi_rsdp(pos); copy_smbios(pos); } + +void *find_acpi_rsdp(void) +{ + extern u8 zonefseg_start[], zonefseg_end[]; + unsigned long start = (unsigned long)zonefseg_start; + unsigned long end = (unsigned long)zonefseg_end; + unsigned long pos; + + for (pos = ALIGN(start, 0x10); pos += 0x10; pos <= ALIGN_DOWN(end, 0x10)) + if (test_acpi_rsdp((void *)pos, end - pos)) + return (void *)pos; + + return NULL; +}