ohmu
·
2026-10-15
1#include "bios.h"
2#include "common/debug.h"
3#include "common/smbios.h"
4
5#ifdef _WIN32
6 #include "common/windows/registry.h"
7
8 #include <ntstatus.h>
9 #include "common/windows/nt.h"
10#elif __OpenBSD__
11 #include "common/io.h"
12
13 #include <fcntl.h>
14 #include <unistd.h>
15#elif __sun
16 #include <libdevinfo.h>
17 #include <sys/sunddi.h>
18#elif __APPLE__
19 #include "common/apple/cf_helpers.h"
20 #include <IOKit/IOKitLib.h>
21#endif
22
23typedef struct [[gnu::packed]] FFSmbiosBios {
24 FFSmbiosHeader Header;
25
26 uint8_t Vendor; // string
27 uint8_t BiosVersion; // string
28 uint16_t BiosStartingAddressSegment; // varies
29 uint8_t BiosReleaseDate; // string
30 uint8_t BiosRomSize; // string
31 uint64_t BiosCharacteristics; // bit field
32
33 // 2.4+
34 uint8_t BiosCharacteristicsExtensionBytes[2]; // bit field
35 uint8_t SystemBiosMajorRelease; // varies
36 uint8_t SystemBiosMinorRelease; // varies
37 uint8_t EmbeddedControllerFirmwareMajorRelease; // varies
38 uint8_t EmbeddedControllerFirmwareMinorRelease; // varies
39
40 // 3.1+
41 uint16_t ExtendedBiosRomSize; // bit field
42} FFSmbiosBios;
43
44static_assert(offsetof(FFSmbiosBios, ExtendedBiosRomSize) == 0x18,
45 "FFSmbiosBios: Wrong struct alignment");
46
47const char* ffDetectBios(FFBiosResult* bios) {
48 const FFSmbiosHeaderTable* smbiosTable = ffGetSmbiosHeaderTable();
49 if (!smbiosTable) {
50 FF_DEBUG("BIOS: failed to get SMBIOS data");
51 return "Failed to get SMBIOS data";
52 }
53
54 const FFSmbiosBios* data = (const FFSmbiosBios*) (*smbiosTable)[FF_SMBIOS_TYPE_BIOS];
55 if (!data) {
56 FF_DEBUG("BIOS: section is not found in SMBIOS data");
57 return "BIOS section is not found in SMBIOS data";
58 }
59
60 const char* strings = (const char*) data + data->Header.Length;
61
62 ffStrbufSetStatic(&bios->version, ffSmbiosLocateString(strings, data->BiosVersion));
63 ffCleanUpSmbiosValue(&bios->version);
64 ffStrbufSetStatic(&bios->vendor, ffSmbiosLocateString(strings, data->Vendor));
65 ffCleanUpSmbiosValue(&bios->vendor);
66 ffStrbufSetStatic(&bios->date, ffSmbiosLocateString(strings, data->BiosReleaseDate));
67 ffCleanUpSmbiosValue(&bios->date);
68
69 if (data->Header.Length > offsetof(FFSmbiosBios, SystemBiosMajorRelease)) {
70 ffStrbufSetF(&bios->release, "%u.%u", data->SystemBiosMajorRelease, data->SystemBiosMinorRelease);
71 }
72
73#ifdef _WIN32
74 // Same as GetFirmwareType, but support (?) Windows 7
75 // https://ntdoc.m417z.com/system_information_class
76 SYSTEM_BOOT_ENVIRONMENT_INFORMATION sbei;
77 if (NT_SUCCESS(NtQuerySystemInformation(SystemBootEnvironmentInformation, &sbei, sizeof(sbei), nullptr))) {
78 switch (sbei.FirmwareType) {
79 case FirmwareTypeBios:
80 ffStrbufSetStatic(&bios->type, "BIOS");
81 break;
82 case FirmwareTypeUefi:
83 ffStrbufSetStatic(&bios->type, "UEFI");
84 break;
85 default:
86 break;
87 }
88 }
89#elif __sun
90 di_node_t rootNode = di_init("/", DINFOPROP);
91 if (rootNode != DI_NODE_NIL) {
92 char* efiVersion = nullptr;
93 if (di_prop_lookup_strings(DDI_DEV_T_ANY, rootNode, "efi-version", &efiVersion) > 0) {
94 ffStrbufSetStatic(&bios->type, "UEFI");
95 } else {
96 ffStrbufSetStatic(&bios->type, "BIOS");
97 }
98 }
99 di_fini(rootNode);
100#elif __HAIKU__ || __OpenBSD__
101 // Currently SMBIOS detection is supported in legacy BIOS only
102 ffStrbufSetStatic(&bios->type, "BIOS");
103#elif __APPLE__
104 // Intel Macs use UEFI from day one
105 FF_IOOBJECT_AUTO_RELEASE io_registry_entry_t deviceEfi = IORegistryEntryFromPath(MACH_PORT_NULL, "IODeviceTree:/efi");
106 ffStrbufSetStatic(&bios->type, deviceEfi ? "UEFI" : "BIOS");
107#endif
108
109 return nullptr;
110}