aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorWarner Losh <imp@FreeBSD.org>2016-04-14 04:59:51 +0000
committerWarner Losh <imp@FreeBSD.org>2016-04-14 04:59:51 +0000
commitbd3bce41db1e29fb96124a57e89d02e56c4c242b (patch)
treefe9a1d88c1c4bc8f8964451ce33426ad54a424a5
parent47754aa24056aba4a2242c53b2aaf4225f190740 (diff)
downloadsrc-bd3bce41db1e29fb96124a57e89d02e56c4c242b.tar.gz
src-bd3bce41db1e29fb96124a57e89d02e56c4c242b.zip
Deprecate using hints.acpi.0.rsdp to communicate the RSDP to the
system. This uses the hints mechnanism. This mostly works today because when there's no static hints (the default), this value can be fetched from the hint. When there is a static hints file, the hint passed from the boot loader to the kernel is ignored, but for the BIOS case we're able to find it anyway. However, with UEFI, the fallback doesn't work, so we get a panic instead. Switch to acpi.rsdp and use TUNABLE_ULONG_FETCH instead. Continue to generate the old values to allow for transitions. In addition, fall back to the old method if the new method isn't present. Add comments about all this. Differential Revision: https://reviews.freebsd.org/D5866
Notes
Notes: svn path=/head/; revision=297954
-rw-r--r--sys/boot/efi/loader/arch/amd64/elf64_freebsd.c17
-rw-r--r--sys/boot/i386/libi386/biosacpi.c17
-rw-r--r--sys/x86/acpica/OsdEnvironment.c11
3 files changed, 44 insertions, 1 deletions
diff --git a/sys/boot/efi/loader/arch/amd64/elf64_freebsd.c b/sys/boot/efi/loader/arch/amd64/elf64_freebsd.c
index 1b95cdede4b5..a1096d9a650b 100644
--- a/sys/boot/efi/loader/arch/amd64/elf64_freebsd.c
+++ b/sys/boot/efi/loader/arch/amd64/elf64_freebsd.c
@@ -101,6 +101,17 @@ elf64_exec(struct preloaded_file *fp)
char buf[24];
int revision;
+ /*
+ * Report the RSDP to the kernel. While this can be found with
+ * a BIOS boot, the RSDP may be elsewhere when booted from UEFI.
+ * The old code used the 'hints' method to communite this to
+ * the kernel. However, while convenient, the 'hints' method
+ * is fragile and does not work when static hints are compiled
+ * into the kernel. Instead, move to setting different tunables
+ * that start with acpi. The old 'hints' can be removed before
+ * we branch for FreeBSD 12.
+ */
+
rsdp = efi_get_table(&acpi20_guid);
if (rsdp == NULL) {
rsdp = efi_get_table(&acpi_guid);
@@ -108,23 +119,29 @@ elf64_exec(struct preloaded_file *fp)
if (rsdp != NULL) {
sprintf(buf, "0x%016llx", (unsigned long long)rsdp);
setenv("hint.acpi.0.rsdp", buf, 1);
+ setenv("acpi.rsdp", buf, 1);
revision = rsdp->Revision;
if (revision == 0)
revision = 1;
sprintf(buf, "%d", revision);
setenv("hint.acpi.0.revision", buf, 1);
+ setenv("acpi.revision", buf, 1);
strncpy(buf, rsdp->OemId, sizeof(rsdp->OemId));
buf[sizeof(rsdp->OemId)] = '\0';
setenv("hint.acpi.0.oem", buf, 1);
+ setenv("acpi.oem", buf, 1);
sprintf(buf, "0x%016x", rsdp->RsdtPhysicalAddress);
setenv("hint.acpi.0.rsdt", buf, 1);
+ setenv("acpi.rsdt", buf, 1);
if (revision >= 2) {
/* XXX extended checksum? */
sprintf(buf, "0x%016llx",
(unsigned long long)rsdp->XsdtPhysicalAddress);
setenv("hint.acpi.0.xsdt", buf, 1);
+ setenv("acpi.xsdt", buf, 1);
sprintf(buf, "%d", rsdp->Length);
setenv("hint.acpi.0.xsdt_length", buf, 1);
+ setenv("acpi.xsdt_length", buf, 1);
}
}
diff --git a/sys/boot/i386/libi386/biosacpi.c b/sys/boot/i386/libi386/biosacpi.c
index bedc722e850d..8167fca7b622 100644
--- a/sys/boot/i386/libi386/biosacpi.c
+++ b/sys/boot/i386/libi386/biosacpi.c
@@ -60,25 +60,40 @@ biosacpi_detect(void)
if ((rsdp = biosacpi_find_rsdp()) == NULL)
return;
- /* export values from the RSDP */
+ /*
+ * Report the RSDP to the kernel. While this can be found with
+ * a BIOS boot, the RSDP may be elsewhere when booted from UEFI.
+ * The old code used the 'hints' method to communite this to
+ * the kernel. However, while convenient, the 'hints' method
+ * is fragile and does not work when static hints are compiled
+ * into the kernel. Instead, move to setting different tunables
+ * that start with acpi. The old 'hints' can be removed before
+ * we branch for FreeBSD 12.
+ */
sprintf(buf, "0x%08x", VTOP(rsdp));
setenv("hint.acpi.0.rsdp", buf, 1);
+ setenv("acpi.rsdp", buf, 1);
revision = rsdp->Revision;
if (revision == 0)
revision = 1;
sprintf(buf, "%d", revision);
setenv("hint.acpi.0.revision", buf, 1);
+ setenv("acpi.revision", buf, 1);
strncpy(buf, rsdp->OemId, sizeof(rsdp->OemId));
buf[sizeof(rsdp->OemId)] = '\0';
setenv("hint.acpi.0.oem", buf, 1);
+ setenv("acpi.oem", buf, 1);
sprintf(buf, "0x%08x", rsdp->RsdtPhysicalAddress);
setenv("hint.acpi.0.rsdt", buf, 1);
+ setenv("acpi.rsdt", buf, 1);
if (revision >= 2) {
/* XXX extended checksum? */
sprintf(buf, "0x%016llx", rsdp->XsdtPhysicalAddress);
setenv("hint.acpi.0.xsdt", buf, 1);
+ setenv("acpi.xsdt", buf, 1);
sprintf(buf, "%d", rsdp->Length);
setenv("hint.acpi.0.xsdt_length", buf, 1);
+ setenv("acpi.xsdt_length", buf, 1);
}
}
diff --git a/sys/x86/acpica/OsdEnvironment.c b/sys/x86/acpica/OsdEnvironment.c
index be612b5335aa..ab8a7fbaacc0 100644
--- a/sys/x86/acpica/OsdEnvironment.c
+++ b/sys/x86/acpica/OsdEnvironment.c
@@ -30,6 +30,7 @@ __FBSDID("$FreeBSD$");
#include <sys/types.h>
#include <sys/bus.h>
+#include <sys/kernel.h>
#include <sys/sysctl.h>
#include <contrib/dev/acpica/include/acpi.h>
@@ -59,6 +60,16 @@ acpi_get_root_from_loader(void)
{
long acpi_root;
+ if (TUNABLE_ULONG_FETCH("acpi.rsdp", &acpi_root))
+ return (acpi_root);
+
+ /*
+ * The hints mechanism is unreliable (it fails if anybody ever
+ * compiled in hints to the kernel). It has been replaced
+ * by the tunable method, but is used here as a fallback to
+ * retain maximum compatibility between old loaders and new
+ * kernels. It can be removed after 11.0R.
+ */
if (resource_long_value("acpi", 0, "rsdp", &acpi_root) == 0)
return (acpi_root);