Script 'mail_helper' called by obssrc
Hello community,

here is the log from the commit of package grub2 for openSUSE:Factory checked 
in at 2026-04-22 17:12:53
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/grub2 (Old)
 and      /work/SRC/openSUSE:Factory/.grub2.new.11940 (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Package is "grub2"

Wed Apr 22 17:12:53 2026 rev:388 rq:1348785 version:2.14

Changes:
--------
--- /work/SRC/openSUSE:Factory/grub2/grub2.changes      2026-04-21 
12:42:51.717544630 +0200
+++ /work/SRC/openSUSE:Factory/.grub2.new.11940/grub2.changes   2026-04-22 
17:12:55.220991292 +0200
@@ -2,68 +1,0 @@
-Mon Apr 20 09:03:24 UTC 2026 - Michael Chang <[email protected]>
-
-- VUL-0: grub: potentially problematic utf8 conversion in bli patches 
(bsc#1262129)
-  * 0001-Fix-problematic-utf8-conversion-in-bli-patches.patch
-
--------------------------------------------------------------------
-Fri Apr 17 07:45:21 UTC 2026 - Radoslav Kolev <[email protected]>
-
-- Fix build for glibc 2.43 by taking upstream changes (bsc#1257256)
-  * 0001-osdep-linux-ofpath-Update-strstr-calls.patch
-  * 0001-util-probe-Save-strrchr-ret-val-to-const-data-ptr.patch
-  * 0002-util-resolve-Save-str-r-chr-ret-val-to-const-data-pt.patch
-
--------------------------------------------------------------------
-Tue Apr 14 12:34:01 UTC 2026 - Danilo Spinella <[email protected]>
-
-- Fix string to integer conversion for LoaderConfigTimeout
-  * 0004-bli-Add-support-for-LoaderConfigTimeout-and-LoaderCo.patch
-
--------------------------------------------------------------------
-Tue Apr 14 00:39:13 UTC 2026 - Michael Chang <[email protected]>
-
-- grub2.spec: When building the grubbls image, do not hardcode the timeout
-  value in the early config because it is set by bli.mod when it is loaded
-- grub2.spec: Remove hardcoded terminal and theme settings from the early
-  config as they are now applied at runtime
-
--------------------------------------------------------------------
-Mon Apr 13 07:12:45 UTC 2026 - Michael Chang <[email protected]>
-
-- Fix missing install device check in grub2-install on PowerPC which could lead
-  to bootlist corruption (bsc#1221126)
-  * 0001-Mandatory-install-device-check-for-PowerPC.patch
-
--------------------------------------------------------------------
-Tue Apr  7 06:45:13 UTC 2026 - Michael Chang <[email protected]>
-
-- Fix double free in xen booting if root filesystem is Btrfs (bsc#1259543)
-  * grub2-btrfs-01-add-ability-to-boot-from-subvolumes.patch
-  * grub2-btrfs-09-get-default-subvolume.patch
-
--------------------------------------------------------------------
-Mon Mar 23 16:16:32 UTC 2026 - Danilo Spinella <[email protected]>
-
-- Rewrite BLI patches:
-  * 0001-blsuki-Add-support-for-LoaderEntries.patch
-  * 0002-menu-Allow-default-entry-to-have-.conf-suffix.patch
-  * 0003-bli-Add-support-for-LoaderEntryDefault-and-LoaderEnt.patch
-  * 0004-bli-Add-support-for-LoaderConfigTimeout-and-LoaderCo.patch
-  * 0005-bls_bumpcounter-Add-command-to-bump-boot-counter-for.patch
-  * 0006-bli-Add-support-for-LoaderFeatures.patch
-  * 0007-blsuki-Fix-sorting-for-entries-with-boot-counting-en.patch
-  * 0008-blsuki-append-leftover-LoaderEntries.patch
-  * 0009-blsuki-conservative-UTF-8-buffer-size.patch
-- Remove patches:
-  * 0001-bls-Accept-.conf-suffix-in-setting-default-entry.patch
-  * grub2-bls-boot-counting.patch
-  * grub2-bls-boot-assessment.patch
-  * grub2-blscfg-set-efivars.patch
-  * grub2-bls-loader-entry-oneshot.patch
-  * grub2-blsbumpcounter-menu.patch
-  * grub2-bls-loader-entry-default.patch
-  * grub2-bls-loader-entries-boot-counting.patch
-  * grub2-bls-loader-features.patch
-  * grub2-bls-loader-config-timeout.patch
-  * grub2-bls-loader-config-timeout-fix.patch
-
--------------------------------------------------------------------

Old:
----
  0001-Fix-problematic-utf8-conversion-in-bli-patches.patch
  0001-Mandatory-install-device-check-for-PowerPC.patch
  0001-blsuki-Add-support-for-LoaderEntries.patch
  0001-osdep-linux-ofpath-Update-strstr-calls.patch
  0001-util-probe-Save-strrchr-ret-val-to-const-data-ptr.patch
  0002-menu-Allow-default-entry-to-have-.conf-suffix.patch
  0002-util-resolve-Save-str-r-chr-ret-val-to-const-data-pt.patch
  0003-bli-Add-support-for-LoaderEntryDefault-and-LoaderEnt.patch
  0004-bli-Add-support-for-LoaderConfigTimeout-and-LoaderCo.patch
  0005-bls_bumpcounter-Add-command-to-bump-boot-counter-for.patch
  0006-bli-Add-support-for-LoaderFeatures.patch
  0007-blsuki-Fix-sorting-for-entries-with-boot-counting-en.patch
  0008-blsuki-append-leftover-LoaderEntries.patch
  0009-blsuki-conservative-UTF-8-buffer-size.patch

New:
----
  0001-bls-Accept-.conf-suffix-in-setting-default-entry.patch
  grub2-bls-boot-assessment.patch
  grub2-bls-boot-counting.patch
  grub2-bls-loader-config-timeout-fix.patch
  grub2-bls-loader-config-timeout.patch
  grub2-bls-loader-entries-boot-counting.patch
  grub2-bls-loader-entry-default.patch
  grub2-bls-loader-entry-oneshot.patch
  grub2-bls-loader-features.patch
  grub2-blsbumpcounter-menu.patch
  grub2-blscfg-set-efivars.patch

----------(Old B)----------
  Old: WARN: 0001-Fix-problematic-utf8-conversion-in-bli-patches.patch not 
found in changes
 
  Old: WARN: 0001-Mandatory-install-device-check-for-PowerPC.patch not found in 
changes
 
  Old: WARN: 0001-blsuki-Add-support-for-LoaderEntries.patch not found in 
changes
 
  Old: WARN: 0001-osdep-linux-ofpath-Update-strstr-calls.patch not found in 
changes
 
  Old: WARN: 0001-util-probe-Save-strrchr-ret-val-to-const-data-ptr.patch not 
found in changes
 
  Old: WARN: 0002-menu-Allow-default-entry-to-have-.conf-suffix.patch not found 
in changes
 
  Old: WARN: 0002-util-resolve-Save-str-r-chr-ret-val-to-const-data-pt.patch 
not found in changes
 
  Old: WARN: 0003-bli-Add-support-for-LoaderEntryDefault-and-LoaderEnt.patch 
not found in changes
 
  Old: WARN: 0004-bli-Add-support-for-LoaderConfigTimeout-and-LoaderCo.patch 
not found in changes
 
  Old: WARN: 0005-bls_bumpcounter-Add-command-to-bump-boot-counter-for.patch 
not found in changes
 
  Old: WARN: 0006-bli-Add-support-for-LoaderFeatures.patch not found in changes
 
  Old: WARN: 0007-blsuki-Fix-sorting-for-entries-with-boot-counting-en.patch 
not found in changes
 
  Old: WARN: 0008-blsuki-append-leftover-LoaderEntries.patch not found in 
changes
 
  Old: WARN: 0009-blsuki-conservative-UTF-8-buffer-size.patch not found in 
changes
 
----------(Old E)----------

----------(New B)----------
  New:- Fix grub-bls does not rollback via setting new default (bsc#1237198)
  * 0001-bls-Accept-.conf-suffix-in-setting-default-entry.patch
  New:  * grub2-bls-boot-counting.patch
  * grub2-bls-boot-assessment.patch
  * grub2-bls-boot-show-snapshot.patch
  New:  * 0001-blscfg-read-fragments-in-order.patch
  * grub2-bls-boot-counting.patch
  * grub2-bls-boot-assessment.patch
  New:- Fix LoaderConfigTimeout and LoaderConfigTimeoutOneshot (bsc#1259477)
  * grub2-bls-loader-config-timeout-fix.patch
  New:  * grub2-bls-loader-features.patch
  * grub2-bls-loader-config-timeout.patch
- New patch
  New:  entries with boot counting enabled
  * grub2-bls-loader-entries-boot-counting.patch
  * grub2-bls-loader-features.patch
  New:- Add support for `LoaderEntryDefault` EFI variable
  * grub2-bls-loader-entry-default.patch
  New:  * 0001-Improve-TPM-key-protection-on-boot-interruptions.patch
  * grub2-bls-loader-entry-oneshot.patch
  * grub2-blsbumpcounter-menu.patch
  New:  * grub2-bls-loader-entries-boot-counting.patch
  * grub2-bls-loader-features.patch
  * grub2-bls-loader-config-timeout.patch
  New:  * grub2-bls-loader-entry-oneshot.patch
  * grub2-blsbumpcounter-menu.patch
- Patch removed
  New:  * grub2-bls-boot-show-snapshot.patch
  * grub2-blscfg-set-efivars.patch
  * 0001-Improve-TPM-key-protection-on-boot-interruptions.patch
----------(New E)----------

++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Other differences:
------------------
++++++ grub2.spec ++++++
--- /var/tmp/diff_new_pack.lBGNPX/_old  2026-04-22 17:13:00.989230071 +0200
+++ /var/tmp/diff_new_pack.lBGNPX/_new  2026-04-22 17:13:00.993230237 +0200
@@ -359,6 +359,7 @@
 Patch232:       0001-ieee1275-support-added-for-multiple-nvme-bootpaths.patch
 Patch236:       0001-kern-main-Fix-cmdpath-in-root-directory.patch
 Patch237:       grub2-s390x-secure-execution-support.patch
+Patch259:       0001-bls-Accept-.conf-suffix-in-setting-default-entry.patch
 Patch263:       0001-autofs-Ignore-zfs-not-found.patch
 Patch264:       0001-s390x-emu-Pass-through-PAES-cipher-as-AES.patch
 Patch274:       0001-ofpath-Add-error-check-in-NVMEoF-device-translation.patch
@@ -366,10 +367,15 @@
 Patch277:       0001-prep_loadenv-Measure-the-environment-block-into-PCR-.patch
 Patch294:       0001-Fix-PowerPC-CAS-reboot-to-evaluate-menu-context.patch
 Patch295:       0001-blscfg-read-fragments-in-order.patch
+Patch296:       grub2-bls-boot-counting.patch
+Patch297:       grub2-bls-boot-assessment.patch
 Patch298:       grub2-bls-boot-show-snapshot.patch
+Patch300:       grub2-blscfg-set-efivars.patch
 Patch309:       0001-Improve-TPM-key-protection-on-boot-interruptions.patch
 Patch310:       0004-Key-revocation-on-out-of-bound-file-access.patch
+Patch311:       grub2-bls-loader-entry-oneshot.patch
 Patch312:       0001-mkconfig-Determine-GRUB_DISTRIBUTOR-from-etc-SUSE-br.patch
+Patch313:       grub2-blsbumpcounter-menu.patch
 Patch315:       0001-test-Fix-f-test-on-files-over-network.patch
 Patch316:       0002-http-Return-HTTP-status-code-in-http_establish.patch
 Patch317:       0003-docs-Clarify-test-for-files-on-TFTP-and-HTTP.patch
@@ -379,7 +385,11 @@
 Patch336:       0002-linux-fallback-to-direct-PE-entry-boot-on-arm64.patch
 Patch337:       0003-efi-chainloader-fallback-to-direct-image-execution.patch
 Patch338:       0004-efi-chainloader-fix-missing-file_path-in-loaded_imag.patch
+Patch342:       grub2-bls-loader-entry-default.patch
 Patch344:       grub2-i386-pc-no-pageflipping.patch
+Patch401:       grub2-bls-loader-entries-boot-counting.patch
+Patch402:       grub2-bls-loader-features.patch
+Patch403:       grub2-bls-loader-config-timeout.patch
 Patch404:       0001-editenv-create-health_check_flag-env-var-on-RW-raw-b.patch
 Patch405:       0001-00_header-Omit-loading-efi_uga-on-non-x86-EFI-platfo.patch
 Patch406:       0001-Revert-configure-Print-a-more-helpful-error-if-autoc.patch
@@ -388,21 +398,8 @@
 Patch409:       0001-bls-Allow-configuration-of-active-console-type.patch
 Patch410:       0002-grubbls-Add-automatic-fwsetup-menu-entry.patch
 Patch411:       0001-ieee1275-support-dm-multipath-bootlist.patch
+Patch412:       grub2-bls-loader-config-timeout-fix.patch
 Patch413:       0001-mdraid1x-fix-raid_disks-decoding-on-big-endian-syste.patch
-Patch414:       0001-blsuki-Add-support-for-LoaderEntries.patch
-Patch415:       0002-menu-Allow-default-entry-to-have-.conf-suffix.patch
-Patch416:       0003-bli-Add-support-for-LoaderEntryDefault-and-LoaderEnt.patch
-Patch417:       0004-bli-Add-support-for-LoaderConfigTimeout-and-LoaderCo.patch
-Patch418:       0005-bls_bumpcounter-Add-command-to-bump-boot-counter-for.patch
-Patch419:       0006-bli-Add-support-for-LoaderFeatures.patch
-Patch420:       0007-blsuki-Fix-sorting-for-entries-with-boot-counting-en.patch
-Patch421:       0008-blsuki-append-leftover-LoaderEntries.patch
-Patch422:       0009-blsuki-conservative-UTF-8-buffer-size.patch
-Patch423:       0001-Mandatory-install-device-check-for-PowerPC.patch
-Patch424:       0001-osdep-linux-ofpath-Update-strstr-calls.patch
-Patch425:       0001-util-probe-Save-strrchr-ret-val-to-const-data-ptr.patch
-Patch426:       0002-util-resolve-Save-str-r-chr-ret-val-to-const-data-pt.patch
-Patch427:       0001-Fix-problematic-utf8-conversion-in-bli-patches.patch
 
 %if 0%{?suse_version} < 1600
 Requires:       gettext-runtime
@@ -736,7 +733,7 @@
 %define _configure ../configure
 
 # We don't want to let rpm override *FLAGS with default a.k.a bogus values.
-CFLAGS="-fno-strict-aliasing -fno-inline-functions-called-once"
+CFLAGS="-fno-strict-aliasing -fno-inline-functions-called-once 
-Wno-error=discarded-qualifiers"
 CXXFLAGS=" "
 FFLAGS=" "
 export CFLAGS CXXFLAGS FFLAGS
@@ -787,7 +784,7 @@
 PXE_MODULES="tftp http"
 CRYPTO_MODULES="luks luks2 gcry_rijndael gcry_sha1 gcry_sha256 gcry_sha512 
crypttab"
 %ifarch %{efi}
-CD_MODULES="${CD_MODULES} chain efifwsetup efinet read tpm tss2 
tpm2_key_protector memdisk tar squash4 xzio blsuki bls_bumpcounter"
+CD_MODULES="${CD_MODULES} chain efifwsetup efinet read tpm tss2 
tpm2_key_protector memdisk tar squash4 xzio blsuki blsbumpcounter"
 PXE_MODULES="${PXE_MODULES} efinet"
 %else
 CD_MODULES="${CD_MODULES} net ofnet"
@@ -861,10 +858,23 @@
 
 regexp --set 1:root '\((.*)\)' "$cmdpath"
 
+set timeout=8
 set gfxmode=auto
 set gfxpayload=keep
 set enable_blscfg=1
 
+terminal_input console
+terminal_output console
+terminal_output --append gfxterm
+
+loadfont (memdisk)/boot/grub/themes/DejaVuSans-Bold14.pf2
+loadfont (memdisk)/boot/grub/themes/DejaVuSans10.pf2
+loadfont (memdisk)/boot/grub/themes/DejaVuSans12.pf2
+loadfont (memdisk)/boot/grub/themes/ascii.pf2
+
+set theme=(memdisk)/boot/grub/themes/theme.txt
+export theme
+
 EOF
 
 %if 0%{?suse_version} > 1500
@@ -880,7 +890,7 @@
     %{?sbat_generation:--sbat sbat.csv} \
     -d grub-core \
     all_video boot font gfxmenu gfxterm gzio halt jpeg minicmd normal part_gpt 
png reboot video \
-    fat tpm tss2 tpm2_key_protector memdisk tar squash4 xzio blsuki 
bls_bumpcounter linux bli regexp loadenv test echo true sleep efifwsetup
+    fat tpm tss2 tpm2_key_protector memdisk tar squash4 xzio blsuki 
blsbumpcounter linux bli regexp loadenv test echo true sleep efifwsetup
 %endif
 
 %ifarch x86_64 aarch64

++++++ 0001-bls-Accept-.conf-suffix-in-setting-default-entry.patch ++++++
>From e873743f4ed7841542dd7dc11a183cb136670382 Mon Sep 17 00:00:00 2001
From: Michael Chang <[email protected]>
Date: Wed, 19 Feb 2025 14:52:52 +0800
Subject: [PATCH] bls: Accept .conf suffix in setting default entry

Signed-off-by: Michael Chang <[email protected]>
---
 grub-core/normal/menu.c | 20 ++++++++++++++++++++
 1 file changed, 20 insertions(+)

diff --git a/grub-core/normal/menu.c b/grub-core/normal/menu.c
index b11b28e0d9..dfdf0c7268 100644
--- a/grub-core/normal/menu.c
+++ b/grub-core/normal/menu.c
@@ -557,6 +557,26 @@ get_entry_number (grub_menu_t menu, const char *name)
              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 */
-- 
2.48.1



++++++ grub2-bls-boot-assessment.patch ++++++
Implement Automatic Boot Assessment for grub2-bls.

https://systemd.io/AUTOMATIC_BOOT_ASSESSMENT/

The entries are ordered first by the boot tries left, keeping
the one without available tries (e.g. <entry>+0-3.conf)
after the one without a boot counter or with a positive boot counter.

After removing the boot counter from the release string, keep the ordering
as it worked previously.

--- a/grub-core/commands/blsuki.c
+++ b/grub-core/commands/blsuki.c
@@ -255,6 +255,39 @@
   return ret;
 }
 
+static long
+tries_left (const char *filename)
+{
+  char *tries_left_str;
+  long ret = -1;
+  char *str = grub_strdup (filename);
+
+  if (str == NULL)
+    return -1;
+
+  /* Search for the start of the tries left, as per boot assessment */
+  tries_left_str = grub_strrchr (str, '+');
+
+  if (tries_left_str != NULL)
+    {
+      const char *end;
+      long tries;
+
+      ++tries_left_str;
+      tries = grub_strtol (tries_left_str, (const char **) &end, 10);
+
+      if (grub_errno == GRUB_ERR_NONE)
+       {
+         if (*end == '-' || *end == '.')
+           ret = tries;
+       }
+      else
+       grub_errno = GRUB_ERR_NONE;
+    }
+
+  grub_free (str);
+  return ret;
+}
 /*
  * Add a new grub_blsuki_entry_t struct to the entries list and sort it's
  * position on the list.
@@ -274,10 +307,19 @@
 
   FOR_BLSUKI_ENTRIES (e)
     {
+      long t1, t2;
+     
       rc = filevercmp (entry->filename, e->filename);
       if (rc == 0)
        return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("duplicate file: `%s'"), 
entry->filename);
 
+      t1 = tries_left (entry->filename);
+      t2 = tries_left (e->filename);
+      if (t2 == 0 && t1 != 0)
+       rc = 1;
+      else if (t2 != 0 && t1 == 0)
+       rc = -1;
+
       if (rc > 0)
        {
          grub_dprintf ("blsuki", "Add entry with id \"%s\"\n", 
entry->filename);

++++++ grub2-bls-boot-counting.patch ++++++
Add a new bls_bumpcunter grub command that implement boot counting for bls 
entries.

Boot counting, explained in systemd Automatic Boot Assessment, keep track of the
avaiable tries for each entry and the number of attempted boot. The 
bls_bumpcunter
command parse the entry id, check if there is a boot count enabled and update
its value accordingly. Then, EFI_SIMPLE_FILE_SYSTEM_PROTOCOL is used to rename
the entry on the EFI partition.

https://systemd.io/AUTOMATIC_BOOT_ASSESSMENT/

--- /dev/null
+++ b/include/grub/efi/filesystem.h
@@ -0,0 +1,155 @@
+/*
+ *  GRUB  --  GRand Unified Bootloader
+ *
+ *  GRUB is free software: you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation, either version 3 of the License, or
+ *  (at your option) any later version.
+ *
+ *  GRUB is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with GRUB.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef GRUB_EFI_TPM_HEADER
+#define GRUB_EFI_TPM_HEADER 1
+
+#include <grub/efi/api.h>
+#include <grub/env.h>
+
+struct grub_efi_file_io_token {
+  grub_efi_event_t Event;
+  grub_efi_status_t Status;
+  grub_efi_uint64_t BufferSize;
+  void *Buffer;
+};
+
+typedef struct grub_efi_file_io_token grub_efi_file_io_token_t;
+
+
+struct grub_efi_file_protocol
+{
+  grub_efi_uint64_t Revision;
+
+  grub_efi_status_t
+  (__grub_efi_api *Open) (struct grub_efi_file_protocol *this,
+                  struct grub_efi_file_protocol **new_handle,
+                  grub_efi_char16_t *filename,
+                  grub_efi_uint64_t open_mode,
+                  grub_efi_uint64_t attributes);
+
+  grub_efi_status_t
+  (__grub_efi_api *Close) (struct grub_efi_file_protocol *this);
+
+  grub_efi_status_t
+  (__grub_efi_api *Delete) (struct grub_efi_file_protocol *this);
+
+  grub_efi_status_t
+  (__grub_efi_api *Read) (struct grub_efi_file_protocol *this,
+                  grub_efi_uint64_t *buffer_size,
+                  void *buffer);
+
+  grub_efi_status_t
+  (__grub_efi_api *Write) (struct grub_efi_file_protocol *this,
+                  grub_efi_uint64_t *buffer_size,
+                  void *buffer);
+
+  grub_efi_status_t
+  (__grub_efi_api *GetPosition) (struct grub_efi_file_protocol *this,
+                  grub_efi_uint64_t *position);
+
+  grub_efi_status_t
+  (__grub_efi_api *SetPosition) (struct grub_efi_file_protocol *this,
+                  grub_efi_uint64_t position);
+
+  grub_efi_status_t
+  (__grub_efi_api *GetInfo) (struct grub_efi_file_protocol *this,
+                  grub_guid_t *information_type,
+                  grub_efi_uint64_t *buffer_size,
+                  void *buffer);
+
+  grub_efi_status_t
+  (__grub_efi_api *SetInfo) (struct grub_efi_file_protocol *this,
+                  grub_guid_t *information_type,
+                  grub_efi_uint64_t buffer_size,
+                  void *buffer);
+
+  grub_efi_status_t
+  (__grub_efi_api *Flush) (struct grub_efi_file_protocol *this);
+
+  grub_efi_status_t
+  (__grub_efi_api *OpenEx) (struct grub_efi_file_protocol *this,
+                  struct grub_efi_file_protocol **new_handle,
+                  grub_efi_char16_t *filename,
+                  grub_efi_uint64_t open_mode,
+                  grub_efi_uint64_t attributes,
+                  grub_efi_file_io_token_t *token);
+
+  grub_efi_status_t
+  (__grub_efi_api *ReadEx) (struct grub_efi_file_protocol *this,
+                  grub_efi_file_io_token_t *token);
+
+  grub_efi_status_t
+  (__grub_efi_api *WriteEx) (struct grub_efi_file_protocol *this,
+                  grub_efi_file_io_token_t *token);
+
+  grub_efi_status_t
+  (__grub_efi_api *FlushEx) (struct grub_efi_file_protocol *this,
+                  grub_efi_file_io_token_t *token);
+};
+
+typedef struct grub_efi_file_protocol grub_efi_file_protocol_t;
+
+/*******************************************************
+  Open Modes
+ ******************************************************/
+#define GRUB_EFI_FILE_MODE_READ       0x0000000000000001
+#define GRUB_EFI_FILE_MODE_WRITE      0x0000000000000002
+#define GRUB_EFI_FILE_MODE_CREATE     0x8000000000000000
+
+/*******************************************************
+  File Attributes
+ ******************************************************/
+#define GRUB_EFI_FILE_READ_ONLY       0x0000000000000001
+#define GRUB_EFI_FILE_HIDDEN          0x0000000000000002
+#define GRUB_EFI_FILE_SYSTEM          0x0000000000000004
+#define GRUB_EFI_FILE_RESERVED        0x0000000000000008
+#define GRUB_EFI_FILE_DIRECTORY       0x0000000000000010
+#define GRUB_EFI_FILE_ARCHIVE         0x0000000000000020
+#define GRUB_EFI_FILE_VALID_ATTR      0x0000000000000037
+
+struct grub_efi_file_info {
+  grub_efi_uint64_t Size;
+  grub_efi_uint64_t FileSize;
+  grub_efi_uint64_t PhysicalSize;
+  grub_efi_time_t CreateTime;
+  grub_efi_time_t LastAccessTime;
+  grub_efi_time_t ModificationTime;
+  grub_efi_uint64_t Attribute;
+  grub_efi_char16_t FileName[];
+};
+
+typedef struct grub_efi_file_info grub_efi_file_info_t;
+
+#define GRUB_EFI_FILE_INFO_ID \
+ {0x09576e92,0x6d3f,0x11d2, \
+    {0x8e,0x39,0x00,0xa0,0xc9,0x69,0x72,0x3b} \
+ }
+
+struct grub_efi_simple_file_system_protocol
+{
+  grub_efi_uint64_t Revision;
+
+  grub_efi_status_t
+  (__grub_efi_api *OpenVolume) (struct grub_efi_simple_file_system_protocol 
*this,
+                                 struct grub_efi_file_protocol **root);
+};
+
+typedef struct grub_efi_simple_file_system_protocol 
grub_efi_simple_file_system_protocol_t;
+
+
+#endif
--- /dev/null
+++ b/grub-core/commands/blsbumpcounter.c
@@ -0,0 +1,54 @@
+/*-*- Mode: C; c-basic-offset: 2; indent-tabs-mode: t -*-*/
+
+/* blsbumpcounter.c - implementation of boot counting for the Automatic Boot 
Assessment */
+
+/*
+ *  GRUB  --  GRand Unified Bootloader
+ *
+ *  GRUB is free software: you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation, either version 3 of the License, or
+ *  (at your option) any later version.
+ *
+ *  GRUB is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with GRUB.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <grub/extcmd.h>
+#include <grub/dl.h>
+
+#include <stddef.h>
+
+GRUB_MOD_LICENSE ("GPLv3+");
+
+
+static grub_err_t
+grub_cmd_bumpcounters (grub_extcmd_context_t ctxt __attribute__ ((unused)),
+         int argc __attribute__ ((unused)), char **args __attribute__ 
((unused)))
+{
+    /* placeholder, as blsbumpcounter only work on EFI platforms */
+  return GRUB_ERR_NONE;
+}
+
+
+static grub_extcmd_t cmd;
+
+GRUB_MOD_INIT(blsbumpcounter)
+{
+  cmd = grub_register_extcmd ("bls_bumpcounter",
+                  grub_cmd_bumpcounters,
+                  0,
+                  NULL,
+                  N_("Bump the boot entry counting (only works on EFI)."),
+                  NULL);
+}
+
+GRUB_MOD_FINI(blsbumpcounter)
+{
+  grub_unregister_extcmd (cmd);
+}
--- a/grub-core/Makefile.core.def
+++ b/grub-core/Makefile.core.def
@@ -869,6 +869,13 @@
 };
 
 module = {
+  name = blsbumpcounter;
+  common = commands/blsbumpcounter.c;
+  efi = commands/efi/blsbumpcounter.c;
+};
+
+
+module = {
   name = boot;
   common = commands/boot.c;
   i386_pc = lib/i386/pc/biosnum.c;
--- /dev/null
+++ b/grub-core/commands/efi/blsbumpcounter.c
@@ -0,0 +1,252 @@
+/*-*- Mode: C; c-basic-offset: 2; indent-tabs-mode: t -*-*/
+
+/* bls.c - implementation of the boot loader spec */
+
+/*
+ *  GRUB  --  GRand Unified Bootloader
+ *
+ *  GRUB is free software: you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation, either version 3 of the License, or
+ *  (at your option) any later version.
+ *
+ *  GRUB is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with GRUB.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <grub/extcmd.h>
+#include <grub/fs.h>
+#include <grub/env.h>
+#include <grub/lib/envblk.h>
+#include <grub/efi/api.h>
+#include <grub/efi/efi.h>
+#include <grub/efi/filesystem.h>
+
+#include <stddef.h>
+
+GRUB_MOD_LICENSE ("GPLv3+");
+
+#define GRUB_BLS_CONFIG_PATH "\\loader\\entries\\"
+
+#define GRUB_EFI_LOADER_GUID \
+        { 0x4a67b082, 0x0a4c, 0x41cf, { 0xb6, 0xc7, 0x44, 0x0b, 0x29, 0xbb, 
0x8c, 0x4f } }
+
+static grub_guid_t grub_simple_file_system_guid = 
GRUB_EFI_SIMPLE_FILE_SYSTEM_PROTOCOL_GUID;
+static grub_guid_t grub_efi_loader_guid = GRUB_EFI_LOADER_GUID;
+
+static grub_err_t
+grub_cmd_bumpcounters (grub_extcmd_context_t ctxt __attribute__ ((unused)),
+         int argc, char **args)
+{
+  grub_efi_file_info_t *file_info = NULL;
+  grub_efi_file_protocol_t *handle = NULL;
+  grub_efi_file_protocol_t *root = NULL;
+  grub_efi_simple_file_system_protocol_t *volume = NULL;
+  char* id = NULL;
+
+  grub_dprintf("bls_bumpcounter", "starting bumpcounter\n");
+  /* There should be exactly two arguments, the entry that is getting booted 
and the disk where
+     it can be found */
+  if (argc != 1) {
+    grub_dprintf("bls_bumpcounter", "one argument should be passed\n");
+    return GRUB_ERR_BAD_ARGUMENT;
+  }
+  id = args[0];
+
+  /* Look for the start of the count
+     If no '+' symbol has been found, the boot counting isn't enabled for the 
selected entry */
+  if (grub_strrchr(id, '+') == NULL) {
+    grub_dprintf("bls_bumpcounter", "boot counting is not in effect for id 
%s\n", id);
+    return GRUB_ERR_NONE;
+  }
+
+  grub_efi_loaded_image_t *image = NULL;
+  grub_dprintf("bls_bumpcounter", "Using loaded EFI image device\n");
+  image = grub_efi_get_loaded_image (grub_efi_image_handle);
+
+  if (!image) {
+    grub_dprintf("bls_bumpcounter", "grub_efi_get_loaded_image failed\n");
+    return 0;
+  }
+
+  grub_efi_status_t err;
+  grub_efi_boot_services_t *bs;
+  bs = grub_efi_system_table->boot_services;
+  err = bs->handle_protocol (image->device_handle,
+                               (void *) &grub_simple_file_system_guid, (void 
*) &volume);
+  if (err != GRUB_EFI_SUCCESS) {
+    grub_dprintf("bls_bumpcounter", "Cannot get handle to 
EFI_SIMPLE_FILE_SYSTEM_PROTOCOL: %lu\n", (unsigned long)err);
+    return GRUB_ERR_BAD_DEVICE; 
+  }
+  volume->OpenVolume(volume, &root);
+  if (err != GRUB_EFI_SUCCESS) {
+    grub_dprintf("bls_bumpcounter", "Cannot open the volume: %lu\n", (unsigned 
long)err);
+    return GRUB_ERR_BAD_DEVICE;
+  }
+
+  char *blsdir = (char *)grub_env_get ("blsdir");
+  char *tmp = NULL;
+  if (blsdir) {
+    tmp = blsdir;
+    while (*tmp) {
+      if (*tmp == '/') {
+        /* Replace linux path delimiter (/) with EFI compatible (\) */
+        *tmp = '\\';
+      }
+      tmp++;
+    }
+  } else {
+    blsdir = (char *)GRUB_BLS_CONFIG_PATH;
+  }
+
+  unsigned long int len = grub_strlen(blsdir) + grub_strlen(id) + 
sizeof(".conf") + 1;
+  grub_efi_char16_t* old_path = grub_malloc(len * sizeof(grub_efi_char16_t));
+  if (!old_path)
+  {
+    grub_error (GRUB_ERR_OUT_OF_MEMORY, N_("out of memory"));
+    goto finish;
+  }
+  grub_efi_char16_t* tmp_path = old_path;
+  tmp = blsdir;
+  while (*tmp) {
+      *tmp_path++ = (grub_efi_char16_t)*tmp++;
+  }
+  tmp = id;
+  while (*tmp) {
+      *tmp_path++ = (grub_efi_char16_t)*tmp++;
+  }
+  static const char* ext = ".conf";
+  tmp = (char *)ext;
+  while (*tmp) {
+      *tmp_path++ = (grub_efi_char16_t)*tmp++;
+  }
+  *tmp_path = (grub_efi_char16_t)'\0';
+
+  err = root->Open(root, &handle, old_path, 
GRUB_EFI_FILE_MODE_READ|GRUB_EFI_FILE_MODE_WRITE, 0);
+  grub_free(old_path);
+  if (err != GRUB_EFI_SUCCESS) {
+    grub_dprintf("bls_bumpcounter", "Cannot open the entry %s%s.conf : %lu\n", 
blsdir, id, (unsigned long)err);
+    goto finish;
+  }
+
+  /* Just like get_file_info works in systemd:src/boot/efi/util.c, get the 
file_info */
+  grub_efi_uint64_t size = offsetof(grub_efi_file_info_t, FileName) + 256U * 
sizeof(grub_efi_char16_t);
+  file_info = grub_malloc(size);
+  if (!file_info)
+  {
+    grub_error (GRUB_ERR_OUT_OF_MEMORY, N_("out of memory"));
+    goto finish;
+  }
+  grub_guid_t grub_efi_file_info_guid = GRUB_EFI_FILE_INFO_ID;
+  err = handle->GetInfo(handle, &grub_efi_file_info_guid, &size, file_info);
+  if (err == GRUB_EFI_BUFFER_TOO_SMALL) {
+    grub_free(file_info);
+    file_info = grub_malloc(size);
+    if (!file_info) {
+      grub_error (GRUB_ERR_OUT_OF_MEMORY, N_("out of memory"));
+      goto finish;
+    }
+    err = handle->GetInfo(handle, &grub_efi_file_info_guid, &size, file_info);
+  }
+
+  if (err != GRUB_EFI_SUCCESS) {
+    grub_dprintf("bls_bumpcounter", "Cannot get the file_info of the entry: 
%lu\n", (unsigned long)err);
+    goto finish;
+  }
+
+  /* Calculate the new filename with the bumped counter
+     Look for the start of the count */
+  tmp = grub_strrchr(id, '+');
+  *tmp = '\0';
+  int tries = -1;
+  int tries_left = grub_strtol(++tmp, (const char**) &tmp, 10);
+  /* The parsing succeeded */
+  if (tmp != NULL) {
+    if (tries_left > 0) {
+      tries_left--;
+    }
+    if (*tmp == '-') {
+      tmp++;
+      tries = grub_strtol(tmp, (const char**) &tmp, 10);
+      if (tmp != NULL) {
+        tries++;
+      } else {
+        tries = -1;
+      }
+    }
+  } else {
+      goto finish;
+  }
+
+  char *new_path;
+  if (tries == -1) {
+    /* This is the first try, rename accordingly */
+    new_path = grub_xasprintf ("%s+%d-1.conf", id, tries_left);
+  } else {
+    new_path = grub_xasprintf ("%s+%d-%d.conf", id, tries_left, tries);
+  }
+  grub_dprintf("bls_bumpcounter", "renaming entry to %s\n", new_path);
+
+  /* Copy the new filename into the file_info struct */
+  char* src = new_path;
+  grub_efi_char16_t *dst = file_info->FileName;
+  while (*src) {
+    *dst++ = (grub_efi_char16_t) *src++;
+  }
+  *dst = (grub_efi_char16_t) '\0';
+
+  handle->SetInfo(handle, &grub_efi_file_info_guid, size, file_info);
+
+  if (err != GRUB_EFI_SUCCESS) {
+    grub_dprintf("bls_bumpcounter", "Cannot rename file: %lu\n", (unsigned 
long)err);
+    goto finish;
+  }
+
+  handle->Flush(handle);
+  grub_dprintf("bls_bumpcounter", "entry renamed\n");
+  handle->Close(handle);
+
+  char* loader_boot_count_path = grub_xasprintf("%s%s", blsdir, new_path);
+  grub_free(new_path);
+  grub_efi_set_variable_to_string("LoaderBootCountPath", 
&grub_efi_loader_guid, loader_boot_count_path,
+                                             
GRUB_EFI_VARIABLE_BOOTSERVICE_ACCESS |
+                                             GRUB_EFI_VARIABLE_RUNTIME_ACCESS);
+  grub_free(loader_boot_count_path);
+
+  if (err != GRUB_EFI_SUCCESS) {
+      goto finish;
+  }
+
+  grub_free(file_info);
+
+  return GRUB_ERR_NONE;
+
+finish:
+  grub_free(file_info);
+
+  return GRUB_ERR_BAD_DEVICE;
+}
+
+
+static grub_extcmd_t cmd;
+
+GRUB_MOD_INIT(blsbumpcounter)
+{
+  grub_dprintf("bls_bumpcounter", "%s got here\n", __func__);
+  cmd = grub_register_extcmd ("bls_bumpcounter",
+                  grub_cmd_bumpcounters,
+                  0,
+                  NULL,
+                  N_("Bump the boot entry counting."),
+                  NULL);
+}
+
+GRUB_MOD_FINI(blsbumpcounter)
+{
+  grub_unregister_extcmd (cmd);
+}
--- a/grub-core/commands/blsuki.c
+++ b/grub-core/commands/blsuki.c
@@ -1044,6 +1044,8 @@
   grub_size_t size;
   bool blsuki_save_default;
 
+  char *bumpcounter = NULL;
+
   linux_path = blsuki_get_val (entry, "linux", NULL);
   if (linux_path == NULL)
     {
@@ -1089,10 +1091,23 @@
   if (grub_errno != GRUB_ERR_NONE)
     goto finish;
 
+  /* "bls_bumpcounter " + id + "\n" */
+  int bumpcounter_size = sizeof("bls_bumpcounter ") + grub_strlen(id) + 1;
+  bumpcounter = grub_malloc(bumpcounter_size);
+  if (!bumpcounter)
+  {
+    grub_error (GRUB_ERR_OUT_OF_MEMORY, N_("out of memory"));
+    goto finish;
+  }
+  char *tmp = bumpcounter;
+  tmp = grub_stpcpy(tmp, "bls_bumpcounter ");
+  tmp = grub_stpcpy(tmp, id);
+  tmp = grub_stpcpy(tmp, "\n");
+
   blsuki_save_default = grub_env_get_bool ("blsuki_save_default", false);
-  src = grub_xasprintf ("%s%s%s%s",
+  src = grub_xasprintf ("%s%s%s%s%s",
                        blsuki_save_default ? "savedefault\n" : "",
-                       linux_cmd, initrd_cmd ? initrd_cmd : "",
+                       linux_cmd, bumpcounter ? bumpcounter : "", initrd_cmd ? 
initrd_cmd : "",
                        dt_cmd ? dt_cmd : "");
 
   grub_normal_add_menu_entry (argc, argv, classes, id, users, hotkey, NULL, 
src, 0, entry, 0);
@@ -1105,6 +1120,7 @@
   grub_free (args);
   grub_free (argv);
   grub_free (src);
+  grub_free (bumpcounter);
 }
 
 #ifdef GRUB_MACHINE_EFI

++++++ grub2-bls-loader-config-timeout-fix.patch ++++++
Index: grub-2.14/grub-core/normal/menu.c
===================================================================
--- grub-2.14.orig/grub-core/normal/menu.c
+++ grub-2.14/grub-core/normal/menu.c
@@ -46,6 +46,8 @@
         { 0x4a67b082, 0x0a4c, 0x41cf, { 0xb6, 0xc7, 0x44, 0x0b, 0x29, 0xbb, 
0x8c, 0x4f } }
 static grub_guid_t grub_efi_loader_guid = GRUB_EFI_LOADER_GUID;
 
+#define GRUB_EFI_UINT_MAX 4294967295U
+
 #define GRUB_EFI_LOADER_FEATURE_CONFIG_TIMEOUT          (1 << 0)
 #define GRUB_EFI_LOADER_FEATURE_CONFIG_TIMEOUT_ONE_SHOT (1 << 1)
 #define GRUB_EFI_LOADER_FEATURE_ENTRY_DEFAULT           (1 << 2)
@@ -68,7 +70,8 @@ grub_err_t (*grub_gfxmenu_try_hook) (int
 enum timeout_style {
   TIMEOUT_STYLE_MENU,
   TIMEOUT_STYLE_COUNTDOWN,
-  TIMEOUT_STYLE_HIDDEN
+  TIMEOUT_STYLE_HIDDEN,
+  TIMEOUT_STYLE_DISABLED,
 };
 
 struct timeout_style_name {
@@ -78,6 +81,7 @@ struct timeout_style_name {
   {"menu", TIMEOUT_STYLE_MENU},
   {"countdown", TIMEOUT_STYLE_COUNTDOWN},
   {"hidden", TIMEOUT_STYLE_HIDDEN},
+  {"disabled", TIMEOUT_STYLE_DISABLED},
   {NULL, 0}
 };
 
@@ -858,59 +862,60 @@ run_menu (grub_menu_t menu, int nested,
 #ifdef GRUB_MACHINE_EFI
   if (val && (val[0] == '1' || val[0] == 'y'))
     {
-      int timeout_oneshot = -1;
+      unsigned long timeout_oneshot;
+      bool has_timeout_oneshot = false;
       /* https://systemd.io/BOOT_LOADER_INTERFACE/ */
       char* loader_config_timeout_oneshot = 
get_efivar("LoaderConfigTimeoutOneShot");
-      grub_dprintf("bls", "%s\n", loader_config_timeout_oneshot);
       if (loader_config_timeout_oneshot)
       {
+        /* Remove any value */
         grub_efi_set_variable_to_string("LoaderConfigTimeoutOneShot",
                 &grub_efi_loader_guid, "", 0);
-        timeout_oneshot = (int) grub_strtoul (loader_config_timeout_oneshot, 
0, 0);
+        timeout_oneshot = grub_strtoul (loader_config_timeout_oneshot, 0, 0);
         if (grub_errno != GRUB_ERR_NONE)
-          {
-            grub_errno = GRUB_ERR_NONE;
-            timeout_oneshot = -1;
-          }
+          grub_errno = GRUB_ERR_NONE;
         /* We have a valid value */
-        if (timeout_oneshot != -1)
+        else
           {
             if (timeout_oneshot == 0)
-              {
-                /* Wait indefinitely. In this case we want to set the timeout 
value to -1.
-                   In this case unsetting timeout will have the same effect. */
-                grub_env_unset ("timeout");
-              } else {
-                grub_menu_set_timeout (timeout_oneshot);
-              }
-              grub_env_set("timeout_style", "menu");
+              /* Wait indefinitely. */
+              grub_env_unset ("timeout");
+            else {
+              grub_menu_set_timeout (timeout_oneshot);
+              has_timeout_oneshot = true;
+            }
+            grub_env_set("timeout_style", "menu");
           }
         grub_free(loader_config_timeout_oneshot);
       }
-    /* If there was no LoaderConfigTimeoutOneShot value or it was invalid
+    /* If there was no LoaderConfigTimeoutOneShot value or it was invalid,
        read LoaderConfigTimeout */
-    if (timeout_oneshot == -1)
+    if (!has_timeout_oneshot)
       {
         char* loader_config_timeout = get_efivar("LoaderConfigTimeout");
         if (loader_config_timeout)
           {
             if (grub_strcmp(loader_config_timeout, "menu-force") == 0)
               {
-                grub_env_unset ("timeout");
+                grub_env_unset("timeout");
+                grub_env_set("timeout_style", "menu");
               } else if (grub_strcmp(loader_config_timeout, "0") == 0 ||
                       grub_strcmp(loader_config_timeout, "menu-hidden") == 0)
               {
-                grub_menu_set_timeout (1);
+                grub_menu_set_timeout (3);
                 grub_env_set("timeout_style", "hidden");
               } else if (grub_strcmp(loader_config_timeout, "menu-disabled") 
== 0)
               {
-                grub_menu_set_timeout (0);
-                grub_env_unset ("timeout");
+                grub_env_set ("timeout", "0");
+                grub_env_set("timeout_style", "disabled");
               } else {
-                int loader_timeout = (int) grub_strtoul 
(loader_config_timeout, 0, 0);
+                unsigned long loader_timeout = grub_strtoul 
(loader_config_timeout, 0, 0);
                 if (grub_errno == GRUB_ERR_NONE)
                   {
-                    grub_menu_set_timeout (loader_timeout);
+                    if (loader_timeout == GRUB_EFI_UINT_MAX)
+                      grub_env_unset("timeout");
+                    else
+                      grub_menu_set_timeout (loader_timeout);
                     grub_env_set("timeout_style", "menu");
                   } else {
                     grub_errno = GRUB_ERR_NONE;
@@ -986,10 +991,11 @@ run_menu (grub_menu_t menu, int nested,
     }
 
   /* If timeout is 0, drawing is pointless (and ugly).  */
-  if (timeout == 0)
+  if (timeout == 0 || timeout_style == TIMEOUT_STYLE_DISABLED)
     {
       *auto_boot = 1;
-      *notify_boot = timeout_style != TIMEOUT_STYLE_HIDDEN;
+      *notify_boot = timeout_style != TIMEOUT_STYLE_HIDDEN &&
+          timeout_style != TIMEOUT_STYLE_DISABLED;
       return default_entry;
     }
 

++++++ grub2-bls-loader-config-timeout.patch ++++++
Add support for  LoaderConfigTimeout and LoaderConfigTimeoutOneShot EFI 
variables.
Index: grub-2.14~rc1/grub-core/normal/menu.c
===================================================================
--- grub-2.14~rc1.orig/grub-core/normal/menu.c
+++ grub-2.14~rc1/grub-core/normal/menu.c
@@ -756,34 +756,38 @@ workaround_snapshot_menu_default_entry (
 }
 
 #ifdef GRUB_MACHINE_EFI
-static int
-get_entry_from_efivar(grub_menu_t menu, const char* efivar)
+static char*
+get_efivar(const char* efivar)
 {
   grub_efi_status_t status;
-  grub_size_t entry_size;
-  grub_efi_char16_t *entry_efi = NULL;
-  char *entry_name = NULL;
-  int entry_index = -1;
+  grub_size_t size;
+  grub_efi_char16_t *val_efi = NULL;
+  char *val = NULL;
   status = grub_efi_get_variable(efivar,
-                                                                
&grub_efi_loader_guid,
-                                                                &entry_size,
-                                                                (void**) 
&entry_efi);
-  if (status == GRUB_EFI_SUCCESS)
+                 &grub_efi_loader_guid,
+                 &size,
+                 (void**) &val_efi);
+  if (status == GRUB_EFI_SUCCESS && size != 0)
        {
-         grub_efi_char16_t *src = entry_efi;
-         int size = 0;
-         while (*src++)
-               size++;
-         if (size != 0)
-               {
-                 entry_name = grub_malloc (size * sizeof (char));
-                 grub_utf16_to_utf8 ((grub_uint8_t*) entry_name,
-                                                         (grub_uint16_t*) 
entry_efi, size);
-                 entry_index = search_entry (menu, entry_name);
-               }
+         val = grub_malloc (size * sizeof (char));
+         grub_utf16_to_utf8 ((grub_uint8_t*) val,
+                         (grub_uint16_t*) val_efi, size);
        }
-  grub_free(entry_name);
-  return entry_index;
+  return val;
+}
+
+static int
+get_entry_from_efivar(grub_menu_t menu, const char* efivar)
+{
+  char* entry_name = get_efivar(efivar);
+  if (entry_name)
+    {
+      int idx = search_entry (menu, entry_name);
+      grub_free(entry_name);
+      return idx;
+    } else {
+      return -1;
+    }
 }
 #endif
 
@@ -814,10 +818,13 @@ run_menu (grub_menu_t menu, int nested,
        {
 
          static long loader_features =
+                 GRUB_EFI_LOADER_FEATURE_CONFIG_TIMEOUT |
+                 GRUB_EFI_LOADER_FEATURE_CONFIG_TIMEOUT_ONE_SHOT |
                  GRUB_EFI_LOADER_FEATURE_ENTRY_DEFAULT |
                  GRUB_EFI_LOADER_FEATURE_ENTRY_ONESHOT |
                  GRUB_EFI_LOADER_FEATURE_BOOT_COUNTING |
-                 GRUB_EFI_LOADER_FEATURE_XBOOTLDR;
+                 GRUB_EFI_LOADER_FEATURE_XBOOTLDR |
+                 GRUB_EFI_LOADER_FEATURE_MENU_DISABLE;
 
          grub_efi_set_variable("LoaderFeatures", &grub_efi_loader_guid, 
&loader_features, sizeof(long));
 
@@ -845,6 +852,72 @@ run_menu (grub_menu_t menu, int nested,
   if (default_entry < 0 || default_entry >= menu->size)
     default_entry = 0;
 
+#ifdef GRUB_MACHINE_EFI
+  if (val && (val[0] == '1' || val[0] == 'y'))
+    {
+      int timeout_oneshot = -1;
+      /* https://systemd.io/BOOT_LOADER_INTERFACE/ */
+      char* loader_config_timeout_oneshot = 
get_efivar("LoaderConfigTimeoutOneShot");
+      grub_dprintf("bls", "%s\n", loader_config_timeout_oneshot);
+      if (loader_config_timeout_oneshot)
+      {
+        grub_efi_set_variable_to_string("LoaderConfigTimeoutOneShot",
+                &grub_efi_loader_guid, "", 0);
+        timeout_oneshot = (int) grub_strtoul (loader_config_timeout_oneshot, 
0, 0);
+        if (grub_errno != GRUB_ERR_NONE)
+          {
+            grub_errno = GRUB_ERR_NONE;
+            timeout_oneshot = -1;
+          }
+        /* We have a valid value */
+        if (timeout_oneshot != -1)
+          {
+            if (timeout_oneshot == 0)
+              {
+                /* Wait indefinitely. In this case we want to set the timeout 
value to -1.
+                   In this case unsetting timeout will have the same effect. */
+                grub_env_unset ("timeout");
+              } else {
+                grub_menu_set_timeout (timeout_oneshot);
+              }
+              grub_env_set("timeout_style", "menu");
+          }
+        grub_free(loader_config_timeout_oneshot);
+      }
+    /* If there was no LoaderConfigTimeoutOneShot value or it was invalid
+       read LoaderConfigTimeout */
+    if (timeout_oneshot == -1)
+      {
+        char* loader_config_timeout = get_efivar("LoaderConfigTimeout");
+        if (loader_config_timeout)
+          {
+            if (grub_strcmp(loader_config_timeout, "menu-force") == 0)
+              {
+                grub_env_unset ("timeout");
+              } else if (grub_strcmp(loader_config_timeout, "0") == 0 ||
+                      grub_strcmp(loader_config_timeout, "menu-hidden") == 0)
+              {
+                grub_menu_set_timeout (1);
+                grub_env_set("timeout_style", "hidden");
+              } else if (grub_strcmp(loader_config_timeout, "menu-disabled") 
== 0)
+              {
+                grub_menu_set_timeout (0);
+                grub_env_unset ("timeout");
+              } else {
+                int loader_timeout = (int) grub_strtoul 
(loader_config_timeout, 0, 0);
+                if (grub_errno == GRUB_ERR_NONE)
+                  {
+                    grub_menu_set_timeout (loader_timeout);
+                    grub_env_set("timeout_style", "menu");
+                  } else {
+                    grub_errno = GRUB_ERR_NONE;
+                  }
+              }
+            grub_free(loader_config_timeout);
+          }
+      }
+    }
+#endif
   timeout = grub_menu_get_timeout ();
   if (timeout < 0)
     /* If there is no timeout, the "countdown" and "hidden" styles result in

++++++ grub2-bls-loader-entries-boot-counting.patch ++++++
Index: grub-2.14~rc1/grub-core/commands/blsuki.c
===================================================================
--- grub-2.14~rc1.orig/grub-core/commands/blsuki.c
+++ grub-2.14~rc1/grub-core/commands/blsuki.c
@@ -1565,7 +1565,10 @@ blsuki_create_entries (bool show_default
 #ifdef GRUB_MACHINE_EFI
          grub_size_t len = grub_strlen (entry->filename);
 
-         if (len > BLS_EXT_LEN && grub_strcmp (entry->filename + len - 
BLS_EXT_LEN, ".conf") == 0)
+         char *boot_counting_start = grub_strrchr(entry->filename, '+');
+         if (boot_counting_start != NULL)
+           size += (boot_counting_start - entry->filename + 1);
+         else if (len > BLS_EXT_LEN && grub_strcmp (entry->filename + len - 
BLS_EXT_LEN, ".conf") == 0)
            size += (len - BLS_EXT_LEN + 1);
          else
            size += (len + 1);
@@ -1588,7 +1591,10 @@ blsuki_create_entries (bool show_default
        {
          grub_size_t len = grub_strlen (entry->filename);
 
-         if (len > BLS_EXT_LEN && grub_strcmp (entry->filename + len - 
BLS_EXT_LEN, ".conf") == 0)
+         char *boot_counting_start = grub_strrchr(entry->filename, '+');
+         if (boot_counting_start != NULL)
+           len = boot_counting_start - entry->filename;
+      else if (len > BLS_EXT_LEN && grub_strcmp (entry->filename + len - 
BLS_EXT_LEN, ".conf") == 0)
            len -= BLS_EXT_LEN;
 
          if (r_size < (len + 1))

++++++ grub2-bls-loader-entry-default.patch ++++++
Factoring out get_entry_from_efivar helper to reduce code duplication
and add support for LoaderEntryDefault.

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
@@ -741,6 +741,38 @@ workaround_snapshot_menu_default_entry (
   return;
 }
 
+#ifdef GRUB_MACHINE_EFI
+static int
+get_entry_from_efivar(grub_menu_t menu, const char* efivar)
+{
+  grub_efi_status_t status;
+  grub_size_t entry_size;
+  grub_efi_char16_t *entry_efi = NULL;
+  char *entry_name = NULL;
+  int entry_index = -1;
+  status = grub_efi_get_variable(efivar,
+                                                                
&grub_efi_loader_guid,
+                                                                &entry_size,
+                                                                (void**) 
&entry_efi);
+  if (status == GRUB_EFI_SUCCESS)
+       {
+         grub_efi_char16_t *src = entry_efi;
+         int size = 0;
+         while (*src++)
+               size++;
+         if (size != 0)
+               {
+                 entry_name = grub_malloc (size * sizeof (char));
+                 grub_utf16_to_utf8 ((grub_uint8_t*) entry_name,
+                                                         (grub_uint16_t*) 
entry_efi, size);
+                 entry_index = search_entry (menu, entry_name);
+               }
+       }
+  grub_free(entry_name);
+  return entry_index;
+}
+#endif
+
 #define GRUB_MENU_PAGE_SIZE 10
 
 /* Show the menu and handle menu entry selection.  Returns the menu entry
@@ -766,36 +798,19 @@ run_menu (grub_menu_t menu, int nested,
   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)
+         int oneshot_entry, default_entry_efi;
+         oneshot_entry = get_entry_from_efivar(menu, "LoaderEntryOneShot");
+         if (oneshot_entry != -1)
                {
-                 grub_efi_char16_t *src = oneshot_entry_efi;
-                 int size = 0;
-                 while (*src++)
-                       size++;
-                 if (size == 0)
+                 default_entry = oneshot_entry;
+                 grub_efi_set_variable_to_string("LoaderEntryOneShot",
+                                                                               
  &grub_efi_loader_guid, "", 0);
+               } else {
+                 default_entry_efi = get_entry_from_efivar(menu, 
"LoaderEntryDefault");
+                 if (default_entry_efi != -1)
                        {
-                         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);
+                         default_entry = default_entry_efi;
                        }
-                 grub_free(oneshot_entry_efi);
                }
        }
 #endif

++++++ grub2-bls-loader-entry-oneshot.patch ++++++
Add support for LoaderEntryOneshot EFI variable

--- a/grub-core/normal/menu.c
+++ b/grub-core/normal/menu.c
@@ -37,6 +37,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.  */
@@ -563,6 +573,62 @@
     }
 }
 
+/* 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->blsuki)
+         {
+               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
@@ -581,53 +647,7 @@
 
   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)
@@ -725,6 +745,45 @@
 
   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

++++++ grub2-bls-loader-features.patch ++++++
Add support for LoaderFeatures EFI variable.
Index: grub-2.14~rc1/grub-core/normal/menu.c
===================================================================
--- grub-2.14~rc1.orig/grub-core/normal/menu.c
+++ grub-2.14~rc1/grub-core/normal/menu.c
@@ -46,6 +46,14 @@
         { 0x4a67b082, 0x0a4c, 0x41cf, { 0xb6, 0xc7, 0x44, 0x0b, 0x29, 0xbb, 
0x8c, 0x4f } }
 static grub_guid_t grub_efi_loader_guid = GRUB_EFI_LOADER_GUID;
 
+#define GRUB_EFI_LOADER_FEATURE_CONFIG_TIMEOUT          (1 << 0)
+#define GRUB_EFI_LOADER_FEATURE_CONFIG_TIMEOUT_ONE_SHOT (1 << 1)
+#define GRUB_EFI_LOADER_FEATURE_ENTRY_DEFAULT           (1 << 2)
+#define GRUB_EFI_LOADER_FEATURE_ENTRY_ONESHOT           (1 << 3)
+#define GRUB_EFI_LOADER_FEATURE_BOOT_COUNTING           (1 << 4)
+#define GRUB_EFI_LOADER_FEATURE_XBOOTLDR                (1 << 5)
+#define GRUB_EFI_LOADER_FEATURE_MENU_DISABLE            (1 << 13)
+
 #endif
 
 /* Time to delay after displaying an error message about a default/fallback
@@ -805,6 +813,15 @@ run_menu (grub_menu_t menu, int nested,
   const char* val = grub_env_get ("enable_blscfg");
   if (val && (val[0] == '1' || val[0] == 'y'))
        {
+
+         static long loader_features =
+                 GRUB_EFI_LOADER_FEATURE_ENTRY_DEFAULT |
+                 GRUB_EFI_LOADER_FEATURE_ENTRY_ONESHOT |
+                 GRUB_EFI_LOADER_FEATURE_BOOT_COUNTING |
+                 GRUB_EFI_LOADER_FEATURE_XBOOTLDR;
+
+         grub_efi_set_variable("LoaderFeatures", &grub_efi_loader_guid, 
&loader_features, sizeof(long));
+
          int oneshot_entry, default_entry_efi;
          oneshot_entry = get_entry_from_efivar(menu, "LoaderEntryOneShot");
          if (oneshot_entry != -1)

++++++ grub2-blsbumpcounter-menu.patch ++++++
Call the command bls_bumpcounter when an entry is executed. Adding the
bls_bumpcounter command in the list of commands generated by blscfg breaks FDE,
as each command is logged in the PCR. Do not unset `enable_blscfg` grub env var,
otherwise bls_bumpcounter would not be called.

--- a/grub-core/normal/menu.c
+++ b/grub-core/normal/menu.c
@@ -332,6 +332,29 @@
     grub_env_set ("default", ptr + 1);
   else
     grub_env_unset ("default");
+
+#ifdef GRUB_MACHINE_EFI
+  const char* val = grub_env_get ("enable_blscfg");
+  if (val && (val[0] == '1' || val[0] == 'y') && entry->blsuki != NULL)
+    {
+      char* id = grub_strdup (entry->blsuki->filename);
+
+      if (id == NULL)
+       grub_print_error ();
+      else
+       {
+         char* args[] = { id };
+         grub_size_t id_len = grub_strlen (id);
+
+         if (id_len >= 4 && grub_strcmp (id + id_len - 4, ".conf") == 0)
+           id[id_len - 4] = '\0';
+         grub_command_execute ("bls_bumpcounter", 1, args);
+         grub_free (id);
+       }
+    }
+  grub_env_unset ("enable_blscfg");
+#endif
+
 #ifdef GRUB_MACHINE_IEEE1275
   char *cas_entry_id = NULL;
   char *cas_entry_source;
--- a/grub-core/normal/main.c
+++ b/grub-core/normal/main.c
@@ -356,7 +356,6 @@
       /* Ignore any error.  */
       grub_errno = GRUB_ERR_NONE;
       /* unset to let configfile and source commands continue to work */
-      grub_env_unset ("enable_blscfg");
       goto check_batch;
     }
 #endif
--- a/grub-core/commands/blsuki.c
+++ b/grub-core/commands/blsuki.c
@@ -1094,8 +1094,6 @@
   grub_size_t size;
   bool blsuki_save_default;
 
-  char *bumpcounter = NULL;
-
   linux_path = blsuki_get_val (entry, "linux", NULL);
   if (linux_path == NULL)
     {
@@ -1156,23 +1154,10 @@
   if (grub_errno != GRUB_ERR_NONE)
     goto finish;
 
-  /* "bls_bumpcounter " + id + "\n" */
-  int bumpcounter_size = sizeof("bls_bumpcounter ") + grub_strlen(id) + 1;
-  bumpcounter = grub_malloc(bumpcounter_size);
-  if (!bumpcounter)
-  {
-    grub_error (GRUB_ERR_OUT_OF_MEMORY, N_("out of memory"));
-    goto finish;
-  }
-  char *tmp = bumpcounter;
-  tmp = grub_stpcpy(tmp, "bls_bumpcounter ");
-  tmp = grub_stpcpy(tmp, id);
-  tmp = grub_stpcpy(tmp, "\n");
-
   blsuki_save_default = grub_env_get_bool ("blsuki_save_default", false);
-  src = grub_xasprintf ("%s%s%s%s%s",
+  src = grub_xasprintf ("%s%s%s%s",
                        blsuki_save_default ? "savedefault\n" : "",
-                       linux_cmd, bumpcounter ? bumpcounter : "", initrd_cmd ? 
initrd_cmd : "",
+                       linux_cmd, initrd_cmd ? initrd_cmd : "",
                        dt_cmd ? dt_cmd : "");
 
   grub_normal_add_menu_entry (argc, argv, classes, id, users, hotkey, NULL, 
src, 0, entry, 0);
@@ -1186,7 +1171,6 @@
   grub_free (args);
   grub_free (argv);
   grub_free (src);
-  grub_free (bumpcounter);
 }
 
 #ifdef GRUB_MACHINE_EFI

++++++ grub2-blscfg-set-efivars.patch ++++++
Set the EFI variables LoaderEntries and LoaderEntrySelected to
follow systemd-boot implementation and make bootctl work.

--- a/grub-core/commands/efi/blsbumpcounter.c
+++ b/grub-core/commands/efi/blsbumpcounter.c
@@ -60,8 +60,14 @@
 
   /* Look for the start of the count
      If no '+' symbol has been found, the boot counting isn't enabled for the 
selected entry */
+  char* new_path = grub_xasprintf ("%s.conf", id);
+  grub_efi_set_variable_to_string("LoaderEntrySelected", 
&grub_efi_loader_guid, new_path,
+                                             
GRUB_EFI_VARIABLE_BOOTSERVICE_ACCESS |
+                                             GRUB_EFI_VARIABLE_RUNTIME_ACCESS);
+  grub_free(new_path);
   if (grub_strrchr(id, '+') == NULL) {
     grub_dprintf("bls_bumpcounter", "boot counting is not in effect for id 
%s\n", id);
+
     return GRUB_ERR_NONE;
   }
 
@@ -183,7 +189,6 @@
       goto finish;
   }
 
-  char *new_path;
   if (tries == -1) {
     /* This is the first try, rename accordingly */
     new_path = grub_xasprintf ("%s+%d-1.conf", id, tries_left);
--- a/grub-core/commands/blsuki.c
+++ b/grub-core/commands/blsuki.c
@@ -45,6 +45,14 @@
 #define GRUB_BOOT_DEVICE ""
 #endif
 
+#ifdef GRUB_MACHINE_EFI
+#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
+
 GRUB_MOD_LICENSE ("GPLv3+");
 
 #define GRUB_BLS_CONFIG_PATH "/loader/entries/"
@@ -1537,6 +1545,12 @@
   const char *def_entry = NULL;
   grub_blsuki_entry_t *entry = NULL;
   int idx = 0;
+#ifdef GRUB_MACHINE_EFI
+  grub_size_t size = 0, r_size;
+  grub_efi_char16_t *efi_entries = NULL;
+  grub_efi_char16_t *p = NULL;
+  char* tmp = NULL;
+#endif
 
   def_entry = grub_env_get ("default");
 
@@ -1558,11 +1572,58 @@
            uki_create_entry (entry);
 #endif
          entry->visible = true;
+#ifdef GRUB_MACHINE_EFI
+         grub_size_t len = grub_strlen (entry->filename);
+
+         if (len > BLS_EXT_LEN && grub_strcmp (entry->filename + len - 
BLS_EXT_LEN, ".conf") == 0)
+           size += (len - BLS_EXT_LEN + 1);
+         else
+           size += (len + 1);
+#endif
        }
 
       idx++;
     }
 
+#ifdef GRUB_MACHINE_EFI
+  efi_entries = grub_malloc (size * sizeof (grub_efi_char16_t));
+  if (efi_entries == NULL)
+    return grub_errno;
+
+  p = efi_entries;
+  r_size = size;
+  FOR_BLSUKI_ENTRIES (entry)
+    {
+      if (entry->visible)
+       {
+         grub_size_t len = grub_strlen (entry->filename);
+
+         if (len > BLS_EXT_LEN && grub_strcmp (entry->filename + len - 
BLS_EXT_LEN, ".conf") == 0)
+           len -= BLS_EXT_LEN;
+
+         if (r_size < (len + 1))
+           {
+             grub_dprintf ("blsuki", "LoaderEntries buffer too small\n");
+             break;
+           }
+
+         r_size -= (len + 1);
+         tmp = entry->filename;
+         while (len)
+           {
+             *p++ = (grub_efi_char16_t) *tmp++;
+             len--;
+           }
+         *p++ = (grub_efi_char16_t) '\0';
+       }
+    }
+  grub_efi_set_variable_with_attributes ("LoaderEntries", 
&grub_efi_loader_guid,
+                                             efi_entries, (size - r_size) * 
sizeof (grub_efi_char16_t),
+                                             
GRUB_EFI_VARIABLE_BOOTSERVICE_ACCESS |
+                                             GRUB_EFI_VARIABLE_RUNTIME_ACCESS);
+  grub_free (efi_entries);
+#endif
+
   return GRUB_ERR_NONE;
 }
 

++++++ grub2-btrfs-01-add-ability-to-boot-from-subvolumes.patch ++++++
--- /var/tmp/diff_new_pack.lBGNPX/_old  2026-04-22 17:13:01.905267991 +0200
+++ /var/tmp/diff_new_pack.lBGNPX/_new  2026-04-22 17:13:01.913268322 +0200
@@ -25,9 +25,6 @@
   * Fix gcc-12 error: the comparison will always evaluate as 'true' for the
     address of 'label' will never be NULL [-Werror=address]
 
-v3:
-  * Check find_pathname() in grub_cmd_btrfs_list_subvols() and return an error
-    on failure
 ---
 
  grub-core/fs/btrfs.c |  561 
+++++++++++++++++++++++++++++++++++++++++++++++++--
@@ -375,7 +372,7 @@
  
    grub_btrfs_unmount (data);
  
-@@ -2431,6 +2638,253 @@
+@@ -2431,6 +2638,248 @@
  }
  #endif
  
@@ -581,12 +578,7 @@
 +        }
 +        buf[elemsize] = 0;
 +
-+      err = find_pathname(data, ref->dirid, fs_root, ref->name, &p);
-+      if (err)
-+        {
-+          r = -err;
-+          break;
-+        }
++      find_pathname(data, ref->dirid, fs_root, ref->name, &p);
 +
 +      if (print)
 +        {
@@ -629,7 +621,7 @@
  static struct grub_fs grub_btrfs_fs = {
    .name = "btrfs",
    .fs_dir = grub_btrfs_dir,
-@@ -2446,13 +2900,89 @@
+@@ -2446,13 +2895,89 @@
  #endif
  };
  

++++++ grub2-btrfs-09-get-default-subvolume.patch ++++++
--- /var/tmp/diff_new_pack.lBGNPX/_old  2026-04-22 17:13:01.965270475 +0200
+++ /var/tmp/diff_new_pack.lBGNPX/_new  2026-04-22 17:13:01.973270806 +0200
@@ -3,15 +3,9 @@
   * Use overflow checking primitives where the arithmetic expression for
     buffer allocations may include unvalidated data
 
-v2:
-  * Check find_pathname() in grub_btrfs_get_parent_subvol_path() and return
-    an error on failure
-  * Use get_fs_root() with offset -1 in grub_btrfs_get_parent_subvol_path() so
-    lower_bound() can find the highest-offset ROOT_ITEM for the subvolume id
-
 --- a/grub-core/fs/btrfs.c
 +++ b/grub-core/fs/btrfs.c
-@@ -3146,6 +3146,260 @@
+@@ -3104,6 +3104,254 @@
    return 0;
  }
  
@@ -76,7 +70,7 @@
 +  ref = (struct grub_btrfs_root_ref *)buf;
 +
 +  err = get_fs_root(data, data->sblock.root_tree, grub_le_to_cpu64 
(key_out.offset),
-+                    -1, &fs_root);
++                    0, &fs_root);
 +  if (err)
 +    {
 +      grub_free(buf);
@@ -84,13 +78,7 @@
 +      return err;
 +    }
 +
-+  err = find_pathname(data, grub_le_to_cpu64 (ref->dirid), fs_root, 
ref->name, &parent_path);
-+  if (err)
-+    {
-+      grub_free(buf);
-+      free_iterator(&desc);
-+      return err;
-+    }
++  find_pathname(data, grub_le_to_cpu64 (ref->dirid), fs_root, ref->name, 
&parent_path);
 +
 +  if (child_path)
 +    {
@@ -272,7 +260,7 @@
  static struct grub_fs grub_btrfs_fs = {
    .name = "btrfs",
    .fs_dir = grub_btrfs_dir,
-@@ -3164,6 +3418,7 @@
+@@ -3122,6 +3370,7 @@
  static grub_command_t cmd_info;
  static grub_command_t cmd_mount_subvol;
  static grub_extcmd_t cmd_list_subvols;
@@ -280,7 +268,7 @@
  
  static char *
  subvolid_set_env (struct grub_env_var *var __attribute__ ((unused)),
-@@ -3235,6 +3490,11 @@
+@@ -3192,6 +3441,11 @@
                                         "[-p|-n] [-o var] DEVICE",
                                         "Print list of BtrFS subvolumes on "
                                         "DEVICE.", options);

Reply via email to