diff options
| author | Toomas Soome <tsoome@me.com> | 2016-10-09 17:12:23 +0300 |
|---|---|---|
| committer | Hans Rosenfeld <rosenfeld@grumpf.hope-2000.org> | 2017-01-31 16:24:49 +0100 |
| commit | dcba96fe6535681ea4a912e4b512a4e5ba59182e (patch) | |
| tree | 498f21e69b51f9a80c8dd39065e512c87833d444 | |
| parent | 22cc5444cba0d30b59582f255e2eb24e8a702824 (diff) | |
| download | illumos-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/Makefile | 4 | ||||
| -rw-r--r-- | usr/src/boot/sys/boot/efi/loader/acpi.c | 75 | ||||
| -rw-r--r-- | usr/src/boot/sys/boot/efi/loader/main.c | 18 | ||||
| -rw-r--r-- | usr/src/boot/sys/boot/i386/libi386/smbios.c | 98 |
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) { |
