git: a2e28ba79238 - main - kboot: Support reading the smbios vis sysfs

From: Andrew Turner <andrew_at_FreeBSD.org>
Date: Mon, 18 Aug 2025 09:46:10 UTC
The branch main has been updated by andrew:

URL: https://cgit.FreeBSD.org/src/commit/?id=a2e28ba79238ef5842db7e4581ed85c2fb63c317

commit a2e28ba79238ef5842db7e4581ed85c2fb63c317
Author:     Andrew Turner <andrew@FreeBSD.org>
AuthorDate: 2025-07-25 02:07:17 +0000
Commit:     Andrew Turner <andrew@FreeBSD.org>
CommitDate: 2025-07-30 18:35:29 +0000

    kboot: Support reading the smbios vis sysfs
    
    When reading the smbios on Linux we try to access it via /dev/mem. On
    some systems we can't do this as /dev/mem is locked down. To handle
    this try reading the sysfs file first, and if that fails fall back to
    /dev/mem.
    
    Reviewed by:    imp
    Sponsored by:   Arm Ltd
    Differential Revision:  https://reviews.freebsd.org/D51413
---
 stand/kboot/kboot/main.c | 49 ++++++++++++++++++++++++++++++++++++++++++------
 1 file changed, 43 insertions(+), 6 deletions(-)

diff --git a/stand/kboot/kboot/main.c b/stand/kboot/kboot/main.c
index a8c725a514be..4a136b42a4a1 100644
--- a/stand/kboot/kboot/main.c
+++ b/stand/kboot/kboot/main.c
@@ -229,6 +229,7 @@ static struct mapping
 	uintptr_t pa;
 	caddr_t va;
 } map[MAX_MAP];
+static bool smbios_mmap_file;
 static int smbios_fd;
 static int nmap;
 
@@ -238,12 +239,17 @@ caddr_t ptov(uintptr_t pa)
 	uintptr_t pa2;
 	struct mapping *m = map;
 
-	pa2 = rounddown(pa, PAGE);
+	if (smbios_mmap_file)
+		pa2 = rounddown(pa, PAGE);
+	else
+		pa2 = pa;
 	for (int i = 0; i < nmap; i++, m++) {
 		if (m->pa == pa2) {
 			return (m->va + pa - m->pa);
 		}
 	}
+	if (!smbios_mmap_file)
+		panic("Out of bounds smbios access");
 	if (nmap == MAX_MAP)
 		panic("Too many maps for smbios");
 
@@ -298,6 +304,7 @@ static void
 find_smbios(void)
 {
 	char buf[40];
+	void *dmi_data;
 	uintptr_t pa;
 	caddr_t va;
 
@@ -306,17 +313,47 @@ find_smbios(void)
 	if (pa == 0)
 		return;
 
+	dmi_data = NULL;
+	smbios_fd = host_open("/sys/firmware/dmi/tables/DMI", O_RDONLY, 0);
+	if (smbios_fd >= 0) {
+		struct host_kstat sb;
+		struct mapping *m;
+
+		if (host_fstat(smbios_fd, &sb) < 0) {
+			host_close(smbios_fd);
+			goto try_dev_mem;
+		}
+
+		dmi_data = malloc(sb.st_size);
+		if (dmi_data == NULL) {
+			host_close(smbios_fd);
+			goto try_dev_mem;
+		}
+
+		host_read(smbios_fd, dmi_data, sb.st_size);
+
+		m = &map[nmap++];
+		m->pa = pa;
+		m->va = dmi_data;
+		smbios_mmap_file = false;
+	} else {
+try_dev_mem:
+		smbios_fd = host_open("/dev/mem", O_RDONLY, 0);
+		if (smbios_fd < 0) {
+			printf("Can't open /sys/firmware/dmi/tables/DMI or "
+			    "/dev/mem to read smbios\n");
+			return;
+		}
+		smbios_mmap_file = true;
+	}
 	snprintf(buf, sizeof(buf), "%#jx", (uintmax_t)pa);
 	setenv("hint.smbios.0.mem", buf, 1);
-	smbios_fd = host_open("/dev/mem", O_RDONLY, 0);
-	if (smbios_fd < 0) {
-		printf("Can't open /dev/mem to read smbios\n");
-		return;
-	}
+
 	va = ptov(pa);
 	printf("Start of smbios at pa %p va %p\n", (void *)pa, va);
 	smbios_detect(va);
 	smbios_cleanup();
+	free(dmi_data);
 	host_close(smbios_fd);
 }