2013. január 9., szerda

Converting a dual-boot MBR partitioned disk to GPT

Background story

I always liked computer games. My first PC was a Pentium 100 MHz machine with very little RAM, which was dedicated almost entirely to a RAM disk. My first precious PC was lacking a hard drive. Every time I wanted to use it, I had to boot up from a floppy and copy software from a few other floppies to the RAM disk. One of my favourite games was UFO: Enemy Unknown. It took a lot of time to boot and copy everything in place, so my machine was on most of the time, and I played a lot on it :) This kinda shows my commitment to PC games.

The famous game was recently rebooted by Firaxis as "XCOM: Enemy Unkown". The game was kinda sluggish on my current setup, so I decided to buy new hardware.


 The new setup

  • Asrock X79 Extreme6 GB motherboard (with UEFI)
  • INTEL Core i7-3820 3.60GHz LGA-2011 processor
  • 2 Corsair Vengeance 16GB quad kits, 2400 MHz
  • 2 SEAGATE Barracuda ST3000DM001 (3000GB, 7200rpm 64MB cache, SATA3)
  • New PSU, new chassis, display, graphics card, you name it.
After long debugging, involving a Memtest86+ bug it turned out that two identical RAM kits might not work together on full speed, and one kit is flawed, anyway, RMA in progress.


Always keep two copies. And a few backups too.

I always take backup seriously. Programming and fiddling with hardware and software quickly became a profession of mine. I cannot afford to lose my data.

 The old setup had one 2TB fixed HDD and a 640GB HDD that was lying in the drawer, holding backups. Important git repositories was also on the Company's dev server, and in S3 too.

The drawback of this solution is downtime. If the fixed disk (holding the OS-es) would have failed, I would have to reinstall everything.

This is why I decided to buy two identical hard disks. My intention was to keep two copies of the whole system(s), so if one fails, I can always plug in the other. No precious time wasted. A new disk and on overnight dd can restore redundancy.


Moving the data to the new disks

Actually "overnight dd" part was when I discovered that something is terribly wrong with the new rig, and the three day nightmare of memtest86+ debugging and data copying started.

Finally, I managed to copy the 2TB old disk to both 3TB disks. Both could be booted up.

I have two operating systems: an Ubuntu Precise for fun & profit, and a Windows 8 for fun only (yes, games). Both systems could be booted up at this point. I use Grub 2.

Too bad the old disks used old MBR partition tables. This kind of partition table can't handle disks larger than about 2 Terabytes, so at this point I had absolutely no use of the 1 extra terabyte at the end of the disk. What a waste of money.


Converting a disk to GPT

To do this, I booted from one HDD, and left the other one in an eSATA rack.

The conversion can be done with the gdisk (for GPT fdisk) software from ubuntu. It can be installed like this:

 apt-get install gdisk

To convert an MS-DOS partition table to GPT, just launch gdisk, and hit "w" to write the new, converted GPT to the disk. The data will remain untouched, however, the disk will become unbootable.

I sorted the partitions so that their entries in the partition table were the same as they appear on the disk, so the partition numbering was messed up beyond recognition. The data is still there, but the OSes could not boot up due to several equally forbidding reasons.

I used gparted tool to resize and move the partitions. Windows got almos 1TB, and Linux got the rest.

Converting a disk from MBR to GPT _and_ having Windows to boot up without a reinstall is pretty much impossible with my little knowledge on Windows. The terrible documentation and limited range of tools makes the situation even worse, so I decided to completely reinstall Windows 8 Pro. I've lost no data, since the other disk, and the old disks held the old Windows partition, and I only used it to play with stuff downloaded from Steam, so everything "important" was also in the cloud.

Installing Windows on GPT with UEFI

Windows can only be installed on GPT if it is booted up in UEFI mode.

I realized that the Windows 8 Pro update disk I've bought is only willing to boot up in legacy (a.k.a. BIOS mode). Darn.

The problem is that the CD is constructed in such a way, that it is almost possible to boot up in UEFI mode. The files are there, but the CD's filesystem does not allow UEFI to boot from it. If it would be FAT, it could boot. The solution is to copy the entrire Windows 8 Pro install cd onto a FAT formatted flasdrive. After doing so, Windows started happily in UEFI mode, and even run faster from the quick little thumbdrive.

Windows need a few extra partitions on GPT to be happy. Actually UEFI itself requires a FAT32 partition to be able to boot (this is why the thumbdrive was needed in the first place).

In the Windows installer, I removed the Windows partition, and told Windows to install itself on the resulting "free space". It figured out the situation, and created the UEFI system partition (the stuff for booting wit the FAT filesystem), a partition for recovery, one MSR for it's private business, and a data partition for the actual filesystem mortals use for their everyday business.

Installation went smoothly, Windows finally booted up form the disk, in UEFI. Now was time to fix Ubuntu.

Installing GRUB 2 in UEFI mode

In Ubuntu, I had to create a /boot/efi mount point, and mount the UEFI system partition, uninstall the old grub2, and install grub-efi.

To install grub-efi, one has to be boot the system in UEFI mode. What?!

This chicken-and-egg problem can be solved with a recent Ubuntu desktop live CD by setting the UEFI setup to boot the DVD in UEFI mode. Yepp, Ubuntu's install CD can boot up in UEFI mode no problem, Windows can't. +1 for Ubuntu again.

To install grub, one has to mount the / partition under somewhere, like /mnt. After chroot-ing into this partition, /proc, /dev, /dev/pts, /sys and the aformentioned /boot partition have to be mounted with mount <mount point> commands. After this, a grub-install writes the necessary files onto the UEFI boot partition, and update-grub writes grub.cfg.

Chainloading the Windows UEFI boot loader from Grub-EFI

To be able to do this, I followed the advice at http://askubuntu.com/questions/193144/dual-boot-uefi-windows-7-and-ubuntu-12-04-both-64-bits-w7-entry-doesnt-appea. Basicly:

grub-probe --target=fs_uuid /boot/efi/efi/Microsoft/Boot/bootmgfw.efi

This will output an UUID. Take a note of this.
Add this to /etc/grub.d/40_custom:

menuentry "Windows 8" {
    search --fs-uuid --no-floppy --set=root UUID
   chainloader (${root})/efi/Microsoft/Boot/bootmgfw.efi

And run update-grub after this.

Fixing the boot order

Windows and Ubuntu create entries in the motherboard's NVRAM for their boot managers. You can select the default operation system at the UEFI setup (by quickly pressing something like DEL, or F1, or F2 when the system starts).

However, whenever Windows starts, it makes itself the default operating system in that list. So after every Windows session, Windows will start again by default on the next boot. Nice huh?

No, it isn't. Let's solve this.

According to Microsoft's support forum, it's impossible to make Windows to accept itself other than the first place on the boot list.

The solution is to create a batch file that runs at every bootup, and makes GRUB2 the default entry in the NVRAM.

This can be done by opening up the group policy editor (search this in Metro UI), and navigation to the startup scripts section.

The .bat file should look like this:

bcdedit /set {fwbootmgr} DEFAULT {appropriate UUID}

Where "appropriate UUID" is the UUID in GRUB, and can be read from the list that "bcedit /enum firmware".

So Windows will make itself default, just to undo int a bit later when this file runs. Not a pretty solution, but it works.