aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJohn-Mark Gurney <jmg@FreeBSD.org>2023-02-22 02:27:37 +0000
committerJohn-Mark Gurney <jmg@FreeBSD.org>2023-02-22 04:10:12 +0000
commitee97f198b42d50437f87aa4111d478eca2a5be16 (patch)
tree58fc17f9bb0f5f1e01491cd2eefbef0aa8c0d028
parent19850ee07363ffd97b4ba3c06361392ce9834440 (diff)
downloadsrc-ee97f198b42d50437f87aa4111d478eca2a5be16.tar.gz
src-ee97f198b42d50437f87aa4111d478eca2a5be16.zip
Support SMBIOS v3 for 64-bit entry systems
Summary: Under QEMU on arm64 systems, the smbios table is above 4GB requiring a 64-bit address to access. Reviewers: manu Subscribers: imp, bcran, dab Differential Revision: https://reviews.freebsd.org/D38721
-rw-r--r--stand/efi/loader/main.c3
-rw-r--r--stand/libsa/smbios.c54
2 files changed, 48 insertions, 9 deletions
diff --git a/stand/efi/loader/main.c b/stand/efi/loader/main.c
index 446c267a517a..9ff5f1dd7674 100644
--- a/stand/efi/loader/main.c
+++ b/stand/efi/loader/main.c
@@ -1187,7 +1187,8 @@ main(int argc, CHAR16 *argv[])
#if !defined(__arm__)
for (k = 0; k < ST->NumberOfTableEntries; k++) {
guid = &ST->ConfigurationTable[k].VendorGuid;
- if (!memcmp(guid, &smbios, sizeof(EFI_GUID))) {
+ if (!memcmp(guid, &smbios, sizeof(EFI_GUID)) ||
+ !memcmp(guid, &smbios3, sizeof(EFI_GUID))) {
char buf[40];
snprintf(buf, sizeof(buf), "%p",
diff --git a/stand/libsa/smbios.c b/stand/libsa/smbios.c
index 61bd82f9d6f0..15c5c7e50565 100644
--- a/stand/libsa/smbios.c
+++ b/stand/libsa/smbios.c
@@ -32,6 +32,11 @@ __FBSDID("$FreeBSD$");
#define PTOV(x) ptov(x)
+/* Only enable 64-bit entry point if it makes sense */
+#if __SIZEOF_POINTER__ > 4
+#define HAS_SMBV3 1
+#endif
+
/*
* Detect SMBIOS and export information about the SMBIOS into the
* environment.
@@ -53,11 +58,13 @@ __FBSDID("$FreeBSD$");
#define SMBIOS_LENGTH 0x10000
#define SMBIOS_STEP 0x10
#define SMBIOS_SIG "_SM_"
+#define SMBIOS3_SIG "_SM3_"
#define SMBIOS_DMI_SIG "_DMI_"
#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))
@@ -80,6 +87,9 @@ struct smbios_attr {
};
static struct smbios_attr smbios;
+#ifdef HAS_SMBV3
+static int isv3;
+#endif
static uint8_t
smbios_checksum(const caddr_t addr, const uint8_t len)
@@ -98,12 +108,23 @@ smbios_sigsearch(const caddr_t addr, const uint32_t len)
caddr_t cp;
/* 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) {
+ /* v2.1, 32-bit Entry point */
+ if (strncmp(cp, SMBIOS_SIG, sizeof(SMBIOS_SIG) - 1) == 0 &&
smbios_checksum(cp, SMBIOS_GET8(cp, 0x05)) == 0 &&
strncmp(cp + 0x10, SMBIOS_DMI_SIG, 5) == 0 &&
smbios_checksum(cp + 0x10, 0x0f) == 0)
return (cp);
+
+#ifdef HAS_SMBV3
+ /* v3.0, 64-bit Entry point */
+ if (strncmp(cp, SMBIOS3_SIG, sizeof(SMBIOS3_SIG) - 1) == 0 &&
+ smbios_checksum(cp, SMBIOS_GET8(cp, 0x06)) == 0) {
+ isv3 = 1;
+ return (cp);
+ }
+#endif
+ }
return (NULL);
}
@@ -450,6 +471,8 @@ smbios_probe(const caddr_t addr)
{
caddr_t saddr, info;
uintptr_t paddr;
+ int maj_off;
+ int min_off;
if (smbios.probed)
return;
@@ -461,10 +484,25 @@ smbios_probe(const caddr_t addr)
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 */
+#ifdef HAS_SMBV3
+ if (isv3) {
+ smbios.length = SMBIOS_GET16(saddr, 0x0c); /* Structure Table Length */
+ paddr = SMBIOS_GET64(saddr, 0x10); /* Structure Table Address */
+ smbios.count = -1; /* not present in V3 */
+ smbios.ver = 0; /* not present in V3 */
+ maj_off = 0x07;
+ min_off = 0x08;
+ } else
+#endif
+ {
+ 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 */
+ maj_off = 0x06;
+ min_off = 0x07;
+ }
+
if (smbios.ver != 0) {
smbios.major = smbios.ver >> 4;
@@ -473,8 +511,8 @@ smbios_probe(const caddr_t addr)
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.major = SMBIOS_GET8(saddr, maj_off);/* SMBIOS Major Version */
+ smbios.minor = SMBIOS_GET8(saddr, min_off);/* SMBIOS Minor Version */
}
smbios.ver = (smbios.major << 8) | smbios.minor;
smbios.addr = PTOV(paddr);