USB Booting Linux on a Mac with 32-bit EFI

A friend recently gave me his old Apple iMac (Late 2006) after it began having graphics issues. Before freecycling it, I wanted to try to boot Linux on it, just for kicks. That turned out to be harder than I imagined it would be…

There were two main problems:

  1. Some Macs of this era had only 32-bit  EFI bootloaders; and
  2. Many Linux distributions are only designed to do 64-bit  UEFI boot.
This page describes how I overcame these obstacles. It assumes you are using a Mac to prepare the USB device, but the instructions can easily be adapted for other situations.

If you want to skip the backstory, jump directly to Booting Linux.

Table of contents:

Booting memtest86

The first thing I wanted to try was memtest86. I downloaded the memtest86 bootable USB image, then used diskutil to find and prepare my USB stick, and dd to copy the memtest86 image to my USB device:

$ diskutil list
/dev/disk0
   #:                       TYPE NAME                    SIZE       IDENTIFIER
   0:      GUID_partition_scheme                        *500.3 GB   disk0
   1:                        EFI EFI                     209.7 MB   disk0s1
   2:          Apple_CoreStorage                         499.4 GB   disk0s2
   3:                 Apple_Boot Recovery HD             650.0 MB   disk0s3
/dev/disk1
   #:                       TYPE NAME                    SIZE       IDENTIFIER
   0:                  Apple_HFS Macintosh HD           *499.1 GB   disk1
                                 Logical Volume on disk0s2
                                 88325CAC-4B98-4658-B4D2-3EE43D41DBAD
                                 Unlocked Encrypted
/dev/disk2
   #:                       TYPE NAME                    SIZE       IDENTIFIER
   0:     FDisk_partition_scheme                        *16.2 GB    disk2
   1:               Windows_NTFS Untitled                16.2 GB    disk2s1
# diskutil unmountDisk /dev/disk2
Unmount of all volumes on disk2 was successful
# dd if=memtest86-usb.img of=/dev/disk2 bs=4096k
37+1 records in
37+1 records out
157286400 bytes transferred in 25.257847 secs (6227229 bytes/sec)

Holding down Option while booting brought up the Startup Manager, which allowed me to select EFI Boot. Worked perfectly! (No memory errors, by the way. ;-)

In fact, there were two EFI Boot  entries, which both worked – more on that later.

Examining the memtest86 image

Unlike many of the Linux distribution images, which come as ISO files, memtest86 came already designed for USB booting. Here are some of its properties, information which would later be useful.

Checking the image file itself, notice that it’s actually a hard drive image:

$ file memtest86-usb.img
memtest86-usb.img: x86 boot sector; partition 1: ID=0xee, starthead 0, startsector 1, 307199 sectors, code offset 0xc0

At first its partition layout looked pretty odd to me:

$ fdisk memtest86-usb.img
Disk: memtest86-usb.img	geometry: 609/8/63 [307200 sectors]
Signature: 0xAA55
         Starting       Ending
 #: id  cyl  hd sec -  cyl  hd sec [     start -       size]
------------------------------------------------------------------------
 1: EE    0   0   2 -   19  31  12 [         1 -     307199] <Unknown ID>
 2: 00    0   0   0 -    0   0   0 [         0 -          0] unused
 3: 00    0   0   0 -    0   0   0 [         0 -          0] unused
 4: 00    0   0   0 -    0   0   0 [         0 -          0] unused
I did some reading, and discovered that partition type EE is known as a protective MBR, used when the drive is partitioned using the newer GUID Partition Table (GPT) standard.

The GPT layout looks like:

$ gpt show memtest86-usb.img
   start    size  index  contents
       0       1         PMBR
       1       1         Pri GPT header
       2      32         Pri GPT table
      34    2014         
    2048  100353      1  GPT part - EBD0A0A2-B9E5-4433-87C0-68B6B72699C7
  102401    2047         
  104448  202719      2  GPT part - C12A7328-F81F-11D2-BA4B-00A0C93EC93B
  307167      32         Sec GPT table
  307199       1         Sec GPT header

The GUIDs have some meaning, which is:

GUIDPurpose
EBD0A0A2-B9E5-4433-87C0-68B6B72699C7Basic data partition
Used for storing the majority of data on the device
C12A7328-F81F-11D2-BA4B-00A0C93EC93BEFI System partition
Contains EFI bootloaders, etc

By default, only the data partition is mounted, but one can mount the EFI System partition also:

# diskutil mountDisk /dev/disk2
Volume(s) mounted successfully
$ mount | grep -i disk2
/dev/disk2s1 on /Volumes/Untitled (msdos, local, nodev, nosuid, noowners)
/dev/disk2s2 on /Volumes/Untitled 1 (msdos, local, nodev, nosuid, noowners)

Here is a listing of the EFI directory from the data partition:

$ find -s /Volumes/Untitled/EFI
/Volumes/Untitled/EFI
/Volumes/Untitled/EFI/BOOT
/Volumes/Untitled/EFI/BOOT/BOOTIA32.efi
/Volumes/Untitled/EFI/BOOT/BOOTX64.efi
/Volumes/Untitled/EFI/BOOT/Benchmark
/Volumes/Untitled/EFI/BOOT/mt86.png
/Volumes/Untitled/EFI/BOOT/unifont.bin

And here is a listing of the EFI directory from the EFI System partition:

$ find -s /Volumes/Untitled\ 1/EFI
/Volumes/Untitled 1/EFI
/Volumes/Untitled 1/EFI/BOOT
/Volumes/Untitled 1/EFI/BOOT/BOOTIA32.efi
/Volumes/Untitled 1/EFI/BOOT/BOOTX64.efi
/Volumes/Untitled 1/EFI/BOOT/Benchmark
/Volumes/Untitled 1/EFI/BOOT/mt86.png
/Volumes/Untitled 1/EFI/BOOT/unifont.bin

Originally I thought that the two EFI Boot  entries were explained by having both BOOTIA32.efi and BOOTX64.efi, but now I know that it is caused by having the EFI bootloader in both partitions.

Summary

For this particular image, we have:

32-bit vs 64-bit EFI

One of the first things I checked on this Mac was whether it had a 32-bit or 64-bit processor. The processor is an Intel® Core™2 Duo Processor T7400 which, according to ARK, is 64-bit. So I mistakenly thought that the EFI would be 64-bit, too. Wrong!

EveryMac.com has an excellent list of machines and which processor and EFI they support. There I found that this Mac had a 32-bit EFI.

Another way to find this information is with a command:

$ ioreg -l -p IODeviceTree | grep firmware-abi
    | |   "firmware-abi" = <"EFI32">

Note that you can boot a 64-bit kernel from a 32-bit EFI, provided that the bootloader and kernel support it.

Booting Linux

General procedure

The goal is to get a USB stick with:

  1. a writeable data partition (so we can, eg, make changes to the grub.cfg file); and
  2. a 32-bit EFI bootloader in /EFI/BOOT/BOOTIA32.efi
Most Linux distributions don’t seem to ship a 32-bit EFI bootloader, but Debian does, so we can just rip it out of there.

What doesn’t work: dding the hybrid ISO directly

Your initial thought might be to use dd to write a hybrid ISO (as most Linux distributions come these days) directly to the USB stick, just as you’d do for a PC. That’s going to fail.

The Ubuntu 15.10 (amd64) ISO looks like this:

$ file -k ubuntu-15.10-desktop-amd64.iso
ubuntu-15.10-desktop-amd64.iso: ISO 9660 CD-ROM filesystem data 'Ubuntu 15.10 amd64             ' (bootable)
- x86 boot sector; partition 2: ID=0xef, starthead 254, startsector 2279532, 4544 sectors, code offset 0x52
% fdisk ubuntu-15.10-desktop-amd64.iso
Disk: ubuntu-15.10-desktop-amd64.iso	geometry: 570/64/63 [2301536 sectors]
Signature: 0xAA55
         Starting       Ending
 #: id  cyl  hd sec -  cyl  hd sec [     start -       size]
------------------------------------------------------------------------
 1: 00    0   0   0 -    0   0   0 [         0 -          0] unused      
 2: EF 1023 254  63 - 1023 254  63 [   2279532 -       4544] 
 3: 00    0   0   0 -    0   0   0 [         0 -          0] unused      
 4: 00    0   0   0 -    0   0   0 [         0 -          0] unused      
$ gpt show ubuntu-15.10-desktop-amd64.iso
    start     size  index  contents
        0        1         MBR
        1  2279531         
  2279532     4544      2  MBR part 239
  2284076    17460         
While you could theoretically modify the EFI System partition, there really isn’t enough space on there to put everything. The data partition is ISO9660 format, which some systems might let you mount read-write, but I couldn’t see how in OS X.

Using UNetbootin

By using UNetbootin, one can prepare the USB key for editing. I won’t go into the operation of UNetbootin since I think it’s fairly self-explanatory. (One tip, though: erase the disk in Disk Utility first.)

The new USB disk looks like:

# fdisk /dev/disk2
Disk: /dev/disk2	geometry: 1972/255/63 [31690752 sectors]
Signature: 0xAA55
         Starting       Ending
 #: id  cyl  hd sec -  cyl  hd sec [     start -       size]
------------------------------------------------------------------------
*1: 0B 1023 254  63 - 1023 254  63 [         2 -   31690750] Win95 FAT-32
 2: 00    0   0   0 -    0   0   0 [         0 -          0] unused      
 3: 00    0   0   0 -    0   0   0 [         0 -          0] unused      
 4: 00    0   0   0 -    0   0   0 [         0 -          0] unused      

Adding 32-bit GRUB EFI

Now that you have a read-write partition, you can add the 32-bit GRUB EFI bootloader. I took the one from the Debian netinst (“network install”) CD image. From that image, you need:

which, conveniently, need to be placed in the exact same location on your USB device. I used 7-Zip to extract the contents from the ISO, but you could use any program you find convenient.

Here are the commands I used:

$ cd /Volumes/Ubuntu   # the name you used in Disk Utility when erasing the disk
$ 7z x ~/Downloads/debian-8.3.0-amd64-i386-netinst.iso efi/boot/bootia32.efi boot/grub/i386-efi/

7-Zip [64] 15.09 beta : Copyright (c) 1999-2015 Igor Pavlov : 2015-10-16
p7zip Version 15.09 beta (locale=utf8,Utf16=on,HugeFiles=on,64 bits,8 CPUs x64)

Scanning the drive for archives:
1 file, 583008256 bytes (556 MiB)  

Extracting archive: /Users/fission/Downloads/debian-8.3.0-amd64-i386-netinst.iso

WARNINGS:
There are data after the end of archive

--
Path = /Users/fission/Downloads/debian-8.3.0-amd64-i386-netinst.iso
Type = Iso
WARNINGS:
There are data after the end of archive
Physical Size = 581793792
Tail Size = 1214464
Created = 2016-01-23 15:20:13
Modified = 2016-01-23 15:20:13

Everything is Ok

Archives with Warnings: 1

Warnings: 1
Folders: 1
Files: 242
Size:       1925797
Compressed: 583008256

And that’s it! You now have a USB device that will boot on a Mac with 32-bit EFI.

Odds & sods

There are a couple of quirks I found (not related to EFI booting) which I thought I’d include here for reference.

Video modes

I found it was necessary to edit boot/grub/grub.cfg to include the kernel option nomodeset to prevent the console video from being trashed. I changed the original:

linux /casper/vmlinuz.efi file=/cdrom/preseed/ubuntu.seed boot=casper quiet splash ---
to:
linux /casper/vmlinuz.efi file=/cdrom/preseed/ubuntu.seed boot=casper nomodeset ---

You may find a slightly different command necessary depending on your hardware and kernel release. digium has a good article on their site for this: How to disable the Linux frame buffer if it’s causing problems.

Console-only boots

For somewhat murky reasons, many distributions have switched over to the confusing systemd. On these systems (eg Ubuntu), the text kernel option no longer does what it’s supposed to. (One would think the systemd folks could’ve made it work but I guess they chose not to.)

Anyhow, there is a (much longer and less obvious) option which does work. Add systemd.unit=multi-user.target to your kernel parameters, eg:

linux /casper/vmlinuz.efi file=/cdrom/preseed/ubuntu.seed boot=casper nomodeset systemd.unit=multi-user.target ---

Typically I’ll have a graphical entry and a text entry so I can decide at boot time without having to remember that particular incantation.

References

  1. GUID Partition Table - Wikipedia
  2. EveryMac.com: Which [Intel Macs] have a 64-bit EFI?
  3. UEFIBooting - Ubuntu Community Help Wiki
  4. Ask Ubuntu: 32-Bit UEFI Boot Support