5593c8
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
5593c8
From: =?UTF-8?q?Renaud=20M=C3=A9trich?= <rmetrich@redhat.com>
5593c8
Date: Tue, 8 Feb 2022 08:39:11 +0100
5593c8
Subject: [PATCH] search: new --efidisk-only option on EFI systems
5593c8
MIME-Version: 1.0
5593c8
Content-Type: text/plain; charset=UTF-8
5593c8
Content-Transfer-Encoding: 8bit
5593c8
5593c8
When using 'search' on EFI systems, we sometimes want to exclude devices
5593c8
that are not EFI disks (e.g. md, lvm).
5593c8
This is typically used when wanting to chainload when having a software
5593c8
raid (md) for EFI partition:
5593c8
with no option, 'search --file /EFI/redhat/shimx64.efi' sets root envvar
5593c8
to 'md/boot_efi' which cannot be used for chainloading since there is no
5593c8
effective EFI device behind.
5593c8
5593c8
This commit also refactors handling of --no-floppy option.
5593c8
5593c8
Signed-off-by: Renaud Métrich <rmetrich@redhat.com>
5593c8
[rharwood: apply rmetrich's flags initialization fix]
5593c8
Signed-off-by: Robbie Harwood <rharwood@redhat.com>
5593c8
---
5593c8
 grub-core/commands/search.c      | 27 +++++++++++++++++++++++----
5593c8
 grub-core/commands/search_wrap.c | 18 ++++++++++++------
5593c8
 include/grub/search.h            | 15 ++++++++++++---
5593c8
 3 files changed, 47 insertions(+), 13 deletions(-)
5593c8
5593c8
diff --git a/grub-core/commands/search.c b/grub-core/commands/search.c
fd0330
index 51656e361c..57d26ced8a 100644
5593c8
--- a/grub-core/commands/search.c
5593c8
+++ b/grub-core/commands/search.c
5593c8
@@ -47,7 +47,7 @@ struct search_ctx
5593c8
 {
5593c8
   const char *key;
5593c8
   const char *var;
5593c8
-  int no_floppy;
5593c8
+  enum search_flags flags;
5593c8
   char **hints;
5593c8
   unsigned nhints;
5593c8
   int count;
5593c8
@@ -62,10 +62,29 @@ iterate_device (const char *name, void *data)
5593c8
   int found = 0;
5593c8
 
5593c8
   /* Skip floppy drives when requested.  */
5593c8
-  if (ctx->no_floppy &&
5593c8
+  if (ctx->flags & SEARCH_FLAGS_NO_FLOPPY &&
5593c8
       name[0] == 'f' && name[1] == 'd' && name[2] >= '0' && name[2] <= '9')
5593c8
     return 0;
5593c8
 
5593c8
+  /* Limit to EFI disks when requested.  */
5593c8
+  if (ctx->flags & SEARCH_FLAGS_EFIDISK_ONLY)
5593c8
+    {
5593c8
+      grub_device_t dev;
5593c8
+      dev = grub_device_open (name);
5593c8
+      if (! dev)
5593c8
+	{
5593c8
+	  grub_errno = GRUB_ERR_NONE;
5593c8
+	  return 0;
5593c8
+	}
5593c8
+      if (! dev->disk || dev->disk->dev->id != GRUB_DISK_DEVICE_EFIDISK_ID)
5593c8
+	{
5593c8
+	  grub_device_close (dev);
5593c8
+	  grub_errno = GRUB_ERR_NONE;
5593c8
+	  return 0;
5593c8
+	}
5593c8
+      grub_device_close (dev);
5593c8
+    }
5593c8
+
5593c8
 #ifdef DO_SEARCH_FS_UUID
5593c8
 #define compare_fn grub_strcasecmp
5593c8
 #else
5593c8
@@ -261,13 +280,13 @@ try (struct search_ctx *ctx)
5593c8
 }
5593c8
 
5593c8
 void
5593c8
-FUNC_NAME (const char *key, const char *var, int no_floppy,
5593c8
+FUNC_NAME (const char *key, const char *var, enum search_flags flags,
5593c8
 	   char **hints, unsigned nhints)
5593c8
 {
5593c8
   struct search_ctx ctx = {
5593c8
     .key = key,
5593c8
     .var = var,
5593c8
-    .no_floppy = no_floppy,
5593c8
+    .flags = flags,
5593c8
     .hints = hints,
5593c8
     .nhints = nhints,
5593c8
     .count = 0,
5593c8
diff --git a/grub-core/commands/search_wrap.c b/grub-core/commands/search_wrap.c
fd0330
index 47fc8eb996..0b62acf853 100644
5593c8
--- a/grub-core/commands/search_wrap.c
5593c8
+++ b/grub-core/commands/search_wrap.c
5593c8
@@ -40,6 +40,7 @@ static const struct grub_arg_option options[] =
5593c8
      N_("Set a variable to the first device found."), N_("VARNAME"),
5593c8
      ARG_TYPE_STRING},
5593c8
     {"no-floppy",	'n', 0, N_("Do not probe any floppy drive."), 0, 0},
5593c8
+    {"efidisk-only",	0, 0, N_("Only probe EFI disks."), 0, 0},
5593c8
     {"hint",	        'h', GRUB_ARG_OPTION_REPEATABLE,
5593c8
      N_("First try the device HINT. If HINT ends in comma, "
5593c8
 	"also try subpartitions"), N_("HINT"), ARG_TYPE_STRING},
5593c8
@@ -73,6 +74,7 @@ enum options
5593c8
     SEARCH_FS_UUID,
5593c8
     SEARCH_SET,
5593c8
     SEARCH_NO_FLOPPY,
5593c8
+    SEARCH_EFIDISK_ONLY,
5593c8
     SEARCH_HINT,
5593c8
     SEARCH_HINT_IEEE1275,
5593c8
     SEARCH_HINT_BIOS,
5593c8
@@ -89,6 +91,7 @@ grub_cmd_search (grub_extcmd_context_t ctxt, int argc, char **args)
5593c8
   const char *id = 0;
5593c8
   int i = 0, j = 0, nhints = 0;
5593c8
   char **hints = NULL;
5593c8
+  enum search_flags flags = 0;
5593c8
 
5593c8
   if (state[SEARCH_HINT].set)
5593c8
     for (i = 0; state[SEARCH_HINT].args[i]; i++)
5593c8
@@ -180,15 +183,18 @@ grub_cmd_search (grub_extcmd_context_t ctxt, int argc, char **args)
5593c8
       goto out;
5593c8
     }
5593c8
 
5593c8
+  if (state[SEARCH_NO_FLOPPY].set)
5593c8
+    flags |= SEARCH_FLAGS_NO_FLOPPY;
5593c8
+
5593c8
+  if (state[SEARCH_EFIDISK_ONLY].set)
5593c8
+    flags |= SEARCH_FLAGS_EFIDISK_ONLY;
5593c8
+
5593c8
   if (state[SEARCH_LABEL].set)
5593c8
-    grub_search_label (id, var, state[SEARCH_NO_FLOPPY].set, 
5593c8
-		       hints, nhints);
5593c8
+    grub_search_label (id, var, flags, hints, nhints);
5593c8
   else if (state[SEARCH_FS_UUID].set)
5593c8
-    grub_search_fs_uuid (id, var, state[SEARCH_NO_FLOPPY].set,
5593c8
-			 hints, nhints);
5593c8
+    grub_search_fs_uuid (id, var, flags, hints, nhints);
5593c8
   else if (state[SEARCH_FILE].set)
5593c8
-    grub_search_fs_file (id, var, state[SEARCH_NO_FLOPPY].set, 
5593c8
-			 hints, nhints);
5593c8
+    grub_search_fs_file (id, var, flags, hints, nhints);
5593c8
   else
5593c8
     grub_error (GRUB_ERR_INVALID_COMMAND, "unspecified search type");
5593c8
 
5593c8
diff --git a/include/grub/search.h b/include/grub/search.h
fd0330
index d80347df34..4190aeb2cb 100644
5593c8
--- a/include/grub/search.h
5593c8
+++ b/include/grub/search.h
5593c8
@@ -19,11 +19,20 @@
5593c8
 #ifndef GRUB_SEARCH_HEADER
5593c8
 #define GRUB_SEARCH_HEADER 1
5593c8
 
5593c8
-void grub_search_fs_file (const char *key, const char *var, int no_floppy,
5593c8
+enum search_flags
5593c8
+  {
5593c8
+    SEARCH_FLAGS_NO_FLOPPY	= 1,
5593c8
+    SEARCH_FLAGS_EFIDISK_ONLY	= 2
5593c8
+  };
5593c8
+
5593c8
+void grub_search_fs_file (const char *key, const char *var,
5593c8
+			  enum search_flags flags,
5593c8
 			  char **hints, unsigned nhints);
5593c8
-void grub_search_fs_uuid (const char *key, const char *var, int no_floppy,
5593c8
+void grub_search_fs_uuid (const char *key, const char *var,
5593c8
+			  enum search_flags flags,
5593c8
 			  char **hints, unsigned nhints);
5593c8
-void grub_search_label (const char *key, const char *var, int no_floppy,
5593c8
+void grub_search_label (const char *key, const char *var,
5593c8
+			enum search_flags flags,
5593c8
 			char **hints, unsigned nhints);
5593c8
 
5593c8
 #endif