Ipodlinux:compile

From LQWiki
Jump to navigation Jump to search

I'm assuming that you downloaded all the files from "Getting the required files" into ~/ipod (~ stands for your home directory, e.g. /home/flonejek/ is mine, so ~/ipod would be /home/flonejek/ipod)

Note: We will use %1 for kernel version and %2 for patch version throughout the document.

Overview

Requirements

  1. iPod (surprise!). iPod generation 1 (scroll wheel), generation 2 (touch wheel) and generation 3 (docking) iPods work well.
  2. These instructions assume the iPod configured as "Windows", that is the filesystem is FAT32. HFS+ is supported in the CVS version of the kernel however there is no simple way to configure the user tools.
  3. You should be willing to accept that if you ruin your ipod there is very little chance apple will repair/replace it, though this is unlikely if you RTFM.
  4. A toolchain to build the software (the arm-elf-tools).
  5. Currently the build environment is Linux (x86) based. If you have another system (e.g. a Mac) you are currently on your own. Please edit this documentation to include workarounds that resulted in success.
  6. The ability to mount and umount your ipod
  • Next we will install the arm-elf-tools toolchain to prepare the build environment. This enables us to compile programs for architectures different to our own (the host), i.e. the ipod. The build environment is based on the gcc compiler toolchain.
  • Once the build environment is prepped we will backup the ipod firmware, in a safe place, so if you make a mistake you can revert to the original firmware.
  • Now we build the patched linux kernel for the ipod
  • Then we will install the bootloader and kernel to the ipod. Not quite finished though, we still have to install the root filesystem
  • Finally we copy over either our own compiled root file system (from uClinux distro) or the root filesystem designed for the ipod (comes with podzilla).

Preparing the Build Environment

The build environment requires a compiler that targets the ARM processor (the CPU on the iPod). Normally you can simply install a cross-compiling tool chain based on the GNU tools (that is binutils and gcc). If you are running an Linux system on a x86 CPU, or MacOSX, then you can just download (Linux, MacOSX) the toolchain as a binary. It likes to live in /usr/local/ so if that is okay on your system you can just untar it there.

# cd ~/ipod
# sh ./arm-elf-tools-version.sh

On any other system you will need to build the tool chain from source. There are pointers on the Web to do this. Good luck :) Once your binutils and gcc are targeted for arm-elf you can proceed. Note, in order to build user tools you will also need a C runtime library (a "libc"). The above toolchain includes a binary for uClibc which is a small implementation of the C library.

Backing Up Your Ipod's Firmware and Bootloader

The iPod "firmware" is a complex beast that actually consists of some code stored on flash ROM as well as code stored on the hard drive. For the moment we shall say that the hard drive contains the operating system and bootloader which is loaded into the flash rom upon boot. We are going to replace the firmware (OS and bootloader), and thus need to make a backup of that code.

The hard drive in the iPod is partitioned by default into two partitions. Normally these will be visible under Linux as /dev/sda1 and /dev/sda2. If you are currently using Linux tools to manage your music (i.e. gtkpod) you would be familiar with the second partition as it is a FAT32 formatted partition and contains your music.

Once you can successfully access your iPod from Linux (for example mount -t msdos /dev/sda2 /mnt/iPod) you can make a backup of your iPod OS partition.

# dd if=/dev/sda1 of=ipodfirmware
# dd if=/dev/sda  of=ipodbootloader bs=512 count=1

This will make a complete copy of the /dev/sda1 partition and save it to the file ipodfirmware, as well as saving the master boot record too ipodbootloader. You can modify the parameters to suite your local setup.

To restore this data to your iPod you would simply switch the if and of arguments. That is:

# dd if=ipodfirmware of=/dev/sda1
# dd if=ipodbootloader  of=/dev/sda bs=512 count=1

Note, in order to do this you need to have your iPod in "diskmode". This is because its risky to write to the partition while the os is running, but in diskmode, the os isn't running, making for a safer restore. In order to boot in "diskmode" you need to reset the iPod by holding down the menu and play/pause buttons for 10 seconds and then when the Apple icon appears hold down the fast forward and rewind buttons until the "OK to disconnect" message appears.

In this forced diskmode removing the firewire cable does not cause the iPod to reboot as it would normally. Again you need to reset by holding down the fast forward and rewind buttons. If you have reverted to the Apple firmware it should start shortly after the Apple icon appears.

Building The Kernel

  • Unpack the vanilla sources
# tar xvzf linux-%1.tar.gz     OR     # tar xvjf linux-%1.tar.bz2

(The x stands for Extract, the v for Verbose (okay, yes, this is optional), the j for Decompress with bzip2 OR the z for Decompress with gunzip, the p for Preserve permissions and the f to denote that we want to extract a file, not standard input.)

  • Change to kernel source directory
# cd kernel-%1
  • Apply the uClinux patch
# gzip -d -c uClinux-2.4.20-uc0.diff.gz | patch -p1
  • Apply the ipodlinux patch - note that you can use cvs but this isn't reccommended, as you may bork your ipod.
# gzip -d -c ipodlinux-2.4.20-0.1.diff.gzip | patch -p0
  • Copy over a default config for the ipod
# cp arch/armnommu/def-configs/ipod .config
  • Edit the default config for the ipod - optional, but if you don't do this you might as well have used the precompiled kernel.
# make oldconfig
select the options you want, then save your config and exit
  • Compile the kernel
# make dep && make && make modules

Installing the Kernel

In this step the ELF format kernel is patched into the current firmware image. To do this we first need to prepare the kernel image by converting it to a binary format. The kernel_pad.S file is simply an ARM exception table and some padding, I hope to find a cleaner solution than this hack.

The steps in this process are as follows:

  • convert the kernel to a raw binary image
# arm-elf-as kernel.S -o kernel_pad
# arm-elf-objcopy -O binary kernel_pad kernel_pad.bin
# arm-elf-objcopy -O binary linux linux_tmp.bin
# cat kernel_pad.bin linux_tmp.bin > linux.bin
# rm linux_tmp.bin kernel_pad kernel_pad.bin 
  • Use the make_fw tool from the iPod Boot Loader to extract and patch the Apple firmware.
# cd ~/ipod
# tar -xvzf ipodloader-version.tar.gz
# cd ipodloader-version
# make_fw -o ../apple_fw.bin -e 0 ../ipodfirmware
# make_fw -o ../my_fw.bin -i ../apple_fw.bin -l ../kernel-%1/linux.bin loader.bin

Partition the ipod for bootloader (plug in the ipod if it isn't already plugged in)

# umount /dev/sda2
  • Start fdisk
# fdisk /dev/sda
The number of cylinders for this disk is set to 2431.
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)
# fdisk /dev/sda
Command (m for help):
  • Delete Firmware Partition
Command (m for help): d
Partition number (1-4): 1
  • Create a new primary partition with a length of 1 cylinder.
Command (m for help): n
Command action
e extended
p primary partition (1-4)
p
Partition number (1-4): 1
First cylinder (1-2431, default 1): 1
Last cylinder or +size or +sizeM or +sizeK (1-5, default 5): 1
  • Activate the first partition.
Command (m for help): a
Partition number (1-4): 1
  • Set partition type to 'Empty'
Command (m for help): t
Partition number (1-4): 1
Hex code (type L to list codes): 0
  • Create the 3rd primary partition from 2nd to 5th Cylinder (this is around 30 megs in size)
Command (m for help): n
Command action
e extended
p primary partition (1-4)
p
Partition number (1-4): 3
First cylinder (1-2431, default 1): 2
Last cylinder or +size or +sizeM or +sizeK (1-5, default 5): 5
  • Review the changes. Note, this is for a 20GB verison, the sda2 parition size will vary.
Command (m for help): p
Disk /dev/sda: 20.0 GB, 20000268288 bytes
255 heads, 63 sectors/track, 2431 cylinders
Units = cylinders of 16065 * 512 = 8225280 bytes
    Device Boot    Start       End    Blocks   Id  System
/dev/sda1   *         1         1      8001    0  Empty
/dev/sda2   *         6      2431  19486845    b  Win95 FAT32
/dev/sda3             2         5     32130   83  Linux
Partition table entries are not in disk order
  • If everything looks ok, write out the partition table.
Command (m for help): w
  • fdisk will now exit and we can create the new filesystem.
# mke2fs -j /dev/sda3
  • If you don't want your ipod to run disk checks at boot, set the maximal mount count to never.
# tune2fs -c 0 /dev/sda3
tune2fs 1.34 (25-Jul-2003)
Setting maximal mount count to -1

Copy over files

  • Copy the patched firmware/bootloader back to the ipod
# cd ~/ipod
# dd if=my_fw.bin of=/dev/sda1
  • Copy the kernel modules to the ipod root filesystem
# umount /mnt/ipod (just in case)
# mount -t ext3 /dev/sda3 /mnt/ipod
# cp -r /linux-%1/lib /mnt/ipod

Once you have installed the kernel you can test it by resetting your iPod. You should see the kernel startup messages displayed on the LCD. Since you do not have any user tools installed the kernel will likely panic. This is expected, you will need to reset your iPod back into diskmode in order to install some user tools (see the details in 'Backing up your iPod firmware and bootloader').


Now you can either follow the last step in the simple install, copying over the root filesystem or you can compile your own root filesystem from the uClinux distro source

  • will add docs on compiling uClinux later, still haven't managed to download it properly*

Back to documentation