aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorOlivier Certner <olce@FreeBSD.org>2025-03-03 21:10:25 +0000
committerOlivier Certner <olce@FreeBSD.org>2025-03-11 13:54:09 +0000
commit7f005c6699f429c2f762b4dd8fb39b3bcf5378e2 (patch)
tree452b0c6e99d434f81cf767b88510cedeeee217a6
parent3f744fb8b2c5528c2170be113e0e4947eee3cffc (diff)
libsa: smbios: Use 64-bit entry point if table below 4GB on non-EFI boot
On amd64, boot blocks and the non-EFI loader are 32-bit compiled as clients of BTX, so cannot access addresses beyond 4GB. However, the 64-bit entry point may refer to a structure table below 4GB, which we want to use if the BIOS does not provide a 32-bit entry point. The situation is similar for powerpc64. Consequently, always compile-in support for the 64-bit entry point, but ensure that it is not selected on 32-bit-compiled boot loaders if the structure table it points to grows beyond 4GB (as it is then not accessible). PR: 284460 Reviewed by: markj MFC after: 2 weeks Relnotes: yes Sponsored by: The FreeBSD Foundation Differential Revision: https://reviews.freebsd.org/D49288
-rw-r--r--stand/libsa/smbios.c37
1 files changed, 14 insertions, 23 deletions
diff --git a/stand/libsa/smbios.c b/stand/libsa/smbios.c
index 2477c0ccf2d3..e0531eab01da 100644
--- a/stand/libsa/smbios.c
+++ b/stand/libsa/smbios.c
@@ -29,11 +29,6 @@
#define PTOV(x) ptov(x)
-/* Only enable 64-bit entry point if it makes sense */
-#if __SIZEOF_POINTER__ > 4
-#define SMBIOS_64BIT_EP 1
-#endif
-
/*
* Detect SMBIOS and export information about the SMBIOS into the
* environment.
@@ -145,9 +140,7 @@ SMBIOS_GET64(const caddr_t base, int off)
struct smbios_attr {
int probed;
-#ifdef SMBIOS_64BIT_EP
int is_64bit_ep;
-#endif
caddr_t addr;
size_t length;
size_t count;
@@ -184,7 +177,6 @@ smbios_sigsearch(const caddr_t addr, const uint32_t len)
/* Search on 16-byte boundaries. */
for (cp = addr; cp < addr + len; cp += SMBIOS_STEP) {
-#ifdef SMBIOS_64BIT_EP
/* v3.0, 64-bit Entry point */
if (strncmp(cp, SMBIOS3_SIG, sizeof(SMBIOS3_SIG) - 1) == 0 &&
/*
@@ -195,10 +187,19 @@ smbios_sigsearch(const caddr_t addr, const uint32_t len)
*/
SMBIOS_GET8(cp, 0x0a) != 0 &&
smbios_checksum(cp, SMBIOS_GET8(cp, 0x06)) == 0) {
+#ifdef __ILP32__
+ uint64_t end_addr;
+
+ end_addr = SMBIOS_GET64(cp, 0x10) + /* Start address. */
+ SMBIOS_GET32(cp, 0x0c); /* Maximum size. */
+ /* Is the table (or part of it) located above 4G? */
+ if (end_addr >= (uint64_t)1 << 32)
+ /* Can't access it with 32-bit addressing. */
+ continue;
+#endif
smbios.is_64bit_ep = 1;
return (cp);
}
-#endif
/* v2.1, 32-bit Entry point */
if (strncmp(cp, SMBIOS_SIG, sizeof(SMBIOS_SIG) - 1) == 0 &&
@@ -207,13 +208,9 @@ smbios_sigsearch(const caddr_t addr, const uint32_t len)
smbios_checksum(cp + 0x10, 0x0f) == 0) {
/*
* Note that we saw this entry point, but don't return
- * it right now on SMBIOS_64BIT_EP as we favor the 64-bit
- * one if present.
+ * it right now as we favor the 64-bit one if present.
*/
v2_p = cp;
-#ifndef SMBIOS_64BIT_EP
- break;
-#endif
}
}
return (v2_p);
@@ -586,7 +583,6 @@ smbios_probe(const caddr_t addr)
if (saddr == NULL)
return;
-#ifdef SMBIOS_64BIT_EP
if (smbios.is_64bit_ep) {
/* Structure Table Length */
smbios.length = SMBIOS_GET32(saddr, 0x0c);
@@ -601,9 +597,7 @@ smbios_probe(const caddr_t addr)
smbios.ver = 0;
maj_off = 0x07;
min_off = 0x08;
- } else
-#endif
- {
+ } else {
/* Structure Table Length */
smbios.length = SMBIOS_GET16(saddr, 0x16);
/* Structure Table Address */
@@ -661,11 +655,8 @@ smbios_detect(const caddr_t addr)
dmi < smbios.addr + smbios.length && i < smbios.count; i++)
dmi = smbios_parse_table(dmi);
- setenv("smbios.entry_point_type",
-#ifdef SMBIOS_64BIT_EP
- smbios.is_64bit_ep ? "v3 (64-bit)" :
-#endif
- "v2.1 (32-bit)", 1);
+ setenv("smbios.entry_point_type", smbios.is_64bit_ep ?
+ "v3 (64-bit)" : "v2.1 (32-bit)", 1);
sprintf(buf, "%d.%d", smbios.major, smbios.minor);
setenv("smbios.version", buf, 1);
if (smbios.enabled_memory > 0 || smbios.old_enabled_memory > 0) {