File 0001-blsuki-Add-support-for-LoaderEntries.patch of Package grub2
From c114cc791483dee8f833e9ed303b78b60922551b Mon Sep 17 00:00:00 2001
From: Danilo Spinella <danilo.spinella@suse.com>
Date: Tue, 10 Mar 2026 16:38:34 +0100
Subject: [PATCH 1/9] blsuki: Add support for LoaderEntries
---
grub-core/commands/blsuki.c | 156 ++++++++++++++++++++++++++++++++++++
1 file changed, 156 insertions(+)
diff --git a/grub-core/commands/blsuki.c b/grub-core/commands/blsuki.c
index 4133d3111..2664a9fc4 100644
--- a/grub-core/commands/blsuki.c
+++ b/grub-core/commands/blsuki.c
@@ -33,9 +33,15 @@
#include <filevercmp.h>
#ifdef GRUB_MACHINE_EFI
+#include <grub/charset.h>
#include <grub/efi/efi.h>
#include <grub/efi/disk.h>
#include <grub/efi/pe32.h>
+
+static const grub_guid_t bli_vendor_guid = GRUB_EFI_VENDOR_BOOT_LOADER_INTERFACE_GUID;
+
+#define GRUB_BLSUKI_ENTRIES_BLS "blsuki_entries_bls"
+#define GRUB_BLSUKI_ENTRIES_UKI "blsuki_entries_uki"
#endif
#ifdef GRUB_MACHINE_EMU
@@ -1373,6 +1379,152 @@ blsuki_is_default_entry (const char *def_entry, grub_blsuki_entry_t *entry, int
return false;
}
+#ifdef GRUB_MACHINE_EFI
+/* Set LoaderEntries for uki and blscfg generated entries */
+static grub_err_t
+set_bli_loader_entries (enum blsuki_cmd_type cmd_type)
+{
+ grub_blsuki_entry_t *entry = NULL;
+ grub_size_t size = 0, remaining_size, len, written, prev_entries_size = 0, len16;
+ grub_efi_char16_t *prev_entries_start = NULL;
+ grub_size_t prev_entries_start_size = 0;
+ grub_efi_char16_t *efi_entries = NULL, *prev_entries = NULL, *p = NULL, *tmp16;
+ char *boot_counting_idx, *prev_entry;
+ const char* env = NULL;
+ grub_efi_status_t status;
+ int rc;
+
+ FOR_BLSUKI_ENTRIES (entry)
+ {
+ if (entry->visible)
+ {
+ /* Calculate the size of LoaderEntries string */
+ len = grub_strlen (entry->filename);
+ /* Skip boot counting if found */
+ boot_counting_idx = grub_strrchr(entry->filename, '+');
+ if (boot_counting_idx != NULL)
+ len = boot_counting_idx - entry->filename;
+ /* Skip ".conf" extension if found */
+ else if (len > BLS_EXT_LEN
+ && grub_strcmp (entry->filename + len - BLS_EXT_LEN, ".conf") == 0)
+ len -= BLS_EXT_LEN;
+ else if (len > UKI_EXT_LEN
+ && grub_strcmp (entry->filename + len - UKI_EXT_LEN, ".efi") == 0)
+ len -= UKI_EXT_LEN;
+
+ size += len + 1;
+ }
+ }
+
+ /* When calling blscfg command, there might be entries generated by uki command,
+ and viceversa. Use GRUB_BLSUKI_ENTRIES_BLS and GRUB_BLSUKI_ENTRIES_UKI env variables
+ to check if the current value of LoaderEntries should be appended to the new one */
+ if (cmd_type == BLSUKI_BLS_CMD)
+ {
+ env = grub_env_get (GRUB_BLSUKI_ENTRIES_UKI);
+ } else if (cmd_type == BLSUKI_UKI_CMD) {
+ env = grub_env_get (GRUB_BLSUKI_ENTRIES_BLS);
+ }
+ if (env && grub_strcmp (env, "1") == 0)
+ {
+ status = grub_efi_get_variable ("LoaderEntries",
+ &bli_vendor_guid,
+ &prev_entries_start_size,
+ (void**) &prev_entries_start);
+ /* Get the value of the other generated entries */
+ if (status != GRUB_EFI_SUCCESS || prev_entries_start_size == 0)
+ {
+ prev_entries_start = NULL;
+ prev_entries_start_size = 0;
+ }
+ }
+ efi_entries = grub_malloc (size * sizeof (grub_efi_char16_t) + prev_entries_start_size);
+ if (efi_entries == NULL)
+ return grub_errno;
+
+ prev_entries = prev_entries_start;
+ prev_entries_size = prev_entries_start_size;
+ p = efi_entries;
+ remaining_size = size;
+ /* Create a null separated list of all entries (with the extension removed) */
+ FOR_BLSUKI_ENTRIES (entry)
+ {
+ if (entry->visible)
+ {
+ len = grub_strlen (entry->filename);
+
+ boot_counting_idx = grub_strrchr(entry->filename, '+');
+ if (boot_counting_idx != NULL)
+ len = boot_counting_idx - entry->filename;
+ else if ((len > BLS_EXT_LEN)
+ && grub_strcmp (entry->filename + len - BLS_EXT_LEN, ".conf") == 0)
+ len -= BLS_EXT_LEN;
+ else if ((len > UKI_EXT_LEN)
+ && grub_strcmp (entry->filename + len - UKI_EXT_LEN, ".efi") == 0)
+ len -= UKI_EXT_LEN;
+
+ if (remaining_size < len + 1)
+ {
+ grub_dprintf ("blsuki", "LoaderEntries buffer too small\n");
+ break;
+ }
+
+ if (prev_entries_size != 0 && prev_entries)
+ {
+ do {
+ tmp16 = prev_entries;
+ len16 = 0;
+ while (*tmp16++ != '\0')
+ len16++;
+ prev_entry = grub_malloc (len16 + 1);
+ *grub_utf16_to_utf8 ((grub_uint8_t*) prev_entry, prev_entries, len16) = '\0';
+ rc = filevercmp (prev_entry, entry->filename);
+ if (rc == 0)
+ {
+ grub_free (prev_entry);
+ grub_free (prev_entries_start);
+ grub_free (efi_entries);
+ return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("duplicate file: `%s'"), entry->filename);
+ }
+
+ if (rc > 0)
+ {
+ grub_memcpy (p, prev_entries, len16 * sizeof (*prev_entries));
+ p += len16;
+ *p++ = (grub_efi_char16_t) '\0';
+ remaining_size -= len16 + 1;
+ prev_entries += len16 + 1;
+ prev_entries_size -= (len16 + 1) * sizeof (*prev_entries);
+ }
+ grub_free (prev_entry);
+ } while (prev_entries_size > 0 && rc > 0);
+ }
+
+ written = grub_utf8_to_utf16 (p, remaining_size,
+ (grub_uint8_t*) entry->filename, len, NULL);
+ p += written;
+ *p++ = (grub_efi_char16_t) '\0';
+ remaining_size -= written + 1;
+ }
+ }
+
+ status = grub_efi_set_variable_with_attributes ("LoaderEntries", &bli_vendor_guid,
+ efi_entries,
+ size * sizeof (grub_efi_char16_t) + prev_entries_start_size - prev_entries_size,
+ GRUB_EFI_VARIABLE_BOOTSERVICE_ACCESS |
+ GRUB_EFI_VARIABLE_RUNTIME_ACCESS);
+ /* Record that we set the generated entries by this command to LoaderEntries */
+ if (cmd_type == BLSUKI_BLS_CMD)
+ grub_env_set (GRUB_BLSUKI_ENTRIES_BLS, "1");
+ else if (cmd_type == BLSUKI_UKI_CMD)
+ grub_env_set (GRUB_BLSUKI_ENTRIES_UKI, "1");
+ grub_free (efi_entries);
+ grub_free (prev_entries_start);
+
+ return status;
+}
+#endif
+
/*
* This function creates a GRUB boot menu entry for each BLS or UKI entry in
* the entries list.
@@ -1409,6 +1561,10 @@ blsuki_create_entries (bool show_default, bool show_non_default, char *entry_id,
idx++;
}
+#ifdef GRUB_MACHINE_EFI
+ set_bli_loader_entries (cmd_type);
+#endif
+
return GRUB_ERR_NONE;
}
--
2.53.0