File grub2-bls-loader-entry-oneshot.patch of Package grub2
Add support for LoaderEntryOneshot EFI variable
Index: grub-2.12/grub-core/normal/menu.c
===================================================================
--- grub-2.12.orig/grub-core/normal/menu.c
+++ grub-2.12/grub-core/normal/menu.c
@@ -36,6 +36,16 @@
#ifdef GRUB_MACHINE_IEEE1275
#include <grub/ieee1275/ieee1275.h>
#endif
+#ifdef GRUB_MACHINE_EFI
+#include <grub/charset.h>
+#include <grub/efi/api.h>
+#include <grub/efi/efi.h>
+
+#define GRUB_EFI_LOADER_GUID \
+ { 0x4a67b082, 0x0a4c, 0x41cf, { 0xb6, 0xc7, 0x44, 0x0b, 0x29, 0xbb, 0x8c, 0x4f } }
+static grub_guid_t grub_efi_loader_guid = GRUB_EFI_LOADER_GUID;
+
+#endif
/* Time to delay after displaying an error message about a default/fallback
entry failing to boot. */
@@ -562,6 +572,62 @@ menuentry_eq (const char *id, const char
}
}
+/* Search for an entry in the menu by its name */
+static int
+search_entry (grub_menu_t menu, const char* name)
+{
+ /* See if the variable matches the title of a menu entry. */
+ grub_menu_entry_t e = menu->entry_list;
+ int i;
+ int entry;
+
+ /* Skip hidden entries */
+ while (e && e->hidden)
+ e = e->next;
+
+ grub_errno = GRUB_ERR_NONE;
+
+ for (i = 0; e; i++)
+ {
+ if (menuentry_eq (e->title, name)
+ || menuentry_eq (e->id, name))
+ {
+ entry = i;
+ break;
+ }
+
+ if (e->bls)
+ {
+ char *v, *ext;
+
+ if ((v = grub_strdup (name)) &&
+ (ext = grub_strrchr (v, '.')) &&
+ grub_strcmp (ext, ".conf") == 0)
+ {
+ *ext = '\0';
+ if (menuentry_eq (e->id, v))
+ {
+ entry = i;
+ grub_free (v);
+ break;
+ }
+ }
+ grub_free (v);
+ }
+
+ e = e->next;
+
+ /* Skip hidden entries */
+ while (e && e->hidden)
+ e = e->next;
+ }
+
+ if (! e)
+ entry = -1;
+
+ return entry;
+}
+
/* Get the entry number from the variable NAME. */
static int
@@ -580,53 +646,7 @@ get_entry_number (grub_menu_t menu, cons
if (grub_errno == GRUB_ERR_BAD_NUMBER)
{
- /* See if the variable matches the title of a menu entry. */
- grub_menu_entry_t e = menu->entry_list;
- int i;
-
- /* Skip hidden entries */
- while (e && e->hidden)
- e = e->next;
-
- grub_errno = GRUB_ERR_NONE;
-
- for (i = 0; e; i++)
- {
- if (menuentry_eq (e->title, val)
- || menuentry_eq (e->id, val))
- {
- entry = i;
- break;
- }
-
- if (e->bls)
- {
- char *v, *ext;
-
- if ((v = grub_strdup (val)) &&
- (ext = grub_strrchr (v, '.')) &&
- grub_strcmp (ext, ".conf") == 0)
- {
- *ext = '\0';
- if (menuentry_eq (e->id, v))
- {
- entry = i;
- grub_free (v);
- break;
- }
- }
- grub_free (v);
- }
-
- e = e->next;
-
- /* Skip hidden entries */
- while (e && e->hidden)
- e = e->next;
- }
-
- if (! e)
- entry = -1;
+ entry = search_entry (menu, val);
}
if (grub_errno != GRUB_ERR_NONE)
@@ -724,6 +744,45 @@ run_menu (grub_menu_t menu, int nested,
default_entry = get_entry_number (menu, "default");
+#ifdef GRUB_MACHINE_EFI
+ /* verify we are using blscfg */
+ const char* val = grub_env_get ("enable_blscfg");
+ if (val && (val[0] == '1' || val[0] == 'y'))
+ {
+ grub_efi_status_t status;
+ int oneshot_entry_index;
+ grub_efi_char16_t *oneshot_entry_efi = NULL;
+ char *oneshot_entry = NULL;
+ grub_size_t oneshot_entry_size;
+ status = grub_efi_get_variable("LoaderEntryOneShot",
+ &grub_efi_loader_guid,
+ &oneshot_entry_size,
+ (void**) &oneshot_entry_efi);
+ if (status == GRUB_EFI_SUCCESS)
+ {
+ grub_efi_char16_t *src = oneshot_entry_efi;
+ int size = 0;
+ while (*src++)
+ size++;
+ if (size == 0)
+ {
+ oneshot_entry = grub_malloc (size * sizeof (char));
+ grub_utf16_to_utf8 ((grub_uint8_t*) oneshot_entry,
+ (grub_uint16_t*) oneshot_entry_efi, size);
+ oneshot_entry_index = search_entry (menu, oneshot_entry);
+ if (oneshot_entry_index != -1)
+ {
+ default_entry = oneshot_entry_index;
+ grub_efi_set_variable_to_string("LoaderEntryOneShot",
+ &grub_efi_loader_guid, "", 0);
+ }
+ grub_free(oneshot_entry);
+ }
+ grub_free(oneshot_entry_efi);
+ }
+ }
+#endif
+
workaround_snapshot_menu_default_entry (menu, "default", &default_entry);
/* If DEFAULT_ENTRY is not within the menu entries, fall back to