88 lines
3.7 KiB
Diff
88 lines
3.7 KiB
Diff
From 796573e6f530d4736bcd9d81a6dc113f928a4d27 Mon Sep 17 00:00:00 2001
|
|
From: Laszlo Ersek <lersek@redhat.com>
|
|
Date: Fri, 2 Dec 2022 13:44:09 +0100
|
|
Subject: [PATCH] convert_windows: fix up the UEFI fallback boot loader if
|
|
broken
|
|
|
|
The "fallback" (or "default") boot behavior is described at great length
|
|
here:
|
|
|
|
https://blog.uncooperative.org/uefi/linux/shim/efi%20system%20partition/2014/02/06/the-efi-system-partition.html
|
|
|
|
The gist of it applies to all UEFI OSes, including Windows. For the
|
|
fallback boot behavior to work, the \EFI\BOOT\BOOTX64.efi boot loader on
|
|
the EFI system partition must match the installed operating system. We've
|
|
encountered a physical machine, during a virt-p2v conversion, where (a)
|
|
\EFI\BOOT\BOOTX64.efi belongs to a previously installed, but now wiped,
|
|
RHEL (hence shim+grub) deployment, and (b) the currently installed
|
|
operating system is Windows.
|
|
|
|
Virt-v2v never transfers the UEFI variables (including the UEFI boot
|
|
options) of the source, therefore the converted VM always relies on the
|
|
default boot behavior when it is first started up. In the above scenario,
|
|
where \EFI\BOOT\BOOTX64.efi is actually "shim", the mismatch is triggered
|
|
at first boot after conversion, and a broken grub shell is reached instead
|
|
of the Windows boot loader.
|
|
|
|
Detect this situation by investigating \EFI\BOOT\BOOTX64.efi on the EFI
|
|
system partition of a Windows disk image. If the file is missing, or is
|
|
not -- as expected -- a duplicate of \EFI\Microsoft\Boot\bootmgfw.efi,
|
|
then copy the latter to the former.
|
|
|
|
Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=2149629
|
|
Signed-off-by: Laszlo Ersek <lersek@redhat.com>
|
|
Message-Id: <20221202124409.11741-3-lersek@redhat.com>
|
|
Reviewed-by: Richard W.M. Jones <rjones@redhat.com>
|
|
(cherry picked from commit 9d4b58dcecc40da5c97a0e716f44757c422160f0)
|
|
---
|
|
convert/convert_windows.ml | 25 +++++++++++++++++++++++++
|
|
1 file changed, 25 insertions(+)
|
|
|
|
diff --git a/convert/convert_windows.ml b/convert/convert_windows.ml
|
|
index 34a5044d..57a7ff03 100644
|
|
--- a/convert/convert_windows.ml
|
|
+++ b/convert/convert_windows.ml
|
|
@@ -836,17 +836,42 @@ let convert (g : G.guestfs) _ inspect _ static_ips =
|
|
);
|
|
with
|
|
Not_found -> ()
|
|
+
|
|
+ and fix_win_uefi_fallback esp_path uefi_arch =
|
|
+ (* [esp_path] is on NTFS, and therefore it is considered case-sensitive;
|
|
+ * refer to
|
|
+ * <https://libguestfs.org/guestfs.3.html#guestfs_case_sensitive_path>.
|
|
+ * However, the EFI system partition mounted under [esp_path] is FAT32 per
|
|
+ * UEFI spec, and the Linux vfat driver in the libguestfs appliance treats
|
|
+ * pathnames case-insensitively. Therefore, we're free to use any case in
|
|
+ * the ESP-relative pathnames below.
|
|
+ *)
|
|
+ let bootmgfw = sprintf "%s/efi/microsoft/boot/bootmgfw.efi" esp_path in
|
|
+ if g#is_file bootmgfw then
|
|
+ let bootdir = sprintf "%s/efi/boot" esp_path in
|
|
+ let fallback = sprintf "%s/boot%s.efi" bootdir uefi_arch in
|
|
+ if not (g#is_file fallback) || not (g#equal fallback bootmgfw) then (
|
|
+ info (f_"Fixing UEFI bootloader.");
|
|
+ g#rm_rf bootdir;
|
|
+ g#mkdir_p bootdir;
|
|
+ g#cp_a bootmgfw fallback
|
|
+ )
|
|
in
|
|
|
|
match inspect.i_firmware with
|
|
| I_BIOS -> ()
|
|
| I_UEFI esp_list ->
|
|
let esp_temp_path = g#mkdtemp "/Windows/Temp/ESP_XXXXXX" in
|
|
+ let uefi_arch = get_uefi_arch_suffix inspect.i_arch in
|
|
|
|
List.iter (
|
|
fun dev_path ->
|
|
g#mount dev_path esp_temp_path;
|
|
fix_win_uefi_bcd esp_temp_path;
|
|
+ (match uefi_arch with
|
|
+ | Some uefi_arch -> fix_win_uefi_fallback esp_temp_path uefi_arch
|
|
+ | None -> ()
|
|
+ );
|
|
g#umount esp_temp_path;
|
|
) esp_list;
|
|
|