Skip to content

Commit

Permalink
7649 loader.efi: fix extraction of firmare table info for smbios and …
Browse files Browse the repository at this point in the history
…acpi.

Reviewed by: Robert Mustacchi <rm@joyent.com>
Reviewed by: Richard Lowe <richlowe@richlowe.net>
Approved by: Hans Rosenfeld <rosenfeld@grumpf.hope-2000.org>
  • Loading branch information
tsoome authored and hrosenfeld committed Jan 31, 2017
1 parent 22cc544 commit dcba96f
Show file tree
Hide file tree
Showing 4 changed files with 154 additions and 41 deletions.
4 changes: 2 additions & 2 deletions usr/src/boot/sys/boot/efi/loader/Makefile
Expand Up @@ -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
Expand Down
75 changes: 75 additions & 0 deletions 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);
}
}
18 changes: 6 additions & 12 deletions usr/src/boot/sys/boot/efi/loader/main.c
Expand Up @@ -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);
Expand Down Expand Up @@ -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;

Expand Down Expand Up @@ -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 */
Expand Down
98 changes: 71 additions & 27 deletions usr/src/boot/sys/boot/i386/libi386/smbios.c
Expand Up @@ -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
*/

/*
Expand All @@ -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))
Expand Down Expand Up @@ -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);
}

Expand Down Expand Up @@ -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) {
Expand Down

0 comments on commit dcba96f

Please sign in to comment.