Script 'mail_helper' called by obssrc
Hello community,

here is the log from the commit of package grub2 for openSUSE:Factory checked 
in at 2025-04-29 16:39:46
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/grub2 (Old)
 and      /work/SRC/openSUSE:Factory/.grub2.new.30101 (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Package is "grub2"

Tue Apr 29 16:39:46 2025 rev:360 rq:1273319 version:2.12

Changes:
--------
--- /work/SRC/openSUSE:Factory/grub2/grub2.changes      2025-04-24 
17:25:14.580653304 +0200
+++ /work/SRC/openSUSE:Factory/.grub2.new.30101/grub2.changes   2025-04-29 
16:39:54.332993295 +0200
@@ -1,0 +2,15 @@
+Fri Apr 25 17:44:31 UTC 2025 - Andreas Stieger <andreas.stie...@gmx.de>
+
+- grub2-common: use fuse3
+
+-------------------------------------------------------------------
+Wed Apr 23 09:50:10 UTC 2025 - Danilo Spinella <danilo.spine...@suse.com>
+
+- Add support for boot assessment, needed by health-checker
+  * grub2-bls-boot-counting.patch
+  * grub2-bls-boot-assessment.patch
+  * grub2-bls-boot-show-snapshot.patch
+  * grub2-blscfg-fix-hang.patch
+  * grub2-blscfg-set-efivars.patch
+
+-------------------------------------------------------------------

New:
----
  grub2-bls-boot-assessment.patch
  grub2-bls-boot-counting.patch
  grub2-bls-boot-show-snapshot.patch
  grub2-blscfg-fix-hang.patch
  grub2-blscfg-set-efivars.patch

BETA DEBUG BEGIN:
  New:  * grub2-bls-boot-counting.patch
  * grub2-bls-boot-assessment.patch
  * grub2-bls-boot-show-snapshot.patch
  New:- Add support for boot assessment, needed by health-checker
  * grub2-bls-boot-counting.patch
  * grub2-bls-boot-assessment.patch
  New:  * grub2-bls-boot-assessment.patch
  * grub2-bls-boot-show-snapshot.patch
  * grub2-blscfg-fix-hang.patch
  New:  * grub2-bls-boot-show-snapshot.patch
  * grub2-blscfg-fix-hang.patch
  * grub2-blscfg-set-efivars.patch
  New:  * grub2-blscfg-fix-hang.patch
  * grub2-blscfg-set-efivars.patch
BETA DEBUG END:

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

Other differences:
------------------
++++++ grub2.spec ++++++
--- /var/tmp/diff_new_pack.DG8Yzl/_old  2025-04-29 16:39:58.481167530 +0200
+++ /var/tmp/diff_new_pack.DG8Yzl/_new  2025-04-29 16:39:58.485167699 +0200
@@ -34,9 +34,9 @@
 BuildRequires:  fdupes
 BuildRequires:  flex
 BuildRequires:  freetype2-devel
-BuildRequires:  fuse-devel
 BuildRequires:  gcc
 BuildRequires:  glibc-devel
+BuildRequires:  pkgconfig(fuse3)
 %if 0%{?suse_version} >= 1140
 BuildRequires:  dejavu-fonts
 BuildRequires:  gnu-unifont
@@ -466,6 +466,11 @@
 Patch293:       grub2-string-initializer.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
+Patch299:       grub2-blscfg-fix-hang.patch
+Patch300:       grub2-blscfg-set-efivars.patch
 
 %if 0%{?suse_version} < 1600
 Requires:       gettext-runtime
@@ -853,7 +858,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 blscfg"
+CD_MODULES="${CD_MODULES} chain efifwsetup efinet read tpm tss2 
tpm2_key_protector memdisk tar squash4 xzio blscfg blsbumpcounter"
 PXE_MODULES="${PXE_MODULES} efinet"
 %else
 CD_MODULES="${CD_MODULES} net ofnet"
@@ -959,7 +964,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 blscfg linux bli 
regexp loadenv test echo true sleep
+    fat tpm tss2 tpm2_key_protector memdisk tar squash4 xzio blscfg 
blsbumpcounter linux bli regexp loadenv test echo true sleep
 %endif
 
 %ifarch x86_64 aarch64


++++++ 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.

Index: grub-2.12/grub-core/commands/blscfg.c
===================================================================
--- grub-2.12.orig/grub-core/commands/blscfg.c
+++ grub-2.12/grub-core/commands/blscfg.c
@@ -323,9 +323,37 @@ finish:
 /* NULL string pointer returned if nothing found */
 static void
 split_package_string (char *package_string, char **name,
-                     char **version, char **release)
+                     char **version, char **release, int *tries_left)
 {
-  char *package_version, *package_release;
+  char *package_version, *package_release, *tries_left_str, *tmp;
+
+  *tries_left = -1;
+  /* Search for the start of the tries left, as per boot assessment */
+  tries_left_str = grub_strrchr(package_string, '+');
+  if (tries_left_str != NULL)
+    {
+      /* If there the number of tries available is after the number of tries 
left (e.g. +1-2)
+         stop the string at the '-' delimiter, so that strtol
+         does the parsing of the first part and skip the second */
+      tmp = grub_strrchr(tries_left_str, '-');
+      if (tmp != NULL)
+        {
+          *tmp = '\0';
+        }
+      tmp = tries_left_str;
+      *tries_left = grub_strtol(++tmp, (const char **)&tmp, 10);
+
+      /* Conversion failed */
+      if (tmp == tries_left_str)
+        {
+          /* Reset the counter */
+          *tries_left = -1;
+        }
+      else
+        {
+          *tries_left_str = '\0';
+        }
+    }
 
   /* Release */
   package_release = grub_strrchr (package_string, '-');
@@ -372,9 +401,23 @@ split_cmp(char *nvr0, char *nvr1, int ha
   int ret = 0;
   char *name0, *version0, *release0;
   char *name1, *version1, *release1;
+  int tries_left0;
+  int tries_left1;
+
+  split_package_string(nvr0, has_name ? &name0 : NULL, &version0, &release0, 
&tries_left0);
+  split_package_string(nvr1, has_name ? &name1 : NULL, &version1, &release1, 
&tries_left1);
 
-  split_package_string(nvr0, has_name ? &name0 : NULL, &version0, &release0);
-  split_package_string(nvr1, has_name ? &name1 : NULL, &version1, &release1);
+  /* Check for systemd Automatic Boot Assessment
+     0 has no tries left, while 1 doesn't have a boot count / still has tries 
left */
+  if (tries_left0 == 0 && tries_left1 != 0)
+    {
+      return -1;
+    }
+  /* viceversa, b has no tries left */
+  else if (tries_left0 != 0 && tries_left1 == 0)
+    {
+      return 1;
+    }
 
   if (has_name)
     {

++++++ 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/

Index: grub-2.12/include/grub/efi/filesystem.h
===================================================================
--- /dev/null
+++ grub-2.12/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
Index: grub-2.12/grub-core/commands/blscfg.c
===================================================================
--- grub-2.12.orig/grub-core/commands/blscfg.c
+++ grub-2.12/grub-core/commands/blscfg.c
@@ -791,6 +791,8 @@ static void create_entry (struct bls_ent
   int i, index;
   bool add_dt_prefix = false;
 
+  char *bumpcounter = NULL;
+
   grub_dprintf("blscfg", "%s got here\n", __func__);
   clinux = bls_get_val (entry, "linux", NULL);
   if (!clinux)
@@ -949,6 +951,19 @@ static void create_entry (struct bls_ent
       grub_free(prefix);
     }
 
+  /* "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");
+
   grub_dprintf ("blscfg2", "devicetree %s for id:\"%s\"\n", dt, id);
 
   const char *sdval = grub_env_get("save_default");
@@ -961,7 +976,7 @@ static void create_entry (struct bls_ent
                        "insmod gzio\n"
                        "linux %s%s%s%s\n"
 #endif
-                       "%s%s",
+                       "%s%s%s",
                        savedefault ? "savedefault\n" : "",
 #ifdef GRUB_MACHINE_EMU
                        separate_boot ? GRUB_BOOT_DEVICE : "",
@@ -969,7 +984,8 @@ static void create_entry (struct bls_ent
                        bootdev,
 #endif
                        clinux, options ? " " : "", options ? options : "",
-                       initrd ? initrd : "", dt ? dt : "");
+                       bumpcounter ? bumpcounter : "", initrd ? initrd : "",
+                       dt ? dt : "");
 
   grub_normal_add_menu_entry (argc, argv, classes, id, users, hotkey, NULL, 
src, 0, 0, &index, entry);
   grub_dprintf ("blscfg", "Added entry %d id:\"%s\"\n", index, id);
@@ -987,6 +1003,7 @@ finish:
   grub_free (argv);
   grub_free (src);
   grub_free (bootdev);
+  grub_free (bumpcounter);
 }
 
 struct find_entry_info {
Index: grub-2.12/grub-core/commands/blsbumpcounter.c
===================================================================
--- /dev/null
+++ grub-2.12/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 UNUSED,
+         int argc UNUSED, char **args 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);
+}
Index: grub-2.12/grub-core/Makefile.core.def
===================================================================
--- grub-2.12.orig/grub-core/Makefile.core.def
+++ grub-2.12/grub-core/Makefile.core.def
@@ -858,6 +858,13 @@ module = {
 };
 
 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;
Index: grub-2.12/grub-core/commands/efi/blsbumpcounter.c
===================================================================
--- /dev/null
+++ grub-2.12/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 UNUSED,
+         int argc UNUSED, char **args UNUSED)
+{
+  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);
+}

++++++ grub2-bls-boot-show-snapshot.patch ++++++
Index: grub-2.12/grub-core/commands/blscfg.c
===================================================================
--- grub-2.12.orig/grub-core/commands/blscfg.c
+++ grub-2.12/grub-core/commands/blscfg.c
@@ -810,6 +810,7 @@ static void create_entry (struct bls_ent
   const char **argv = NULL;
 
   char *title = NULL;
+  char *version = NULL;
   char *clinux = NULL;
   char *options = NULL;
   char **initrds = NULL;
@@ -853,7 +854,9 @@ static void create_entry (struct bls_ent
   if (dotconf)
     dotconf[0] = '\0';
 
-  title = bls_get_val (entry, "title", NULL);
+  title = grub_strdup(bls_get_val (entry, "title", NULL));
+  version = bls_get_val (entry, "version", NULL);
+  title = version ? grub_xasprintf("%s (%s)", title, version) : title;
   options = expand_val (bls_get_val (entry, "options", NULL));
 
   if (!options)
@@ -1040,6 +1043,7 @@ finish:
   grub_free (devicetree);
   grub_free (initrds);
   grub_free (options);
+  grub_free (title);
   grub_free (classes);
   grub_free (args);
   grub_free (argv);

++++++ grub2-blscfg-fix-hang.patch ++++++
Grub2 was hanging due to a infinite loop on incorrect entries.

Entries that contained the string ".conf" but did not end with it
were causing the loop to never exit. Move dotconf pointer up
if it doesn't trigger the loop exit condition so that
grub_strstr can return a NULL pointer at some point.

Index: grub-2.12/grub-core/commands/blscfg.c
===================================================================
--- grub-2.12.orig/grub-core/commands/blscfg.c
+++ grub-2.12/grub-core/commands/blscfg.c
@@ -850,7 +850,7 @@ static void create_entry (struct bls_ent
   do
     {
       dotconf = grub_strstr(dotconf, ".conf");
-    } while (dotconf != NULL && dotconf[5] != '\0');
+    } while (dotconf != NULL && dotconf[5] != '\0' && *(++dotconf));
   if (dotconf)
     dotconf[0] = '\0';
 

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

Index: grub-2.12/grub-core/commands/blscfg.c
===================================================================
--- grub-2.12.orig/grub-core/commands/blscfg.c
+++ grub-2.12/grub-core/commands/blscfg.c
@@ -47,6 +47,14 @@ GRUB_MOD_LICENSE ("GPLv3+");
 #define GRUB_BOOT_DEVICE "($root)"
 #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
+
 struct keyval
 {
   const char *key;
@@ -1223,6 +1231,12 @@ bls_create_entries (bool show_default, b
   const char *def_entry = NULL;
   struct bls_entry *entry = NULL;
   int idx = 0;
+#ifdef GRUB_MACHINE_EFI
+  int size = 0;
+  grub_efi_char16_t *efi_entries = NULL;
+  grub_efi_char16_t *p = NULL;
+  char* tmp = NULL;
+#endif
 
   def_entry = grub_env_get("default");
 
@@ -1238,10 +1252,38 @@ bls_create_entries (bool show_default, b
        (entry_id && grub_strcmp(entry_id, entry->filename) == 0)) {
       create_entry(entry);
       entry->visible = 1;
+#ifdef GRUB_MACHINE_EFI
+      size += grub_strlen(entry->filename) + 1;
+#endif
     }
     idx++;
   }
 
+#ifdef GRUB_MACHINE_EFI
+  efi_entries = grub_malloc(size * sizeof(grub_efi_char16_t));
+  if (efi_entries == NULL) {
+    return grub_error (GRUB_ERR_OUT_OF_MEMORY,
+                      "couldn't find space for LoaderEntries efi variable");
+  }
+  p = efi_entries;
+  FOR_BLS_ENTRIES(entry) {
+    if (entry->visible) {
+      tmp = entry->filename;
+      while (*tmp) {
+        *p++ = (grub_efi_char16_t) *tmp++;
+      }
+      *p++ = (grub_efi_char16_t) '\0';
+    }
+  }
+  if (efi_entries + size + 1 == p) {
+      return grub_error(GRUB_ERR_BAD_NUMBER, "efi entries value is not 
correct");
+  }
+  grub_efi_set_variable_with_attributes("LoaderEntries", &grub_efi_loader_guid,
+                                             efi_entries, size * 
sizeof(grub_efi_char16_t),
+                                             
GRUB_EFI_VARIABLE_BOOTSERVICE_ACCESS |
+                                             GRUB_EFI_VARIABLE_RUNTIME_ACCESS);
+#endif
+
   return GRUB_ERR_NONE;
 }
 
Index: grub-2.12/grub-core/commands/efi/blsbumpcounter.c
===================================================================
--- grub-2.12.orig/grub-core/commands/efi/blsbumpcounter.c
+++ grub-2.12/grub-core/commands/efi/blsbumpcounter.c
@@ -60,8 +60,14 @@ grub_cmd_bumpcounters (grub_extcmd_conte
 
   /* 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 @@ grub_cmd_bumpcounters (grub_extcmd_conte
       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);

Reply via email to