:: commit 196e07ab05ca1bc1275e59724aeed74d29270e2a

sanana <umutinanerdogan@pm.me> — 2025-03-15 13:22

parents: 214a5be88c

bli: Implement initial Boot Loader Interface support

This patch makes Limine advertise its branding and the ESP partition GUID to
systemd over the Boot Loader Interface specification. There's more to the Boot
Loader Interface than these variables, but this acts as an initial
implementation. See #473.

BLI variables are initialised for all protocols, not just Linux. While currently
only systemd makes use of it, this allows future Limine protocol kernels (or
their userspace) to discover the ESP.
diff --git a/common/lib/bli.c b/common/lib/bli.c
new file mode 100644
index 00000000..ba0d70a3
--- /dev/null
+++ b/common/lib/bli.c
@@ -0,0 +1,36 @@
+#if defined (UEFI)
+
+#include <config.h>
+#include <efi.h>
+#include <lib/bli.h>
+#include <lib/guid.h>
+#include <lib/misc.h>
+
+#define LIMINE_BRAND L"Limine " LIMINE_VERSION
+
+static EFI_GUID bli_vendor_guid = { 0x4a67b082, 0x0a4c, 0x41cf, { 0xb6, 0xc7, 0x44, 0x0b, 0x29, 0xbb, 0x8c, 0x4f } };
+
+void init_bli(void) {
+    gRT->SetVariable(L"LoaderInfo",
+            &bli_vendor_guid,
+            EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS,
+            sizeof(LIMINE_BRAND),
+            LIMINE_BRAND);
+
+    char part_uuid_str[37];
+    guid_to_string(&boot_volume->part_guid, part_uuid_str);
+
+    // Convert part_uuid_str to a wide-char string
+    wchar_t part_uuid[37];
+    for (size_t i = 0; i < 37; i++) {
+        part_uuid[i] = (wchar_t) part_uuid_str[i];
+    }
+
+    gRT->SetVariable(L"LoaderDevicePartUUID",
+            &bli_vendor_guid,
+            EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS,
+            sizeof(part_uuid),
+            part_uuid);
+}
+
+#endif
diff --git a/common/lib/bli.h b/common/lib/bli.h
new file mode 100644
index 00000000..135dba5c
--- /dev/null
+++ b/common/lib/bli.h
@@ -0,0 +1,10 @@
+#ifndef LIB__BLI_H__
+#define LIB__BLI_H__
+
+#if defined (UEFI)
+
+void init_bli(void);
+
+#endif
+
+#endif
diff --git a/common/lib/guid.c b/common/lib/guid.c
index 2e9f4746..06730b0a 100644
--- a/common/lib/guid.c
+++ b/common/lib/guid.c
@@ -67,3 +67,29 @@ bool string_to_guid_mixed(struct guid *guid, const char *s) {
 
     return true;
 }
+
+static void uint_to_hex(uint32_t num, char *dest, int len) {
+    const char digits[] = "0123456789abcdef";
+    for (int i = 0; i < len; i++) {
+        dest[i] = digits[(num >> ((len - 1 - i) * 4)) & 0xf];
+    }
+}
+
+void guid_to_string(const struct guid *guid, char *s) {
+    uint_to_hex(guid->a, s, 8);
+    s[8] = '-';
+    uint_to_hex(guid->b, s + 9, 4);
+    s[13] = '-';
+    uint_to_hex(guid->c, s + 14, 4);
+    s[18] = '-';
+    uint_to_hex(guid->d[0], s + 19, 2);
+    uint_to_hex(guid->d[1], s + 21, 2);
+    s[23] = '-';
+    uint_to_hex(guid->d[2], s + 24, 2);
+    uint_to_hex(guid->d[3], s + 26, 2);
+    uint_to_hex(guid->d[4], s + 28, 2);
+    uint_to_hex(guid->d[5], s + 30, 2);
+    uint_to_hex(guid->d[6], s + 32, 2);
+    uint_to_hex(guid->d[7], s + 34, 2);
+    s[36] = 0;
+}
diff --git a/common/lib/guid.h b/common/lib/guid.h
index c360e88e..82b41c0f 100644
--- a/common/lib/guid.h
+++ b/common/lib/guid.h
@@ -14,5 +14,7 @@ struct guid {
 bool is_valid_guid(const char *s);
 bool string_to_guid_be(struct guid *guid, const char *s);
 bool string_to_guid_mixed(struct guid *guid, const char *s);
+// Assumption: s must be big enough to fit 36 characters and a null byte
+void guid_to_string(const struct guid *guid, char *s);
 
 #endif
diff --git a/common/menu.c b/common/menu.c
index 059b51fd..49b1c16a 100644
--- a/common/menu.c
+++ b/common/menu.c
@@ -12,6 +12,7 @@
 #include <lib/gterm.h>
 #include <lib/getchar.h>
 #include <lib/uri.h>
+#include <lib/bli.h>
 #include <mm/pmm.h>
 #include <drivers/vbe.h>
 #include <drivers/vga_textmode.h>
@@ -1165,6 +1166,9 @@ noreturn void boot(char *config) {
 #if defined (__riscv)
     init_riscv(config);
 #endif
+#if defined (UEFI)
+    init_bli();
+#endif
 
     char *cmdline = config_get_value(config, 0, "KERNEL_CMDLINE");
     if (!cmdline) {
tab: 248 wrap: offon