I’m going to describe a method here which I’ve used successfully to move a Windows XP system to a new hard drive. This is one of the things that commercial programs like Norton Ghost do. But the method I’ll describe here has worked for me several times, requires no expensive proprietary software, and provides a fun excuse to learn interesting stuff.
The first thing you should know about shenanigans like this is that it’s extremely extremely easy to make colossal errors which will utterly and irrevocably destroy all the data on your hard drive. Make a backup! Also, there are huge gaps in my knowledge. I wouldn’t trust me if I were you. Don’t do anything without understanding why! I’m not writing this as an authority, but as a story-teller. I would’ve like to find a narrative through this, because the references I found in Google to this kind of stuff were pretty fragmentary and allusive.
The first thing you’ll need is a free unix boot disk. You can use a CD-ROM installation disk for this – anything which will give you a shell and have the two crucial programs dd and fdisk. A boot floppy could work fine too, though it’s obviously hard to fit a great deal of Unix on one mere floppy. I like Tom’s Root Boot, which has a surprising amount of stuff.
You can use fdisk and dd to do nifty things like imaging a computer from somewhere on your network, but what I’m going to describe is what I’ve done most recently, which is moving a Windows system from a small, slow disk to a larger, faster one. I had two IDE drives, the original 6 GB and a blank 80 GB. I plugged both of them into the machine, and booted up. I wanted the hard drives on different IDE buses, since transferring a lot of data from master to slave drive on the same bus is slower than doing it between two different buses, so that’s how I set it up – the 6G drive was disk 0 on the first bus, and the 80G drive was disk 0 on the second.
Brief discursion for Windows folks – in Unix, physical devices are represented as files, found in the /dev/ directory. Tom’s Root Boot is linuxy, so the first IDE hard drive is the /dev/hda file. If there’s a slave on that bus it’ll be hdb, but my second drive was on the second bus so it was hdc. These files refer to the whole entire hard drive, including the partition table and everything, so you will very rarely want to write anything to them directly. The partitions of a disk are represented by similarly named device files, with numbers in their names. So the first partition on my first IDE drive was called /dev/hda1. This is the c: drive. There was another 2G partition on the original drive which I didn’t care about.
Now, I wanted to create a partition on the new drive, /dev/hdc. This is where I will copy /dev/hda1 to, so I want the new partition of hdc to be exactly the same size as hda1. To find out the size of hda1, I run “fdisk /dev/hda”, and hit p to print the partition table. I get some output like:
Disk /dev/hda: 255 heads, 63 sectors, 784 cylinders
Units = cylinders of 16065 * 512 bytes
Device Boot Start End Blocks Id System
/dev/hda1 * 1 522 4192933+ 7 HPFS/NTFS
/dev/hda2 blah blah I don't care about this partition
So how big is that hda1 partition? Well, it’s made up of 522 cylinders. And each cylinder is 16065 * 512 = 8225280 bytes. So we’re looking at 4293596160 bytes, i.e. 4G.
Now I wanted to make a new partition, hdc1, on the new drive, hdc, so I ran “fdisk /dev/hdc”. When I printed the partition table I saw one crucial nice thing – the cylinder size on the new hard drive was the same as on the old one. I don’t even know if this method would work if the hard drives had different cylinder sizes – I’ve tried it and had it fail, but I have reason to believe that was due to one of my test-subject hard drives being broken.
With the cylinder size the same, it’s easy to create a partition of the same size – just use the same number of cylinders.
So I hit “n” in fdisk to create a new partition. I’m prompted to say whether I want a primary partition or an extended partition. I want this new partition to be partition 1, so I hit “p”. Now I’m prompted for the partition number, i.e. 1. Now I’m prompted for which cylinder should be the first cylinder in this partition, i.e. 1, and which I want to be the last, i.e. 522.
OK, I’ve created the partition and if I print the partition table I now see
Disk /dev/hdc: 16 heads, 63 sectors, 39560 cylinders
Units = cylinders of 1008 * 512 bytes
Device Boot Start End Blocks Id System
/dev/hdc 1 522 4192933+ 83 Linux
There are still two changes I have to make to get hdc1 to match hda1. First I hit “a” to flag hdc1 as a bootable partition. And then I hit “t” and change the partition type to 7, which means NTFS. And now I’m happy with my new partition so I hit “w” to write the new partition table I’ve created to the hard drive.
Now we copy the old partition over to the new one, by running the command “dd if=/dev/hda1 of=/dev/hdc1”. This will take a long time – it could easily be an hour or significantly more, depending on partition size. Since dd gives no satisfying output whatsoever, no progress bar, no nothing, you might as well go write up a blog entry about how to do this process, or something…
OK, when it’s done I’ve cloned the c: drive successfully! But the new hard drive still isn’t bootable – it has no master boot record (MBR). The MBR is a groovy little program kept at the very beginning of the partition table — the BIOS loads it during the boot process, and it tells the computer which partition to boot from. It’s 512 bytes long. As it happens, simply copying the first 512 bytes from hda onto the beginning of hdc will make hdc bootable. It’s weird that that works. I suspect it would mess up if you did much differently, e.g. if you copied hda1 to any partition on hdc other than hdc1. But anyways, here’s how you copy those 512 bytes: “dd if=/dev/hda of=/dev/hdc bs=512 count=1”. Note that if you screw anything up at all with this command, you’re in hot water – for instance, if you switch the values of the “if” and “of” parameters you’ll end out with neither disk bootable. Be careful!