master ohmu/fastfetch-openbsd / src / detection / bootmgr / bootmgr_bsd.c
ohmu  ·  2026-10-15
 1#include "bootmgr.h"
 2#include "efi_helper.h"
 3#include "common/debug.h"
 4#include "common/io.h"
 5
 6#ifdef __OpenBSD__
 7    #include <dev/efi/efiio.h>
 8#else
 9    #include <sys/efiio.h>
10#endif
11#include <sys/ioctl.h>
12#include <fcntl.h>
13#include <stdalign.h>
14
15#ifdef __NetBSD__
16typedef uint16_t efi_char;
17#endif
18
19#ifndef EFI_GLOBAL_VARIABLE
20    #define EFI_GLOBAL_VARIABLE { 0x8be4df61, 0x93ca, 0x11d2, 0xaa, 0x0d, { 0x00, 0xe0, 0x98, 0x03, 0x2b, 0x8c } }
21#endif
22
23const char* ffDetectBootmgr(FFBootmgrResult* result) {
24    FF_AUTO_CLOSE_FD int efifd = open("/dev/efi", O_RDWR | O_CLOEXEC);
25    if (efifd < 0) {
26        FF_DEBUG("open(\"/dev/efi\") failed: %s", strerror(errno));
27        return "open(/dev/efi) failed";
28    }
29
30    alignas(uint16_t) uint8_t buffer[2048];
31    struct efi_var_ioc ioc = {
32        .vendor = EFI_GLOBAL_VARIABLE,
33        .data = buffer,
34    };
35
36    ioc.datasize = sizeof(buffer);
37    ioc.name = (efi_char[]) { 'B', 'o', 'o', 't', 'C', 'u', 'r', 'r', 'e', 'n', 't', '\0' };
38    ioc.namesize = sizeof("BootCurrent") * 2;
39    if (ioctl(efifd, EFIIOC_VAR_GET, &ioc) < 0 || ioc.datasize != 2) {
40        FF_DEBUG("ioctl(EFIIOC_VAR_GET, BootCurrent) failed");
41        return "ioctl(EFIIOC_VAR_GET, BootCurrent) failed";
42    }
43
44    result->order = *(uint16_t*) buffer;
45
46    unsigned char hex[5];
47    snprintf((char*) hex, sizeof(hex), "%04X", result->order);
48    ioc.datasize = sizeof(buffer);
49    ioc.name = (efi_char[]) { 'B', 'o', 'o', 't', hex[0], hex[1], hex[2], hex[3], '\0' };
50    ioc.namesize = sizeof("Boot####") * 2;
51    if (ioctl(efifd, EFIIOC_VAR_GET, &ioc) < 0 || ioc.datasize == sizeof(buffer)) {
52        FF_DEBUG("ioctl(EFIIOC_VAR_GET, Boot####) failed");
53        return "ioctl(EFIIOC_VAR_GET, Boot####) failed";
54    }
55
56    ffEfiFillLoadOption((FFEfiLoadOption*) buffer, result);
57
58    ioc.name = (efi_char[]) { 'S', 'e', 'c', 'u', 'r', 'e', 'B', 'o', 'o', 't', '\0' };
59    ioc.namesize = sizeof("SecureBoot") * 2;
60    ioc.datasize = sizeof(buffer);
61    if (ioctl(efifd, EFIIOC_VAR_GET, &ioc) == 0 && ioc.datasize == 1) {
62        result->secureBoot = !!buffer[0];
63    }
64
65    return nullptr;
66}