If the guest uses BIOS firmware but GPT partitioned disk, and in
addition has "bios, esp" flag enabled on its "/boot" partition, then
inspection wrongly detects UEFI firmware and v2v ends up with the error:
"error: no bootloader detected".

Let's fix this by checking for the presence of BIOS boot partition (0xef02
type for gdisk, "bios_grub" flag for parted), which is used to store a
bootloader code in BIOS+GPT configurations.  If such a partition is
present, then it's likely a BIOS+GPT setup.

Signed-off-by: Andrey Drobyshev <andrey.drobys...@virtuozzo.com>
---
 convert/inspect_source.ml | 27 +++++++++++++++++++++++----
 1 file changed, 23 insertions(+), 4 deletions(-)

diff --git a/convert/inspect_source.ml b/convert/inspect_source.ml
index 056d0bca..6650e136 100644
--- a/convert/inspect_source.ml
+++ b/convert/inspect_source.ml
@@ -219,6 +219,9 @@ and list_applications g root = function
 (* 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 a BIOS boot partition (BIOS+GPT setup), then [BIOS] is
+ * returned.
+ *
  * If it has ESP(s), then [UEFI devs] is returned where [devs] is the
  * list of at least one ESP.
  *
@@ -226,9 +229,13 @@ and list_applications g root = function
  *)
 and get_firmware_bootable_device g =
   let rec uefi_ESP_guid = "C12A7328-F81F-11D2-BA4B-00A0C93EC93B"
+  and bios_boot_guid = "21686148-6449-6E6F-744E-656564454649"
   and is_uefi_ESP dev part =
     let partnum = g#part_to_partnum part in
     g#part_get_gpt_type dev partnum = uefi_ESP_guid
+  and is_bios_boot dev part =
+    let partnum = g#part_to_partnum part in
+    g#part_get_gpt_type dev partnum = bios_boot_guid
   and parttype_is_gpt dev =
     try g#part_get_parttype dev = "gpt"
     with G.Error msg as exn ->
@@ -239,14 +246,26 @@ and get_firmware_bootable_device g =
   and is_uefi_bootable_part part =
     let dev = g#part_to_dev part in
     parttype_is_gpt dev && is_uefi_ESP dev part
+  and is_bios_gpt_part part =
+    let dev = g#part_to_dev part in
+    parttype_is_gpt dev && is_bios_boot dev part
   in
 
   let partitions = Array.to_list (g#list_partitions ()) in
-  let partitions = List.filter is_uefi_bootable_part partitions in
+  let esp_partitions = List.filter is_uefi_bootable_part partitions in
 
-  match partitions with
-  | [] -> I_BIOS
-  | partitions -> I_UEFI partitions
+  (* If there's a BIOS boot partition present (0xef02 type for gdisk,
+   * "bios_grub" flag for parted), then this is likely a BIOS+GPT setup.
+   * Note that if a source VM is using UEFI firmware and has a secondary
+   * non-bootable disk attached which contains such a partition, the
+   * firmware detection will detect I_BIOS wrongly.  But this can only be
+   * done manually, and we assume that there's no point doing it on purpose.
+   *)
+  if List.exists is_bios_gpt_part partitions then I_BIOS
+  else
+    match esp_partitions with
+    | [] -> I_BIOS
+    | esp_partitions -> I_UEFI esp_partitions
 
 (* If some inspection fields are "unknown", then that indicates a
  * failure in inspection, and we shouldn't continue.  For an example
-- 
2.31.1

_______________________________________________
Libguestfs mailing list
Libguestfs@redhat.com
https://listman.redhat.com/mailman/listinfo/libguestfs

Reply via email to