From 82df76851478f52e02ed6beef0f1576772d066cd Mon Sep 17 00:00:00 2001 From: Pavel Butsykin Date: Sat, 11 Jun 2016 13:29:41 +0300 Subject: [PATCH] v2v: fill the list of the EFI system partitions Store the list of EFI system partitions on the inspect object in order to be able to tune their contents later in the process. Signed-off-by: Pavel Butsykin --- v2v/convert_linux.ml | 7 +++---- v2v/inspect_source.ml | 41 ++++++++++++++++++++++++++++------------- v2v/types.ml | 12 +++++++++--- v2v/types.mli | 8 +++++++- v2v/v2v.ml | 5 ++++- v2v/v2v_unit_tests.ml | 2 +- 6 files changed, 52 insertions(+), 23 deletions(-) diff --git a/v2v/convert_linux.ml b/v2v/convert_linux.ml index 82a158563..2cfe3a7a6 100644 --- a/v2v/convert_linux.ml +++ b/v2v/convert_linux.ml @@ -97,10 +97,9 @@ let rec convert ~keep_serial_console (g : G.guestfs) inspect source rcaps = "/boot/grub/grub.conf", `Grub1; ] in let locations = - if inspect.i_uefi then - ("/boot/efi/EFI/redhat/grub.cfg", `Grub2) :: locations - else - locations in + match inspect.i_firmware with + | I_UEFI _ -> ("/boot/efi/EFI/redhat/grub.cfg", `Grub2) :: locations + | I_BIOS -> locations in try List.find ( fun (grub_config, _) -> g#is_file ~followsymlinks:true grub_config diff --git a/v2v/inspect_source.ml b/v2v/inspect_source.ml index 65dcb889c..86d78924e 100644 --- a/v2v/inspect_source.ml +++ b/v2v/inspect_source.ml @@ -65,11 +65,6 @@ let rec inspect_source root_choice g = StringMap.add name (app :: vs) map ) StringMap.empty apps in - (* See if this guest could use UEFI to boot. It should use GPT and - * it should have an EFI System Partition (ESP). - *) - let uefi = has_uefi_bootable_device g in - let inspect = { i_root = root; i_type = g#inspect_get_type root; @@ -84,7 +79,7 @@ let rec inspect_source root_choice g = i_mountpoints = mps; i_apps = apps; i_apps_map = apps_map; - i_uefi = uefi + i_firmware = get_firmware_bootable_device g; } in debug "%s" (string_of_inspect inspect); @@ -153,10 +148,20 @@ and reject_if_not_installed_image g root = if fmt <> "installed" then error (f_"libguestfs thinks this is not an installed operating system (it might be, for example, an installer disk or live CD). If this is wrong, it is probably a bug in libguestfs. root=%s fmt=%s") root fmt -and has_uefi_bootable_device g = +(* See if this guest could use UEFI to boot. It should use GPT and + * it should have an EFI System Partition (ESP). + * + * If it has ESP(s), then [UEFI devs] is returned where [devs] is the + * list of at least one ESP. + * + * Otherwise, [BIOS] is returned. + *) +and get_firmware_bootable_device g = let rec uefi_ESP_guid = "C12A7328-F81F-11D2-BA4B-00A0C93EC93B" and is_uefi_ESP dev { G.part_num = partnum } = g#part_get_gpt_type dev (Int32.to_int partnum) = uefi_ESP_guid + and part_dev_name dev { G.part_num = partnum } = + sprintf "%s%d" dev (Int32.to_int partnum) and parttype_is_gpt dev = try g#part_get_parttype dev = "gpt" with G.Error msg as exn -> @@ -164,14 +169,24 @@ and has_uefi_bootable_device g = if g#last_errno () <> G.Errno.errno_EINVAL then raise exn; debug "%s (ignored)" msg; false - and is_uefi_bootable_device dev = - parttype_is_gpt dev && ( - let partitions = Array.to_list (g#part_list dev) in - List.exists (is_uefi_ESP dev) partitions - ) + and is_uefi_bootable_part dev part = + parttype_is_gpt dev && is_uefi_ESP dev part in let devices = Array.to_list (g#list_devices ()) in - List.exists is_uefi_bootable_device devices + let uefi_list = ref [] in + + List.iter ( + fun dev -> + Array.iter ( + fun part -> + if is_uefi_bootable_part dev part then + uefi_list := part_dev_name dev part :: !uefi_list + ) (g#part_list dev) + ) devices; + + match !uefi_list with + | [] -> I_BIOS + | devices -> I_UEFI devices (* If some inspection fields are "unknown", then that indicates a * failure in inspection, and we shouldn't continue. For an example diff --git a/v2v/types.ml b/v2v/types.ml index 08e1631e2..bff03a291 100644 --- a/v2v/types.ml +++ b/v2v/types.ml @@ -301,6 +301,10 @@ let string_of_target_firmware = function | TargetBIOS -> "bios" | TargetUEFI -> "uefi" +type i_firmware = + | I_BIOS + | I_UEFI of string list + type inspect = { i_root : string; i_type : string; @@ -315,7 +319,7 @@ type inspect = { i_mountpoints : (string * string) list; i_apps : Guestfs.application2 list; i_apps_map : Guestfs.application2 list StringMap.t; - i_uefi : bool; + i_firmware : i_firmware; } let string_of_inspect inspect = @@ -330,7 +334,7 @@ i_package_format = %s i_package_management = %s i_product_name = %s i_product_variant = %s -i_uefi = %b +i_firmware = %s " inspect.i_root inspect.i_type inspect.i_distro @@ -341,7 +345,9 @@ i_uefi = %b inspect.i_package_management inspect.i_product_name inspect.i_product_variant - inspect.i_uefi + (match inspect.i_firmware with + | I_BIOS -> "BIOS" + | I_UEFI devices -> sprintf "UEFI [%s]" (String.concat ", " devices)) type mpstat = { mp_dev : string; diff --git a/v2v/types.mli b/v2v/types.mli index dacc99194..25420df94 100644 --- a/v2v/types.mli +++ b/v2v/types.mli @@ -204,6 +204,10 @@ type target_firmware = TargetBIOS | TargetUEFI val string_of_target_firmware : target_firmware -> string +type i_firmware = + | I_BIOS + | I_UEFI of string list + type inspect = { i_root : string; (** Root device. *) i_type : string; (** Usual inspection fields. *) @@ -221,7 +225,9 @@ type inspect = { (** This is a map from the app name to the application object. Since RPM allows multiple packages with the same name to be installed, the value is a list. *) - i_uefi : bool; (** True if the guest could boot with UEFI. *) + i_firmware : i_firmware; + (** The list of EFI system partitions for the guest with UEFI, + otherwise the BIOS identifier. *) } (** Inspection information. *) diff --git a/v2v/v2v.ml b/v2v/v2v.ml index fe81df5aa..79b6f0460 100644 --- a/v2v/v2v.ml +++ b/v2v/v2v.ml @@ -555,7 +555,10 @@ and get_target_firmware inspect guestcaps source output = | BIOS -> TargetBIOS | UEFI -> TargetUEFI | UnknownFirmware -> - if inspect.i_uefi then TargetUEFI else TargetBIOS in + match inspect.i_firmware with + | I_BIOS -> TargetBIOS + | I_UEFI devs -> TargetUEFI + in let supported_firmware = output#supported_firmware in if not (List.mem target_firmware supported_firmware) then error (f_"this guest cannot run on the target, because the target does not support %s firmware (supported firmware on target: %s)") diff --git a/v2v/v2v_unit_tests.ml b/v2v/v2v_unit_tests.ml index 8e8957d76..60644487f 100644 --- a/v2v/v2v_unit_tests.ml +++ b/v2v/v2v_unit_tests.ml @@ -30,7 +30,7 @@ let inspect_defaults = { i_major_version = 0; i_minor_version = 0; i_root = ""; i_package_format = ""; i_package_management = ""; i_product_name = ""; i_product_variant = ""; i_mountpoints = []; - i_apps = []; i_apps_map = StringMap.empty; i_uefi = false + i_apps = []; i_apps_map = StringMap.empty; i_firmware = I_BIOS } let test_get_ostype ctx =