Sign Up
Log In
Log In
or
Sign Up
Places
All Projects
Status Monitor
Collapse sidebar
openSUSE:Step:FrontRunner
grub2.29024
0001-install-fix-software-raid1-on-esp.patch
Overview
Repositories
Revisions
Requests
Users
Attributes
Meta
File 0001-install-fix-software-raid1-on-esp.patch of Package grub2.29024
From 6444774dae24f439dae3b4bc8d73449d50f06240 Mon Sep 17 00:00:00 2001 From: Michael Chang <mchang@suse.com> Date: Thu, 31 Dec 2020 21:54:07 +0800 Subject: [PATCH] install: fix software raid1 on esp While running grub-install on an efi system where efi system partition is configured as mdadm software raid1, it fails with errors like this: grub2-install: info: copying `/boot/grub2/x86_64-efi/core.efi' -> `/boot/efi/EFI/opensuse/grubx64.efi'. grub2-install: info: Registering with EFI: distributor = `opensuse', path = `\EFI\opensuse\grubx64.efi', ESP at mduuid/9182c46b9d469f79b48850b68f3371a5. grub2-install: info: executing efibootmgr --version </dev/null >/dev/null. grub2-install: info: executing modprobe -q efivars. grub2-install: info: executing efibootmgr -c -d. efibootmgr: option requires an argument -- 'd' efibootmgr version 14 usage: efibootmgr [options] This should work with mdadm raid1 with metadata 0.9 and 1.0 whose superblocks are at the end of device. However grub_install_register_efi() doesn't seem to work if the target is multiple devices so that it errors out. The patch changes grub_install_register_efi() to accept multiple devices that can be used to creating efi boot entries for probed raid1 member devices on mounted efi system partition. This patch also adds check for metadata 0.9 or 1.0 or the validation will fail to continue the install. Signed-off-by: Michael Chang <mchang@suse.com> --- grub-core/disk/diskfilter.c | 27 +++---- grub-core/disk/mdraid1x_linux.c | 3 + grub-core/osdep/basic/no_platform.c | 3 +- grub-core/osdep/unix/platform.c | 57 +++++++++++---- grub-core/osdep/windows/platform.c | 3 +- include/grub/diskfilter.h | 3 +- include/grub/util/install.h | 5 +- util/grub-install.c | 107 ++++++++++++++++++++++++++-- 8 files changed, 171 insertions(+), 37 deletions(-) diff --git a/grub-core/disk/diskfilter.c b/grub-core/disk/diskfilter.c index 39d74cb867..de0c02cf94 100644 --- a/grub-core/disk/diskfilter.c +++ b/grub-core/disk/diskfilter.c @@ -159,8 +159,8 @@ scan_disk_partition_iter (grub_disk_t disk, grub_partition_t p, void *data) for (m = arr->pvs; m; m = m->next) if (m->disk && m->disk->id == disk->id && m->disk->dev->id == disk->dev->id - && m->part_start == grub_partition_get_start (disk->partition) - && m->part_size == grub_disk_native_sectors (disk)) + && grub_partition_get_start (m->disk->partition) == grub_partition_get_start (disk->partition) + && grub_disk_native_sectors (m->disk) == grub_disk_native_sectors (disk)) return 0; } @@ -1330,19 +1330,23 @@ insert_array (grub_disk_t disk, const struct grub_diskfilter_pv_id *id, ? (grub_memcmp (pv->id.uuid, id->uuid, id->uuidlen) == 0) : (pv->id.id == id->id)) { + char *part_name = NULL; struct grub_diskfilter_lv *lv; /* FIXME: Check whether the update time of the superblocks are the same. */ - if (pv->disk && grub_disk_native_sectors (disk) >= pv->part_size) + if (pv->disk && grub_disk_native_sectors (disk) >= grub_disk_native_sectors (pv->disk)) return GRUB_ERR_NONE; - pv->disk = grub_disk_open (disk->name); + if (disk->partition) + { + char *p = grub_partition_get_name (disk->partition); + if (p) + part_name = grub_xasprintf ("%s,%s", disk->name, p); + grub_free (p); + } + pv->disk = grub_disk_open (part_name ? : disk->name); + grub_free (part_name); if (!pv->disk) return grub_errno; - /* This could happen to LVM on RAID, pv->disk points to the - raid device, we shouldn't change it. */ - pv->start_sector -= pv->part_start; - pv->part_start = grub_partition_get_start (disk->partition); - pv->part_size = grub_disk_native_sectors (disk); #ifdef GRUB_UTIL { @@ -1359,7 +1363,6 @@ insert_array (grub_disk_t disk, const struct grub_diskfilter_pv_id *id, #endif if (start_sector != (grub_uint64_t)-1) pv->start_sector = start_sector; - pv->start_sector += pv->part_start; /* Add the device to the array. */ for (lv = array->lvs; lv; lv = lv->next) if (!lv->became_readable_at && lv->fullname && is_lv_readable (lv, 0)) @@ -1447,8 +1450,8 @@ grub_diskfilter_get_pv_from_disk (grub_disk_t disk, { if (pv->disk && pv->disk->id == disk->id && pv->disk->dev->id == disk->dev->id - && pv->part_start == grub_partition_get_start (disk->partition) - && pv->part_size == grub_disk_native_sectors (disk)) + && grub_partition_get_start (pv->disk->partition) == grub_partition_get_start (disk->partition) + && grub_disk_native_sectors (pv->disk) == grub_disk_native_sectors (disk)) { if (vg_out) *vg_out = vg; diff --git a/grub-core/disk/mdraid1x_linux.c b/grub-core/disk/mdraid1x_linux.c index 38444b02c7..a2aafb69fb 100644 --- a/grub-core/disk/mdraid1x_linux.c +++ b/grub-core/disk/mdraid1x_linux.c @@ -208,6 +208,9 @@ grub_mdraid_detect (grub_disk_t disk, grub_le_to_cpu32 (sb.chunksize), grub_le_to_cpu32 (sb.layout), grub_le_to_cpu32 (sb.level)); +#ifdef GRUB_UTIL + array->mdraid1x_minor_version = minor_version; +#endif return array; } diff --git a/grub-core/osdep/basic/no_platform.c b/grub-core/osdep/basic/no_platform.c index dfbdd58e4e..37b9570dbc 100644 --- a/grub-core/osdep/basic/no_platform.c +++ b/grub-core/osdep/basic/no_platform.c @@ -33,7 +33,8 @@ grub_install_register_ieee1275 (int is_prep, const char *install_device, void grub_install_register_efi (grub_device_t efidir_grub_dev, const char *efifile_path, - const char *efi_distributor) + const char *efi_distributor, + const char *force_disk) { grub_util_error ("%s", _("no EFI routines are available for your platform")); } diff --git a/grub-core/osdep/unix/platform.c b/grub-core/osdep/unix/platform.c index 68186480b2..c7cf74c677 100644 --- a/grub-core/osdep/unix/platform.c +++ b/grub-core/osdep/unix/platform.c @@ -132,15 +132,14 @@ grub_install_remove_efi_entries_by_distributor (const char *efi_distributor) } int -grub_install_register_efi (grub_device_t efidir_grub_dev, +grub_install_register_efi (const grub_disk_t *efidir_grub_disk, const char *efifile_path, - const char *efi_distributor) + const char *efi_distributor, + const char *force_disk) { - const char * efidir_disk; - int efidir_part; int ret; - efidir_disk = grub_util_biosdisk_get_osdev (efidir_grub_dev->disk); - efidir_part = efidir_grub_dev->disk->partition ? efidir_grub_dev->disk->partition->number + 1 : 1; + const grub_disk_t *curdisk; + int ndev = 0; if (grub_util_exec_redirect_null ((const char * []){ "efibootmgr", "--version", NULL })) { @@ -158,22 +157,50 @@ grub_install_register_efi (grub_device_t efidir_grub_dev, if (ret) return ret; - char *efidir_part_str = xasprintf ("%d", efidir_part); + for (curdisk = efidir_grub_disk; *curdisk; curdisk++) + ndev++; - if (!verbosity) - ret = grub_util_exec ((const char * []){ "efibootmgr", "-q", + for (curdisk = efidir_grub_disk; *curdisk; curdisk++) + { + const char * efidir_disk; + int efidir_part; + char *efidir_part_str; + char *new_efi_distributor = NULL; + grub_disk_t disk = *curdisk; + + efidir_disk = force_disk ? : grub_util_biosdisk_get_osdev (disk); + if (!efidir_disk) + grub_util_error (_("%s: no device for efi"), disk->name); + + efidir_part = disk->partition ? disk->partition->number + 1 : 1; + efidir_part_str = xasprintf ("%d", efidir_part); + if (ndev > 1) + { + const char *p = grub_strrchr (efidir_disk, '/'); + new_efi_distributor = xasprintf ("%s (%s%d)\n", + efi_distributor, + p ? p + 1: efidir_disk, + efidir_part); + } + + if (!verbosity) + ret = grub_util_exec ((const char * []){ "efibootmgr", "-q", "-c", "-d", efidir_disk, "-p", efidir_part_str, "-w", - "-L", efi_distributor, "-l", + "-L", new_efi_distributor ? : efi_distributor, "-l", efifile_path, NULL }); - else - ret = grub_util_exec ((const char * []){ "efibootmgr", + else + ret = grub_util_exec ((const char * []){ "efibootmgr", "-c", "-d", efidir_disk, "-p", efidir_part_str, "-w", - "-L", efi_distributor, "-l", + "-L", new_efi_distributor ? : efi_distributor, "-l", efifile_path, NULL }); - free (efidir_part_str); - return ret; + free (efidir_part_str); + free (new_efi_distributor); + if (ret) + return ret; + } + return 0; } void diff --git a/grub-core/osdep/windows/platform.c b/grub-core/osdep/windows/platform.c index 1d2e356e6b..3517803251 100644 --- a/grub-core/osdep/windows/platform.c +++ b/grub-core/osdep/windows/platform.c @@ -204,7 +204,8 @@ set_efi_variable_bootn (grub_uint16_t n, void *in, grub_size_t len) int grub_install_register_efi (grub_device_t efidir_grub_dev, const char *efifile_path, - const char *efi_distributor) + const char *efi_distributor, + const char *force_disk) { grub_uint16_t *boot_order, *new_boot_order; grub_uint16_t *distributor16; diff --git a/include/grub/diskfilter.h b/include/grub/diskfilter.h index 8deb1a8c30..94ed8673d7 100644 --- a/include/grub/diskfilter.h +++ b/include/grub/diskfilter.h @@ -49,6 +49,7 @@ struct grub_diskfilter_vg { #ifdef GRUB_UTIL struct grub_diskfilter *driver; + grub_uint8_t mdraid1x_minor_version; #endif }; @@ -66,8 +67,6 @@ struct grub_diskfilter_pv { /* Optional. */ char *name; grub_disk_t disk; - grub_disk_addr_t part_start; - grub_disk_addr_t part_size; grub_disk_addr_t start_sector; /* Sector number where the data area starts. */ struct grub_diskfilter_pv *next; /* Optional. */ diff --git a/include/grub/util/install.h b/include/grub/util/install.h index 456955c3d7..9f9e0b2ac1 100644 --- a/include/grub/util/install.h +++ b/include/grub/util/install.h @@ -237,9 +237,10 @@ int grub_install_get_powerpc_secure_boot (void); int -grub_install_register_efi (grub_device_t efidir_grub_dev, +grub_install_register_efi (const grub_disk_t *efidir_grub_disk, const char *efifile_path, - const char *efi_distributor); + const char *efi_distributor, + const char *force_disk); void grub_install_register_ieee1275 (int is_prep, const char *install_device, diff --git a/util/grub-install.c b/util/grub-install.c index 213f54a782..0cabc79119 100644 --- a/util/grub-install.c +++ b/util/grub-install.c @@ -1694,6 +1694,40 @@ main (int argc, char *argv[]) } } prefix_drive = xasprintf ("(%s)", grub_drives[0]); + + if (platform == GRUB_INSTALL_PLATFORM_X86_64_EFI + && grub_dev->disk + && grub_dev->disk->partition + && grub_fs->fs_uuid) + { + int raid_level; + char *uuid = NULL; + char *escaped_relpath = NULL; + + raid_level = probe_raid_level (grub_dev->disk); + if (raid_level != 1) + goto out; + + escaped_relpath = escape (relative_grubdir); + if (!escaped_relpath) + goto out; + + if (grub_fs->fs_uuid (grub_dev, &uuid) || !uuid) + { + grub_print_error (); + grub_errno = 0; + goto out; + } + + if (!load_cfg_f) + load_cfg_f = grub_util_fopen (load_cfg, "wb"); + have_load_cfg = 1; + fprintf (load_cfg_f, "search --no-floppy --fs-uuid --set=root --hint='%s' %s\n", grub_drives[0], uuid); + fprintf (load_cfg_f, "set prefix=($root)'%s'\n", escaped_relpath); + grub_install_push_module ("search"); + out: + grub_free (escaped_relpath); + } } #ifdef __linux__ @@ -2232,9 +2266,13 @@ main (int argc, char *argv[]) { /* Try to make this image bootable using the EFI Boot Manager, if available. */ int ret; - ret = grub_install_register_efi (efidir_grub_dev, + grub_disk_t efidir_grub_disk[2]; + efidir_grub_disk[0] = efidir_grub_dev->disk; + efidir_grub_disk[1] = NULL; + ret = grub_install_register_efi (efidir_grub_disk, "\\System\\Library\\CoreServices", - efi_distributor); + efi_distributor, + NULL); if (ret) grub_util_error (_("efibootmgr failed to register the boot entry: %s"), strerror (ret)); @@ -2287,7 +2325,11 @@ main (int argc, char *argv[]) { char * efifile_path; char * part; + int raid_level; int ret; + grub_disk_t *efidir_grub_disk; + grub_disk_memberlist_t list = NULL, cur; + char * force_disk = NULL; /* Try to make this image bootable using the EFI Boot Manager, if available. */ if (!efi_distributor || efi_distributor[0] == '\0') @@ -2304,8 +2346,65 @@ main (int argc, char *argv[]) efidir_grub_dev->disk->name, (part ? ",": ""), (part ? : "")); grub_free (part); - ret = grub_install_register_efi (efidir_grub_dev, - efifile_path, efi_distributor); + + raid_level = probe_raid_level (efidir_grub_dev->disk); + if (raid_level >= 0 && raid_level != 1) + grub_util_warn (_("unsupported raid level %d detected for efi system partition"), raid_level); + if (raid_level == 1 && !efidir_grub_dev->disk->partition) + { + const char *raidname = NULL; + + if (efidir_grub_dev->disk->dev->disk_raidname) + raidname = efidir_grub_dev->disk->dev->disk_raidname (efidir_grub_dev->disk); + if (raidname + && (grub_strncmp (raidname, "mdraid09", sizeof ("mdraid09")) == 0 + || (grub_strcmp (raidname, "mdraid1x") == 0 + && ((struct grub_diskfilter_lv *) efidir_grub_dev->disk->data)->vg->mdraid1x_minor_version == 0))) + { + if (efidir_grub_dev->disk->dev->disk_memberlist) + list = efidir_grub_dev->disk->dev->disk_memberlist (efidir_grub_dev->disk); + } + else + { + grub_util_warn (_("this array has metadata at the start and may not be suitable as a efi system partition." + " please ensure that your firmware understands md/v1.x metadata, or use --metadata=0.90" + " to create the array.")); + /* Try to continue regardless metadata, nothing to lose here */ + if (efidir_grub_dev->disk->dev->disk_memberlist) + list = efidir_grub_dev->disk->dev->disk_memberlist (efidir_grub_dev->disk); + } + } + else if (raid_level == 1) + force_disk = grub_util_get_os_disk (install_device); + if (list) + { + int i; + int ndisk = 0; + + for (cur = list; cur; cur = cur->next) + ++ndisk; + efidir_grub_disk = xcalloc (ndisk + 1, sizeof (*efidir_grub_disk)); + for (cur = list, i = 0; i < ndisk; cur = cur->next, i++) + efidir_grub_disk[i] = cur->disk; + efidir_grub_disk[ndisk] = NULL; + } + else + { + efidir_grub_disk = xcalloc (2, sizeof (*efidir_grub_disk)); + efidir_grub_disk[0] = efidir_grub_dev->disk; + efidir_grub_disk[1] = NULL; + } + ret = grub_install_register_efi (efidir_grub_disk, + efifile_path, efi_distributor, + force_disk); + while (list) + { + cur = list; + list = list->next; + grub_free (cur); + } + grub_free (force_disk); + grub_free (efidir_grub_disk); if (ret) grub_util_error (_("efibootmgr failed to register the boot entry: %s"), strerror (ret)); -- 2.34.1
Locations
Projects
Search
Status Monitor
Help
OpenBuildService.org
Documentation
API Documentation
Code of Conduct
Contact
Support
@OBShq
Terms
openSUSE Build Service is sponsored by
The Open Build Service is an
openSUSE project
.
Sign Up
Log In
Places
Places
All Projects
Status Monitor