mirror of
				https://git.proxmox.com/git/grub2
				synced 2025-11-03 23:50:02 +00:00 
			
		
		
		
	
		
			
				
	
	
		
			203 lines
		
	
	
		
			6.2 KiB
		
	
	
	
		
			Diff
		
	
	
	
	
	
			
		
		
	
	
			203 lines
		
	
	
		
			6.2 KiB
		
	
	
	
		
			Diff
		
	
	
	
	
	
From c009126d6256205355a392dc7002ed1dac2dc59f Mon Sep 17 00:00:00 2001
 | 
						|
From: Steve McIntyre <93sam@debian.org>
 | 
						|
Date: Wed, 3 Dec 2014 01:25:12 +0000
 | 
						|
Subject: Add support for forcing EFI installation to the removable media path
 | 
						|
 | 
						|
Add an extra option to grub-install "--force-extra-removable". On EFI
 | 
						|
platforms, this will cause an extra copy of the grub-efi image to be
 | 
						|
written to the appropriate removable media patch
 | 
						|
/boot/efi/EFI/BOOT/BOOT$ARCH.EFI as well. This will help with broken
 | 
						|
UEFI implementations where the firmware does not work when configured
 | 
						|
with new boot paths.
 | 
						|
 | 
						|
Signed-off-by: Steve McIntyre <93sam@debian.org>
 | 
						|
 | 
						|
Bug-Debian: https://bugs.debian.org/767037 https://bugs.debian.org/773092
 | 
						|
Forwarded: Not yet
 | 
						|
Last-Update: 2014-12-20
 | 
						|
 | 
						|
Patch-Name: grub-install-extra-removable.patch
 | 
						|
---
 | 
						|
 util/grub-install.c | 110 +++++++++++++++++++++++++++++++++++++++++++-
 | 
						|
 1 file changed, 108 insertions(+), 2 deletions(-)
 | 
						|
 | 
						|
diff --git a/util/grub-install.c b/util/grub-install.c
 | 
						|
index 7a24767c1..1fbb4c7da 100644
 | 
						|
--- a/util/grub-install.c
 | 
						|
+++ b/util/grub-install.c
 | 
						|
@@ -56,6 +56,7 @@
 | 
						|
 
 | 
						|
 static char *target;
 | 
						|
 static int removable = 0;
 | 
						|
+static int force_extra_removable = 0;
 | 
						|
 static int recheck = 0;
 | 
						|
 static int update_nvram = 1;
 | 
						|
 static char *install_device = NULL;
 | 
						|
@@ -113,7 +114,8 @@ enum
 | 
						|
     OPTION_LABEL_BGCOLOR,
 | 
						|
     OPTION_PRODUCT_VERSION,
 | 
						|
     OPTION_UEFI_SECURE_BOOT,
 | 
						|
-    OPTION_NO_UEFI_SECURE_BOOT
 | 
						|
+    OPTION_NO_UEFI_SECURE_BOOT,
 | 
						|
+    OPTION_FORCE_EXTRA_REMOVABLE
 | 
						|
   };
 | 
						|
 
 | 
						|
 static int fs_probe = 1;
 | 
						|
@@ -216,6 +218,10 @@ argp_parser (int key, char *arg, struct argp_state *state)
 | 
						|
       removable = 1;
 | 
						|
       return 0;
 | 
						|
 
 | 
						|
+    case OPTION_FORCE_EXTRA_REMOVABLE:
 | 
						|
+      force_extra_removable = 1;
 | 
						|
+      return 0;
 | 
						|
+
 | 
						|
     case OPTION_ALLOW_FLOPPY:
 | 
						|
       allow_floppy = 1;
 | 
						|
       return 0;
 | 
						|
@@ -322,6 +328,9 @@ static struct argp_option options[] = {
 | 
						|
    N_("do not install an image usable with UEFI Secure Boot, even if the "
 | 
						|
       "system was currently started using it. "
 | 
						|
       "This option is only available on EFI."), 2},
 | 
						|
+  {"force-extra-removable", OPTION_FORCE_EXTRA_REMOVABLE, 0, 0,
 | 
						|
+   N_("force installation to the removable media path also. "
 | 
						|
+      "This option is only available on EFI."), 2},
 | 
						|
   {0, 0, 0, 0, 0, 0}
 | 
						|
 };
 | 
						|
 
 | 
						|
@@ -835,6 +844,91 @@ fill_core_services (const char *core_services)
 | 
						|
   free (sysv_plist);
 | 
						|
 }
 | 
						|
 
 | 
						|
+/* Helper routine for also_install_removable() below. Walk through the
 | 
						|
+   specified dir, looking to see if there is a file/dir that matches
 | 
						|
+   the search string exactly, but in a case-insensitive manner. If so,
 | 
						|
+   return a copy of the exact file/dir that *does* exist. If not,
 | 
						|
+   return NULL */
 | 
						|
+static char *
 | 
						|
+check_component_exists(const char *dir,
 | 
						|
+		       const char *search)
 | 
						|
+{
 | 
						|
+  grub_util_fd_dir_t d;
 | 
						|
+  grub_util_fd_dirent_t de;
 | 
						|
+  char *found = NULL;
 | 
						|
+
 | 
						|
+  d = grub_util_fd_opendir (dir);
 | 
						|
+  if (!d)
 | 
						|
+    grub_util_error (_("cannot open directory `%s': %s"),
 | 
						|
+		     dir, grub_util_fd_strerror ());
 | 
						|
+
 | 
						|
+  while ((de = grub_util_fd_readdir (d)))
 | 
						|
+    {
 | 
						|
+      if (strcasecmp (de->d_name, search) == 0)
 | 
						|
+	{
 | 
						|
+	  found = xstrdup (de->d_name);
 | 
						|
+	  break;
 | 
						|
+	}
 | 
						|
+    }
 | 
						|
+  grub_util_fd_closedir (d);
 | 
						|
+  return found;
 | 
						|
+}
 | 
						|
+
 | 
						|
+/* Some complex directory-handling stuff in here, to cope with
 | 
						|
+ * case-insensitive FAT/VFAT filesystem semantics. Ugh. */
 | 
						|
+static void
 | 
						|
+also_install_removable(const char *src,
 | 
						|
+		       const char *base_efidir,
 | 
						|
+		       const char *efi_suffix_upper)
 | 
						|
+{
 | 
						|
+  char *efi_file = NULL;
 | 
						|
+  char *dst = NULL;
 | 
						|
+  char *cur = NULL;
 | 
						|
+  char *found = NULL;
 | 
						|
+
 | 
						|
+  if (!efi_suffix_upper)
 | 
						|
+    grub_util_error ("%s", _("efi_suffix_upper not set"));
 | 
						|
+  efi_file = xasprintf ("BOOT%s.EFI", efi_suffix_upper);
 | 
						|
+
 | 
						|
+  /* We need to install in $base_efidir/EFI/BOOT/$efi_file, but we
 | 
						|
+   * need to cope with case-insensitive stuff here. Build the path one
 | 
						|
+   * component at a time, checking for existing matches each time. */
 | 
						|
+
 | 
						|
+  /* Look for "EFI" in base_efidir. Make it if it does not exist in
 | 
						|
+   * some form. */
 | 
						|
+  found = check_component_exists(base_efidir, "EFI");
 | 
						|
+  if (found == NULL)
 | 
						|
+    found = xstrdup("EFI");
 | 
						|
+  dst = grub_util_path_concat (2, base_efidir, found);
 | 
						|
+  cur = xstrdup (dst);
 | 
						|
+  free (dst);
 | 
						|
+  free (found);
 | 
						|
+  grub_install_mkdir_p (cur);
 | 
						|
+
 | 
						|
+  /* Now BOOT */
 | 
						|
+  found = check_component_exists(cur, "BOOT");
 | 
						|
+  if (found == NULL)
 | 
						|
+    found = xstrdup("BOOT");
 | 
						|
+  dst = grub_util_path_concat (2, cur, found);
 | 
						|
+  cur = xstrdup (dst);
 | 
						|
+  free (dst);
 | 
						|
+  free (found);
 | 
						|
+  grub_install_mkdir_p (cur);
 | 
						|
+
 | 
						|
+  /* Now $efi_file */
 | 
						|
+  found = check_component_exists(cur, efi_file);
 | 
						|
+  if (found == NULL)
 | 
						|
+    found = xstrdup(efi_file);
 | 
						|
+  dst = grub_util_path_concat (2, cur, found);
 | 
						|
+  cur = xstrdup (dst);
 | 
						|
+  free (dst);
 | 
						|
+  free (found);
 | 
						|
+  grub_install_copy_file (src, cur, 1);
 | 
						|
+
 | 
						|
+  free (cur);
 | 
						|
+  free (efi_file);
 | 
						|
+}
 | 
						|
+
 | 
						|
 int
 | 
						|
 main (int argc, char *argv[])
 | 
						|
 {
 | 
						|
@@ -852,6 +946,7 @@ main (int argc, char *argv[])
 | 
						|
   char *relative_grubdir;
 | 
						|
   char **efidir_device_names = NULL;
 | 
						|
   grub_device_t efidir_grub_dev = NULL;
 | 
						|
+  char *base_efidir = NULL;
 | 
						|
   char *efidir_grub_devname;
 | 
						|
   int efidir_is_mac = 0;
 | 
						|
   int is_prep = 0;
 | 
						|
@@ -884,6 +979,9 @@ main (int argc, char *argv[])
 | 
						|
       bootloader_id = xstrdup ("grub");
 | 
						|
     }
 | 
						|
 
 | 
						|
+  if (removable && force_extra_removable)
 | 
						|
+    grub_util_error (_("Invalid to use both --removable and --force_extra_removable"));
 | 
						|
+
 | 
						|
   if (!grub_install_source_directory)
 | 
						|
     {
 | 
						|
       if (!target)
 | 
						|
@@ -1093,6 +1191,8 @@ main (int argc, char *argv[])
 | 
						|
       if (!efidir_is_mac && grub_strcmp (fs->name, "fat") != 0)
 | 
						|
 	grub_util_error (_("%s doesn't look like an EFI partition"), efidir);
 | 
						|
 
 | 
						|
+      base_efidir = xstrdup(efidir);
 | 
						|
+
 | 
						|
       /* The EFI specification requires that an EFI System Partition must
 | 
						|
 	 contain an "EFI" subdirectory, and that OS loaders are stored in
 | 
						|
 	 subdirectories below EFI.  Vendors are expected to pick names that do
 | 
						|
@@ -1980,9 +2080,15 @@ main (int argc, char *argv[])
 | 
						|
 	    fprintf (config_dst_f, "configfile $prefix/grub.cfg\n");
 | 
						|
 	    fclose (config_dst_f);
 | 
						|
 	    free (config_dst);
 | 
						|
+	    if (force_extra_removable)
 | 
						|
+	      also_install_removable(efi_signed, base_efidir, efi_suffix_upper);
 | 
						|
 	  }
 | 
						|
 	else
 | 
						|
-	  grub_install_copy_file (imgfile, dst, 1);
 | 
						|
+	  {
 | 
						|
+	    grub_install_copy_file (imgfile, dst, 1);
 | 
						|
+	    if (force_extra_removable)
 | 
						|
+	      also_install_removable(imgfile, base_efidir, efi_suffix_upper);
 | 
						|
+	  }
 | 
						|
 	free (dst);
 | 
						|
       }
 | 
						|
       if (!removable && update_nvram)
 |