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 | 41 ++++++++++++++++++++++++++++++++++------- 2 files changed, 35 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..c7d498d 100644 --- a/src/fw/biostables.c +++ b/src/fw/biostables.c @@ -60,22 +60,35 @@ copy_mptable(void *pos) memcpy((void*)newpos + length, (void*)p->physaddr, mpclength); }
-static void -copy_acpi_rsdp(void *pos) +static int +get_acpi_rsdp_length(void *pos, unsigned size) { - if (RsdpAddr) - return; struct rsdp_descriptor *p = pos; if (p->signature != RSDP_SIGNATURE) - return; + return -1; u32 length = 20; + if (length > size) + return -1; if (checksum(pos, length) != 0) - return; + return -1; if (p->revision > 1) { length = p->length; + if (length > size) + return -1; if (checksum(pos, length) != 0) - return; + return -1; } + return length; +} + +static void +copy_acpi_rsdp(void *pos) +{ + if (RsdpAddr) + return; + int length = get_acpi_rsdp_length(pos, -1); + if (length < 0) + return; void *newpos = malloc_fseg(length); if (!newpos) { warn_noalloc(); @@ -118,3 +131,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 <= ALIGN_DOWN(end, 0x10); pos += 0x10) + if (get_acpi_rsdp_length((void *)pos, end - pos) >= 0) + return (void *)pos; + + return NULL; +}