How to copy VirtualBox VDI contents to a partition and dual boot the OS from it?
I'm a Linux user but I keep a compressed Windows XP ISO with me on a pen drive for the case I absolutely need Windows to do something. This works in VirtualBox most of the time.
But now I want to play some games, so I would like to run the Windows image natively. My computer don't have CD drive so cannot just burn the ISO and make an install normally.
What I trying to do is moving the installed Windows image to a physical NTFS partition on my HDD and set up GRUB to let me dual boot it.
I found many tutorials that deal with making VDI to physical drive. But they assume I want to overwrite my entire drive. Moving the raw disk image with dd
to the partition resulted in a corrupt partition.
I also tried the VMDK trick to use that empty partition and install the Windows on it. Although the text mode phase of the installation finishes without problems, the VM won't work, either crashes and keeps rebooting or just immediately freezes (depending on how I created the VMDK, with -rawdisk /dev/sda3
or -rawdisk /dev/sda -partition 3
).
I spent all yesterday with research, and finally was able to make Windows XP boot. It should be somewhat similar for other OS-es too. But the operation is everything but not trivial.
Because this a dangerous operation, I recommend backing up your precious data.
Here is the steps:
Preparation
In the case Windows XP you need to make it forget the current disk letter and partition settings, so you need to erase all values from the HKEY_LOCAL_MACHINE/MountedDevices key on the virtual machine before the migration. The kernel will rebuild it on the next reboot. On Linux virtual machines, this mean fixing the fstab after migration.
Mounting the VDI image
You cannot just copy the entire VDI to a partition, because it contains an MBR too. You need to copy only the virtual partition, so first you need to find a way to mount the VDI.
You need the nbd
driver and the qemu-nbd
command. On Ubuntu it's in the qemu-kvm
package.
First load the nbd driver:
# modprobe nbd
This should make some nbd
devices in /dev
.
Then mount the VDI:
# qemu-nbd -c /dev/nbd0 path_to.vdi
This should make /dev/nbd0p1
, /dev/nbd0p2
, /dev/nbd0p3
etc for all virtual partitions. These can be mounted like any ordinary devices.
Migrating the partition
Use dd
for that, unmount both partitions before the operation:
# dd -if=<nbd_device> -of=<real_partition>
eg.:
# dd -if=/dev/nbd0p3 -of=/dev/sda4
Operation of the dd
is silent, this may take several minutes, even a half hour. During the operation you may open a terminal and use fdisk -l
to see all is going well.
UPDATE:
Apparently nbd is not a foolproof solution. It may cause I/O error and make dd fail. Moreover next try fails immediately. You can also try making a raw disk VMDK with this command (under linux):
$ VBoxManage internalcommands createrawvmdk -filename physical.vmdk -rawdisk /dev/sda
You need to be in the disk
group to make it work. Then add this vmdk to the virtual machine as a secondary hard drive, then use a Live Linux ISO to dd
the partition.
Fixing the boot sector of the NTFS partition
This is the hackish part.
We are almost ready, but Windows XP won't boot, because we need to set the number of hidden sectors of the filesystem at the offset 0x1C
. This basically a number of sectors before NTFS partition. We can get this number from the fdisk -ul
command. The start
field of the output states which sector the given partition starts at, which is basically the number of sectors before the partition. So get the number from there, convert it to hexadecimal using gcalctool for example.
Open the partition with hexedit
, like this:
# hexedit /dev/sda4
Then write the number of hidden sectors in little endian order at the 1C
offset. Little endiean means: 0xABCDEFGH
will be GH EF CD AB
. If the hexa number is shorter that 8 digits, precede it with zero.
When done, save it and exit (Ctrl+X).
Setting up GRUB
You must tell GRUB to boot directly that partition, for GRUB add the following menu entry:
title Microsoft Windows XP Professional
root (hd0,3)
savedefault
makeactive
chainloader +1
Where (hdX, Y)
identifies the partition. X is 0 for the default harddisk, 1 for /dev/sda
, 2 for /dev/sdb
etc. Y is the partition number. 0 for /dev/sda1
, 1 for /dev/sda2
, etc.
This should be similar for GRUB2 too, but it uses a bit different syntax for menu entries.
Final touches
The new NTFS partition is ready to boot up. But you still need some hacking to reach the Windows XP desktop. Other systems might need different hacks. First the boot.ini needs to be fixed.
[boot loader]
timeout=1
default=multi(0)disk(0)rdisk(0)partition(3)\WINDOWS
[operating systems]
multi(0)disk(0)rdisk(0)partition(3)\WINDOWS="Microsoft Windows XP Professional" /noexecute=optin /fastdetect
Set the parition number accordingly. I installed it on the /dev/sda4. So the partition number should be 3.
You may need to fix the MountedDevices entry in the registry if Windows freezes right before the logon screen.
The registry is at <path to windows>/system32/config/system
you can view it by chntpw
.
This can be a problem if your system drive letter is not C. Since chntpw
's registry writing capabilities are quite limited, you need to fallback and use a hexeditor, like ghex2 to fix it. You need to find \DosDevices\C:
and replace the C with a different drive letter, F
in my case.
After these, you should be able to reach the desktop, now you need to hunt for all drivers, but this is out of the scope of this tutorial.
Sources
Moving Windows XP to a different partition
Mount a VDI under linux