For reasons unknown virt-v2v recomputed the CurrentControlSet from
first principles, and passed %systemroot% around to all functions.
However that data is available from the libguestfs inspection APIs.
---
customize/firstboot.ml | 7 +------
v2v/convert_windows.ml | 52 ++++++++++++++++++++++----------------------------
v2v/inspect_source.ml | 17 ++++++++++++++++-
v2v/types.ml | 6 ++++++
v2v/types.mli | 2 ++
v2v/v2v_unit_tests.ml | 3 ++-
v2v/windows_virtio.ml | 31 +++++++++++++++---------------
v2v/windows_virtio.mli | 7 +++----
8 files changed, 69 insertions(+), 56 deletions(-)
diff --git a/customize/firstboot.ml b/customize/firstboot.ml
index 5396ded..3a5c10a 100644
--- a/customize/firstboot.ml
+++ b/customize/firstboot.ml
@@ -318,12 +318,7 @@ echo uninstalling firstboot service
let filename = g#case_sensitive_path filename in
Registry.with_hive_write g filename
(fun root_node ->
- (* Find the 'Current' ControlSet. *)
- let current_cs =
- let select = g#hivex_node_get_child root_node "Select" in
- let valueh = g#hivex_node_get_value select "Current" in
- let value = int_of_le32 (g#hivex_value_value valueh) in
- sprintf "ControlSet%03Ld" value in
+ let current_cs = g#inspect_get_windows_current_control_set root in
(* Add a new rhsrvany service to the system registry to execute
* firstboot. NB: All these edits are in the HKLM\SYSTEM hive.
diff --git a/v2v/convert_windows.ml b/v2v/convert_windows.ml
index a231219..eabbd56 100644
--- a/v2v/convert_windows.ml
+++ b/v2v/convert_windows.ml
@@ -68,17 +68,16 @@ let convert ~keep_serial_console (g : G.guestfs) inspect source rcaps
=
None
) in
- (* Get the Windows %systemroot%. *)
- let systemroot = g#inspect_get_windows_systemroot inspect.i_root in
-
(* Get the software and system hive files. *)
let software_hive_filename =
- let filename = sprintf "%s/system32/config/software" systemroot in
+ let filename = sprintf "%s/system32/config/software"
+ inspect.i_windows_systemroot in
let filename = g#case_sensitive_path filename in
filename in
let system_hive_filename =
- let filename = sprintf "%s/system32/config/system" systemroot in
+ let filename = sprintf "%s/system32/config/system"
+ inspect.i_windows_systemroot in
let filename = g#case_sensitive_path filename in
filename in
@@ -223,13 +222,6 @@ let convert ~keep_serial_console (g : G.guestfs) inspect source rcaps
=
(*----------------------------------------------------------------------*)
(* Perform the conversion of the Windows guest. *)
- (* Find the 'Current' ControlSet. *)
- let get_current_cs root =
- let select = g#hivex_node_get_child root "Select" in
- let valueh = g#hivex_node_get_value select "Current" in
- let value = int_of_le32 (g#hivex_value_value valueh) in
- sprintf "ControlSet%03Ld" value in
-
let rec configure_firstboot () =
wait_pnp ();
(match installer with
@@ -298,8 +290,8 @@ reg delete \"%s\" /v %s /f" strkey name
let name = "SuppressUI" in
let value = Registry.with_hive_write g system_hive_filename (
fun root ->
- let current_cs = get_current_cs root in
- set_reg_val_dword_1 root (current_cs :: key_path) name
+ set_reg_val_dword_1 root (inspect.i_windows_current_control_set
+ :: key_path) name
) in
reg_restore ("HKLM\\SYSTEM\\CurrentControlSet" :: key_path) name
value
@@ -402,18 +394,16 @@ if errorlevel 3010 exit /b 0
(* Update the SYSTEM hive. When this function is called the hive has
* already been opened as a hivex handle inside guestfs.
*)
- let current_cs = get_current_cs root in
- debug "current ControlSet is %s" current_cs;
+ disable_xenpv_win_drivers root;
+ disable_prl_drivers root;
+ disable_autoreboot root;
+ Windows_virtio.install_drivers g inspect root rcaps
- disable_xenpv_win_drivers root current_cs;
- disable_prl_drivers root current_cs;
- disable_autoreboot root current_cs;
- Windows_virtio.install_drivers g inspect systemroot
- root current_cs rcaps
-
- and disable_xenpv_win_drivers root current_cs =
+ and disable_xenpv_win_drivers root =
(* Disable xenpv-win service (RHBZ#809273). *)
- let services = Registry.get_node g root [current_cs; "Services"] in
+ let services =
+ Registry.get_node g root
+ [inspect.i_windows_current_control_set; "Services"] in
match services with
| None -> ()
@@ -422,9 +412,11 @@ if errorlevel 3010 exit /b 0
if node <> 0L then
g#hivex_node_set_value node "Start" 4_L (le32_of_int 4_L)
- and disable_prl_drivers root current_cs =
+ and disable_prl_drivers root =
(* Prevent Parallels drivers from loading at boot. *)
- let services = Registry.get_node g root [current_cs; "Services"] in
+ let services =
+ Registry.get_node g root
+ [inspect.i_windows_current_control_set; "Services"] in
let prl_svcs = [ "prl_boot"; "prl_dd"; "prl_eth5";
"prl_fs"; "prl_memdev";
"prl_mouf"; "prl_pv32"; "prl_pv64";
"prl_scsi";
"prl_sound"; "prl_strg"; "prl_tg";
"prl_time";
@@ -447,7 +439,8 @@ if errorlevel 3010 exit /b 0
* HKLM,
System\CurrentControlSet\Control\Class\{4d36e967-e325-11ce-bfc1-08002be10318},
LowerFilters, 0x00018002, prl_strg
*)
let strg_cls = Registry.get_node g root
- [current_cs; "Control"; "Class";
+ [inspect.i_windows_current_control_set;
+ "Control"; "Class";
"{4d36e967-e325-11ce-bfc1-08002be10318}"] in
match strg_cls with
| None -> ()
@@ -467,12 +460,13 @@ if errorlevel 3010 exit /b 0
g#hivex_node_set_value strg_cls lfkey 7_L data
)
- and disable_autoreboot root current_cs =
+ and disable_autoreboot root =
(* If the guest reboots after a crash, it's hard to see the original
* error (eg. the infamous 0x0000007B). Turn off autoreboot.
*)
let crash_control =
- Registry.get_node g root [current_cs; "Control";
"CrashControl"] in
+ Registry.get_node g root [inspect.i_windows_current_control_set;
+ "Control"; "CrashControl"] in
match crash_control with
| None -> ()
| Some crash_control ->
diff --git a/v2v/inspect_source.ml b/v2v/inspect_source.ml
index 3936e72..3b16c42 100644
--- a/v2v/inspect_source.ml
+++ b/v2v/inspect_source.ml
@@ -32,6 +32,8 @@ let rec inspect_source root_choice g =
reject_if_not_installed_image g root;
+ let typ = g#inspect_get_type root in
+
(* Mount up the filesystems. *)
let mps = g#inspect_get_mountpoints root in
let cmp (a,_) (b,_) = compare (String.length a) (String.length b) in
@@ -65,9 +67,20 @@ let rec inspect_source root_choice g =
StringMap.add name (app :: vs) map
) StringMap.empty apps in
+ (* If the guest is Windows, get some Windows-specific inspection
+ * data, else (for simplicity when accessing) use empty strings.
+ *)
+ let systemroot, current_cs =
+ match typ with
+ | "windows" ->
+ g#inspect_get_windows_systemroot root,
+ g#inspect_get_windows_current_control_set root
+ | _ ->
+ "", "" in
+
let inspect = {
i_root = root;
- i_type = g#inspect_get_type root;
+ i_type = typ;
i_distro = g#inspect_get_distro root;
i_arch = g#inspect_get_arch root;
i_major_version = g#inspect_get_major_version root;
@@ -80,6 +93,8 @@ let rec inspect_source root_choice g =
i_apps = apps;
i_apps_map = apps_map;
i_firmware = get_firmware_bootable_device g;
+ i_windows_systemroot = systemroot;
+ i_windows_current_control_set = current_cs;
} in
debug "%s" (string_of_inspect inspect);
diff --git a/v2v/types.ml b/v2v/types.ml
index afeb178..7fd6327 100644
--- a/v2v/types.ml
+++ b/v2v/types.ml
@@ -324,6 +324,8 @@ type inspect = {
i_apps : Guestfs.application2 list;
i_apps_map : Guestfs.application2 list StringMap.t;
i_firmware : i_firmware;
+ i_windows_systemroot : string;
+ i_windows_current_control_set : string;
}
let string_of_inspect inspect =
@@ -339,6 +341,8 @@ i_package_management = %s
i_product_name = %s
i_product_variant = %s
i_firmware = %s
+i_windows_systemroot = %s
+i_windows_current_control_set = %s
" inspect.i_root
inspect.i_type
inspect.i_distro
@@ -352,6 +356,8 @@ i_firmware = %s
(match inspect.i_firmware with
| I_BIOS -> "BIOS"
| I_UEFI devices -> sprintf "UEFI [%s]" (String.concat ", "
devices))
+ inspect.i_windows_systemroot
+ inspect.i_windows_current_control_set
type mpstat = {
mp_dev : string;
diff --git a/v2v/types.mli b/v2v/types.mli
index 96ab36a..df50b1b 100644
--- a/v2v/types.mli
+++ b/v2v/types.mli
@@ -230,6 +230,8 @@ type inspect = {
i_firmware : i_firmware;
(** The list of EFI system partitions for the guest with UEFI,
otherwise the BIOS identifier. *)
+ i_windows_systemroot : string;
+ i_windows_current_control_set : string;
}
(** Inspection information. *)
diff --git a/v2v/v2v_unit_tests.ml b/v2v/v2v_unit_tests.ml
index 1133d92..af86afa 100644
--- a/v2v/v2v_unit_tests.ml
+++ b/v2v/v2v_unit_tests.ml
@@ -30,7 +30,8 @@ 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_firmware = I_BIOS
+ i_apps = []; i_apps_map = StringMap.empty; i_firmware = I_BIOS;
+ i_windows_systemroot = ""; i_windows_current_control_set = "";
}
let test_get_ostype ctx =
diff --git a/v2v/windows_virtio.ml b/v2v/windows_virtio.ml
index a63ab44..2c28524 100644
--- a/v2v/windows_virtio.ml
+++ b/v2v/windows_virtio.ml
@@ -37,9 +37,9 @@ let scsi_class_guid =
"{4D36E97B-E325-11CE-BFC1-08002BE10318}"
let viostor_pciid = "VEN_1AF4&DEV_1001&SUBSYS_00021AF4&REV_00"
let vioscsi_pciid = "VEN_1AF4&DEV_1004&SUBSYS_00081AF4&REV_00"
-let rec install_drivers g inspect systemroot root current_cs rcaps =
+let rec install_drivers g inspect root rcaps =
(* Copy the virtio drivers to the guest. *)
- let driverdir = sprintf "%s/Drivers/VirtIO" systemroot in
+ let driverdir = sprintf "%s/Drivers/VirtIO" inspect.i_windows_systemroot in
g#mkdir_p driverdir;
if not (copy_drivers g inspect driverdir) then (
@@ -98,22 +98,22 @@ let rec install_drivers g inspect systemroot root current_cs rcaps =
(* Block driver needs tweaks to allow booting; the rest is set up by PnP
* manager *)
let source = driverdir // (driver_name ^ ".sys") in
- let target = sprintf "%s/system32/drivers/%s.sys" systemroot
driver_name in
+ let target = sprintf "%s/system32/drivers/%s.sys"
+ inspect.i_windows_systemroot driver_name in
let target = g#case_sensitive_path target in
g#cp source target;
- add_guestor_to_registry g root current_cs driver_name
- viostor_pciid;
+ add_guestor_to_registry g inspect root driver_name viostor_pciid;
Virtio_blk
| Some Virtio_SCSI, _, true ->
(* Block driver needs tweaks to allow booting; the rest is set up by PnP
* manager *)
let source = driverdir // "vioscsi.sys" in
- let target = sprintf "%s/system32/drivers/vioscsi.sys" systemroot in
+ let target = sprintf "%s/system32/drivers/vioscsi.sys"
+ inspect.i_windows_systemroot in
let target = g#case_sensitive_path target in
g#cp source target;
- add_guestor_to_registry g root current_cs "vioscsi"
- vioscsi_pciid;
+ add_guestor_to_registry g inspect root "vioscsi" vioscsi_pciid;
Virtio_SCSI
| Some IDE, _, _ ->
@@ -168,18 +168,18 @@ let rec install_drivers g inspect systemroot root current_cs rcaps
=
(block, net, video)
)
-and add_guestor_to_registry g root current_cs drv_name drv_pciid =
+and add_guestor_to_registry g inspect root drv_name drv_pciid =
let ddb_node = g#hivex_node_get_child root "DriverDatabase" in
let regedits =
if ddb_node = 0L then
- cdb_regedits current_cs drv_name drv_pciid
+ cdb_regedits inspect drv_name drv_pciid
else
- ddb_regedits current_cs drv_name drv_pciid in
+ ddb_regedits inspect drv_name drv_pciid in
let drv_sys_path = sprintf "system32\\drivers\\%s.sys" drv_name in
let common_regedits = [
- [ current_cs; "Services"; drv_name ],
+ [ inspect.i_windows_current_control_set; "Services"; drv_name ],
[ "Type", REG_DWORD 0x1_l;
"Start", REG_DWORD 0x0_l;
"Group", REG_SZ "SCSI miniport";
@@ -189,19 +189,20 @@ and add_guestor_to_registry g root current_cs drv_name drv_pciid =
reg_import g root (regedits @ common_regedits)
-and cdb_regedits current_cs drv_name drv_pciid =
+and cdb_regedits inspect drv_name drv_pciid =
(* See
http://rwmj.wordpress.com/2010/04/30/tip-install-a-device-driver-in-a-win...
* NB: All these edits are in the HKLM\SYSTEM hive. No other
* hive may be modified here.
*)
[
- [ current_cs; "Control"; "CriticalDeviceDatabase";
+ [ inspect.i_windows_current_control_set;
+ "Control"; "CriticalDeviceDatabase";
"PCI#" ^ drv_pciid ],
[ "Service", REG_SZ drv_name;
"ClassGUID", REG_SZ scsi_class_guid ];
]
-and ddb_regedits current_cs drv_name drv_pciid =
+and ddb_regedits inspect drv_name drv_pciid =
(* Windows >= 8 doesn't use the CriticalDeviceDatabase. Instead
* one must add keys into the DriverDatabase.
*)
diff --git a/v2v/windows_virtio.mli b/v2v/windows_virtio.mli
index 1d25260..4ceeebe 100644
--- a/v2v/windows_virtio.mli
+++ b/v2v/windows_virtio.mli
@@ -19,17 +19,16 @@
(** Functions for installing Windows virtio drivers. *)
val install_drivers
- : Guestfs.guestfs -> Types.inspect -> string -> Registry.node -> string
->
+ : Guestfs.guestfs -> Types.inspect -> Registry.node ->
Types.requested_guestcaps ->
Types.guestcaps_block_type * Types.guestcaps_net_type * Types.guestcaps_video_type
-(** [install_drivers g inspect systemroot root current_cs rcaps]
+(** [install_drivers g inspect root rcaps]
installs virtio drivers from the driver directory or driver
ISO into the guest driver directory and updates the registry
so that the [viostor.sys] driver gets loaded by Windows at boot.
[root] is the root node of the system hive (which is open for writes
- when this function is called). [current_cs] is the name of the
- [CurrentControlSet] (eg. ["ControlSet001"]).
+ when this function is called).
[rcaps] is the set of guest "capabilities" requested by the caller. This
may include the type of the block driver, network driver, and video driver.
--
2.10.2