This tutorial is a translation of a german blog post which I wrote about a year ago and is available here
Every linux user knows that for some Windows programs or services do not exist equivalent linux programs. This is especially true if the internal functionality of such programs should be kept secret (for example DRM based software), so you need to use Windows or Wine. One way to keep your normal desktop enviroment while doing this, is to use a virtual machine like Virtualbox or KVM. This works well, as long as you don't want to play games or use any other software which makes heavy usage of 3D. In this case you need to use a real Windows installation and you most likely will end up with two Windows installations which needlessly consume more space than they should. In this article I will show how to boot an existing Windows 7 Installation in Virtualbox/KVM/VMware, so that you will only need one Installation, which can be booted inside a VM or on your real system.
From a technical point of view this "Dualboot" method works flawless though it is not compatible with Microsofts license restrictions. Microsoft wants you to buy a second license if you want to use the system inside a VM and on a real machine disregarding the fact that the installation can not be used twice at the same time. Even if you would buy a second license of Windows 7 the system would still not be able to make use of both of them since you can only enter a single serial number which is used during the activation. This may lead to the problem that Windows wants to be reactivated after every switch between the VM and a real boot as the activation system will detect the change of the hardware. Depending on the used VM software it is possible to tweak some settings like HDD serial numbers and similar stuff to prevent this, but this is still kind of a hack.
This tutorial should be considered as proof-of-concept because of the license problems mentioned above
Before we are going to start, I would like to explain why it makes sense to follow this more complex tutorial and not one of the easier ones you can find in the internet.
Most other tutorials create a new Master Boot Record (MBR) including a new partition table which basically contains the same partition layout as your real hard drive. The problem is that not all information is copied, most noticeable the Disk Signature is left out. This signature is written by Windows during the installation and is used by the kernel to identify the device containing the Windows installation you want to boot. There is also a similar system on Linux which is based on UUIDs and allows you to define the partitions in /etc/fstab without the problem that your drive letters (sda/sdb/..) may change on each boot. If you don't pay attention to this signature Windows can not be booted and you need to repair the system using the installation CD and it is necessary to repeat this step every time you want to switch between the VM and a real boot. In this tutorial we are going to create a MBR which contains exactly the same signature so that it is not necessary to alter anything in your current Windows installation.
If you installed Windows on a separate hard disk instead of a separate partition it is not necessary to pay attention to this signature and you can skip some of the steps inside this tutorial (as long as the Windows 7 boot partition is also on this hard disk).
Another advantage of the described method is that it is almost independent from the used virtualization software and we do not rely on any special features so that you can switch between different VM software at any time. We just need some linux commands and a Windows DVD (which we could avoid, but this would require some more effort) and create a virtual hard disk pointing to the real Windows partitions. It contains everything we need to boot Windows and you just need to select it inside your VM software. Some other tutorials use a special function of Virtualbox which needs full read access to your hard drive (not only the windows partitions!) to create the necessary virtual hard drive. Since this step is necessary every time you want to start Windows in the VM, it is a significant security risk, as all programs running with this user account could modify all files on the hard drive. This tutorial will just require read and write access on the Windows partitions when using the VM.
If you still want to follow this tutorial although it is not compatible with Microsofts license restrictions, I recommend you to create a backup of your windows partition. We are working with raw disk access and a small mistake may damage the containing NTFS filesystem and therefore make it unreadable. If you have any questions while following the described steps feel free to write a comment so that we may help you before you accidentally do something wrong. Your question may also help other people who try to follow this guide.
If you are using Windows on a separate hard disk you can skip the first steps and directly continue with Step 5. If this is not the case for you and you just installed it to a separate partition, it is necessary to do some extra work to convince Windows that there is no difference between our virtual disk and the real hard disk. Before we can create this virtual hard drive we need to collect some information which is used in the following steps. First of all, we need the partition layout of the hard drive containing Windows. In my case the Windows partition is located on /dev/sda and we can use fdisk to get then necessary information:
sudo fdisk -l /dev/sda Disk /dev/sda: 1000.2 GB, 1000204886016 bytes 255 heads, 63 sectors/track, 121601 cylinders, total 1953525168 sectors Units = sectors of 1 * 512 = 512 bytes Sector size (logical/physical): 512 bytes / 512 bytes I/O size (minimum/optimal): 512 bytes / 512 bytes Disk identifier: 0xdee1dee1 Device Boot Start End Blocks Id System /dev/sda1 * 2048 206847 102400 7 HPFS/NTFS/exFAT /dev/sda2 206848 204802047 102297600 7 HPFS/NTFS/exFAT /dev/sda3 204804094 1953523711 874359809 5 Extended /dev/sda5 1937899520 1953523711 7812096 82 Linux swap / Solaris /dev/sda6 204804096 1937899519 866547712 83 Linux Partition table entries are not in disk order
As you can see in the output of fdisk, there are two partitions used by Windows 7 /dev/sda1 and /dev/sda2. The first one is only about 102400 Blocks big and contains the bootloader and the Recovery System. We need both partitions to boot Windows inside a VM. In my case the partitions are located at the beginning of the drive which makes the next step a bit easier. Before we create the virtual hard drive which points to these two partitions, you should make sure that you have a Windows 7 DVD either as real disk or as iso file since it is required in the next step.
2. Creating a virtual hard drive pointing to real partitions
In theory we just need to forward these two partitions to a VM and we should be able to boot Windows, but it is a bit more complicated. First of all our virtual hard drive would not have a Master Boot Record (which is required to boot) since the MBR is located in the first Sector of the hard disk. Moreover Windows has saved the location (i.e. start address) where the windows partition can be found on the hard drive. To get around these problems we need to create a virtual hard drive which points to the two windows partitions and which additionally contains a valid MBR + partition table.
As we saw in Step 1 the first 2048 Sectors are not used by any system (0-2047) and the first partition (in my case the windows partition) starts at sector 2048. We need to fill this hole, but we can not take the real 2048 bytes as they contain the Grub bootloader. Instead we simply make a small image file:
dd if=/dev/zero of=boot.mbr count=2048
count is the number of sectors we need to fill up and depends on the output of fdisk during the first step. It may also necessary to adjust the size of a sector which can be done by specifying bs=… as paramter. In my case the size of a sectors is 512 (as written in the output of fdisk) and this is also the standard sector size for dd and I can therefore skip this parameter. If you need to fill up several GBs, it is recommended to use a sparse file instead of a normal files. A sparse file is not really filled up with zeros but only saves the amount of zeros it contains and therefore saves a lot of disk space. You could create one with the following command:
dd if=/dev/zero of=boot.mbr count=0 seek=2048
Sparse files are much slower, if a program tries to write to arbitrary positions in the file, than normal files but as we just use the first 512 Bytes of this file it won't be a problem.
Now we need to create a virtual hard disk which contains our image as well as the 2 windows partitions. The easiest way to accomplish this is to use a software RAID. We can use the linear raid mode (NRAID) offered by the linux kernel to simply to put them together. Before we can do this, we need to install the mdadm utility which allows us to configure such RAIDs and we also need to load the required kernel module:
sudo apt-get install mdadm sudo modprobe linear
The RAID module can only use devices as source disks but not images, so we first need to create loop back device from our image file before we are finally able to put them together:
sudo losetup /dev/loop0 boot.mbr sudo mdadm --build /dev/md0 --level=linear --raid-devices=3 /dev/loop0 /dev/sda1 /dev/sda2
The virtual disk is created and we now need to fill up the partition table with useful values as it contains only 0s at the moment.
We can use fdisk again to accomplish this:
sudo fdisk /dev/md0
If your sector size does not match 512 byte, you need to need to tell the correct size to fdisk by using the parameter -b. This time we are in the interactive mode of fdisk and we need to recreate the partition table from above but we can skip everything beside the Windows partitions.
You can create new partitions by pressing n, the key a can be used to mark them as bootable, the filesystem type can be changed with t (for Windows/NTFS the type is 7), p allows you to take a look at the current layout and w finally write everything to the disk and exits the program.
The easiest way to recreate the partition table is to create the partitions in the same order as shown in Step 1. Be careful that every number is correct and that there is no difference between the recreated and the original partition table. This is the most critical step in the tutorial and you can easily destroy your NTFS filesystem by doing a mistake here. In my case the recreated partition table is:
Device Boot Start End Blocks Id System boot.mbr1 * 2048 206847 102400 7 HPFS/NTFS/exFAT boot.mbr2 206848 204802047 102297600 7 HPFS/NTFS/exFAT
One way to check whether the partition table is most probably correct is to mount the partitions /dev/md0p1 or /dev/md0p2 in Linux as read only. If you can mount them and browse through files without problems you most probably did everything right.
One thing which is very important is that Linux now recognizes your Windows partitions on 2 different drives (for example /dev/sda1 and /dev/md0p1) and won't prevent you from mounting the same partition twice. This will most likely destroy the file systems located on them, so you should always double check that you do not accidentally get into this situation. As we are going to use the virtual hard drive in the VM as next step, you should unmount it again.
3. Using the virtual hard drive inside a VM
As the next step depends on the used VM software they are split into sections and I will explain the necessary steps for Virtualbox, KVM and VMWare Player.
We need to create pseudo VMDK file which simply points to our virtual hard drive so that we can select it as hard disk file in Virtualbox:
sudo VBoxManage internalcommands createrawvmdk -filename windows.vmdk -rawdisk /dev/md0
KVM does not need any extra file. You just need to select /dev/md0 as hard disk with the format raw.
3.3. VMWare Player
As first step wee need to create a new VM by using the wizard and we also need to create a dummy hard disk (which we do not need) during this step as the wizard does not allow us to directly select a physical disk. You can delete the dummy hard disk later on. After creating the VM, edit it again, remove the dummy hard disk and add a new hard disk. Select “Use a physical disk”, enter /dev/md0 als device path and finally select “Use entire disk” to use our virtual hard disk.
4. Installation of the Bootloader
The next required step is to install a bootloader into our MBR. We could use GRUB as in our real system, but GRUB has the disadvantage that it needs a partition where it can store it configuration files and this would require us to create an additional one. We can get around this problem by simply using the original Windows 7 bootloader since we already have a working Windows 7 boot partition in our virtual hard drive. The only thing we need to do is to use the Windows DVD inside our VM and tell it to write the bootloader into our MBR (which is located in the image file we created).
Before we can do this, we must gain access to our virtual hard drive as it is currently owned by root,otherwise Virtualbox/KVM/VMWare can not access them. The best method is to use chown and set our user account as owner of the virtual hdd (so we will be able to access the windows partitions but not the linux partitions on the real hard drive), which can be accomplished by executing:
chown user:group /dev/md0. For a short test it is also possible to start the VM software as root.
If you did not already create a new VM instance in Virtualbox/KVM it's now time to do this. Simply create a new VM with the default settings for Windows 7 and attach your Windows DVD to it. For Virtualbox you just need to select the windows.vmdk file as hard disk and kvm users just select /dev/md0 on the command line or via the virt manager. It is not time to fire up our VM for the first time.
You need to press a key when the Windows DVD shows up the corresponding message to boot from the DVD. After some seconds you should see a language selection dialog and you need to press SHIFT + F10 now to get the command line interface (it would be much more complicated to click through the gui to get to the required commands).
Simply execute the following command to fix the bootloader inside our virtual MBR:
You could now assume that we did everything necessary to boot up Windows but as I mentioned a bit earlier, windows has a bad surprise for us: The bootloader and the windows system identifies itself by using a disk signature which is a 4 Byte unsigned integer plus the start offset of the partition. The start offset should be the same as we copied the necessary parts of the original partition layout, but the disk signature is now different. We need to fix this problem by altering the disk signature inside our virtual MBR as described on TechNet. We can now either change it by using a hex editor or by using some commands inside the recovery environment. Since we are already inside the recovery environment I decided to use the second approach.
First of all we need to find out the value which is expected by Windows and the easiest way to do this, is to read this information from the registry. We therefore need to find out which drive letter was assigned to our windows partition and load the registry. Since we only have two partitions, we can simply take a quick look at their content:
dir C: dir D:
One of them should be empty, as all files are hidden (the boot partition) and the other one should contain the usual directories of a windows installation (Windows, Users,…).
To load the registry hives (as described for examplehere) we just use
reg load and start regedit (In my case D: was assigned to my windows partition):
reg load HKLM\Computer_System D:\Windows\system32\config\system regedit
Now navigate to
HKEY_LOCAL_MACHINE\Computer_System\MountedDevices and you should see a listing with all hard drives. We are just interested in the first 4 byte / 8 characters of the Windows drive (usually
\DosDevices\C:). These are the values of the disk signature and are required for the next step.
Before we can set the value inside our MBR we need to pay attention to the fact that the byte order between the registry and the utility which we are going to use for setting the id is different. We need to swap the values between little endian and big endian: For example if you see the values
ab cd ef gh in the registry you will need to convert it to
gh ef cd ab for the next command. The id can be simply set by using the
diskpart DISKPART> select disk 0 DISKPART> uniqueid disk id=ghefcdab DISKPART> exit
You may now come across the problem that a Windows does not load all drivers during the boot and therefore may not be able to access the hard drive as only the drivers are loaded which are normally required to access the device on a real boot (i.e. SATA or IDE drivers). If you want to use the IDE device controller in KVM or a PIIX3/PIIX4 IDE controller in VirtualBox or if you are using the VMWare Player, make sure that the following entries in the registry:
HKEY_LOCAL_MACHINE\Computer_System\ControlSet001\services\atapi\Start HKEY_LOCAL_MACHINE\Computer_System\ControlSet001\services\intelide\Start HKEY_LOCAL_MACHINE\Computer_System\ControlSet001\services\pciide\Start
are set to zero / 0. Windows will not load the IDE drivers if it is installed to a SATA disk since this will speed up the boot sequence but may get you into trouble if you want to backup the system or use it in a VM like in our case.
That's all we need to do before we can start our System for the first time. Simply close regedit and unload the registry hives again:
reg unload HKLM\Computer_System
All changes we have done so far affected only our virtual MBR and the real partitions were not altered yet (except enabling additional drivers if required). Now it is time to adjust some settings and fire up our Windows installation in a VM.
5. Using Windows 7 in a VM
If you installed Windows to a separate hard drive or followed all the steps till here, we just need to alter some settings in our VM before we can finally boot Windows 7 for the first time inside our VM. You should now have the disk attached to a virtual machine as described in Step 3 and we need to tweak some CPU settings since Windows uses different kernels for different CPUs and you may get problems if you CPU supports less features than during the installation.
Go to System -> Acceleration and make sure that VT-X/AMD-V is enabled. As next step check that PAE/NX is enabled at System -> Processor, since this is one of the features which is used to distinguish between the different kernel versions. Moreover NX is also a security feature and it is therefore recommended to enable it anyway.
If you are using the virt-manager, you can simply go to the options of the Windows VM and click "Copy Host-CPU-Configuration" under Processor and then save the changes.
If you are directly using the command line interface, you can achieve the same by passing
-cpu host as parameter. You can also find some performance tips on the website of KVM.
5.3. VMware Player
The default settings are already optimal, if you choosed Windows 7 (x64) as operating system. You just may need to enable the sound manually.
If you try to boot Windows 7 and did not enable a required driver in Step 4, you will most likely see the following Bluescreen:
The cryptic error code 0x0000007B simply means INACCESSIBLE_BOOT_DEVICE and wants to tell us that the bootloader was able to find the Windows partition and that the kernel was loaded, but it can not access any files on this partition. As described above this is caused by the fact that you are using a different device driver (i.e different IDE or SATA Controller) between your real device and inside of the VM. Windows does not load all of them to shorten the boot time.
If you have problems booting Windows inside of Virtualbox, the easiest way to fix this problem is to try out the different supported IDE and SATA controllers as one of them is most probably supported by the loaded Windows drivers.
During my first try I was able to boot my system with the IDE controller and the ICH6 chipset even without enabling additional drivers inside the registry but I had problems with constant freezes. I therefore tried to exchange the controller with a SATA controller and got a bluescreen again.
Interestingly, the problem was gone after exchanging the IDE controller, which was used by the virtual CD drive, with a SATA controller, so that only SATA controllers were used.
If you want to improve the integration of the VM into your current system, you can install the Guest Additions. They won't have any bad impact if you do a real boot since the devices offered by Virtualbox are not available during a normal boot and therefore the corresponding drivers will not be loaded. The only thing you need to pay attention to is 3D Acceleration. In (at least) older versions of VirtualBox, there was no direct support for DirectX and the Guest Additions replaced the DirectX 8/9 DLLs with the wrapper libraries of Wine which translate the Direct3D functions to OpenGL, so that the host system only needs to offer OpenGL support. This would also affect a real boot since some system DLLs get replaced in this step. Newer versions of Virtualbox support a WDM driver, which is simply an additional graphic driver that does all the 3D acceleration work, so that all your system files stay untouched. Be sure to select the WDM driver if the installer asks you (may require to boot into safe mode).
If you followed all the steps, your result should look like:
If you want to use the IDE controller in KVM, you most likely need to change some registry settings in Step 4 to be able to boot the system but I would recommend to use the VirtIO driver instead, since it is known to have a better performance. You will need to download and install the VirtIO driver from the KVM website in Windows before you can enable it in KVM. I didn't test this driver as I required 3D acceleration, which is not yet supported by KVM, and therefore didn't want to install additional drivers for virtual machines. Anyway, the system also worked with the IDE drivers but was very slow.
6.3. VMware Player
The virtual hard disk is added as IDE device in VMWare and I therefore had to enable the IDE drivers, as described in Step 4, to be able to boot the system. The performance of the system was good and I was able to play videos after installing the VMWare Tools. Compared to Virtualbox, I was also able to get a better 3D performance but I wouldn't expect it to be enough to play 3D games.
I rarely used Windows 7 since I wrote the original german version of this tutorial a year ago, but it was still handy sometimes when I had to work with Windows programs, for example Visual Studio which I had to use for some university project. I mostly boot the system in a VM, but it also happened that I had to use some hardware which did not work well on Linux and I was happy that I could simply boot the same system outside of a VM. Although my real hardware setup (two Nvidia GTX 260 with 2 screens attached) is quite different from the one inside of a normal VM, I never had any problems and the hardware was always correctly detected. Moreover Windows allows you to define hardware profiles which can be selected during the boot sequence so that you can manually define which drivers should be loaded. This approach might be useful if the automatic detection does not work as expected.
I hope you enjoyed the tutorial and feel free to write a comment with your experiences or if you encounter any problems. If you are using a different VM software and got it to work, write me a message so that I can add the necessary commands.