Introduction

This posting documents how I configured triple boot environment of Ubuntu 9.10 karmic, Mac OS X 10.6 and Windows 7 on ?one of my machines. All operating systems are installed on a single physical disk. Grub 2[1] boot loader installed by Ubuntu will be used as the primary boot loader. Grub will be then used to boot Chameleon[2] boot loader which boots Mac OS X. Grub boots Ubuntu’s Linux kernel directly and Windows by chain-loading the Windows boot loader from the Windows partition.

Partitioning the disk

Partitioning the disk causes headache and requires some tweaking as we have to install both GUID Partition Table[3] and Master Boot Record Partition Table[4] on the same disk. Mac OS X only supports system disks with GPT. But Windows doesn’t support booting from a disk with GPT[5]. Ubuntu is happy to boot from disks paritioned using both GPT and MBR. Thus we have to create hybrid GPT/MBR boot record[6].

We’re going to do the initial partitioning of the system disk from within Mac OS X installer environment using diskutil(8)[7] tool. Follow the instructions in the posting Create Mac OS X 10.6 Snow Leopard USB installation media for Hackintosh and create bootable Mac OS X installer USB media that works with your system. Of course if your system boots with the retail Mac OS X DVD, you can use that too.

Next we have to decide the partition table layout. When installing Grub 2 on a disk with GPT, it’s recommended to have BIOS Boot Partition[8],[9]. With the hybrid partition table in place, you’re limited to only 4 partitions that are available to Windows. And two of these partitions are reserved (EFI Partition and BIOS Boot Partition) so you only have 2 primary partitions to configure at your will. Also it’ll be difficult to work with the partitioning after we’ve finished with the installations and gotten everything to work so it’s better to do good initial planning.

Ubuntu 9.10 karmic and later install Grub 2 that is capable of handling LVM. Since we’re going to install Ubuntu on logical volume(s), there’s not need for a separate partition for /boot file system. That’s great!

I partitioned my 600GB disk as follows:

  • Partition 1: 200MB HFS+ volume labeled EFI. This is created automatically when partitioning the disk with diskutil(8)[7]. Chameleon boot loader code and support files are also installed on this volume. This way there’s no need to do any customization to the Mac OS X volume described below.
  • Partition 2: 2MB volume for the BIOS Boot Partition. Used by Grub.
  • Partition 3: 150GB NTFS volume for Windows.
  • Partition 4: 50GB Physical volume for volume group managed by LVM. The volume group will house the Ubuntu installation.
  • Partition 5: 100GB Mac OS X system volume labeled Hackintosh HD for the operating system, applications and user home directories.
  • Partition 6: ~300GB HFS+ volume labeled Video for video archive and scratch space used during editing of home videos.

To partition the disk boot Mac OS X installer and launch Terminal.app from the Utilities menu. First identify the system disk.

    -bash-3.2# diskutil list

In my system the system disk is /dev/disk7. Then I partitioned the disk using the following command.

    -bash-3.2# diskutil partitionDisk /dev/disk7 GPT \
        "MS-DOS FAT32" %noformat% 2M \
        "MS-DOS FAT32" %noformat% 150G \
        "MS-DOS FAT32" %noformat% 50G \
        "Journaled HFS+" "Hackintosh HD" 100G \
        "Journaled HFS+" Video 0b

As noted above, this will create total of six partitions. In addition to the five partitions listed above, the 200MB EFI partition is automatically created by diskutil(8)[7] as the first partition of the disk. I marked the Windows, Linux and BIOS boot partitions temporarily as FAT32 so that the space gets allocated for these partitions. The Windows partition will be formatted as NTFS when installing Windows 7, the Linux partition will be added to the volume group when installing Ubuntu and Grub installer will use the BIOS boot partition.

Installing Chameleon boot loader

The empty, just partitioned hard disk is not bootable and won’t be even after installing Mac OS X in the next step. But we can copy Chameleon boot loader and its configuration from the Mac OS X USB installer to the system disk. See my guide for more details about Chameleon. These steps assume that the Mac OS X installer was created like documented in that posting. While still in the Mac OS X installer with Terminal.app running, execute the following commands.

  1. Create HFS+ file system on the EFI volume and mount it.

    -bash-3.2# newfs_hfs -v EFI /dev/disk7s1
    -bash-3.2# mkdir /Volumes/EFI
    -bash-3.2# mount_hfs /dev/disk7s1 /Volumes/EFI
    
    
  2. Mark the EFI file system so that fseventsd doesn’t keep any logs there.

    -bash-3.2# mkdir /Volumes/EFI/.fseventsd
    -bash-3.2# touch /Volumes/EFI/.fseventsd/no_log
    -bash-3.2# chmod -R g-rwx,o-rwx /Volumes/EFI/.fseventsd
    -bash-3.2# chown -R root:admin /Volumes/EFI/.fseventsd
    
    
  3. Copy the Chameleon boot loader binaries to the root of the EFI volume. You really need the boot file, which is the last stage of Chameleon boot system and contains bulk of the Chameleon code, but it’s a good idea to have the images of the first stages at hand, too.

    -bash-3.2# ditto /Volumes/Hackintosh\ Snow\ Leopard\ Install\ Disk/boot /Volumes/EFI
    -bash-3.2# ditto /Volumes/Hackintosh\ Snow\ Leopard\ Install\ Disk/boot0 /Volumes/EFI
    -bash-3.2# ditto /Volumes/Hackintosh\ Snow\ Leopard\ Install\ Disk/boot1h /Volumes/EFI
    
    
  4. Copy Chameleon support file directory Extra to the EFI volume.

    -bash-3.2# ditto /Volumes/Hackintosh\ Snow\ Leopard\ Install\ Disk/Extra /Volumes/EFI/Extra
    
    
  5. Unmount the EFI volume.

    -bash-3.2# umount /dev/disk7s1
    -bash-3.2# rmdir /Volumes/EFI
    
    
  6. Eject the system disk so that you can write to the block device file in the next step.

    -bash-3.2# diskutil eject /dev/disk7
    
    
  7. Now you can copy the Chameleon initial boot code from the installer file system to the Master Boot Record at the beginning of the system disk.

    -bash-3.2# dd if=/Volumes/Hackintosh\ Snow\ Leopard\ Install\ Disk/boot0 of=/dev/disk7 bs=440 count=1
    
    
  8. Then copy the Chameleon 2nd stage boot code from the installer file system to the beginning of the EFI partition.

    -bash-3.2# dd if=/Volumes/Hackintosh\ Snow\ Leopard\ Install\ Disk/boot1h of=/dev/disk7s1
    
    
  9. Bootloader installation is now ready. Mount the Mac OS X volume so you can install Mac OS X onto it.

    -bash-3.2# diskutil mount /dev/disk7s5
    
    
  10. Finally, quit Terminal.app.

Installing Mac OS X 10.6 Snow Leopard

Go ahead and install Mac OS X normally on the Mac OS X volume (Hackintosh HD). After the installation is finished, the machine should boot to Mac OS X as we installed the Chameleon boot loader to the Master Boot Record and support files to the EFI partition in the previous steps. It’s a good idea to create backups of the Master Boot Record of the system disk at this stage so you can revert back if needed. You can use e.g. dd(1)[10] in Mac OS X installer shell.

    -bash-3.2# dd if=/dev/disk7 of=/Volumes/BackupVolume/mbr-backup bs=512 count=1

Installing Windows 7

When the system disk was partitioned above with diskutil(8)[7], it also created the hybrid GUID/MBR partition table. You can now boot Windows 7 installer and format the partition dedicated to Windows as NTFS. Proceed to install Windows on this partition. After Windows is installed, the machine now boots Windows as the Windows installer replaced Chameleon boot code in the Master Boot Record with its own boot code. No need to worry, we’ll get Mac OS X back after installing Ubuntu and configuring Grub.

Installing Ubuntu 9.10 karmic

Use Ubuntu alternate installer[11]. Boot the installer and proceed to the disk partitioning step. Choose manual partitioning and create a volume group to the partition dedicated to Ubuntu, create required volumes and install Ubuntu there. When the installer prompts for boot loader device installation, don’t answer yet but switch to the console (Alt-F2). We need to activate the BIOS Boot Partition first. In the following setup /dev/sda is the physical system disk.

  1. Mount the special file systems at the target file system.

    ~ # mount -o bind /dev /target/dev
    ~ # mount -o bind /sys /target/sys
    ~ # mount -o bind /proc /target/proc
    
    
  2. Enable BIOS Boot Partition using parted(1)[12].

    ~ # chroot /target parted /dev/sda set 2 bios_grub on
    
    
  3. Unmount the special file systems at the target file system.

    ~ # umount /target/dev
    ~ # umount /target/sys
    ~ # umount /target/proc
    
    

Now switch back to the installer virtual console (Alt-F1) and input the system disk block device name /dev/sda and finish with Ubuntu installation.

Restoring hybrid partition table

After installing Ubuntu, you should be able to boot it using Grub. However, Ubuntu installer and parted(1) have destroyed the hybrid GPT/MBR partition table. But we can fix that using the gptsync(1) tool which is part of the rEFIt[13]. gptsync package is available for Ubuntu[14], but unfortunately the version in karmic is too old to support BIOS Boot Partitions[15]. This has been fixed in the version 0.13-4 of the package. Until there’s a working version of gptsync package in Ubuntu, you can use the package from Debian[16]. When you have a version of gptsync(1) installed which supports BIOS Boot Partitions, go ahead and re-create the hybrid partition table.

    ~$ sudo gptsync /dev/sda

Updating Grub boot menu

Ubuntu installer should detect the Windows 7 installation and create a Grub menu entry for it. It’ll also detect the Mac OS X installation and create menu entry for that, too. However, that is no good to us since it uses Grub’s native Mach kernel loading facilities[17] but we want to use Chameleon to boot Mac OS X.

So let’s create a custom menu entry that will boot Chameleon. Save the following script as /etc/grub.d/99_local_chameleon and set it executable.

#!/bin/sh

cat <<END_OF_MENU_ENTRY
menuentry "Mac OS X via Chameleon" {
        insmod hfsplus
        set root=(hd0,1)
        multiboot /boot
}
END_OF_MENU_ENTRY

Download script

    ~$ sudo chmod 755 /etc/grub.d/99_local_chameleon

And update the Grub configuration.

    ~$ sudo update-grub

Now you should have Grub menu from which you can choose whether to boot Ubuntu, Mac OS X or Windows.

Fixing Windows

Unfortunately, partition changes related to Ubuntu installation breaks Windows on my machine. When trying to boot Windows, I get Windows Boot Manager error screen with status 0xc00000e. To fix this, boot to Windows Recovery Environment and start Command Prompt. With Windows 7 retail DVD in hand, boot it, choose your language and locale settings and choose Repair your computer. If the Recovery Environment asks Do you want to apply repairs and restart your computer, choose No. Choose Use recovery tools that can help fix problems starting Windows and then clck Command Prompt. In the Command Prompt find the drive that contains the Windows installation. Most likely it’s C:. Run the following commands to repair Windows Boot Catalog.

    bcdedit /set {default} device partition=c:
    bcdedit /set {default} osdevice partition=c:
    bcdedit /set {bootmgr} device partition=c:

It should now be possible to boot Windows from the Grub boot menu.

References