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

openSUSE Build Service is sponsored by