UPDATE 2011/12: this tutorial is in many ways a little outdated, but I'll leave it for reference, as a number of things are still valid. In short, setting Debian up on the MBA31 is much easier now, as a lot has been merged upstream, both within Debian and the Linux Kernel. It was originally written in November 2010.
The new Apple Macbook Air 11,6" is sexy. But if you're reading this, chances are that you know that already, and that after falling for it just like me, you're struggling to get some flavour of GNU/Linux running on it properly.
So, here's my documentation on how to install Debian GNU/Linux on a custom MacBookAir3,1 (1.6ghz C2D, 4gb RAM, 128gb SSD). Note: I have the SuperDrive and the Ethernet dongle, because I need them both. It's possible to setup some GNU/Linux distributions without those, but I didn't bother trying, for I had enough on my hands already.
Also, if you want to go for the quick and easy, you should know that installing Ubuntu Maverick on the MBA31 is fairly straightforward, and thanks to its dedicated and active community, most things now seem to be running well. To do so, you can jump to the Ubuntu wiki [1], and read through the forum thread for additionnal details [2]. If you'd rather have plain Debian as I do, read on, and please correct me when I'm wrong!
Note: Some downloads are available in the files [3] section!
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 firmware updates (which sometimes fix nasty bugs). On the plus side: it's UNIX, so it's pretty comfortable as a fallback in some cases (fire up Terminal.app and you can feel at home!). Of course, MacOS X spans the entire disk by default, so we need to shrink its partition. You can do that easily by using the Bootcamp Assistant (in Applications -> Utilities). I shrinked OS X as much as I could (a little less than 20gb), leaving ~100gb to be partitionned for GNU/Linux.
Since the MBA ships a SSD, some special things are to be taken into account. If you search the Internet, you'll find countless threads about SSD optimization and techniques [1] to avoid performance degradation. It's a pretty complex & confusing subject, but it mostly revolves around two words: TRIM (also called discard) and "alignment", as in aligning partitions to the size of the SSD erase block. On modern SSDs, it is believed to be multiples of 512KiB; as a result, recent partitionning software defaults to 1MiB alignements [2].
I won't talk about TRIM because it doesn't apply to my usecase (yet): I'll be using LVM over dm-crypt (while TRIM was made available to DM targets in Linux 2.6.36 [3], the crypt target was left out). But I was concerned about alignement. Because partman (from D-I) does not seem to be configurable when it comes to partition alignement, and because Intel Macs use modern GPT partitionning instead of the traditionnal DOS style partitionning, I decided to partition my SSD under MacOS X using GPT fdisk [4]. It's free software, and it does the right alignment by default.
The MacBookAir uses EFI, not BIOS. Unfortunately, EFI booting is quite difficult to achieve and generally breaks some things, because of lack of driver support (no video acceleration in most cases). Apple's EFI firmware allows to boot in BIOS emulation mode, and this is how most Intel Macs are being used. So we're gonna boot in BIOS mode, which means we'll need a bootloader, usually located on the MBR. With GPT partitionning, the reserved space for putting the bootloader is not there, so one needs to create a dedicated BIOS boot partition [5] for grub2 to install its stage2.
So, after downloading and installing GPT fdisk on MacOS X, I opened a
terminal and typed sudo gdisk /dev/disk0
, in order to create our partitions.
The BIOS boot partition can be really small (I chose 512K, which is big) and
just needs to have the right type (ef02). Because I intended to encrypt the
root filesystem, I also created a separate /boot partition, to store kernels
and initrd images. In the end, my partition tables looked like that:
Number Start (sector) End (sector) Size Code Name
1 40 409639 200.0 MiB EF00 EFI System Partition
2 409640 39472143 18.6 GiB AF00 MacOS X
3 39472144 39473167 512.0 KiB EF02 BIOS boot partition
4 39473168 39997455 256.0 MiB 0700 boot
5 39997456 236978142 93.9 GiB 0700 system
Oh, and while you're still in MacOS X, download and install rEFIt [6], which makes life way easier when multibooting. It's not a recquirement, but trust me, it's handy.
UPDATE 2011/12: The Debian installer should now work out of the box, but I'm keeping the manual debootstrap based install documented below for reference.
Now that the SSD is partitioned, we can proceed with the installation. Unfortunately, as of early December, it's impossible to install Debian GNU/Linux on the MBA31 using the standard Debian Installer. Here's why: much like the MacBookPro7,1, the MacBookAir3,1 uses a MCP89 SATA controller. For unknown reasons (most likely a bug in Apple's EFI firmware), the matching driver (nv_sata) does not recognize the SSD attached to the controller when booting in BIOS emulation mode. It can be accessed through the ata_generic driver, however. The problem is that Debian kernels didn't include by default until recently [1]. They now do, but the Debian Installer does not include it yet [2].
I did build a custom D-I mini.iso by patching kernel-wedge, but it ended up segfaulting, so I chose to use a D-I derivation that shipped a compatible kernel: Ubuntu Maverick's alternate CD installer [3]. To boot the installer, just hold 'c' after you hear the "Apple ding". The CD spins, and few seconds later you're in. Esc and Enter allows to leave the graphical menu and get a boot prompt. Type expert reboot=pci and the installer launches. The reboot=pci allows the system to reboot, otherwise it hangs and you have to power it down (yet another BIOS emulation firmware bug, AFAIK).
Once in the familiar looking installer, go through all the steps until disk partitionning (language selection, loading CD components, detect/configure network, etc.). Did I mention I used the USB Ethernet dongle? Given that the wifi chipset's open source driver is in the staging branch for the next Linux release [4], I doubt many installers will ship with it and enable it by default. Anyways, the idea is to use the Ubuntu installer as a GNU/Linux environment to install a pure Debian system using debootstap.
Move to a terminal (alt+F2), and partition your disks. You can do it through partman but I wanted custom alignment options for dm-crypt and LVM. However, the Ubuntu installer ships with crypsetup 1.1.2, and 1.1.3 is required to read disk topology from the kernel [1]. Fortunately, it's possible to download the latest version into the installer's ramdisk by doing:
wget \
http://ftp.fr.debian.org/debian/pool/main/c/cryptsetup/cryptsetup_1.1.3-4_amd64.deb
udpkg -i cryptsetup_1.1.3-4_amd64.deb
Then, let's create our crypto device with the right alignment [2]:
cryptsetup -y luksFormat --align-payload=2048 /dev/sda5
Note: if you want to use Partman to do that, it's possible to hack the
/lib/partman/lib/crypto-base.sh script by adding --align-payload=2048
after luksFormat (use the nano
editor to do so).
Now let's open our crypto device:
cryptsetup luksOpen /dev/sda5 crypt
This creates /dev/mapper/crypt. We want to make that a LVM physical volume (with the right alignment [3]), in order to create a volume group and logical volumes on top of it, so let's go:
pvcreate --dataalignment 512 /dev/mapper/crypt
pvs -o +pe_start # just checking
vgcreate vg0 /dev/mapper/crypt
vgchange -a y
We now want to create at least two logical volumes (virtual partitions one could say) in the contents VG, root & swap:
lvcreate --name swap --size 2G vg0
vgdisplay | grep Free # to check the amount of available extents
lvcreate --name root --extents 23980 # replace by your extent num.
We now have two logical volumes waiting for filesystems to go on top, /dev/contents/swap and /dev/contents/root.
So, let's do the swap thing:
mkswap /dev/contents/swap
sync
swapon /dev/contents/swap
Then, let's format the root filesystem:
mkfs.ext4 /dev/contents/root
...and mount it so we can install the system in it:
mkdir /target
mount -o noatime /dev/contents/root /target
Let's not forget the /boot partition, which is gonna be the only unencrypted bit of our install:
mkfs.ext4 /dev/sda4
mkdir /target/boot
mount -o noatime /dev/sda4 /target/boot
We're now ready to install Debian using debootstrap:
debootstrap --arch amd64 squeeze /target \
http://ftp.fr.debian.org/debian # or the mirror of your choice
When the base system is installed, we can enter our new system and proceed with the rest of the install. Before that, however, let's bind mount some useful pseudo filesystems like devpts, sysfs & proc from the host to make it available to our newly installed chrooted environment:
mount -o bind /proc /target/proc
mount -o bind /sys /target/sys
mount -o bind /dev /target/dev
mount -o bind /dev/pts /target/dev/pts
We need all those to be able to access the LVM volume group and logical volumes within the chroot, and generate the initramfs image for the kernel we're about to install in it. Now let's jump in there:
chroot /target /bin/bash
...and set up some basic configuration files, like /etc/fstab, /etc/hosts, /etc/network/interfaces, /etc/hostname, /etc/resolv.conf, /etc/apt/sources.list. Please refer to the D-I documentation for detailed examples [4] for those. In the case of an encrypted configuration like this one, it is crucial to generate the /etc/crypttab file such as:
# <target name> <source device> <key file> <options>
sda5_crypt /dev/sda5 none luks
Note: you should consider using the UUID instead of /dev/sda5 (for
/etc/fstab too), which you can obtain with the blkid
command.
Don't forget to set a passwd for root using passwd
and create a normal
user, which will be a member of the fine groups:
adduser --gid 50 yournick
for group in sudo adm src cdrom audio dip video plugdev ;
do adduser yournick $group ;
done
Now, let's install the crucial tools, kernel and bootloader:
apt-get install cryptsetup lvm2 \
console-setup sudo vim screen mutt \
initramfs-tools linux-image-2.6 grub-pc
If /boot is mounted where it should be, if all the pseudo filesystems are bind mounted from the host, the initrd should be generated automagically. Note: if you don't use an english keyboard layout, it is possible that you have to type your passphrase in qwerty upon reboot, then:
dpkg-reconfigure -plow console-setup
/etc/init.d/console-setup restart
update-initramfs -u
Important: when grub2 asks where to go, don't try to point it towards the BIOS boot partition on /dev/sda3, but to /dev/sda instead. It will find its way to the dedicated partition alone.
UPDATE 2011/12: I've been using linux-image-3.0.0-1-amd64 (from Debian Sid or Experimental, I'm not sure) with success for a while; in other words, no need to apply patches and manually compile the kernel anymore, at least from this Debian Linux kernel onwards.
We shall now see a Tux icon in the rEFIt menu upon reboot, and be able to boot the system. Now comes the hard part, which I haven't all figured out yet: making everything work.
By default, kernel mode setting tries to use the nouveau driver, which
currently doesn't work with the MBA31 and renders nothing but a garbled output
[1]. So you'll want to edit the default grub entry and add nomodeset
reboot=pci in the grub menu. To store it, edit /etc/default/grub, add it
to the GRUBCMDLINE_LINUX_ variable and run sudo update-grub
.
Configure the console font by doing:
sudo dpkg-reconfigure -p low console-setup
I tried different fonts for the console, but the only one that would not force
me to sudo /etc/init.d/console-setup restart
after switching back to console
from X was Terminus, size 16. You can set it up manually in
/etc/default/console-setup, filling the FONTFACE and FONTSIZE variables
(but leaving them empty and using the default kernel font may be a good choice
too). TOCONFIRM
The keyboard requires a kernel patch [1]. Luckily, it has been applied to the Debian kernel in version 2.6.32-28 [2], so it should work out of the box. As for the keymap, it can be tricky to get it right, so here's an excerpt from my /etc/default/keyboard file (which stores keyboard layout for both the console and Xorg in Debian Squeeze):
XKBMODEL="apple"
XKBLAYOUT="fr"
XKBVARIANT="mac"
XKBOPTIONS="lv3:ralt_switch,compose:rwin"
Note: I haven't tried it (yet), but a xmodmap recipe is floating around [3] to invert 'ctrl' and 'option' keys to get a MacOS X like behaviour.
The Debian kernel does include a patch [1], but it was not enough to get multitouch [2] working for me, and I had to recompile the kernel by applying another BCM5974 related patch [3]. Before anything, make sure you have usbfs mounted, and if not, add the following line to your /etc/fstab and then mount it (I couldn't get mouse button emulation to work without that):
usbfs /proc/bus/usb usbfs defaults 0 0
Basically, when starting Xorg for the first time (using the default synaptics driver), I got a pointer that moved and clicked, but behaved wildly on click + movement (unable to drag anything). To make it work properly, I had to install the libmtdev1 library and the multitouch X driver.
They're not in Debian yet, but Nobuhiro Iwamatsu has been working on packaging both mtdev and the X driver. The result is waiting in the NEW queue [4]. In the meantime, packages are available on his people.d.o page [5].
Grab and dpkg -i
libmtdev11.0.11-1_amd64.deb_,
mtdev-tools1.0.11-1_amd64.deb_ and
xserver-xorg-input-multitouch1.0~rc2-2_amd64.deb_, then add the following to
your /etc/X11/xorg.conf (you can also apt-get --purge remove
xserver-xorg-input-synaptics
, which removes
/usr/share/X11/xorg.conf.d/50-synaptics.conf, leaving
/usr/share/X11/xorg.conf.d/50-multitouch.conf to take over):
Section "InputClass"
MatchIsTouchpad "true"
Identifier "Multitouch Touchpad"
Driver "multitouch"
EndSection
Note: you can also build the driver yourself. Since the multitouch X driver is still quite buggy, they're probably gonna be some upstream improvement and it may be very useful to try some patches out. So, for reference, it's just a matter of installing libmtdev1-dev from [5], and then:
sudo -s
cd /usr/src
apt-get install xserver-xorg-dev build-essentials debhelper git-core
git clone http://bitmath.org/git/multitouch.git
cd multitouch
dpkg-buildpackage
dpkg -i ../xf86-input-multitouch_1.0~rc2-mactel1_amd64.deb
In any case, you should be able to see something along the following lines in /var/log/Xorg.0.log upon X startup:
(II) config/udev: Adding input device bcm5974 (/dev/input/event8)
(**) bcm5974: Applying InputClass "evdev touchpad catchall"
(**) bcm5974: Applying InputClass "Multitouch Touchpad"
(II) LoadModule: "multitouch"
(II) Loading /usr/lib/xorg/modules/input/multitouch_drv.so
(II) Module multitouch: vendor="X.Org Foundation"
compiled for 1.7.7, module version = 0.1.0
Module class: X.Org XInput Driver
ABI class: X.Org XInput driver, version 7.0
(**) bcm5974: always reports core events
(II) XINPUT: Adding extended input device "bcm5974" (type: TOUCHPAD)
(II) device control: init
(**) Option "Device" "/dev/input/event8"
(II) multitouch: devname: bcm5974
(II) multitouch: devid: 5ac 243 1
(II) multitouch: caps: left mtdata ibt
(II) multitouch: 0: min: 0 max: 2048
(II) multitouch: 1: min: 0 max: 2048
(II) multitouch: 2: min: 0 max: 2048
(II) multitouch: 3: min: 0 max: 2048
(II) multitouch: 4: min: -16384 max: 16384
(II) multitouch: 5: min: -4616 max: 5112
(II) multitouch: 6: min: -142 max: 5234
(II) pointer_control
(**) bcm5974: (accel) keeping acceleration scheme 1
(**) bcm5974: (accel) acceleration profile 0
(II) pointer_control
(**) bcm5974: (accel) acceleration factor: 2.000
(**) bcm5974: (accel) acceleration threshold: 4
(II) device control: on
(II) pointer_property
(II) pointer_property
You may also want to install the xinput package to debug things if you have trouble getting the touchpad to work. This being said, the multitouch driver still has bugs, which make its use a little hard at times. But from there on, it can only get better!
The nouveau driver should work, for the NVIDIA GeForce 320M is officially supported by it [1]. As previously stated though, it doesn't work (yet) [2], though it'd be the best option for those who don't care about 3D acceleration.
In the meantime, the proprietary NVIDIA [3] driver does work in BIOS emulation mode (people report that it's also broken in EFI mode). We need to pull them out of the experimental [4] repository though.
To do that, let's setup the system to use apt-pinning. Create /etc/apt/preferences.d/pinning and fill it with:
Package: *
Pin: release o=Debian,a=stable
Pin-Priority: 700
Package: *
Pin: release o=Debian,a=testing
Pin-Priority: 800
Package: *
Pin: release o=Debian,a=unstable
Pin-Priority: 90
Package: *
Pin: release o=Debian,a=experimental
Pin-priority: 70
Add the following lines to your /etc/apt/sources.list and apt-get update
:
deb http://ftp.debian.org/debian squeeze main contrib non-free
deb http://ftp.debian.org/debian sid main contrib non-free
deb http://ftp.debian.org/debian experimental main contrib non-free
We need the nvidia-glx package which will compile the nvidia driver using DKMS [5]:
sudo apt-get -t experimental install nvidia-glx
You can then add the following to /etc/X11/xorg.conf:
Section "Device"
Identifier "Device0"
Driver "nvidia"
Option "NoLogo" "True"
VendorName "NVIDIA Corporation"
BoardName "GeForce 320M"
EndSection
You now get graphics using the native 1366x768 resolution, instead of the crappy distorted 1024x768 vesa driver output. However, you'll notice the colors are a bit odd. According to the MBA3 Ubuntu wiki page [6], that's because Apple uses 6-bit LCDs which support only 262144 colours instead of 16 million. It then says So we need to enable dithering at 6 bits per colour channel to smooth colour gradients.
This is done using the nvidia-settings package [6]. Unfortunately, the Debian package is totally outdated [7]. It will have to be compiled from Ubuntu's source package [8], which requires installing two additionnal packages from the Ubuntu repository, which I couldn't be bothered compiling myself due to their dependencies:
cd /usr/src/
mkdir ubuntu_packages && cd $_
wget \
http://mirror.ovh.net/ubuntu/pool/main/s/screen-resolution-extra/screen-resolution-extra_0.13_all.deb
wget \
http://mirror.ovh.net/ubuntu/pool/main/x/x-kit/python-xkit_0.4.2.2_all.deb
sudo dpkg -i *.deb
Now let's get to make a newer Debian package for nvidia-settings using sources from Ubuntu:
cd /usr/src
sudo apt-get build-dep nvidia-settings
sudo apt-get install build-essentials debhelper
wget \
https://launchpad.net/ubuntu/natty/+source/nvidia-settings/260.19.21-0ubuntu2/+files/nvidia-settings_260.19.21.orig.tar.gz
wget \
https://launchpad.net/ubuntu/natty/+source/nvidia-settings/260.19.21-0ubuntu2/+files/nvidia-settings_260.19.21-0ubuntu2.diff.gz
tar xvfz nvidia-settings_260.19.21.orig.tar.gz
gunzip nvidia-settings_260.19.21-0ubuntu2.diff.gz
cd nvidia-settings/
patch -p1 <../nvidia-settings_260.19.21-0ubuntu2.diff
sudo dpkg-buildpackage
sudo dpkg -i ../nvidia-settings*deb
Here you go. Now, to correct our display, we need to issue the following commands under X:
/usr/bin/nvidia-settings -a [gpu:0]/Dithering[DFP-2]=1
/usr/bin/nvidia-settings -a [gpu:0]/ColorRange[DFP-2]=1
/usr/bin/nvidia-settings -a [gpu:0]/DitheringMode[DFP-2]=1
/usr/bin/nvidia-settings -a [gpu:0]/DitheringDepth[DFP-2]=1
This can be added to your ~/.xsession if you use one, or added at the end of /etc/gdm3/Init/Default.
Note: you may also want to use the same colorspace as in MacOS X. To do so, we need to mount the OS X partition and copy the file which we'll use to calibrate our screen:
sudo apt-get install xcalib
sudo mkdir /etc/xcalib
mount -o ro /dev/sda2 /mnt
cp /mnt/Library/ColorSync/Profiles/Displays/Color\ LCD-00000610-0000-9CF3-0000-000004273CC0.icc \
/etc/xcalib/colorprofile.icc
umount /mnt
xcalib /etc/xcalib/colorprofile.icc
You can can add that last command to your ~/.xsession or to GDM3's init script.
Note: I experienced a weird fontsize problem with GTK applications, which would display way too big fonts (though the default Sans, Regular, size 10 was being used). I walked around the problem by installing the gtk-chtheme package, and setting the font for the default theme to 6 instead of 10.
The current Debian kernel in testing has the right applesmc patch [1] applied already, so the MBA should behave. However, some Ubuntu folks have been working on a macbook fan control daemon, called macfanctld [2]. It is unclear to me whether it is very useful, necessary or not. When I tried it, fans started roaming, even though I blacklisted the two buggy sensors mentionned in the Ubuntu forum thread [3].
You should install the lm-detect package anyways, and add coretemp to
/etc/modules, which monitors the Intel CPU temperature AFAIK (you can run
the sensors-detect
script to do that for you).
The mbp-nvidia-bl driver has been patched [1] in the Debian kernel to include the MBA3. Installing the pommed [2] package makes the backlight keys work in console.
Adding acpi_backlight=vendor as a kernel boot parameter and the following line in the NVIDIA Device section makes it work under X:
Option "RegistryDwords" "EnableBrightessControl=1"
Sound should work out of the box with the previously mentionned Debian kernel
[1], which includes the right patch [20], after installing alsa-base
. It may
be necessary to unmute some channels within alsamixer
though. Headphones work too.
Works flawlessly. The Debian kernel apparently lacks a patch [1] for EHCI power management to work properly. The patch applies cleanly against linux-source-2.6.32 or linux-source-2.6.36. More info on [2], and the original patch on [3].
UPDATE 2011/12: Unfortunately, it seems like little to no progress has been made on this issue.
Haven't had time to dig into it properly. It looks like a patch [1] is required to force EFI booting in physical mode rather than virtual mode, and another patch [2] to add the right video properties to the EFI framebuffer driver.
In addition to that, BIOS dumps seem to be needed, as documented on the Grub wiki page [3].
Threads to read on the subject: https://bbs.archlinux.org/viewtopic.php?id=109754 and https://bbs.archlinux.org/viewtopic.php?id=108846.
I get battery state by installing the acpi package. I got suspend to ram working by installing the acpi-support package and uncommenting LIDSLEEP=TRUE_ in /etc/default/acpi-support.
sudo apt-get install acpi acpi-support
sudo editor /etc/default/acpi_support # uncomment the line
sudo /etc/init.d/acpi-support restart
Waking up from sleep is not as fast as in MacOS X, but I honestly don't care as long as it works. I didn't test suspend to disk (aka hibernation) though.
It seems to work with the open-source driver [1] that has been backported from 2.6.37 to the current Debian kernel. To use it, you need the binary firmware, which is in the firmware-brcm80211 [2] package.
The interface should show up as wlan0. After upping it using sudo ifconfig
wlan0 up
, I could scan for available networks sudo iwlist wlan0 scan
and got
results. I didn't go any further though, for I'm not a big fan of WiFi in
general and don't need it at the moment.
Note: Some people [3] reported the open-source driver as flaky though, and have been using the proprietary driver instead. In Debian, it should be available through the broadcom-sta-source package [4].
I didn't test it, but the Debian kernel includes the right patch [1] there too. To be checked...
It will only work on OS X with this very machine. There's a tutorial floating around the Internet about hacking it to make it work on GNU/Linux, but I'd rather get a cheap USB CD burner rather than void the warranty of an 80€ Apple toy. Pretty annoying though, as I had to boot back to OS X to burn CDs.
To get the most out of the SSD and reduce performance degradation, one has to try to limit writes as much as possible. There's a lot of information on this issue which is scattered across the net, but fortunately, the ArchLinux wiki has an excellent page summing it all up [1].
Here are the steps I've taken so far. First, mounting all system partitions (/boot and /) with the noatime option, so the access time to files is not stored (beware that it breaks new mail detection if you're using mutt with mbox storage).
Second, changing the I/O scheduler from cfq to noop, by appending the following to the kernel options in /etc/default/grub (GRUBCMD_LINUX_):
elevator=noop
Then, telling the OS to swap as little as possible, by adding the following to /etc/sysctl.conf:
vm.swappiness=1
vm.vfs_cache_pressure=50
This machine is (almost ?) fully supported in BIOS emulation mode, but you'll need to use proprietary NVIDIA drivers and may notice a slight performance degradation due to the inability to see the SSD through AHCI. Worked very nicely for me for a little more than a year, before I decided to move back to something heavier with integrated Gigabit Ethernet (the USB dongle only allows for 10/100MBit/s) and an integrated CD-drive/burner.
Unfortunately, it seems like nobody got to tackle around the EFI booting and nouveau driver issues, so EFI booting and open source grahics remain a no go, as of December 2011. Sad, really.
I no longer have such a machine, but feel free to 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 eventually!
mike dentifrice, 2011/12/16