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:
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
First load the nbd driver:
# modprobe nbd
This should make some
nbd devices in
Then mount the VDI:
# qemu-nbd -c /dev/nbd0 path_to.vdi
This should make
/dev/nbd0p3 etc for all virtual partitions. These can be mounted like any ordinary devices.
Migrating the partition
dd for that, unmount both partitions before the operation:
# dd -if=<nbd_device> -of=<real_partition>
# 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.
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
(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
This should be similar for GRUB2 too, but it uses a bit different syntax for menu entries.
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.
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
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.
Moving Windows XP to a different partition
Mount a VDI under linux