Monday, September 3, 2012

Dual Booting Linux and OS X Using Grub2

My interest in the frozen-in-time EverQuest Mac server (Al'kabor), and lack of true Apple hardware, has led me to a foray into the Hackintosh world.  Since I am a full-time Linux user at home, I needed the ability to boot into both my existing Linux (Fedora 17) installation and my new OS X 10.8 Mountain Lion installation.  Fortunately, most modern Linux distributions come equipped with a bootloader that is capable of handling this scenario: Grub2.  In very basic terms, a bootloader is software that acts as the start-up link between a system's low level software that handles the initial checks and communication with the installed hardware (eg BIOS) and the higher level operating system(s).

Given the above setup, there are a couple of options for dual booting the system; each could be a viable solution, depending on the configuration.

The Easy Way

If you don't need any additional boot flags to boot OS X successfully, then you can use a built-in grub tool to automatically detect the location and disk type of all operating systems installed on your local drives -- including OS X.  The tool name and syntax varies between distros, but they will all accomplish the same thing.

For Fedora and similar distros (your grub folder may actually be /boot/grub instead):
sudo grub2-mkconfig -o /boot/grub2/grub.cfg
For Debian/Ubuntu/Mint:
sudo update-grub
Both tools use the built-in scripts located in /etc/grub.d to collect info about installed OSes on your machine and create the appropriate entries in Grub's configuration file at /boot/grub2/grub.cfg.  Once it has finished running, you should have two new entries in Grub's boot menu when you reboot; Mac OS X (32-bit) and Mac OS X (64-bit).  Select the appropriate choice for your system and enjoy the seamless transition into OS X.

The Not-Quite-As-Easy Way

If your system requires the use of additional boot flags to boot into OS X, then the easiest solution will be to use Grub to load a Hackintosh-specific bootloader (eg Chimera or Chameleon), then use the Hackintosh boot loader to pass your required boot flags to the OS X system.  This is called chain loading.

Most Hackintosh guides cover installing a boot loader, so I won't go into that here.  I'm going to assume you have Chimera or Chameleon installed already.  To further complicate things, we will need to use boot0, which is a tiny FreeBSD bootloader, to bridge between Grub and Chimera.  Although this file will be on your OS X drive already, the easiest way will be to just grab it from a download of Chameleon boot loader from the website:  Open a terminal in the directory that you just downloaded Chameleon to.

Uncompress the .tar.gz file and locate boot0 within the i386 directory, and copy it to your /boot folder:
tar -xzvf Chameleon-2.*.tar.gz
For Chameleon versions 2.0.*:
sudo cp Chameleon-2.0*/i386/boot0 /boot/
I believe that in Chameleon versions 2.1+, the folder structure has changed in the tarball, so copy the boot0 from here instead:
sudo cp Chameleon-2.1*/usr/standalone/i386/boot0 /boot/

Now that the boot0 file is in the appropriate directory, we need to add an entry for Grub to use it to get to Chimera.  The best way to do this will be to add an entry in /etc/grub.d/40_custom (as opposed to adding it directly to Grub's pre-generated menu file -- ie /boot/grub2/grub.cfg).  The reason is because if we were add it directly to the grub.cfg file, it would be wiped the next time the "grub update" tool is used -- which happens as part of every kernel upgrade.  So, since /etc/grub.d/40_custom is one of the files that are used by Grub's update tool to generate grub.cfg, our OS X/Chimera entry will be kept between kernel upgrades.  So... back to the command line:

First, we need to figure out what our OS X partition's UUID is, according to Grub -- this is different than the UUID that the blkid tool reports.  The easiest way to do that is to run Grub's update tool to generate an entry for OS X.  This won't be the entry that we use, but it WILL give us the appropriate UUID.

For Fedora and similar distros (your grub folder may actually be /boot/grub instead):
sudo grub2-mkconfig -o /boot/grub2/grub.cfg
For Debian/Ubuntu/Mint:
sudo update-grub
Open the generated grub.cfg file in a text editor and scroll down to find the "Mac OS X ..." entry in the file (your grub folder may actually be /boot/grub instead).
sudo nano /boot/grub2/grub.cfg
Copy the entry's UUID to the clipboard.  This will be a 16-digit hexadecimal value (eg 777eaee489759bd8) and will be listed on a line similar to "search --no-floppy --fs-uuid --set=root 777eaee489759bd8".  Now we will open /etc/grub.d/40_custom in a text editor and create our code that Grub will use to generate a menu entry for Chimera.
sudo nano /etc/grub.d/40_custom
Paste the following at the end of the file and change the partition designations on the "set root=" line and the "chainloader" line:

menuentry "Mac OS X (Chimera)" {
insmod part_gpt
insmod hfsplus

#replace this location with
#your OS X partition
set root='(hd1,gpt2)'

#replace this UUID with the UUID from your grub.cfg
search --no-floppy --fs-uuid --set=root 777eaee489759bd8

#replace the (hd0,2) portion with your
#Linux partition designation
chainloader (hd0,2)/boot/boot0

You should be able to get a good idea of which device ids you need to use by running:
sudo fdisk -l
and comparing that info with the output of:
The hard drive listed with GPT will be your OS X drive.  Typically, your drive with OS X on it will be split into at least 2 partitions: a 200MB EFI system partition (fat32), and a much larger partition that holds the OS (hfs+).  You can verify your OS X drive partitions by running:
sudo parted /dev/sdX
(of course, change the X to the actual drive letter of your OS X drive).  Then, at the (parted) prompt enter:
This will list the partitions on the drive.  It is worth noting here that, by default, the Chameleon bootloader is installed on your EFI system partition and Chimera is installed on your OS X partition.

A note about partition numbering/lettering in Linux and Grub:
The Linux and Grub partition designations differ a bit.  On my system, my OS X partition is located at /dev/sdb2.  This equates to hd1,gpt2 in Grub (since it's a GPT partitioning scheme).  The root of my Linux system is located at /dev/sda2, which is hd0,2 for Grub (non-GPT).  Linux designates physical SATA drives with /dev/sdX, where X is a letter from a to z.  The first drive is /dev/sda, second drive is /dev/sdb, third drive is /dev/sdc, etc.  After the letter comes a number (starting at 1) that represents the partition within that physical drive.  The first partition on the first drive would be /dev/sda1, second partition on the first drive would be /dev/sda2, etc.  Grub's drive designations are represented as hdY, where Y is a number which starts at ZERO.  Conversely, Grub's partition designations start at ONE.  So, the first partition on the first drive for Grub would be hd0,1, second partition on first drive is hd0,2, first partition on second drive is hd1,1, etc.

Once you have your 40_custom file configuration set, run the "grub update" tool again (refer to the above section again for your distro-specific syntax) to generate a new grub.cfg file which will have our new entry in it.  Once it's done, reboot the PC and select the new entry.  If all goes well, you should be presented with the Chimera bootloader, in which you can use your required boot flags.

Troubleshooting The Chainloader

If you have issues getting from Grub to Chimera, you can select the menu entry in Grub and hit "E" to go into editing mode for it.  Here, you are able to do some basic editing so you can mess with your partition designations (both at the set root='...' line and the chainloader line) or any other syntax errors that might be present.  Once you've made your changes, hit F10 to attempt to boot the revised method.

If you're truly unsure of what your partition designations should look like, back out to the Grub menu and hit "C" to get to a Grub command line.  Use the "ls" command to show all of the partitions that Grub can see.  This could help you get a better understanding of the designation that Grub requires (eg if you need to use a hdX,msdosY convention for an MBR partition).

Note that if you make changes in Grub's edit, they will NOT be saved.  You will need to make those same edits in the /etc/grub.d/40_custom file and re-run the "grub update" tool.

You've gotten better at Linux! (1)


  1. You got me very far to where I want to be. I created the chainloader configs in the /etc/grub.d/40_custom file. My numbers were the oposite of your example but I figure out the correct corresponding numbers to grub to the correct partition numbers. I know have an extra choice when booting into my primary boot drive of linux. That choice is boot into Chameleon. Although when I choose that it says it can't find 'boot0' This is becuase I could not find a way to mount the drive and install boot0 into the partition. I am so close it isn't even funny. Do I need to be booted into Mac OS to get into the bootloader? Or can I do this from linux? If so I would so much appreciate it if you can guide me just a little further. Everything else worked perfectly. I first updated grub, and it gave me the extra choices for OSX, but when that loads it loads all messed up becuase it is looking for a transfer to the DSDT file that Chameleon does. So now I got the choice to boot into chameleon but can't figure out how to get boot0 into it.
    Thanks for any response.

    1. I'll try to help.

      Please clarify a few things for me:
      Have you already installed Chameleon along with a working install of OS X?
      If I understand you correctly, you can't even get into Chameleon from GRUB? When it complains about a missing boot0, it usually means that your GRUB entry is pointing to the wrong partition. If you are using Chameleon (and not Chimera), then I believe that your GRUB entry should be pointing at your 200MB EFI partition and NOT your OS X system partition. Check to make sure this is the case -- and if it is, try changing it to point at the system partition instead. I'd recommend using the GRUB command line (hit "C" at the GRUB boot screen), then use the "ls" command. Check your GRUB config file to make sure it matches what "ls" reports.

      Are you using two separate physical hard drives (ie one for Linux and one for OS X)? Two separate drives is the easiest way to go about it, but you should be able to get it to work on the same drive.

  2. Yes I'm using 2 seperate partitions 1 linux, 1 osx. Now when I boot into linux as it is set as the first drive to boot, it gives me 5 choices:1: boot linux, 2: boot linux (troubleshooting mode of some sort)) 3: boot mac osx 32 bit, 4: boot mac osx 64 bit, 5: boot chameleon, so after choosing chameleon it in fact gives me 2 errors I noticed the first being the uuid, is not recognized, the second is it can't find boot0. Now I followed your blog to the letter in finding my uuid in the grub.cfg file. The problem is my uuid is longer than 16 digits. It is more like 32 digits the first set of digits and letters are 8 separated by a dash then 4-4-4-12 digits The first 8 are ef2c2bd7 together without dashes, followed by 3 sets of 4 digits, followed by 12. I scoured the entire config file from top to bottom, that is my uuid number sequence being listed. What I am going to try is to take the last 4 digits from the first 8, then type in the next set of 4 each,which will give me 16 digits, then leave out the last 12, that may be something else related but still listed under the sequence. It's worth a try the worst that can happen is it will still give me a uuid error in the bootloader of chameleon when I choose it.
    BTW ~ I checked and my linux is formated on an MBR partition, using ext4. So I have go over the last part of your blog again and see if that is giving me a wierd uuid sequence compared to a GPT partition.

  3. Update...I got rid of one error. The uuid error was wrong editing on my part. I fixed it.
    I was reading the uuid from the linux drive. I found the proper uuid for the mac osx drive and edited the /etc/grub.d/40_custom file so that error is gone. BTW ~ This may be new to my flavor of linux (linux Mint) but there is no listing as grub2, it is just called grub. but it does give me the correct version as grub2 as 'grub-install.real (GRUB) 2.00-7ubuntu11' I was told in a different google search that legacy grub or grub1 would be listed as 0.98 or earlier. So now I only get the 1 error when choosing chameleon to load into. 'cant find boot0' So I am going to go back into the grub boot menu and go to the command line and see if it shows me where to direct the proper loading in the /etc/grub.d/40_custom file. I got rid of one error I can get rid of the second.

    But to answer your question it "was" giving me an option of booting into chameleon, it just wasn't finding 'boot0', now I have to figure out why.

  4. Yeah, that was giving me problems too. Basically the instructions aren't quite clear. If you have a separate boot partition, instead of "(hd0,1)/boot/boot0" you should probably use "(hd0,1)/boot0". If you just have one big partition, then the above should work fine.

    Next problem is the linked version of Chameleon - that's just a folder, you need to configure those files and build them for this to work. Or, you could do it the simple way - delete the /boot/boot0 folder you created above, mount your OSX partition in linux, copy the {OSXDrive}/usr/standalone/i386/boot0 file to /boot/boot0.

    That should fix your problem.

    1. `` instead of "(hd0,1)/boot/boot0" you should probably use "(hd0,1)/boot0" ``
      thats work like charm for me! thank you very much for that all tips. i got 4 systems in my 2 hds win7 win8 hackintosh and fedora19 its all booting from grub2 now and that is a good thing. PECE!

      Jack from Brazil!

  5. To find Grub's UUID of a drive, simply use the grub-probe command rather than generating, copying and pasting.

    As a side note, this tutorial doesn't work for my situation.

  6. I have a situation where Grub2 does not see the OS X partition at all when doing Sudo grub-update. Wish I could show screenshots because words always come short and even wrong for a non specialist.

    I'll attempt.

    Successfully installed a fully working Snow Leopard. Best choice for a DC7600 motherboard to my opinion. From the Grub2 menu both UBUNTU and XP work. Only OS X fails. It does not fail when engaging from a Chameleon boot menu from an external harddisk. I will have to try that again I think.

    I have no 'boot' directory as you show in the guide. The 'boot' file is in root of the OS X partition, the base directory, and there's no directory called 'boot'. So I don't know where to put boot0 file I got from here

    The occupations on the SSD drive are in order of GPARTED listing ("" are labels given to it by me), [] means no added symbol to GPARTED's partition column:

    /dev/sda1 [] hfs+ "DC7600 OSX_KING_SSD" [37.35 GiB]
    unallocated [] [1.71 GiB]
    /dev/sda2 [key symbol] extended partition [60.55 GiB]
    /deb/sda5 [key symbol] ext4 "UBU_SSD_" [57.76 GiB]
    /dev/sda6 [] linux-swap "swap_KING_SSD" [2.79 GiB]
    /dev/sda3 [] ntfs "WinXP_KING_SSD" [17.73 GiB]
    /dev/sda4 [] hfs+ "BASE_ARCHIVE_KING_SSD" [329.79 GiB]

    I have this entry from a working situation in the past (BURG) but it refuses no to work even though the UUID is correct since I copied it from the GPARTED information of the OS X partition:

    Entry editor - Grub Customizer

    Name: Mac OS X (32-bit) (230GB)

    Type: Other

    Boot sequence

    set root='(hd0,1)'
    search --no-floppy --fs-uuid --set de615d8e-9898-3dfe-8819-e8983277cfaa
    drivemap -s (hd0) ${root}
    chainloader +1

    I really though this was going to be simple.

    Besides, Grub-customizer gives me 'Error building boot sequence' 'Check parameters' all the time, even when selecting Linux and a Linux partition. Something's wrong here I believe.