Mythic Beasts

A walk through for installing Linux onto an Apple TV.

James McKenzie,

Linux on AppleTV dedicated servers now available.

Prerequisites

  • an Apple TV with mb_boot_tv installed
  • a bootable image of your favourite distribution, or instructions on how to create one.

Step 0 - get the boot loader installed

Follow the instructions for installing mb_boot_tv.

Step 1 - partition and mount the Apple TV's disk

If you've just finished the instructions on installing mb_boot_tv then you'll have the disk connected to the computer already. Otherwise do that now. The instructions below assume you've got the disk connected as /dev/hdc.

partition the disk:

[root@banana ~]# parted /dev/hdc
GNU Parted 1.6.19
Copyright (C) 1998 - 2004 Free Software Foundation, Inc.
[...]
Using /dev/hdc
(parted) print
Disk geometry for /dev/hdc: 0.000-38154.375 megabytes
Disk label type: gpt
Minor    Start       End     Filesystem  Name                  Flags
1          0.020     34.019  fat32       EFI                   boot
2         34.020    433.996              Recovery              
3        433.996   1333.992              OSBoot                
4       1333.992  38026.375              Media                 
(parted) rm 4
(parted) mkpart
Partition type?  [primary]?                                               
File system type?  [ext2]? ext3
Start? 1333.992
End? 1383.992
(parted) mkpart
Partition type?  [primary]?                                               
File system type?  [ext2]? ext3
Start? 1383.992
End? 37514.996
(parted) mkpart
Partition type?  [primary]?                                               
File system type?  [ext2]? linux-swap
Start? 37514.996
End? 38026.375
(parted) print
Disk geometry for /root/t1: 0.000-38154.375 megabytes
Disk label type: gpt
Minor    Start       End     Filesystem  Name                  Flags
1          0.020     34.019  fat32       EFI                   boot
2         34.020    433.996              Recovery              
3        433.996   1333.992              OSBoot                
4       1333.992   1383.992                                    
5       1383.992  37514.996                                    
6      37514.996  38026.375                                    
(parted) quit
[root@banana ~]# 
For some unknown reason parted doesn't issue the ioctl to have the kernel re-read the partition table, god alone knows why so use fdisk to do that.
[root@banana ~]# fdisk /dev/hdc

The number of cylinders for this disk is set to 4864.
There is nothing wrong with that, but this is larger than 1024,
and could in certain setups cause problems with:
1) software that runs at boot time (e.g., old versions of LILO)
2) booting and partitioning software from other OSs
   (e.g., DOS FDISK, OS/2 FDISK)

Command (m for help): p

Disk /dev/hdc: 40.0 GB, 40007761920 bytes
255 heads, 63 sectors/track, 4864 cylinders
Units = cylinders of 16065 * 512 = 8225280 bytes

   Device Boot      Start         End      Blocks   Id  System
/dev/hdc1               1        4864    39070079+  ee  EFI GPT

Command (m for help): w
The partition table has been altered!

Calling ioctl() to re-read partition table.

Syncing disks.
[root@banana ~]# dmesg | tail
[...]
 hdc: hdc1 hdc2 hdc3 hdc4 hdc5 hdc6
[root@banana ~]#
now make the file systems, set the check counts and intervals, and mount them.
[root@banana ~]# mke2fs -j /dev/hdc4
mke2fs 1.35 (28-Feb-2004)
Filesystem label=
OS type: Linux
Block size=1024 (log=0)
Fragment size=1024 (log=0)
12824 inodes, 51200 blocks
2560 blocks (5.00%) reserved for the super user
First data block=1
Maximum filesystem blocks=52428800
7 block groups
8192 blocks per group, 8192 fragments per group
1832 inodes per group
Superblock backups stored on blocks: 
        8193, 24577, 40961

[root@banana ~]# mke2fs -j /dev/hdc5
mke2fs 1.35 (28-Feb-2004)
Filesystem label=
OS type: Linux
Block size=4096 (log=2)
Fragment size=4096 (log=2)
4627616 inodes, 9249537 blocks
462476 blocks (5.00%) reserved for the super user
First data block=0
Maximum filesystem blocks=12582912
283 block groups
32768 blocks per group, 32768 fragments per group
16352 inodes per group
Superblock backups stored on blocks: 
        32768, 98304, 163840, 229376, 294912, 819200, 884736, 1605632, 2654208, 
        4096000, 7962624

[root@banana ~]# mkswap /dev/hdc6
Setting up swapspace version 1, size = 536215 kB
[root@banana ~]# tune2fs -c -1 -i 0 /dev/hdc4
tune2fs 1.35 (28-Feb-2004)
Setting maximal mount count to -1
Setting interval between check 0 seconds
[root@banana ~]# tune2fs -c -1 -i 0 /dev/hdc5
tune2fs 1.35 (28-Feb-2004)
Setting maximal mount count to -1
Setting interval between check 0 seconds
[root@banana ~]# mkdir -p /mnt/tv
[root@banana ~]# mount /dev/hdc5 /mnt/tv
[root@banana ~]# mkdir -p /mnt/tv/boot
[root@banana ~]# mount /dev/hdc6 /mnt/tv/boot

Step 2 - install Linux

Now you have your system ready to receive the image of file system. In the simplest case you can copy the file system of another Linux machine (here called orangutan) with tar.
[root@banana ~]# ssh orangutan
root@orangutan's password: 
Last login: Wed Apr 25 13:23:15 2007 from banana
[root@orangutan ~]# mkdir /copy
[root@orangutan ~]# mount --bind / /copy
[root@orangutan ~]# exit
Connection to orangutan closed.
[root@banana ~]# cd /mnt/tv
[root@banana tv]# ssh orangutan "cd /copy && tar cfz - . " | tar xfpBz -
[... long wait ...]
[root@banana ~]# ssh orangutan umount /copy
root@orangutan's password: 
[root@banana ~]#
or if you use debian you could use debootstrap
[root@banana ~]# debootstrap sarge /mnt/tv http://ftp.debian.org/
I: Retrieving debootstrap.invalid_dists_sarge_Release
I: Validating debootstrap.invalid_dists_sarge_Release
I: Retrieving debootstrap.invalid_dists_sarge_main_binary-i386_Packages
[...]
I: Extracting base-files...
I: Extracting base-passwd...
I: Extracting bash...
[...]
Selecting previously deselected package base-files.
(Reading database ... 0 files and directories currently installed.)
Unpacking base-files (from .../base-files_3.1.2_i386.deb) ...
[...]
Setting up base-config (2.53.10.2) ...

I: Base system installed successfully.
umount: /mnt/tv/dev/pts: not mounted
umount: /mnt/tv/dev/shm: not mounted
umount: /mnt/tv/proc/bus/usb: not mounted
[root@banana ~]# 
similar incantations exist for other distributions, Personally I keep a ext3 image of a virgin centos install which I cat into the disk and then use resize2fs to expand it to fit.

Step 3 - Install a working kernel and modules

At this point you can either download a pre-compiled working kernel and a set of modules, or chroot to your new environment and build them in place.

Step 3a - Installing a pre-compiled kernel

[root@banana ~]# cd /tmp
[root@banana tmp]# wget http://www.mythic-beasts.com/resources/appletv/kernel/kernel-kit-2.6.20.6.tar.gz
--16:37:46--  http://www.mythic-beasts.com/resources/appletv/kernel/kernel-kit-2.6.20.6.tar.gz
           => `kernel-kit-2.6.20.6.tar.gz'
Resolving www.mythic-beasts.com... 131.111.64.221
Connecting to www.mythic-beasts.com[131.111.64.221]:80... connected.
HTTP request sent, awaiting response... 200 OK
Length: 3,766,585 [application/x-gzip]

100%[====================================>] 3,766,585    547.66K/s    ETA 00:00

16:37:53 (580.52 KB/s) - `kernel-kit-2.6.20.6.tar.gz' saved [3,766,585/3,766,585]

[root@banana tmp]# cd /mnt/tv
[root@banana tv]# tar xvfz /tmp/kernel-kit-2.6.20.6.tar.gz
boot/
boot/vmlinuz
boot/mb_boot_tv.conf
[...]
lib/modules/2.6.20.6-appletv/modules.ieee1394map
lib/modules/2.6.20.6-appletv/modules.pnpbiosmap
[root@banana tv]# 
at this point you might want to edit the boot loader configuration file a fairly typical mb_boot_tv.conf looks like
#try-net-boot
kernel /vmlinuz
append ro root=/dev/sda5 irqpoll
#initrd /initrd.img
The paths are relative to the root of the partition, here /boot is in its own partition /dev/sda4 and so /boot/vmlinuz is /vmlinuz to the boot loader. Note that mb_boot_tv will consider spaces on the end of the kernel and initrd lines as part of the file name and look for "/vmlinuz ". Uncommenting try-net-boot will make mb_boot_tv try a network boot before falling back to the disk boot.

Step 3b - rolling your own kernel

here you'll chroot in to the installation image you've just created and using the tools there compile and install a new kernel.
[root@banana ~]# chroot /mnt/tv /bin/bash
[root@banana /]# mount /proc
[root@banana /]#
Make absolutely sure you are successfully in the chroot ie you can't see your files, and that the contents of /boot are different from those in the host system. You do not want to install your new kernel into the host and render it un-bootable.

If your method of getting the distribution onto the disk didn't install the tools and packages required to compile and build a kernel, you should install them now using apt-get, or yum or whatever. Then continue with building the kernel.

[root@banana /]# mkdir -p /usr/src
[root@banana /]# cd /usr/src
[root@banana src]# wget ftp://ftp.kernel.org/pub/linux/kernel/v2.6/linux-2.6.20.6.tar.bz2
--14:14:37--  ftp://ftp.kernel.org/pub/linux/kernel/v2.6/linux-2.6.20.6.tar.bz2
           => `linux-2.6.20.6.tar.bz2'
Resolving ftp.kernel.org... 204.152.191.37, 204.152.191.5
Connecting to ftp.kernel.org[204.152.191.37]:21... connected.
Logging in as anonymous ... Logged in!
==> SYST ... done.    ==> PWD ... done.
==> TYPE I ... done.  ==> CWD /pub/linux/kernel/v2.6 ... done.
==> PASV ... done.    ==> RETR linux-2.6.20.6.tar.bz2 ... done.
Length: 43,388,391 (unauthoritative)

100%[====================================>] 43,388,391   412.84K/s    ETA 00:00

14:16:24 (404.20 KB/s) - `linux-2.6.20.6.tar.bz2' saved [43388391]

[root@banana src]# wget -O 2.6.20.6-apletv.patch 'http://svn.sourceforge.net/viewvc/*checkout*/mactel-linux/trunk/mach_linux_boot/kernel/2.6.20.6-apletv.patch?revision=100'
                                      [ or local copy]
           => `2.6.20.6-appletv.patch'
Resolving svn.sourceforge.net... 66.35.250.140
Connecting to svn.sourceforge.net[66.35.250.140]:80... connected.
HTTP request sent, awaiting response... 200 OK
Length: unspecified [text/plain]

    [ <=>                                 ] 8,526         54.76K/s             

14:39:28 (54.59 KB/s) - `2.6.20.6-apletv.patch' saved [8526]

[root@banana src]# wget http://www.mythic-beasts.com/resources/appletv/kernel/config
--14:39:45--  http://www.mythic-beasts.com/resources/appletv/kernel/config
           => `config'
Resolving www.mythic-beasts.com... 131.111.64.221
Connecting to www.mythic-beasts.com[131.111.64.221]:80... connected.
HTTP request sent, awaiting response... 200 OK
Length: 45,211 [text/plain]

100%[====================================>] 45,211        --.--K/s             

14:39:45 (839.32 KB/s) - `config' saved [45211/45211]
[root@banana src]# wget http://www.mythic-beasts.com/resources/appletv/kernel/appletv-rtc.patch
--14:41:49--  http://www.mythic-beasts.com/resources/appletv/kernel/appletv-rtc.patch
           => `appletv-rtc.patch'
Resolving www.mythic-beasts.com... 131.111.64.221
Connecting to www.mythic-beasts.com[131.111.64.221]:80... connected.
HTTP request sent, awaiting response... 200 OK
Length: 503 [text/plain]

100%[====================================>] 503           --.--K/s             

14:41:49 (4.80 MB/s) - `appletv-rtc.patch' saved [503/503]
[root@banana src]# wget http://www.mythic-beasts.com/resources/appletv/kernel/appletv-audio.patch
--13:36:48--  http://www.mythic-beasts.com/resources/appletv/kernel/appletv-audio.patch
           => `appletv-audio.patch'
Resolving www.mythic-beasts.com... 212.69.37.6
Connecting to www.mythic-beasts.com[212.69.37.6]:80... connected.
HTTP request sent, awaiting response... 200 OK
Length: 413 [text/plain]

100%[====================================>] 413           --.--K/s             

13:36:48 (3.94 MB/s) - `appletv-audio.patch' saved [413/413]

[root@banana src]# tar xfj linux-2.6.20.6.tar.bz2
[root@banana src]# cd linux-2.6.20.6
[root@banana linux-2.6.20.6]# patch -p1 < ../2.6.20.6-apletv.patch
patching file arch/i386/kernel/e820.c
patching file arch/i386/kernel/efi.c
patching file arch/i386/kernel/setup.c
patching file drivers/usb/storage/usb.c
patching file drivers/video/imacfb.c
patching file Makefile
[root@banana linux-2.6.20.6]# patch -p1 < ../appletv-rtc.patch
patching file include/asm-i386/time.h
[root@banana linux-2.6.20.6]# patch -p1 < ../appletv-audio.patch
patching file sound/pci/hda/patch_realtek.c
[root@banana linux-2.6.20.6]# cp ../config .config
[root@banana linux-2.6.20.6]# make oldconfig
  HOSTCC  scripts/basic/fixdep
  HOSTCC  scripts/basic/docproc
  HOSTCC  scripts/kconfig/conf.o
[...]
scripts/kconfig/conf -o arch/i386/Kconfig
*
* Linux Kernel Configuration
*
[...]
CRC-CCITT functions (CRC_CCITT) [M/y/?] m
CRC16 functions (CRC16) [M/n/y/?] m
CRC32 functions (CRC32) [Y/?] y
CRC32c (Castagnoli, et al) Cyclic Redundancy-Check (LIBCRC32C) [M/y/?] m
#
# configuration written to .config
#
[root@banana linux-2.6.20.6]# 
you might want to review the configuration in .config and make some changes, when you're done, rerun make oldconfig.
[root@banana linux-2.6.20.6]# make
scripts/kconfig/conf -s arch/i386/Kconfig
  CHK     include/linux/version.h
  UPD     include/linux/version.h
[...]
  CC      sound/soundcore.mod.o
  LD [M]  sound/soundcore.ko
[root@banana linux-2.6.20.6]# make modules_install
  INSTALL arch/i386/crypto/aes-i586.ko
  INSTALL arch/i386/crypto/twofish-i586.ko
[...]
  INSTALL sound/pci/hda/snd-hda-codec.ko
  INSTALL sound/pci/hda/snd-hda-intel.ko
  INSTALL sound/soundcore.ko
[.. followed by a plethora of warnings and errors from depmod ... ]
[root@banana linux-2.6.20.6]# cp arch/i386/boot/bzImage /boot/vmlinuz
[root@banana linux-2.6.20.6]# cat << EOF > /boot/mb_boot_tv.conf
#try-net-boot
kernel /vmlinuz
append ro root=/dev/sda5 irqpoll
EOF
[root@banana linux-2.6.20.6]# 
NB: that mb_boot_tv will consider spaces on the end of the kernel and initrd lines as part of the file name and look for "/vmlinuz " Uncommenting try-net-boot will make mb_boot_tv try a network boot before falling back to the disk boot.

Step 4 - unmount, replace the disk and boot

That's it you should be able to replace the disk into the Apple TV and boot it. exit the chroot (if you used one, and then)
[root@banana linux-2.6.20.6]# cd /
[root@banana /]# umount /mnt/tv/proc
[root@banana /]# umount /mnt/tv/boot
[root@banana /]# umount /mnt/tv
[root@banana /]# 

Copyright © 2000-2012 Mythic Beasts Ltd. All Rights Reserved.