Native VHD boot Windows 7 or Server 2008 R2 from an external USB drive

Guest Post
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]

16 thoughts on “Native VHD boot Windows 7 or Server 2008 R2 from an external USB drive


  1. I dont really know how to thank you enough. Late september 2010 , my internal HDD died due to heating issues (I’d used to keep my laptop working for HOURS downloading MSDN software off my subscription). Anyway , with no suitable explanation to be alloted funds for a new HDD (by my parents) , I was left with no option but to go over to Linux (using Ubuntu ,Kubuntu .. and eventually Mint).

    I was reduced to (and still am , until JUST NOW) using MINT LINUX loaded and booted from a 4GB Pendrive , running on my ancient hp dv2002tu notebook with 1.86Ghz and 32-bit Intel Centrino SoloCore on 512MB Ram..

    Then I stumbled upon WAIK and me and my buddy used this blog to native boot win7 from a 80GB USB HDD.

    I feel very happy to return to beloved Windows. :D Thanks a LOT , Mr.Wilson.


  2. Umm.. yea , regarding that , umm.. I’m in trouble.

    The bootloader modification was for a system already running on Windows OS. I’m running on Mint Linux Via a 4-GB pendrive , used to boot and run my entire system. I dont have an internal hardisk.

    I don’t know how to manipulate bootloader for linux. My external USB hdd has succesfully been loaded with ‘.vhd’ file.

    A little help here , sir.


  3. GREAT INFO!
    A few corrections/clarifications:

    1) The initial CSCRIPT command… the path to install.wim is typically just “\sources\install.wim” (no SERVER)

    2) PSEXEC… run from the folder you extracted pstools.zip to

    3) INITOOL… run from the folder you extracted inifile.zip to and be sure to be within the comand window that was opened by PSEXEC in the previous step

    4) BOOTSECT… part of the WAIK you downloaded
    a) run at the cmd from c:\program files\windows aik\tools\petools\amd64 (if the OS you are currently running is 64-bit) or \x86 (if the OS you are currently running is 32-bit)
    b) this will force your R: to dismount so you need to remount it before the BCDBOOT command will work so perform the following:
    Diskpart
    Select Vdisk file “m:\bootVHDs\w2k8r2ent_diff.vhd”
    Attach Vdisk
    List Volume
    Select Volume 8
    Assign Letter=R
    Exit
    c) Continue with BCDBOOT command
    >> HINT: Next time run the BOOTSECT Command prior to attaching the VDISK and giving it a letter then you won’t need to repeat the above steps.


  4. Windows Update will cause problems, especially when installing a service pack. All the USB inf files are replaced with new ones and placed in different directories. The registry also gets refreshed, so you will need to make the changes specified above multiple times. If you get the blue screen or a message saying the disk is bad, make sure all the inf files are updated properly along with the registry.


  5. Thanks Mark for posting the detail instructions. Be able to boot windows from USB drive is so convenient! Unfortunately it does not seem to work on most hardware. I have success making it work on a couple Wyse Thinclient platforms. I am not able to make it work on any HP or DELL desktops yet. So far I have tried Dell Optiplex 740, 990 desktop, HP 6730b and 6735b laptops. All of them failed (reboot) as soon as windows start booting. It is not BIOS issue because it passes control to the boot manager on the USB drive no problem. Windows would start booting and read all the boot drivers (via BIOS) fine. As soon as windows tried to read boot (USB) disk using its own driver it choked. From kernel debugger I can see that all USB related drivers were loaded at boot time (usbhub.sys, usbuhci.sys, usbport.sys, usbehci.sys, usbccgp.sys, usbd.sys, usbohci.sys, usbstor.sys), then windows bug checked on INACCESSIBLE_BOOT_DEVICE (7b), and the ARC that it failed to read is “multi(0)disk(0)vdisk(0)partition(1)”. I have triple-checked that all the USB drivers remained at boot start in the VHD installation. “detecthal” is on. I also tried both fixed and dynamic VHD file, as well as 2.0 USB stick and 3.0 USB HDD with no difference. Anybody has success on Dell or HP boxes? I do not think I have missed any steps because I was able to make it work on some hardware. Any advice is appreciated. Thanks in advance!


  6. Hi there, I know this post is old, but how can i use Win2008R2SE on an USB 3.0 or it is even possible to run on 3.0 ?
    Thanks for your advice :)

    PS: Great work have you done here!

Leave a Reply