summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorToomas Soome <tsoome@me.com>2016-10-09 17:12:23 +0300
committerHans Rosenfeld <rosenfeld@grumpf.hope-2000.org>2017-01-31 16:24:49 +0100
commitdcba96fe6535681ea4a912e4b512a4e5ba59182e (patch)
tree498f21e69b51f9a80c8dd39065e512c87833d444
parent22cc5444cba0d30b59582f255e2eb24e8a702824 (diff)
downloadillumos-joyent-dcba96fe6535681ea4a912e4b512a4e5ba59182e.tar.gz
7649 loader.efi: fix extraction of firmare table info for smbios and acpi.
Reviewed by: Robert Mustacchi <rm@joyent.com> Reviewed by: Richard Lowe <richlowe@richlowe.net> Approved by: Hans Rosenfeld <rosenfeld@grumpf.hope-2000.org>
-rw-r--r--usr/src/boot/sys/boot/efi/loader/Makefile4
-rw-r--r--usr/src/boot/sys/boot/efi/loader/acpi.c75
-rw-r--r--usr/src/boot/sys/boot/efi/loader/main.c18
-rw-r--r--usr/src/boot/sys/boot/i386/libi386/smbios.c98
4 files changed, 154 insertions, 41 deletions
diff --git a/usr/src/boot/sys/boot/efi/loader/Makefile b/usr/src/boot/sys/boot/efi/loader/Makefile
index fe0ebf02fc..169ec59cbb 100644
--- a/usr/src/boot/sys/boot/efi/loader/Makefile
+++ b/usr/src/boot/sys/boot/efi/loader/Makefile
@@ -26,9 +26,9 @@ MACHINE= $(MACH64)
# architecture-specific loader code
SRCS= autoload.c bootinfo.c conf.c copy.c devicename.c main.c self_reloc.c \
- smbios.c biosacpi.c vers.c
+ smbios.c acpi.c vers.c
OBJS= autoload.o bootinfo.o conf.o copy.o devicename.o main.o self_reloc.o \
- smbios.o biosacpi.o vers.o
+ smbios.o acpi.o vers.o
ASFLAGS=-m64 -fPIC
CFLAGS= -O2
diff --git a/usr/src/boot/sys/boot/efi/loader/acpi.c b/usr/src/boot/sys/boot/efi/loader/acpi.c
new file mode 100644
index 0000000000..ae25c0c0f6
--- /dev/null
+++ b/usr/src/boot/sys/boot/efi/loader/acpi.c
@@ -0,0 +1,75 @@
+/*
+ * This file and its contents are supplied under the terms of the
+ * Common Development and Distribution License ("CDDL"), version 1.0.
+ * You may only use this file in accordance with the terms of version
+ * 1.0 of the CDDL.
+ *
+ * A full copy of the text of the CDDL should have accompanied this
+ * source. A copy of the CDDL is also available via the Internet at
+ * http://www.illumos.org/license/CDDL.
+ */
+
+/*
+ * Copyright 2016 Tooams Soome <tsoome@me.com>
+ */
+
+#include <sys/cdefs.h>
+
+#include <stand.h>
+#include <machine/stdarg.h>
+#include <bootstrap.h>
+#include <efi.h>
+#include <efilib.h>
+
+#include "platform/acfreebsd.h"
+#include "acconfig.h"
+#define ACPI_SYSTEM_XFACE
+#include "actypes.h"
+#include "actbl.h"
+
+ACPI_TABLE_RSDP *rsdp;
+static EFI_GUID acpi_guid = ACPI_TABLE_GUID;
+static EFI_GUID acpi20_guid = ACPI_20_TABLE_GUID;
+
+void
+acpi_detect(void)
+{
+ char buf[24];
+ int revision;
+
+ if ((rsdp = efi_get_table(&acpi20_guid)) == NULL)
+ rsdp = efi_get_table(&acpi_guid);
+
+ if (rsdp == NULL)
+ return;
+
+ /* export values from the RSDP */
+#ifdef _LP64
+ snprintf(buf, sizeof (buf), "0x%016llx", (unsigned long long)rsdp);
+#else
+ snprintf(buf, sizeof (buf), "0x%08x", (unsigned int)rsdp);
+#endif
+ setenv("acpi.rsdp", buf, 1);
+ revision = rsdp->Revision;
+ if (revision == 0)
+ revision = 1;
+ snprintf(buf, sizeof (buf), "%d", revision);
+ setenv("acpi.revision", buf, 1);
+ strncpy(buf, rsdp->OemId, sizeof(rsdp->OemId));
+ buf[sizeof(rsdp->OemId)] = '\0';
+ setenv("acpi.oem", buf, 1);
+#ifdef _LP64
+ snprintf(buf, sizeof (buf), "0x%016llx",
+ (unsigned long long)rsdp->RsdtPhysicalAddress);
+#else
+ snprintf(buf, sizeof (buf), "0x%08x", rsdp->RsdtPhysicalAddress);
+#endif
+ setenv("acpi.rsdt", buf, 1);
+ if (revision >= 2) {
+ snprintf(buf, sizeof (buf), "0x%016llx",
+ (unsigned long long)rsdp->XsdtPhysicalAddress);
+ setenv("acpi.xsdt", buf, 1);
+ snprintf(buf, sizeof (buf), "%d", rsdp->Length);
+ setenv("acpi.xsdt_length", buf, 1);
+ }
+}
diff --git a/usr/src/boot/sys/boot/efi/loader/main.c b/usr/src/boot/sys/boot/efi/loader/main.c
index 249be4a95e..3cf7894d92 100644
--- a/usr/src/boot/sys/boot/efi/loader/main.c
+++ b/usr/src/boot/sys/boot/efi/loader/main.c
@@ -71,7 +71,7 @@ EFI_GUID fdtdtb = FDT_TABLE_GUID;
EFI_GUID inputid = SIMPLE_TEXT_INPUT_PROTOCOL;
EFI_GUID serial_io = SERIAL_IO_PROTOCOL;
-extern void acpi_detect(const caddr_t);
+extern void acpi_detect(void);
void efi_serial_init(void);
#ifdef EFI_ZFS_BOOT
static void efi_zfs_probe(void);
@@ -191,6 +191,7 @@ main(int argc, CHAR16 *argv[])
int i, j, vargood, unit, howto;
struct devsw *dev;
uint64_t pool_guid;
+ void *ptr;
UINTN k;
int has_kbd;
@@ -404,18 +405,11 @@ main(int argc, CHAR16 *argv[])
setenv("LINES", "24", 1); /* optional */
setenv("COLUMNS", "80", 1); /* optional */
setenv("ISADIR", "amd64", 1); /* we only build 64bit */
+ acpi_detect();
- for (k = 0; k < ST->NumberOfTableEntries; k++) {
- guid = &ST->ConfigurationTable[k].VendorGuid;
- if (!memcmp(guid, &smbios, sizeof(EFI_GUID)) ||
- !memcmp(guid, &smbios3, sizeof(EFI_GUID))) {
- smbios_detect(ST->ConfigurationTable[k].VendorTable);
- continue;
- }
- if (!memcmp(guid, &acpi20, sizeof(EFI_GUID))) {
- acpi_detect(ST->ConfigurationTable[k].VendorTable);
- }
- }
+ if ((ptr = efi_get_table(&smbios3)) == NULL)
+ ptr = efi_get_table(&smbios);
+ smbios_detect(ptr);
efi_serial_init(); /* detect and set up serial ports */
interact(NULL); /* doesn't return */
diff --git a/usr/src/boot/sys/boot/i386/libi386/smbios.c b/usr/src/boot/sys/boot/i386/libi386/smbios.c
index 2aa62fa85d..845521dd60 100644
--- a/usr/src/boot/sys/boot/i386/libi386/smbios.c
+++ b/usr/src/boot/sys/boot/i386/libi386/smbios.c
@@ -45,6 +45,8 @@ __FBSDID("$FreeBSD$");
*
* System Management BIOS Reference Specification, v2.6 Final
* http://www.dmtf.org/standards/published_documents/DSP0134_2.6.0.pdf
+ * System Management BIOS (SMBIOS) Reference Specification, v3.1.0
+ * http://www.dmtf.org/sites/default/files/standards/documents/DSP0134_3.1.0.pdf
*/
/*
@@ -60,11 +62,16 @@ __FBSDID("$FreeBSD$");
#define SMBIOS_LENGTH 0x10000
#define SMBIOS_STEP 0x10
#define SMBIOS_SIG "_SM_"
+#define SMBIOS_SIG_LEN (4)
+#define SMBIOS3_SIG "_SM3_"
+#define SMBIOS3_SIG_LEN (5)
#define SMBIOS_DMI_SIG "_DMI_"
+#define SMBIOS_DMI_SIG_LEN (5)
#define SMBIOS_GET8(base, off) (*(uint8_t *)((base) + (off)))
#define SMBIOS_GET16(base, off) (*(uint16_t *)((base) + (off)))
#define SMBIOS_GET32(base, off) (*(uint32_t *)((base) + (off)))
+#define SMBIOS_GET64(base, off) (*(uint64_t *)((base) + (off)))
#define SMBIOS_GETLEN(base) SMBIOS_GET8(base, 0x01)
#define SMBIOS_GETSTR(base) ((base) + SMBIOS_GETLEN(base))
@@ -103,14 +110,71 @@ static caddr_t
smbios_sigsearch(const caddr_t addr, const uint32_t len)
{
caddr_t cp;
+ uintptr_t paddr;
/* Search on 16-byte boundaries. */
- for (cp = addr; cp < addr + len; cp += SMBIOS_STEP)
- if (strncmp(cp, SMBIOS_SIG, 4) == 0 &&
+ for (cp = addr; cp < addr + len; cp += SMBIOS_STEP) {
+ if (strncmp(cp, SMBIOS_SIG, SMBIOS_SIG_LEN) == 0 &&
smbios_checksum(cp, SMBIOS_GET8(cp, 0x05)) == 0 &&
- strncmp(cp + 0x10, SMBIOS_DMI_SIG, 5) == 0 &&
- smbios_checksum(cp + 0x10, 0x0f) == 0)
+ strncmp(cp + 0x10, SMBIOS_DMI_SIG, SMBIOS_DMI_SIG_LEN) == 0
+ && smbios_checksum(cp + 0x10, 0x0f) == 0) {
+
+ /* Structure Table Length */
+ smbios.length = SMBIOS_GET16(cp, 0x16);
+ /* Structure Table Address */
+ paddr = SMBIOS_GET32(cp, 0x18);
+ /* No of SMBIOS Structures */
+ smbios.count = SMBIOS_GET16(cp, 0x1c);
+ /* SMBIOS BCD Revision */
+ smbios.ver = SMBIOS_GET8(cp, 0x1e);
+ if (smbios.ver != 0) {
+ smbios.major = smbios.ver >> 4;
+ smbios.minor = smbios.ver & 0x0f;
+ if (smbios.major > 9 || smbios.minor > 9)
+ smbios.ver = 0;
+ }
+ if (smbios.ver == 0) {
+ /* SMBIOS Major Version */
+ smbios.major = SMBIOS_GET8(cp, 0x06);
+ /* SMBIOS Minor Version */
+ smbios.minor = SMBIOS_GET8(cp, 0x07);
+ }
+ smbios.ver = (smbios.major << 8) | smbios.minor;
+ smbios.addr = PTOV(paddr);
return (cp);
+ }
+#ifdef _LP64
+ /*
+ * Check for the SMBIOS 64-bit entry point introduced in
+ * version 3.0.
+ *
+ * The table address is a 64-bit physical address that may
+ * appear at any 64-bit address. We only search for
+ * the 64-bit entry point when running a 64-bit application.
+ */
+ if (strncmp(cp, SMBIOS3_SIG, SMBIOS3_SIG_LEN) == 0 &&
+ smbios_checksum(cp, SMBIOS_GET8(cp, 0x06)) == 0) {
+
+ /* SMBIOS Major Version */
+ smbios.major = SMBIOS_GET8(cp, 0x07);
+ /* SMBIOS Minor Version */
+ smbios.minor = SMBIOS_GET8(cp, 0x08);
+ /* Entry Point Revision */
+ smbios.ver = SMBIOS_GET8(cp, 0x0a);
+ /* Structure Table maximum size */
+ smbios.length = SMBIOS_GET32(cp, 0x0c);
+ /* Structure Table Address */
+ paddr = SMBIOS_GET64(cp, 0x10);
+ smbios.addr = PTOV(paddr);
+ /*
+ * Calculate upper limit for structure count,
+ * use size of table header (4 bytes).
+ */
+ smbios.count = smbios.length / 4;
+ return (cp);
+ }
+#endif
+ }
return (NULL);
}
@@ -361,37 +425,17 @@ smbios_find_struct(int type)
static void
smbios_probe(const caddr_t addr)
{
- caddr_t saddr, info;
- uintptr_t paddr;
+ caddr_t info;
+ const caddr_t paddr = addr != NULL ? addr : PTOV(SMBIOS_START);
if (smbios.probed)
return;
smbios.probed = 1;
/* Search signatures and validate checksums. */
- saddr = smbios_sigsearch(addr ? addr : PTOV(SMBIOS_START),
- SMBIOS_LENGTH);
- if (saddr == NULL)
+ if (smbios_sigsearch(paddr, SMBIOS_LENGTH) == NULL)
return;
- smbios.length = SMBIOS_GET16(saddr, 0x16); /* Structure Table Length */
- paddr = SMBIOS_GET32(saddr, 0x18); /* Structure Table Address */
- smbios.count = SMBIOS_GET16(saddr, 0x1c); /* No of SMBIOS Structures */
- smbios.ver = SMBIOS_GET8(saddr, 0x1e); /* SMBIOS BCD Revision */
-
- if (smbios.ver != 0) {
- smbios.major = smbios.ver >> 4;
- smbios.minor = smbios.ver & 0x0f;
- if (smbios.major > 9 || smbios.minor > 9)
- smbios.ver = 0;
- }
- if (smbios.ver == 0) {
- smbios.major = SMBIOS_GET8(saddr, 0x06);/* SMBIOS Major Version */
- smbios.minor = SMBIOS_GET8(saddr, 0x07);/* SMBIOS Minor Version */
- }
- smbios.ver = (smbios.major << 8) | smbios.minor;
- smbios.addr = PTOV(paddr);
-
/* Get system information from SMBIOS */
info = smbios_find_struct(0x00);
if (info != NULL) {