MBP82

Debian on the MacBookPro8,2 (late 2011)

About

This page is a writeup about my experience in setting up Debian GNU/Linux on the MacBookPro8,2 (late 2011 edition), in pure EFI booting fashion.

While it certainly does not aim at being an exhaustive documentation on how to perform that, I'll be happy to receive feedback, corrections and tips to make the experience better for libre software enthusiasts using this very hardware.

I will try to update this page as I go. So, please, if you see something wrongly documented or know how to solve an issue or two, drop me a mail!

MBP82 models

Bear in mind there's various versions of the MacBookPro8,2 2011 out there. Apart from different RAM/video options, the line was slightly refreshed end of October 2011. While this move seems to have mostly (if not exclusively) brought a speedbump for CPU, GPU & storage, there may be other differences, in hardware and/or firmware, that may lead to different results when trying to reproduce these steps on early 2011 MBP82 machines.

So, just so we're clear, the laptop I carried this install on is a late 2011 MacBookPro 15", with the following options :

I also switched the internal SATA2 500GB HDD (5400rpm, so slow) with a SATA3 240GB SSD (very fast), but that should not affect your ability to install. Due to the numerous problems that this series of machines has had to run SATA3 disks at full speed though, I feel it's important to mention that it works fine for me.

Pre-install

The laptop comes with MacOS X installed. I advise you not to get rid of it, for it is the only way to carry EFI & SMC firmware updates (which sometimes bring fixes & improvements).

Note: if you laptop shipped with OS X Lion like mine did, I advise you to create a USB Lion Recovery Disk Assistant.

Warning: if you're planning to use MacOS X on an external USB drive, for instance, in order to dedicate the internal disk to Debian only, you will be able to run MacOS X, but it won't allow EFI & SMC firmware updates to be carried, unfortunately.

Of course, MacOS X spans the entire disk by default, so we need to shrink its partition. To do so, You can either use diskutil from the command-line, or the graphical Partition Manager which you'll find in Applications/Utilities.

Because Intel Macs use modern GPT partitionning instead of the traditionnal DOS style partitionning, GPT fdisk is a tool of choice to partition the empty space. It is available both for GNU/Linux and MacOS X. However, I found that it wouldn't rename partitions under Lion, so I used it within the Ubuntu installer instead.

Booting the installation media

Intel Macs use a proprietary variant of UEFI, not BIOS, though they can be booted in BIOS emulation mode. The easiest solution to install GNU/Linux on these machines is to install using an CD or DVD (given EFI firmware restrictions on booting legacy USB devices). However, this proves to be very difficult to do when booting the MacBookPro8,2 in BIOS emulation mode, for the kernel fails to see the CD-ROM device after it booted. You can then mount a USB key containing the installer components, or... boot directly in EFI mode and setup a native EFI system, which is what I did and what I will document further.

Note that the late 2011 model is believed to be incapable of booting grub in BIOS emulation mode due to new firmware restrictions, and that EFI may be the only way to go. Here's some chat from the ##apple IRC channel on Freenode, on November 18th 2011. I sure can't confirm it's true, though I can testify that I've been unable to boot in BIOS emulation mode from a BIOS boot partition:

18:23 <Branes> Apple changed the UEFI structure with the newest MacBook Pro's and the latest 
               iMac refresh.
18:23 <Branes> As such, neither rEFIt nor grub (nor grub+) will work.
18:25 <Branes> The change is a little over five weeks old.
18:26 <Branes> Until the rEFIt people wake up and fix the limitation, it won't work at all 
               with the newest EFI firmware that's been shipping in all machines for just over 
       a month.
18:26 <Branes> rf you just bought it, then it has the new UEFI structure.
18:28 <Branes> Apple use 'Protected GPT' which is a dogs' breakfast.
18:30 <Branes> The main problem with pGPT is twofold: 1) no linux loader knows how to deal 
               with it, and 2) it is no better than MBR in that you are limited to four 
       partitions ... and Apple already use three, one for EFI, one for the main OSX volume, 
       and a third for the Recovery partition.
18:34 <Branes> Best be thankful, then, that you bought a new machine now, and not in four 
               months :)
18:35 <klausa> What will they change in 4 months ;)?
18:35 <Branes> klausa: They adopt the changes to UEFI proposed by Microsoft.
18:35 <Branes> Machines then will *only* be able to boot Mac OS X, iOS Desktop, or 
               Windows 7 -- the hardware will not aloow any other OS.

Some of that info is at least partially wrong, since I'm writing this from Debian on the previously mentionned laptop, which now has 6 GPT partitions, and I did install rEFIt with no issue, as far as EFI booting is concerned...

Anyways, since Debian has no support (yet) for EFI booting an installation media (to my knowledge), I used Ubuntu Oneiric's alternate installer, which is basically the Debian installer with a few things changed, like the ability to boot in EFI mode and provide the user with a familiar Debian-based environment.

Pure EFI vs BIOS emulation

Like I said, I'm not sure there's much choice on the specific MacBookPro model I'm talking about, but please prove me wrong (it's possible to boot in BIOS emulation from a CD, for instance, but you'll most probably need the kernel to be patched to see the CD drive).

In any case, there's benefits to booting in pure EFI over BIOS emulation:

There's some drawbacks too:

Installing

So, boot in EFI mode using Oneiric's alternate installer, configure the basics (keyboard, lang, etc.) and when you reach partman, drop to a shell. I then used gdisk to create my partitions (/boot & another for dm-crypt /). Luckily, it comes pre-installed on the alternate CD.

I carried the rest of the install manually, by using:

I won't go into details on how to install a system using the wonderful debootstrap, as it is documented elsewhere on the net. You can retrace most of my steps by reading the relevant sections of my previous tutorial on how to install Debian on a MacBookAir3,1. A few things have changed (partition alignment should now be automatic due to the use of more recent tools, as far as I know), but it mostly remains the same.

The two things you need to do to achieve a successful EFI booting before exiting the installer are:

GPU options

As previously mentionned, the MBP82 has two GPUs:

If you want a laptop that doesn't have a fan blowing on a permanent basis, and whose battery lasts as long as possible, you'll want to disable the ATI card and use the intel IGD.

Unfortunately, it's not a piece of cake:

As a result, the only viable solution I found was to:

Or, you can do the contrary, and boot using the radeon driver. To do so properly, you will need a few more things:

There should be a third option, though I couldn't get it to work properly, that involves applying another patch on top of the two previously mentionned ones, enabling dynamic graphic switching using the vga_switcheroo mecanism. Please send some feedback about making that work if you managed to do so!

Compiling a kernel

There's a very long thread on ubuntuforums which has a lot of different patches. It was quite hard to figure out which ones were still relevant by kernel 3.1.1 for the particular setup I was trying to achieve, but I've got it (mostly) right for me at least.

Since I want my laptop to be silent and have a long battery life, and don't care about 3D effects, the intel IGD is the perfect choice for me. So, from the alternate installer, after chrooting in my freshly installed system, I did the following:

You will find my .config file and the patches which I updated against kernel 3.1.1 underneath the files directory.

Setting up grub-efi

Within the system's chroot and after having mounted /boot, install the grub-efi-amd64-bin package and do the following:

You now have a grub EFI binary (named BOOTX64.EFI so the Apple EFI bootloader can see it - upon reboot press left alt to show the bootmenu) and its modules, and you only lack a /boot/efi/EFI/BOOT/grub.cfg configuration file containing the following (to be adapted to your setup):

menuentry 'Debian GNU/Linux, with Linux 3.1.1' {
    insmod gzio
    insmod part_gpt
    insmod ext2
    set gfxpayload=keep
    # Switch gmux to IGD
    outb 0x728 1
    outb 0x710 2
    outb 0x740 2
    # Power down ATI
    outb 0x750 0
    set root='(hd0,gpt5)'
    echo    'Loading Linux 3.1.1...'
    linux   /vmlinuz-3.1.1+i915+lvds+bl root=/dev/mapper/system-root ro \
        i915.lvds_channels=2 i915.modeset=1 i915.lvds_use_ssc=0 i915.i915_enable_rc6=1 \
        acpi_backlight=vendor elevator=noop
    echo    'Loading initial ramdisk ...'
    initrd  /initrd.img-3.1.1+i915+lvds+bl
}

Note: the important lines are the outb lines which switch the Intel card on and the ATI card off, as well as the options on the linux line:

Configuring

Screen backlight

Thanks to the apple_bl patch, it is possible to adjust the screen backlight by passing the use_gmux=1 option to the apple_bl driver. To make it permanent, create /etc/modprobe.d/apple_bl.conf with the following contents:

options apple_bl use_gmux=1

Note you can add debug=1 if things don't work as they should and you'd like to try and figure out why.

You can then set the backlight with the xbacklight program, or by fiddling directly with /sys/class/backlight/acpi_video0/brightness.

I'd love to get pommed and the F1/F2 keys to work though, but I have had no success so far. Please share you recipes if it works for you!

Keyboard backlight

Lits up when pommed starts, then shuts. Please contribute solutions. I see that in the logs:

 [   14.117009] Registered led device: smc::kbd_backlight
 [...]
 [   22.356982] applesmc: light sensor data length set to 10
 [   36.577601] applesmc: ALV0: read data fail

Note that apart from lighting up my keyboard for a few minutes, that's the only visible thing pommed does, unfortunately.

Special keys

No success using them to control backlights, sound, eject or any other thing. Any clue ?

You can get the normal Function keys to work without having to press Fn at the same time by issuing the following as root:

echo 2 > /sys/module/hid_apple/parameters/fnmode

SD card reader

This one is a bit of a mystery to me, but I finally got it to work by enabling... Wi-Fi (thanks to alvinwu from the gentoo forums who suggested that in the first place) ! In short, if you want Wi-Fi and the ability to read SD cards, chances are this will work out of the box for you, after having jumped through the Wi-Fi section below. If like me, you don't want Wi-Fi, read further.

Unless the bcma and b43 modules are compiled and loaded, IRQ17 is shut early in the process. Here's what the logs vomit on startup:

[   20.627887] irq 17: nobody cared (try booting with the "irqpoll" option)
[   20.627891] Pid: 0, comm: swapper Not tainted 3.1.1-patches #3
[   20.627893] Call Trace:
[   20.627895]  <IRQ>  [<ffffffff81084b0a>] ? __report_bad_irq+0x25/0xb5
[   20.627904]  [<ffffffff81084eda>] ? note_interrupt+0x170/0x1f2
[   20.627907]  [<ffffffff81083700>] ? handle_irq_event_percpu+0x163/0x182
[   20.627911]  [<ffffffff81007efd>] ? read_tsc+0x5/0x14
[   20.627915]  [<ffffffff8105a643>] ? timekeeping_get_ns+0xd/0x2a
[   20.627917]  [<ffffffff81083754>] ? handle_irq_event+0x35/0x55
[   20.627921]  [<ffffffff810603b1>] ? arch_local_irq_save+0x11/0x17
[   20.627924]  [<ffffffff810855c6>] ? handle_fasteoi_irq+0x7c/0x9e
[   20.627927]  [<ffffffff81003ea9>] ? handle_irq+0x1d/0x21
[   20.627929]  [<ffffffff81003bd9>] ? do_IRQ+0x42/0x98
[   20.627933]  [<ffffffff81363bae>] ? common_interrupt+0x6e/0x6e
[   20.627934]  <EOI>  [<ffffffff810561ae>] ? enqueue_hrtimer+0x43/0x6a
[   20.627942]  [<ffffffff811c3124>] ? intel_idle+0xd5/0xfd
[   20.627944]  [<ffffffff811c3103>] ? intel_idle+0xb4/0xfd
[   20.627948]  [<ffffffff81295c8e>] ? cpuidle_idle_call+0xf0/0x175
[   20.627951]  [<ffffffff81001251>] ? cpu_idle+0x9d/0xe1
[   20.627955]  [<ffffffff816a5b39>] ? start_kernel+0x3be/0x3ca
[   20.627958]  [<ffffffff816a5140>] ? early_idt_handlers+0x140/0x140
[   20.627962]  [<ffffffff816a53a9>] ? x86_64_start_kernel+0x105/0x113
[   20.627963] handlers:
[   20.627969] [<ffffffffa0146727>] sdhci_irq
[   20.627971] Disabling IRQ #17

When blacklisting b43 (I don't want wifi, sorry !), the mmc driver initializes as such:

[    3.641398] sdhci-pci 0000:02:00.1: found 1 slot(s)
[    3.641421] sdhci-pci 0000:02:00.1: PCI INT B -> GSI 17 (level, low) -> IRQ 17
[    3.641425] sdhci-pci 0000:02:00.1: Invalid iomem size. You may experience problems.
[    3.641503] sdhci-pci 0000:02:00.1: setting latency timer to 64
[    3.641508] sdhci [sdhci_add_host()]: mmc0: Auto-CMD23 available
[    3.641527] mmc0: no vmmc regulator found
[    3.641564] sdhci: =========== REGISTER DUMP (mmc0)===========
[    3.641570] sdhci: Sys addr: 0x00000000 | Version:  0x00001502
[    3.641576] sdhci: Blk size: 0x00000000 | Blk cnt:  0x00000000
[    3.641582] sdhci: Argument: 0x00000000 | Trn mode: 0x00000000
[    3.641588] sdhci: Present:  0x1ff80000 | Host ctl: 0x00000000
[    3.641594] sdhci: Power:    0x00000000 | Blk gap:  0x00000000
[    3.641600] sdhci: Wake-up:  0x00000000 | Clock:    0x00000000
[    3.641606] sdhci: Timeout:  0x00000000 | Int stat: 0x00000000
[    3.641612] sdhci: Int enab: 0x00ff0003 | Sig enab: 0x00ff0003
[    3.641618] sdhci: AC12 err: 0x00000000 | Slot int: 0x00000000
[    3.641624] sdhci: Caps:     0x176ec8b0 | Caps_1:   0x03002177
[    3.641630] sdhci: Cmd:      0x00000000 | Max curr: 0x00000000
[    3.641634] sdhci: Host ctl2: 0x00000000
[    3.641640] sdhci: ADMA Err: 0x00000000 | ADMA Ptr: 0x00000000
[    3.641642] sdhci: ===========================================
[    3.641672] Registered led device: mmc0::
[    3.641723] mmc0: clock 0Hz busmode 1 powermode 0 cs 0 Vdd 0 width 0 timing 0
[    3.641781] mmc0: SDHCI controller on PCI [0000:02:00.1] using ADMA
[    3.641874] mmc0: mmc_rescan_try_freq: trying to init card at 400000 Hz
[    3.641878] mmc0: clock 0Hz busmode 1 powermode 1 cs 0 Vdd 21 width 0 timing 0
[    3.652705] mmc0: clock 400000Hz busmode 1 powermode 2 cs 0 Vdd 21 width 0 timing 0

But then disables IRQ17 and issues the previously mentionned output in the logs. Loading the b43 module and {un,re}loading the sdhci & sdhci_pci seems to do the trick.

Note: once b43 has been loaded, it can be safely unloaded for continued SD card operation. If you happen to be more clever and/or more patient than I am and feel like debugging further to get to the core of the problem, be my guest, as I'll be glad to know!

Suspend/resume

You need to install the following packages:

To enable suspend-to-ram, uncomment the following in /etc/default/acpi-support:

LID_SLEEP=true

...and make sure there's a file in /etc/pm/config.d/ with the following:

SLEEP_MODULE="uswsusp"
SUSPEND_MODULES="b43 bcma"

When the laptop suspends to RAM and then comes back from sleep, the discrete graphics (ATI) is awoken. We need to shut it down again so the intel display can take over. To do so, you just need to compile a little C program and have pm-utils call it upon each wakeup:

sudo -s
cd /root
cat > fixgpu.c << EOF

#include <stdio.h>
#include <sys/io.h>

#define PORT_SWITCH_DISPLAY 0x710
#define PORT_SWITCH_SELECT 0x728
#define PORT_SWITCH_DDC 0x740
#define PORT_DISCRETE_POWER 0x750

static int gmux_switch_to_igd()
{
    outb(1, PORT_SWITCH_SELECT);
    outb(2, PORT_SWITCH_DISPLAY);
    outb(2, PORT_SWITCH_DDC);
    return 0;
}

static void mbp_gpu_power(int state)
{
    outb(state, PORT_DISCRETE_POWER);
}

int main(int argc, char **argv)
{
    if (iopl(3) < 0) {
        perror ("No IO permissions");
        return 1;
    }
    mbp_gpu_power(0);
    gmux_switch_to_igd();
    return 0;
}
EOF

gcc -O2 -o /usr/local/sbin/fixgpu fixgpu.c

cat > /etc/pm/sleep.d/10-fixgpu << EOF
#!/bin/sh
#
# reset the IGD
case "${1}" in
    hibernate|suspend)
            ;;
    resume|thaw)
        /usr/local/sbin/fixgpu
            ;;
esac
EOF

chmod a+x /etc/pm/sleep.d/10-fixgpu

Note: you need to make sure you have the vbetool package uninstalled, else it will eat 99% CPU resources and prevent your laptop from going back to sleep.

Touchpad

Works out of the box with the following section in /etc/X11/xorg.conf:

Section "InputClass"
        MatchIsTouchpad "true"
        MatchProduct "bcm5974"
        Identifier "Multitouch Touchpad"
        Driver "multitouch"
    MatchDevicePath "/dev/input/event*"
EndSection

For those who like the OS X Lion "natural scrolling", it is possible to emulate it with the synaptics driver (thanks to Sascha Teske for mentionning this to me). To do so, just issue the following:

xmodmap -e "pointer = 1 2 3 5 4 7 6 8 9 10 11 12"

If you like it, you can add the "pointer = ..." argument to your .xmodmaprc. For details on how this works, please refer to the archwiki page about Xmodmap.

Sound

Works out of the box when installing alsa.

Facetime HD camera

Untested (please contribute).

CD/DVD drive

Seems to work fine out of the box when EFI booting. Burning CD's works, but I fucked two CDs up before getting one properly burnt. I suspect one has to reduce the speed, for writing at top speed (and it is fast indeed) seems to not do things right. It seems like OS X caps writing speed, so emulating it seems wise.

I'll have to carry more tests to figure out the best combination. Feedback welcome.

USB

Seems to work fine out of the box. Haven't made an extensive use of USB devices though.

Ethernet

Gigabit Ethernet works out of the box, using the tg3 driver.

Wi-Fi

Doesn't work out of the box. Not that I really care, but some people out there have made it work with passion. Well, I didn't care, until I realized I needed the working b43 module loaded to get my SD card reader work (see above).

So, to get Wi-Fi working, you need to patch your 3.0-3.1 kernel with some more patches (quite a few, actually), enable BCMA in the kernel, and add firmware to /lib/firmware/b43. You'll find the patch I used against 3.1.1, as well as the firmware binaries (which you should extract with b43-fwcutter, possibly with some help from this bcm43xx reference page) in my files directory.

Note: I got the firmware from the walkthrough Baughn posted on ubuntuforums, as I couldn't be bothered to spend much time on this Wi-Fi thing. So I figured you may want to go down the easy firmware path too ;)

Linux 3.2rc3 (see this post) is supposed to bring out-of-the box support for the BCM4331 802.11a/b/g/n, but I haven't managed to get the intel display to work with it, unfortunately. Fixes highly welcome, for I don't intend to be stuck with kernel 3.1.x all my MBP82 life ! ;)

Bluetooth

Untested. Modules are loaded, but I blacklisted them. Please contribute.

TOFIX/TODO

Please feel free to help with the following:

Please contribute corrections/remarks/tips/solutions (by mailing them to fluor at poivron dot org) and fuel the bugreports, be they on bugs.debian.org or elsewhere, so things go forward!

mike dentifrice, 2011/12/03