Archlinux on a MacBook Pro 15'' Model A1211

Archlinux on a MacBook Pro 15'' Model A1211

History

I got an old Mac from a collegue at work. Apple decided not to support those devices anymore, anyway, they date back to 2006. I think, it’s a pitty, because this Mac has a solid case, a pretty fast 64-bit processor (sorry Archlinux32, no test machine for you) and a graphic chip which is not melting away like in later models (I don’t name brand names here)..

Here the specifications:

  • 2.3 GHz Intel Core 2 Duo
  • 2GB 667 DDR2 SDRAM
  • OSX 10.6.8
  • ATI Radeon X1600 256 MB RAM, 1440x900, 32 bit

I didn’t try any Sierra OS X hacks (or installing a Capitan, rumours are, it works even on such an old laptop) on old hardware and besides, Archlinux is a better choice for a developer on a Mac. Although there are still MacPorts for OS X 10.6.x (no Brew though), it can be quite painful to get something compiled on a Mac OS that old.

As we will see later, we want to keep OS X around to be able to change some settings, extract some firmware, etc.

Installation

Prepare for dual installation

We have a whooping 120 GB hard disk space, so I shrank the OS X partition to 64 GB. This can be done in the Disk Utility.app, just leave EFI in peace, set OSX to 64 GB and assign the rest of the hard disk as free space.

Prepare the USB stick for installation, I had no luck with the standard ISO, but a hand-crafted USB-stick worked:

hdiutil convert -format UDRW -o archlinux-2018.09.01-x86_64.img archlinux-2018.09.01-x86_64.iso 
dd if=archlinux-2018.09.01-x86_64.dmg of=/dev/disk2 bs=1m

EFI boot

I used ReFIT for MAC to improve the somewhat limited EFI environment of an early Mac (don’t get me wrong, it’s pretty impressive that such an old machine already had EFI, but nowadays this EFI shows its age).

The firmware is a 32-bit EFI without a proper command line mode, causing trouble all along. I didn’t take ReFind as I didn’t expect the 32-bit EFI to be currently supported, especially as I see Tianocore failing to build with more modern 32-bit binutils and gcc.

I installed a 32-bit GRUB onto the EFI partition as a second boot option along to OSX. This one then boots ArchLinux. This is easier than trying to load a 64-bit kernel with kernel EFI stub support from an 32-bit EFI environemnt with systemd-boot.

ATI VESA BIOS

I didn’t want to boot into legacy mode to make the VGA BIOS visible, so I got a nice problem during KMS switching during early boot: the graphical output just froze. The irony here is that modern Linux and Xorg don’t care at all about the old VGA/VESA BIOS, but they do so for KMS, where the kernel has to rely on 16-bit firmware functions in the video BIOS to program the video chip for graphics mode.

All I got was the following kernel and Xorg error messages:

[2.052705] [drm] initializing kernel modesetting (RV530 0x1002:0x71C5 0x106B:0x0080 0x00).
[2.052742] radeon 0000:01:00.0: Invalid PCI ROM header signature: expecting 0xaa55, got 0xa1a1
[2.052817] [drm:radeon_get_bios [radeon]] *ERROR* Unable to locate a BIOS ROM
[2.052825] radeon 0000:01:00.0: Fatal error during GPU init
[2.053037] radeon: probe of 0000:01:00.0 failed with error -22
...
[31.041] (EE) open /dev/dri/card0: No such file or directory

So this basically translates to: “I don’t have a direct rendering interface, because there is no video card, because there is no BIOS for that card”.

The key idea was to extract the VESA BIOS on a distribution which handles the KMS switching correctly (in my case an old Ubuntu 10).

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

Verify that you actually got the right firmware. There is an error message when booting the kernel saying:

[2.052742] radeon 0000:01:00.0: Invalid PCI ROM header signature: expecting 0xaa55, got 0xa1a1

so we expect to find that signature at the beginning of the vbios.bin file:

hexdump -C vbios.bin | head -n 1
00000000  55 aa 7d e9 7f 02 00 00  00 00 00 00 00 00 00 00  |U.}.............|

This firmware comes into /lib/firmware/radeon/vbios.bin to be available during boot.

The next problem was that the radeon module in the Linux kernel doesn’t know about this firmware. There is a patch in https://bugs.freedesktop.org/show_bug.cgi?id=26891 for older kernels, but it translates easily to the latest kernel. All it does is to load the vbios.bin file from the right place, when all the other options fail.

My version of the module is here, check out function radeon_read_bios_from_firmware and the code calling that function.

In order to use the Radeon driver for KMS as early as possible, I put it into the init-RAM-disk:

So, I added to /etc/mkinitcpio.conf and rebuilt the ram disks:

MODULES=(radeon)
FILES=(/usr/lib/firmware/radeon/vbios.bin)

“Total Darkness” after 10 minutes

Everything was running smoothly.. for about 10 minutes. Then my LCD display just went pitch black.

Setting the brightness manually didn’t help:

xrandr --output LVDS --brightness 1

(it did work later though to set the brightness between 0.0 and 1.0)

The trick is to tell the radeon module to handle the LCD backlight, not one of the Apple brightness modules. In /etc/modprobe.d/radeon.conf put:

options radeon backlight=1

Also handy is the https://aur.archlinux.org/packages/brightd/, though I think also systemd-backlight can nowadays at least save the brightness across reboots and suspends.

Function keys or special keys

If you don’t need the special keys for controlling the volume and brightness but instead the old Fxx function keys, add the following to /etc/modprobe.d/hid_apple.conf:

options hid_apple fnmode=2

Camera

Here we come to iSight and why we need OS X around to extract the proper firmware.

https://wiki.archlinux.org/index.php/Mac#Webcam has a really nice walkthrough.

Shortly, you need https://aur.archlinux.org/packages/hfsprogs/ to mount the HFS partition. There you will find a file called AppleUSBVideoSupport in /System/Library/Extensions/IOUSBFamily.kext/Contents/PlugIns/AppleUSBVideoSupport.kext/Contents/MacOS.

You will also need https://aur.archlinux.org/packages/isight-firmware-tools/. It contains tools to extract the file containg the firmware called isight.fw from AppleUSBVideoSupport.

Finally it contains an udev rule in /etc/udev/rules.d/isight.rules which then makes sure the firmware is also loaded on startup during detection of the camera via udev.

Wifi

The wireless card was supported without any problems. Just some channels were not visible.

Install wireless-regdb and make sure to enable the proper regulatory domain in /etc/conf.d/wireless-regdom:

WIRELESS_REGDOM="CH"

The regulatory domain has to be set properly, put it into /etc/modprobe.d/regdom.conf:

options cfg80211 ieee80211_regdom=CH

(CH is for Switzerland, pick your own country here)

Note: I think my method is deprecated and you can also specify the regulatory domain directly in wpa_supplicant.conf, but then how to use systemd-networkd with that?

Fans and sensors

macfanctl from the AUR works nicely, also lm_sensors had no problems to get the sensor data.

Power consumption

cpupower seems to work fine. Just make sure the ‘p4-clockmod’ module is loaded at boot.

Note: I didn’t try powertop or other tweaks. I got some worriesome ticking noises of the hard disk after a suspend and my battery is not that powerful anyway, so I’ll run mostly on net power.

Mouse buttons

Managers might like to use only one mouse button. Also keyboard fanatics may be happy by just switching off the mousepad completly.

The one button mouse is a disaster for people being used to Xorg copy- paste or Oberon enthusiasts used to three mouse buttons.

Scrolling with two fingers is nice, but per default they are enabled only for up and down. I enabled also scrolling to the left and right. Besides, the keyboard is missing PageUp, PageDown keys, which is a usability nightmare when you want to scroll bigger source code files or web pages (yes, I know there is Fn-Page, but having Ctrl, Alt, Meta and Fn all on the same spot doesn’t make it easier to find the right one).

Side note: I’m using Fn for keyboard scrolling (PgUp, PgDown), Ctrl for Wordstar short-cuts, “Alt” for Notion (window manager) shortcuts, and they are really CLOSE together..

Change /etc/X11/xorg.conf.d/50-synaptics.conf as follows to your likings:

Section "InputClass"
	Identifier "Touchpad Catchall"
	Driver "synaptics"
	MatchIsTouchpad "on"
	Option "TapButton1" "0"
	Option "TapButton2" "3"
	Option "TapButton3" "2"
	Option "VertTwoFingerScroll" "1"
	Option "HorizTwoFingerScroll" "1"
	Option "ClickFinger2" = 0
	Option "ClickFinger3" = 0
EndSection

TabButton1=1 only leads to all kind of frantic behaviour, because I touch the touchpad by accident too often. ClickButton and TapButton for the second and third button are just completly useless. Either no menu appears for TapButton or a menu appears for ClickFinger, but I can no longer do copy-pastes.

The default modifiers Ctrl, Alt, Meta don’t do anything with the mouse or just very weird stuff, like Alt-2-fingers jumps to the beginning of my text.

For now, I choose TapButtons for copy-paste, as this is the function I need most often.

I might add some Ctrl, Meta modifiers to get 2, 3 mouse button clicks later.

Philosophical Outro

In a world where companies try hard to get people into their ecosystem (controlling what users can do with the products they bought and own, what they can repair or let repair, what kind of operating system and software they are supposed to use), I think, it’s the duty of any tech professional to invest some time to give old hardware back some purpose (hence I’m also working on the Archlinux32 project). Also, throwing away barely used machines, just because a company wants to earn billions, is an ecological disaster. Remember, companies have been invented to make money, don’t get fooled by “we are there to make the world a better place” or any other marketing bs. As the company which should not be named is quite good at this kind of business, I expect all major vendors to follow soon. So that’s why I keep a park of old machines around and I’m not buying new machines since 10 years (I do buy old ones from Ebay though).

References

Addendum 19.2.2021

For kernel 5.7.6 updated version here .

Also a small walkthrough on how to update the module (in a most likely not too official way):

wget https://www.kernel.org/pub/linux/kernel/v5.x/linux-5.7.6.tar.xz
tar xf linux-5.7.6.tar.xz
cd linux-5.7.6
make mrproper
# use the the configuration of the new kernel!
zcat /proc/config.gz > .config
sed -i 's/.*CONFIG_LOCALVERSION=.*/CONFIG_LOCALVERSION="-arch1-1"/g' .config
sed -i 's/.*CONFIG_LOCALVERSION_AUTO.*/# CONFIG_LOCALVERSION_AUTO is not set/g' .config
make oldconfig
make scripts prepare modules_prepare
# copy radeon_bios.c to drivers/gpu/drm/radeon
make -C . M=drivers/gpu/drm/radeon
rm -f /lib/modules/5.7.6-arch1-1/kernel/drivers/gpu/drm/radeon/radeon.ko.xz
xz -c drivers/gpu/drm/radeon/radeon.ko \
        > /lib/modules/5.7.6-arch1-1/kernel/drivers/gpu/drm/radeon/radeon.ko.xz 
depmod -av
mkinitcpio -P
cp /boot/initramfs-linux.img /mnt/efi/.
cp /boot/initramfs-linux-fallback.img /mnt/efi/.

# Archlinux kernel compilation
https://wiki.archlinux.org/index.php/Kernel/Traditional_compilation#Download_the_kernel_source
# build just one module
https://yoursunny.com/t/2018/one-kernel-module/

Where /mnt/efi is the VFAT rEFIt EFI partition which contains grub and the kernel image and RAM disk.

Addendum 18.6.2023

For kernel 6.3.8 updated version here .

Addendum 22.10.2023

Tried a kernel 6.5.8 (still working with the 6.3.8 version of the radeon_bios patch avaiable here).

Here is also another way to build the kernel and the patched radeon module:

mount /mnt/efi (before updating the kernel!)
pacman -Syyu
cp /boot/vmlinuz-linux /mnt/efi/vmlinuz-linux
cp /boot/initramfs-linux.img /mnt/efi/initramfs-linux.img
cp /boot/initramfs-linux-fallback.img /mnt/efi/initramfs-linux-fallback.img

pkgctl repo clone linux
cd linux
makepkg -do
cp ~/radeon_bios-6.3.8.c src/linux-6.5.8/drivers/gpu/drm/radeon/radeon_bios.c 
makepkg -s

cp pkg/linux/usr/lib/modules/6.5.8-arch1-1/kernel/drivers/gpu/drm/radeon/radeon.ko.zst \
  /lib/modules/6.5.8-arch1-1/kernel/drivers/gpu/drm/radeon/radeon.ko.zst 
depmod -av
mkinitcpio -P
cp /boot/initramfs-linux.img /mnt/efi/initramfs-linux.img
cp /boot/initramfs-linux-fallback.img /mnt/efi/initramfs-linux-fallback.img