Skip to content

Commit 9776354

Browse files
shankerwangmiaochenx97
authored andcommitted
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.
1 parent 624eb1c commit 9776354

File tree

1 file changed

+109
-4
lines changed

1 file changed

+109
-4
lines changed

util/grub-install.c

Lines changed: 109 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,7 @@
5555

5656
static char *target;
5757
static int removable = 0;
58+
static int force_extra_removable = 0;
5859
static int recheck = 0;
5960
static int update_nvram = 1;
6061
static char *install_device = NULL;
@@ -109,7 +110,8 @@ enum
109110
OPTION_LABEL_FONT,
110111
OPTION_LABEL_COLOR,
111112
OPTION_LABEL_BGCOLOR,
112-
OPTION_PRODUCT_VERSION
113+
OPTION_PRODUCT_VERSION,
114+
OPTION_FORCE_EXTRA_REMOVABLE,
113115
};
114116

115117
static int fs_probe = 1;
@@ -212,6 +214,10 @@ argp_parser (int key, char *arg, struct argp_state *state)
212214
removable = 1;
213215
return 0;
214216

217+
case OPTION_FORCE_EXTRA_REMOVABLE:
218+
force_extra_removable = 1;
219+
return 0;
220+
215221
case OPTION_ALLOW_FLOPPY:
216222
allow_floppy = 1;
217223
return 0;
@@ -302,6 +308,9 @@ static struct argp_option options[] = {
302308
{"label-color", OPTION_LABEL_COLOR, N_("COLOR"), 0, N_("use COLOR for label"), 2},
303309
{"label-bgcolor", OPTION_LABEL_BGCOLOR, N_("COLOR"), 0, N_("use COLOR for label background"), 2},
304310
{"product-version", OPTION_PRODUCT_VERSION, N_("STRING"), 0, N_("use STRING as product version"), 2},
311+
{"force-extra-removable", OPTION_FORCE_EXTRA_REMOVABLE, 0, 0,
312+
N_("force installation to the removable media path also. "
313+
"This option is only available on EFI."), 2},
305314
{0, 0, 0, 0, 0, 0}
306315
};
307316

@@ -843,12 +852,92 @@ try_open (const char *path)
843852
}
844853
#endif
845854

855+
/* Helper routine for also_install_removable() below. Walk through the
856+
specified dir, looking to see if there is a file/dir that matches
857+
the search string exactly, but in a case-insensitive manner. If so,
858+
return a copy of the exact file/dir that *does* exist. If not,
859+
return NULL */
860+
static char *
861+
check_component_exists(const char *dir,
862+
const char *search)
863+
{
864+
grub_util_fd_dir_t d;
865+
grub_util_fd_dirent_t de;
866+
char *found = NULL;
867+
868+
d = grub_util_fd_opendir (dir);
869+
if (!d)
870+
grub_util_error (_("cannot open directory `%s': %s"),
871+
dir, grub_util_fd_strerror ());
872+
873+
while ((de = grub_util_fd_readdir (d)))
874+
{
875+
if (strcasecmp (de->d_name, search) == 0)
876+
{
877+
found = xstrdup (de->d_name);
878+
break;
879+
}
880+
}
881+
grub_util_fd_closedir (d);
882+
return found;
883+
}
884+
885+
/* Some complex directory-handling stuff in here, to cope with
886+
* case-insensitive FAT/VFAT filesystem semantics. Ugh. */
887+
static void
888+
also_install_removable(const char *src,
889+
const char *base_efidir,
890+
const char *efi_file)
891+
{
892+
char *dst = NULL;
893+
char *cur = NULL;
894+
char *found = NULL;
895+
896+
/* We need to install in $base_efidir/EFI/BOOT/$efi_file, but we
897+
* need to cope with case-insensitive stuff here. Build the path one
898+
* component at a time, checking for existing matches each time. */
899+
900+
/* Look for "EFI" in base_efidir. Make it if it does not exist in
901+
* some form. */
902+
found = check_component_exists(base_efidir, "EFI");
903+
if (found == NULL)
904+
found = xstrdup("EFI");
905+
dst = grub_util_path_concat (2, base_efidir, found);
906+
cur = xstrdup (dst);
907+
free (dst);
908+
free (found);
909+
grub_install_mkdir_p (cur);
910+
911+
/* Now BOOT */
912+
found = check_component_exists(cur, "BOOT");
913+
if (found == NULL)
914+
found = xstrdup("BOOT");
915+
dst = grub_util_path_concat (2, cur, found);
916+
cur = xstrdup (dst);
917+
free (dst);
918+
free (found);
919+
grub_install_mkdir_p (cur);
920+
921+
/* Now $efi_file */
922+
found = check_component_exists(cur, efi_file);
923+
if (found == NULL)
924+
found = xstrdup(efi_file);
925+
dst = grub_util_path_concat (2, cur, found);
926+
cur = xstrdup (dst);
927+
free (dst);
928+
free (found);
929+
grub_install_copy_file (src, cur, 1);
930+
931+
free (cur);
932+
}
933+
846934
int
847935
main (int argc, char *argv[])
848936
{
849937
int is_efi = 0;
850938
const char *efi_distributor = NULL;
851939
const char *efi_file = NULL;
940+
const char *removeable_efi_file = NULL;
852941
char **grub_devices;
853942
grub_fs_t grub_fs;
854943
grub_device_t grub_dev = NULL;
@@ -859,6 +948,7 @@ main (int argc, char *argv[])
859948
char *relative_grubdir;
860949
char **efidir_device_names = NULL;
861950
grub_device_t efidir_grub_dev = NULL;
951+
char *base_efidir = NULL;
862952
char *efidir_grub_devname;
863953
int efidir_is_mac = 0;
864954
int is_prep = 0;
@@ -891,6 +981,9 @@ main (int argc, char *argv[])
891981
bootloader_id = xstrdup ("grub");
892982
}
893983

984+
if (removable && force_extra_removable)
985+
grub_util_error (_("Invalid to use both --removable and --force_extra_removable"));
986+
894987
if (!grub_install_source_directory)
895988
{
896989
if (!target)
@@ -1141,6 +1234,8 @@ main (int argc, char *argv[])
11411234
grub_util_error (_("%s doesn't look like an EFI partition"), efidir);
11421235
}
11431236

1237+
base_efidir = xstrdup(efidir);
1238+
11441239
/* The EFI specification requires that an EFI System Partition must
11451240
contain an "EFI" subdirectory, and that OS loaders are stored in
11461241
subdirectories below EFI. Vendors are expected to pick names that do
@@ -1149,14 +1244,17 @@ main (int argc, char *argv[])
11491244
*/
11501245
char *t;
11511246
efi_distributor = bootloader_id;
1152-
if (removable)
1247+
if (removable || force_extra_removable)
11531248
{
11541249
/* The specification makes stricter requirements of removable
11551250
devices, in order that only one image can be automatically loaded
11561251
from them. The image must always reside under /EFI/BOOT, and it
11571252
must have a specific file name depending on the architecture.
11581253
*/
1159-
efi_distributor = "BOOT";
1254+
if (removable)
1255+
{
1256+
efi_distributor = "BOOT";
1257+
}
11601258
switch (platform)
11611259
{
11621260
case GRUB_INSTALL_PLATFORM_I386_EFI:
@@ -1187,8 +1285,12 @@ main (int argc, char *argv[])
11871285
grub_util_error ("%s", _("You've found a bug"));
11881286
break;
11891287
}
1288+
if (force_extra_removable)
1289+
{
1290+
removeable_efi_file = efi_file;
1291+
}
11901292
}
1191-
else
1293+
if (!removable)
11921294
{
11931295
/* It is convenient for each architecture to have a different
11941296
efi_file, so that different versions can be installed in parallel.
@@ -1989,6 +2091,9 @@ main (int argc, char *argv[])
19892091
char *dst = grub_util_path_concat (2, efidir, efi_file);
19902092
grub_install_copy_file (imgfile, dst, 1);
19912093

2094+
if (force_extra_removable)
2095+
also_install_removable(imgfile, base_efidir, removeable_efi_file);
2096+
19922097
grub_set_install_backup_ponr ();
19932098

19942099
free (dst);

0 commit comments

Comments
 (0)