How to test GRUB 2 on Macbook

This alternate page explains the steps for a Mac Mini.

Build GRUB

Obtain the latest source from svn repository.

For the non latest models, compile 32-bit EFI:

./configure --with-platform=efi --target=i386
make

For the latest models, compile 64-bit EFI:

./configure --with-platform=efi --target=x86_64
make

It is recommended to use a Linux distribution (including its kernel) which has the same architecture (32 or 64 bit) as the EFI, in order to avoid that grub must launch a kernel with a different architecture. However, you can cross compile between i386 and x86_64, just make sure to install the gcc-multilib package.

If you don't want to have all binaries prefixed with i386 or x86_64 add to ./configure --program-prefix=""

If after you've installed and configured, when you reboot you get "error: unsupported while loading grub.efi", it is likely you compiled the wrong version (64 vs 32 bit). Try the other one.

Install GRUB

If you like an adventure, you can install GRUB onto current boot media. If not, try a USB disk. On Mac OS X, create a folder (note that 'something' must be replaced with the Volume name of the USB disk):

sudo mkdir -p /Volumes/something/efi/grub

Then, create an EFI application for GRUB and copy it and the other modules:

Grub <= 1.98

./grub-mkimage -d . -o grub.efi part_gpt hfsplus fat ext2 normal sh chain boot configfile linux
sudo cp grub.efi *.mod *.lst /Volumes/something/efi/grub

Grub > 1.98

./grub-mkimage -O x86_64-efi -d . -o grub.efi -p "" part_gpt hfsplus fat ext2 normal chain boot configfile linux multiboot
sudo cp grub.efi *.mod *.lst /Volumes/something/efi/grub

The safest way to test grub efi is to load it from rEFIt. It's quite easy, just copy grub.efi and related files to /efi/grub/ in any HFS+/EXT2/EXT3/FAT partition, rEFIt will find it automatically and list it in the boot menu.

You can also use grub.efi as standalone loader. First, place grub.efi in a hfs+ partition, such as /Volumes/something, then uses bless it:

sudo bless --folder=/Volumes/something --file=/Volumes/something/efi/grub/grub.efi --setBoot

Use a kernel which recognizes your Mac hardware model

Make sure your kernel knows the "FrameBufferBase" and "PixelsPerScanLine" for your particular Mac hardware model. Type the following command in a MacOS X terminal (for a dual-graphic card system, switch first to the integrated graphics and do a full reboot) :

sudo ioreg -lw0 |grep manufacturer|cut -b25-80;sudo ioreg -lw0|grep "product-name"|cut -b 25-80;sudo dtrace -qn 'BEGIN{boot_args=((struct boot_args*)(`PE_state).bootArgs);printf("FrameBuff erBase: 0x%08x\nPixelsPerScanLine: %d\nHorizontalResolution: %d\nVerticalResolution: %d", boot_args->Video.v_baseAddr, boot_args->Video.v_rowBytes/4, boot_args->Video.v_width, boot_args->Video.v_height);exit(0)} '

which gives the following output :

<"Apple Inc.">
<"MacBookPro5,3">
FrameBufferBase: 0xc0030000
PixelsPerScanLine: 2048
HorizontalResolution: 1440
VerticalResolution: 900

and make sure that the file "drivers/video/efifb.c" of your kernel source has the correct values.

If not, add the following parameter to the linux kernel command line in grub.cfg (to be tested) :

video=efifb:base:0xc0030000,stride:2048,width:1440,height:900

The kernel module "efifb" must be added to the init RAM disk :

echo efifb | sudo tee -a /etc/initramfs-tools/modules
echo uvesafb | sudo tee -a /etc/initramfs-tools/modules # For NVidia splash
sudo update-initramfs -u

If that does not work, recompile your kernel with the correct values and "efifb" compiled statically in the kernel.

Loading OSX

To load OSX, use the following section in grub.cfg:

menuentry "MacOSX" {
  # Search the root device for Mac OS X's loader.
  search --set /usr/standalone/i386/boot.efi
  # Load the loader.
  chainloader /usr/standalone/i386/boot.efi
}

You can also pass parameter to the loader, like this:

menuentry "MacOSX (verbose mode)" {
  # Set the root device for Mac OS X's loader.
  root=(hd0,2)
  # Load the loader.
  chainloader /usr/standalone/i386/boot.efi -v
}

Loading legacy system

You can use appleloader to boot from legacy disk/cdrom/usb:

menuentry "Boot from MBR" {
  appleloader HD
}
menuentry "Boot from CD" {
  appleloader CD
}
menuentry "Boot from USB" {
  appleloader USB
}

The last one may not work on some model.

Loading linux

First of all, you need 2.6.25 kernel, 2.6.24 doesn't work very well. You can use the following section in grub.cfg:

menuentry "Linux (with bios dump)" {
  search /vmlinuz
  loadbios /boot/vbios.bin /boot/int10.bin
  linux /vmlinuz root=/dev/sda3 video=efifb
  initrd /initrd.img
}

menuentry "Linux (with bios dump and fix video)" {
  search /vmlinuz
  fix_video
  loadbios /boot/vbios.bin /boot/int10.bin
  linux /vmlinuz root=/dev/sda3 video=efifb
  initrd /initrd.img
}

menuentry "Linux (without bios dump)" {
  search /vmlinuz
  fakebios
  linux /vmlinuz root=/dev/sda3 video=efifb
  initrd /initrd.img
}

First, you need to decide whether to use a bios dump. Bios dump is necessary for certain x.org drivers, as they need to scan the video rom for important data structure such as DDC table. Some driver even calls INT 10 to locate VESA BIOS, so the IVT for INT10 needs to be set properly as well.

To get the bios dump, you need to boot into pc mode, then use these commands to generate dump files:

dd if=/dev/mem of=/boot/vbios.bin bs=65536 skip=12 count=1
dd if=/dev/mem of=/boot/int10.bin bs=4 skip=16 count=1

It would create /boot/vbios.bin and /boot/int10.bin to be used by the loadbios command.

In some cases, bios dump is not needed, or it's not possible to boot into pc mode (such as Xserver). Then you need to use fakebios, so that grub would try to mimic a bios environment.

For intel cards, you may experience screen distortion in the console mode. To solve this problem, use fix_video command in grub.cfg. Currently, fix_video has been reported to work with Intel 945GM, Intel 965GM and Intel X3100.

Sometimes, x.org driver doesn't work even with bios dump. Then you need to use frame buffer instead. In xorg.conf, use fbdev in Device section, it may look like this:

Section "Device"
        Identifier      "Configured Video Device"
        Driver          "fbdev"
EndSection

Linux boot options

In some cases, you need to add these options to linux command line.

acpi=force

This is usually not needed with fakebios/loadbios, but if you are still having the ata timeout or usb not response issue, try this option.

noefi

In 2.6.27-2.6.28, amd64 kernel, there is a bug that would cause efi to hang. Since 2.6.27, it would only map available RAM, and the efi runtime needs to be mapped with efi_ioremap. However, efi_ioremap only reserves MAX_EFI_IO_PAGES (100) pages for efi, which is not enough for apple 64-bit firmware (about 17m). To workaround this, you need to pass the noefi option which tells the kernel to disable efi.

Key mapping

As EFI doesn't recognize ctrl sequence, we need to use special key to mimic its function. Currently, I use the following mappings:

F1 = ctrl-x
F2 = ctrl-a
F3 = ctrl-e

Troubleshouting

Wrong graphic card is activated

If your grub output looks like the following :

ROM image is present
   [Linux-bzImage, setup=0x3400, size=0x3d56c0]
   [Initrd, addr=0x3f7fff000, size=0x7f0349]

it means it cannot use the activated graphic card. Solution : switch to the other graphic card in MacOS X and reboot. The output should look like the following :

ROM image is present
   [Linux-bzImage, setup=0x3400, size=0x3d56c0]
Video mode: 1440x900-32@0
Display Controller: 2:0.0
Device id: 64710de
MMIO(0): 0xe4000000
VMEM(1): 0xc0000000
MMIO(3): 0xe2000000
Frame buffer base : 0xc0030000
Video line length: 8192
   [Initrd, addr=0x3f7fff000, size=0x7f0349]

GrubWiki: TestingOnMacbook (last edited 2010-09-03 05:17:34 by MetaTech)