This content is 15 years old. I don't routinely update old blog posts as they are only intended to represent a view at a particular point in time. Please be warned that the information here may be out of date.
Are you excited about Native VHD Boot for Windows 7 (Enterprise or Ultimate) and Windows Server 2008 R2 but wish you could use an external USB drive to store the .VHD files? Well unfortunately it isn’t officially supported but, if that doesn’t worry you too much, you might find this post interesting…
Background
In order to get Native VHD Boot working from an external USB Disk, there are a few things we need to understand about device drivers and their load orders.
Setup and the PnP manager configure devices starting with the system root device, followed by the child devices of the root device, the children of those devices, and so on. To influence the driver load order outside of this sequence, we need to change the .INF files for the USB related drivers, specifying relevant values in the service-install-section, specifically the StartType and the LoadOrderGroup entries.
A PnP driver should have a start type of SERVICE_DEMAND_START (0x3), specifying that the PnP manager can load the driver whenever it finds a device that the driver services. USB drivers normally behave in this manner and have this start type.
However, if a driver is required to boot the machine (such as when, oh I don’t know, maybe attempting something like native VHD boot from an external USB drive), the drivers for the device should have a start type of SERVICE_BOOT_START (0x0).
On system boot, the operating system loader loads drivers of type SERVICE_BOOT_START before it transfers control to the kernel. These drivers are in memory when the kernel gets control. Boot-start drivers can use the .INF LoadOrderGroup entries to order their loading. You can see the List order at HKLM/SYSTEM/CurrentControlSet/Control/ServiceGroupOrder.
For Native VHD Boot from an external USB drive to work, we need to modify the behaviour of six device drivers:
- usbccgp – Microsoft USB Generic Parent Driver
- usbehci – Microsoft USB 2.0 Enhanced Host Controller Miniport Driver
- usbohci – Microsoft USB Open Host Controller Miniport Driver
- usbuhci – Microsoft Universal Host Controller Miniport Driver
- usbhub – Microsoft USB Standard Hub Driver
- usbstor – USB Mass Storage Driver
The USB drivers have a LoadOrderGroup entry of Base, which is considerably down the list, and critically much later than we need to use them as a boot device. We therefore need to modify the LoadOrderGroup to something more appropriate that will be processed earlier in the boot cycle. There is some debate about the best entries to use for this purpose, and whilst it seems the below is technically most appropriate, I began this journey with all entries set to use Boot Bus Extender and have continued to use that without issue. However, you may want to try the settings below as an alternative:
- usbccgp – Boot Bus Extender
- usbehci – Boot Bus Extender
- usbohci – Boot Bus Extender
- usbuhci – Boot Bus Extender
- usbhub – System Bus Extender
- usbstor – SCSI Miniport
So, to enable Native VHD Boot from an external USB drive, we need to modify the StartType and LoadOrderGroup of each of those drivers, and critically, ensure that they don’t get reset to their defaults.
Requirements
You’ll need a computer running Windows 7 or Windows Server 2008 R2 and a suitable external USB drive to store your .VHD files and to create the necessary bootloader. You’ll also need the following tools:
Process
Disclaimer: This is close to a step-by-step guide, but it assumes a certain level of technical knowledge and understanding. Hopefully I’ve made it as easy to follow and as painless as possible but tread carefully. To quote Scott Hanselman:
“This is some advanced stuff and you may lose a finger. No warranty express or implied.”
To begin with, we need to create our .VHD file. Mike Kolitz has created a fantastic script called WIM2VHD that takes much of the hard work out of this task for us. The example below uses a Windows Server 2008 R2 WIM file as source, and creates a 49GB Enterprise edition dynamically expanding .VHD file from it.
From an elevated command prompt, run the following command:
CSCRIPT WIM2VHD.WSF /WIM:”M:\Sources\SERVER\install.wim” /SKU:SERVERENTERPRISE /VHD:”M:\BootVHDs\W2K8R2ENT.vhd” /SIZE:50176 /DISKTYPE:DYNAMIC
Now that we have created the .VHD file, we need to make some changes to the operating system contained within it. From the same elevated command prompt used for the previous command, we’ll use diskpart.exe
to mount the .VHD. Note the use of LIST VOLUME
so that we can see the correct volume number, select it, and assign a drive letter to it – you’ll need to change the number in SELECT VOLUME
to match your environment:
DISKPART
SELECT VDISK FILE=”M:\BootVHDs\W2K8R2ENT.vhd”
ATTACH VDISK
LIST VOLUME
SELECT VOLUME 8
ASSIGN LETTER=R
EXIT
At this stage, I use the offline servicing tool, dism.exe
, to change the default language, keyboard layout and timezone to something more appropriate for the United Kingdom. You can obviously make other changes too if necessary:
DISM /IMAGE:R: /Set-SysLocale:en-GB
DISM /IMAGE:R: /Set-UserLocale:en-GB
DISM /IMAGE:R: /Set-InputLocale:409:00000409
DISM /IMAGE:R: /Set-TimeZone:”GMT Standard Time”
Next, we need to make changes to the registry for each of the six USB device drivers. We’ll use the built in reg.exe
command to do this. By default, when an operating system is launched from a dynamically expanding .VHD file using native VHD boot, it expands to its maximum size, reverting to its dynamic size when it is shutdown. I also modify the VirtualDiskExpandOnMount registry value to prevent this:
REG LOAD HKLM\TEMP R:\WINDOWS\SYSTEM32\CONFIG\SYSTEM
REG ADD HKLM\TEMP\ControlSet001\services\usbccgp /v Group /t REG_SZ /d “Boot Bus Extender” /f
REG ADD HKLM\TEMP\ControlSet001\services\usbccgp /v Start /t REG_DWORD /d 0 /f
REG ADD HKLM\TEMP\ControlSet001\services\usbehci /v Group /t REG_SZ /d “Boot Bus Extender” /f
REG ADD HKLM\TEMP\ControlSet001\services\usbehci /v Start /t REG_DWORD /d 0 /f
REG ADD HKLM\TEMP\ControlSet001\services\usbhub /v Group /t REG_SZ /d “Boot Bus Extender” /f
REG ADD HKLM\TEMP\ControlSet001\services\usbhub /v Start /t REG_DWORD /d 0 /f
REG ADD HKLM\TEMP\ControlSet001\services\usbohci /v Group /t REG_SZ /d “Boot Bus Extender” /f
REG ADD HKLM\TEMP\ControlSet001\services\usbohci /v Start /t REG_DWORD /d 0 /f
REG ADD HKLM\TEMP\ControlSet001\services\USBSTOR /v Group /t REG_SZ /d “Boot Bus Extender” /f
REG ADD HKLM\TEMP\ControlSet001\services\USBSTOR /v Start /t REG_DWORD /d 0 /f
REG ADD HKLM\TEMP\ControlSet001\services\usbuhci /v Group /t REG_SZ /d “Boot Bus Extender” /f
REG ADD HKLM\TEMP\ControlSet001\services\usbuhci /v Start /t REG_DWORD /d 0 /f
REG ADD HKLM\TEMP\ControlSet001\services\FsDepends\Parameters /v VirtualDiskExpandOnMount /t REG_DWORD /d 4 /f
REG UNLOAD HKLM\TEMP
The next step is to modify the .INF files so that the operating system does not reset these values to their defaults at any point. As some of the files require SYSTEM permissions to modify them, we use the excellent SysInternals psexec.exe
command to launch a command prompt in the SYSTEM security context.
PSEXEC –i –d –s C:\Windows\System32\cmd.exe
From the resultant command window, we use Horst Schaeffer’s INI File Tool to modify any .INF files that might reset the device driver values to their defaults:
INIFILE R:\Windows\inf\usb.inf [StandardHub.AddService] StartType = 0 ; SERVICE_BOOT_START
INIFILE R:\Windows\inf\usb.inf [StandardHub.AddService] LoadOrderGroup = Boot Bus Extender
INIFILE R:\Windows\inf\usb.inf [CommonClassParent.AddService] StartType = 0 ; SERVICE_BOOT_START
INIFILE R:\Windows\inf\usb.inf [CommonClassParent.AddService] LoadOrderGroup = Boot Bus Extender
INIFILE R:\Windows\inf\usbport.inf [EHCI.AddService] StartType = 0 ; SERVICE_BOOT_START
INIFILE R:\Windows\inf\usbport.inf [EHCI.AddService] LoadOrderGroup = Boot Bus Extender
INIFILE R:\Windows\inf\usbport.inf [OHCI.AddService] StartType = 0 ; SERVICE_BOOT_START
INIFILE R:\Windows\inf\usbport.inf [OHCI.AddService] LoadOrderGroup = Boot Bus Extender
INIFILE R:\Windows\inf\usbport.inf [UHCI.AddService] StartType = 0 ; SERVICE_BOOT_START
INIFILE R:\Windows\inf\usbport.inf [UHCI.AddService] LoadOrderGroup = Boot Bus Extender
INIFILE R:\Windows\inf\usbport.inf [ROOTHUB.AddService] StartType = 0 ; SERVICE_BOOT_START
INIFILE R:\Windows\inf\usbport.inf [ROOTHUB.AddService] LoadOrderGroup = Boot Bus Extender
INIFILE R:\Windows\inf\usbstor.inf [USBSTOR.AddService] StartType = 0 ; SERVICE_BOOT_START
INIFILE R:\Windows\inf\usbstor.inf [USBSTOR.AddService] LoadOrderGroup = Boot Bus Extender
INIFILE R:\Windows\inf\brmfcsto.inf [USBSTOR.AddService] StartType = 0 ; SERVICE_BOOT_START
INIFILE R:\Windows\inf\brmfcsto.inf [USBSTOR.AddService] LoadOrderGroup = Boot Bus Extender
Now we delete the precompiled INF files, and copy our modified INF files to appropriate locations. Note that the file locations differ for x64 and x86 builds.
For x64 builds only:
DEL /Q R:\Windows\inf\usb.pnf
DEL /Q R:\Windows\System32\DriverStore\FileRepository\usb.inf_amd64_neutral_e2b28ecac19a29af\usb.pnf
DEL /Q R:\Windows\winsxs\amd64_usb.inf_31bf3856ad364e35_6.1.7600.16385_none_26ed589d28235a16\usb.pnf
DEL /Q R:\Windows\inf\usbport.pnf
DEL /Q R:\Windows\System32\DriverStore\FileRepository\usbport.inf_amd64_neutral_5a41ca742f7973cc\usbport.pnf
DEL /Q R:\Windows\winsxs\amd64_usbport.inf_31bf3856ad364e35_6.1.7600.16385_none_19b7511a1d3ea7fd\usbport.pnf
DEL /Q R:\Windows\inf\usbstor.pnf
DEL /Q R:\Windows\System32\DriverStore\FileRepository\usbstor.inf_amd64_neutral_c301b770e0bfb179\usbstor.pnf
DEL /Q R:\Windows\winsxs\amd64_usbstor.inf_31bf3856ad364e35_6.1.7600.16385_none_a47b405db18421ea\usbstor.pnf
DEL /Q R:\Windows\inf\brmfcsto.pnf
DEL /Q R:\Windows\System32\DriverStore\FileRepository\brmfcsto.inf_amd64_neutral_2d7208355536945e\brmfcsto.pnf
DEL /Q R:\Windows\winsxs\amd64_brmfcsto.inf_31bf3856ad364e35_6.1.7600.16385_none_7fe64f7a6167bcf6\brmfcsto.pnf
COPY /Y R:\Windows\inf\usb.inf R:\Windows\System32\DriverStore\FileRepository\usb.inf_amd64_neutral_e2b28ecac19a29af
COPY /Y R:\Windows\inf\usb.inf R:\Windows\winsxs\amd64_usb.inf_31bf3856ad364e35_6.1.7600.16385_none_26ed589d28235a16
COPY /Y R:\Windows\inf\usbport.inf R:\Windows\System32\DriverStore\FileRepository\usbport.inf_amd64_neutral_5a41ca742f7973cc
COPY /Y R:\Windows\inf\usbport.inf R:\Windows\winsxs\amd64_usbport.inf_31bf3856ad364e35_6.1.7600.16385_none_19b7511a1d3ea7fd
COPY /Y R:\Windows\inf\usbstor.inf R:\Windows\System32\DriverStore\FileRepository\usbstor.inf_amd64_neutral_c301b770e0bfb179
COPY /Y R:\Windows\inf\usbstor.inf R:\Windows\winsxs\amd64_usbstor.inf_31bf3856ad364e35_6.1.7600.16385_none_a47b405db18421ea
COPY /Y R:\Windows\inf\brmfcsto.inf R:\Windows\System32\DriverStore\FileRepository\brmfcsto.inf_amd64_neutral_2d7208355536945e
COPY /Y R:\Windows\inf\brmfcsto.inf R:\Windows\winsxs\amd64_brmfcsto.inf_31bf3856ad364e35_6.1.7600.16385_none_7fe64f7a6167bcf6
EXIT
For x86 builds only:
DEL /Q R:\Windows\inf\usb.pnf
DEL /Q R:\Windows\System32\DriverStore\FileRepository\usb.inf_x86_neutral_e24d8d3fec6e4567\usb.pnf
DEL /Q R:\Windows\winsxs\x86_usb.inf_31bf3856ad364e35_6.1.7600.16385_none_cacebd196fc5e8e0\usb.pnf
DEL /Q R:\Windows\inf\usbport.pnf
DEL /Q R:\Windows\System32\DriverStore\FileRepository\usbport.inf_x86_neutral_ba59fa32fc6a596d\usbport.pnf
DEL /Q R:\Windows\winsxs\x86_usbport.inf_31bf3856ad364e35_6.1.7600.16385_none_bd98b59664e136c7\usbport.pnf
DEL /Q R:\Windows\inf\usbstor.pnf
DEL /Q R:\Windows\System32\DriverStore\FileRepository\usbstor.inf_x86_neutral_83027f5d5b2468d3\usbstor.pnf
DEL /Q R:\Windows\winsxs\x86_usbstor.inf_31bf3856ad364e35_6.1.7600.16385_none_485ca4d9f926b0b4\usbstor.pnf
DEL /Q R:\Windows\inf\brmfcsto.pnf
DEL /Q R:\Windows\System32\DriverStore\FileRepository\brmfcsto.inf_x86_neutral_39ae61431a44cded\brmfcsto.pnf
DEL /Q R:\Windows\winsxs\x86_brmfcsto.inf_31bf3856ad364e35_6.1.7600.16385_none_23c7b3f6a90a4bc0\brmfcsto.pnf
COPY /Y R:\Windows\inf\usb.inf R:\Windows\System32\DriverStore\FileRepository\usb.inf_x86_neutral_e24d8d3fec6e4567
COPY /Y R:\Windows\inf\usb.inf R:\Windows\winsxs\x86_usb.inf_31bf3856ad364e35_6.1.7600.16385_none_cacebd196fc5e8e0
COPY /Y R:\Windows\inf\usbport.inf R:\Windows\System32\DriverStore\FileRepository\usbport.inf_x86_neutral_ba59fa32fc6a596d
COPY /Y R:\Windows\inf\usbport.inf R:\Windows\winsxs\x86_usbport.inf_31bf3856ad364e35_6.1.7600.16385_none_bd98b59664e136c7
COPY /Y R:\Windows\inf\usbstor.inf R:\Windows\System32\DriverStore\FileRepository\usbstor.inf_x86_neutral_83027f5d5b2468d3
COPY /Y R:\Windows\inf\usbstor.inf R:\Windows\winsxs\x86_usbstor.inf_31bf3856ad364e35_6.1.7600.16385_none_485ca4d9f926b0b4
COPY /Y R:\Windows\inf\brmfcsto.inf R:\Windows\System32\DriverStore\FileRepository\brmfcsto.inf_x86_neutral_39ae61431a44cded
COPY /Y R:\Windows\inf\brmfcsto.inf R:\Windows\winsxs\x86_brmfcsto.inf_31bf3856ad364e35_6.1.7600.16385_none_23c7b3f6a90a4bc0
EXIT
The next part is optional. It creates a differencing .VHD from the original file. The allows you to leave the base .VHD file intact and make all subsequent changes to the differencing .VHD instead. It’s a great way of building a base operating system image and then branching it for development work or testing. Once again, make sure you note the correct volume number when doing this. So, from the original elevated command prompt:
DISKPART
SELECT VDISK FILE=”M:\BootVHDs\W2K8R2ENT.vhd”
DETACH VDISK
CREATE VDISK FILE=”M:\BootVHDs\W2K8R2ENT_DIFF.vhd” PARENT=”M:\BootVHDs\W2K8R2ENT.vhd”
SELECT VDISK FILE=”M:\BootVHDs\W2K8R2ENT_DIFF.vhd”
ATTACH VDISK
LIST VOLUME
SELECT VOLUME 8
ASSIGN LETTER=R
EXIT
Now all that is left to do is to create a bootloader on the external USB disk and create an entry for our Native VHD Boot. When you BCDEDIT /COPY {default} below, note the resultant GUID that you are given and use that instead of the {5aaa2c7a-a627-11de-83c7-001372bf1815} listed in the example. So, continuing from the same command window:
BOOTSECT /NT60 M: /FORCE /MBR
BCDBOOT R:\WINDOWS /S M:
BCDEDIT /STORE M:\BOOT\BCD /COPY {default} /d “Windows Server 2008 R2 Enterprise”
BCDEDIT /STORE M:\BOOT\BCD /SET {5aaa2c7a-a627-11de-83c7-001372bf1815} DEVICE VHD=[LOCATE]\BootVHDs\W2K8R2ENT_DIFF.vhd
BCDEDIT /STORE M:\BOOT\BCD /SET {5aaa2c7a-a627-11de-83c7-001372bf1815} OSDEVICE VHD=[LOCATE]\BootVHDs\W2K8R2ENT_DIFF.vhd
BCDEDIT /STORE M:\BOOT\BCD /SET {5aaa2c7a-a627-11de-83c7-001372bf1815} DETECTHAL ON
And that’s it. Reboot your computer, select your external USB disk as your boot device, and you should see the entry you created above. Windows will start, perform the final stages of setup (rebooting a couple of times in the process) and you will be done.
I have personally used this method to store a large number of .VHD files (fixed, dynamic and differencing) and to use them to boot Windows 7 Enterprise and Ultimate in both x64 and x86 platform versions, and the various Windows Server 2008 R2 editions, and found it to be an extremely flexible option.
I’ve even had some success swapping the external USB disk between machines. It doesn’t always work (and to be honest, I haven’t had the time to look any deeper into why) but I’ve used the same native VHD boot instance on a Fujitsu Siemens Celsius H240, Lifebook T4210 and Lifebook S7220, swapping it backwards and forwards between machines and letting Windows manage the driver changes each time without issue.
I’ve also had success with native VHD boot using .VHD files created from Windows Backup and have recently started looking at using the files created from the SysInternals Disk2vhd tool too. Pop back sometime soon and you may even find another guest post documenting those particular adventures…
[MW: Sounds great Garry! Looking forward to it]