Blob Blame History Raw
From e629bccb2ced5f9e52e142bd841d310434975c63 Mon Sep 17 00:00:00 2001
From: Alexey Dokuchaev <danfe@nsu.ru>
Date: Thu, 30 Nov 2017 16:27:48 +0100
Subject: [PATCH 09/10] UEFI support on FreeBSD

Currently, dmidecode(8) does not work on FreeBSD booted in UEFI mode.
Previously it was understandable, since there are no things like Linuxish
/proc/efi/systab or /sys/firmware/efi/systab to read from under FreeBSD.

However, 7 months ago, ambrisko@ had added support for exposing the SMBIOS
anchor base address via kernel environment:

    https://svnweb.freebsd.org/base?view=revision&revision=307326

I've patched dmidecode.c to try to get the address from hint.smbios.0.mem
and fall back to traditional address space scanning.  I've tested it both
on EFI (amd64 laptop) and non-EFI (i386 desktop) machines.

---
 dmidecode.c | 33 +++++++++++++++++++++++++++++++++
 1 file changed, 33 insertions(+)

diff --git a/dmidecode.c b/dmidecode.c
index 6559567..aadef75 100644
--- a/dmidecode.c
+++ b/dmidecode.c
@@ -64,6 +64,11 @@
 #include <stdlib.h>
 #include <unistd.h>
 
+#ifdef __FreeBSD__
+#include <errno.h>
+#include <kenv.h>
+#endif
+
 #include "version.h"
 #include "config.h"
 #include "types.h"
@@ -4934,13 +4939,18 @@ static int legacy_decode(u8 *buf, const char *devmem, u32 flags)
 #define EFI_NO_SMBIOS   (-2)
 static int address_from_efi(off_t *address)
 {
+#if defined(__linux__)
 	FILE *efi_systab;
 	const char *filename;
 	char linebuf[64];
+#elif defined(__FreeBSD__)
+	char addrstr[KENV_MVALLEN + 1];
+#endif
 	int ret;
 
 	*address = 0; /* Prevent compiler warning */
 
+#if defined(__linux__)
 	/*
 	 * Linux up to 2.6.6: /proc/efi/systab
 	 * Linux 2.6.7 and up: /sys/firmware/efi/systab
@@ -4972,6 +4982,29 @@ static int address_from_efi(off_t *address)
 
 	if (ret == EFI_NO_SMBIOS)
 		fprintf(stderr, "%s: SMBIOS entry point missing\n", filename);
+#elif defined(__FreeBSD__)
+	/*
+	 * On FreeBSD, SMBIOS anchor base address in UEFI mode is exposed
+	 * via kernel environment:
+	 * https://svnweb.freebsd.org/base?view=revision&revision=307326
+	 */
+	ret = kenv(KENV_GET, "hint.smbios.0.mem", addrstr, sizeof(addrstr));
+	if (ret == -1)
+	{
+		if (errno != ENOENT)
+			perror("kenv");
+		return EFI_NOT_FOUND;
+	}
+
+	*address = strtoull(addrstr, NULL, 0);
+	if (!(opt.flags & FLAG_QUIET))
+		printf("# SMBIOS entry point at 0x%08llx\n",
+		    (unsigned long long)*address);
+
+	ret = 0;
+#else
+	ret = EFI_NOT_FOUND;
+#endif
 	return ret;
 }
 
-- 
2.9.5