Index: stand/efi/loader/main.c =================================================================== --- stand/efi/loader/main.c +++ stand/efi/loader/main.c @@ -1161,17 +1161,23 @@ efi_init_environment(); #if !defined(__arm__) - for (k = 0; k < ST->NumberOfTableEntries; k++) { - guid = &ST->ConfigurationTable[k].VendorGuid; - if (!memcmp(guid, &smbios, sizeof(EFI_GUID))) { - char buf[40]; - - snprintf(buf, sizeof(buf), "%p", - ST->ConfigurationTable[k].VendorTable); - setenv("hint.smbios.0.mem", buf, 1); - smbios_detect(ST->ConfigurationTable[k].VendorTable); - break; - } + void *smbios_ep, *smbios3_ep; + + smbios_ep = efi_get_table(&smbios); + smbios_ep3 = efi_get_table(&smbios3); + if (smbios3_ep != NULL) { + char buf[40]; + + snprintf(buf, sizeof(buf), "%p", smbios3_ep); + setenv("hint.smbios3.0.mem", buf, 1); + smbios_detect(smbios3_ep); + } + if (smbios_ep != NULL) { + char buf[40]; + + snprintf(buf, sizeof(buf), "%p", smbios_ep); + setenv("hint.smbios.0.mem", buf, 1); + smbios_detect(smbios_ep); } #endif Index: stand/libsa/smbios.c =================================================================== --- stand/libsa/smbios.c +++ stand/libsa/smbios.c @@ -54,10 +54,12 @@ #define SMBIOS_STEP 0x10 #define SMBIOS_SIG "_SM_" #define SMBIOS_DMI_SIG "_DMI_" +#define SMBIOS3_SIG "_SM3_" #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)) @@ -98,6 +100,11 @@ caddr_t cp; /* Search on 16-byte boundaries. */ + for (cp = addr; cp < addr + len; cp += SMBIOS_STEP) + if (strncmp(cp, SMBIOS3_SIG, 5) == 0 && + smbios_checksum(cp, SMBIOS_GET8(cp, 0x06)) == 0) + return (cp); + for (cp = addr; cp < addr + len; cp += SMBIOS_STEP) if (strncmp(cp, SMBIOS_SIG, 4) == 0 && smbios_checksum(cp, SMBIOS_GET8(cp, 0x05)) == 0 && @@ -423,7 +430,9 @@ return (NULL); for (dmi = smbios.addr, i = 0; - dmi < smbios.addr + smbios.length && i < smbios.count; i++) { + dmi < smbios.addr + smbios.length && + (smbios.count == 0 || i < smbios.count); + i++) { if (SMBIOS_GET8(dmi, 0) == type) return dmi; /* Find structure terminator. */ @@ -437,25 +446,44 @@ } static void -smbios_probe(const caddr_t addr) +smbios_probe(caddr_t addr) { caddr_t saddr, info; uintptr_t paddr; + uint32_t searchlen; + bool ep_64bit; if (smbios.probed) return; smbios.probed = 1; + if (addr == 0) { + addr = PTOV(SMBIOS_START); + searchlen = SMBIOS_LENGTH; + } else { + searchlen = 1; + } + /* Search signatures and validate checksums. */ - saddr = smbios_sigsearch(addr ? addr : PTOV(SMBIOS_START), - SMBIOS_LENGTH); + saddr = smbios_sigsearch(addr, searchlen); if (saddr == 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 */ + ep_64bit = (SMBIOS_GET8(saddr, 0x3) == '3') ? true : false; + + if (ep_64bit) { + /* SMBIOS 3.0 (64-bit) Entry Point */ + smbios.length = SMBIOS_GET32(saddr, 0xc); /* Structure table maximum size */ + paddr = SMBIOS_GET64(saddr, 0x10); /* Structure table address */ + smbios.ver = 0; + smbios.count = 0; + } else { + /* SMBIOS 2.1 (32-bit) Entry Point */ + 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; @@ -464,8 +492,13 @@ 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 */ + if (ep_64bit) { + smbios.major = SMBIOS_GET8(saddr, 0x07);/* SMBIOS Major Version */ + smbios.minor = SMBIOS_GET8(saddr, 0x08);/* SMBIOS Minor Version */ + } else { + 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); @@ -489,12 +522,17 @@ caddr_t dmi; size_t i; + if (smbios.addr != NULL) + return; + smbios_probe(addr); if (smbios.addr == NULL) return; for (dmi = smbios.addr, i = 0; - dmi < smbios.addr + smbios.length && i < smbios.count; i++) + dmi < smbios.addr + smbios.length && + (smbios.count == 0 || i < smbios.count); + i++) dmi = smbios_parse_table(dmi); sprintf(buf, "%d.%d", smbios.major, smbios.minor);