Difference between revisions of "Raspberry Pi Kernel Compilation"

From eLinux.org
Jump to: navigation, search
(Image Generation For Latest Firmware)
(Macports)
 
(105 intermediate revisions by 34 users not shown)
Line 1: Line 1:
 
{{Template:RPi_Software}}
 
{{Template:RPi_Software}}
 
  
 
= Overview =
 
= Overview =
 +
This page explains how to rebuild the kernel image for the Raspberry Pi. There are two possible routes available:
 +
# Compile on the Raspberry Pi itself
 +
# Cross compile on another Linux system
  
First, you are going to get and build the linux kernel and its modules using a suitable compiler (a "cross-compiler" if you aren't building it on the same hardware you will be running it on) and then you are going to create a kernel image from the uncompressed kernel (Image) to place on the sd, along with the modules you build alongside it.
+
Both of these routes are covered below, however, you are strongly recommended to follow the cross-compilation route. The low processing power of the Raspberry Pi means that a local compile will take many hours. A compilation of the latest kernel and modules took about 752 minutes (12h30m)!
  
See below for the various guides to get and compile a suitable kernel for your RPi, and then create a kernel.img according to the steps at the end.
+
If you want to compile an upstream kernel, rather than the Raspberry Pi Foundation's downstream kernel, please see [[RPi_Upstream_Kernel_Compilation]] for a few tips.
  
= Raspberry PI kernel compilation =
+
== Example Checklist/Roadmap ==
 +
This section serves to hold a new user's hand just a bit more than some of the other more generic information below in the document. To get more information on the steps in the roadmap, search this page for additional details. It assumes you can navigate filesystems, move files across systems, and have a general understanding of compiling linux kernels, filesystems, partitions, and block devices.
  
You can compile the kernel on the board itself, but because of the limited resources it will take a lot of time. Alternatively you can crosscompile the kernel on another machine running Linux, Windows or OS X.
+
This series of steps yielded a successful custom/updated hardfp kernel to a stock Raspbian installation, cross compiled from an AMD 64-bit Debian system without regression on any kernel configuration options or requiring modified boot parameters. Be aware that in the worst case, you may need to overlay a stock set of kernel/modules/firmware on the Raspberry Pi if something fails. If you do not know how to do this, then a reimage of the SD card may be necessary. Assuming this is not an issue for your configuration, continue onward:
 +
# Get the latest Raspberry Pi kernel source (https://github.com/raspberrypi/linux)
 +
# Set an environment variable KERNEL_SRC to point to the location of the source (for example, KERNEL_SRC=/home/me/linux/ )
 +
# Get the latest Raspberry Pi compiler (git clone https://github.com/raspberrypi/tools)
 +
# Set an environment variable CCPREFIX to point to the location of tools (for example, CCPREFIX=/home/me/tools/arm-bcm2708/arm-bcm2708-linux-gnueabi/bin/arm-bcm2708-linux-gnueabi- )
 +
# From the kernel clone location, clean the kernel source with "make mrproper"
 +
# Pull the /proc/config.gz from the running Raspbian installation
 +
# Prime the kernel with the old configuration by running "ARCH=arm CROSS_COMPILE=${CCPREFIX} make oldconfig"
 +
# Modify the kernel configuration by either modifying the .config file or using "ARCH=arm CROSS_COMPILE=${CCPREFIX} make menuconfig"
 +
# Build the new kernel by using "ARCH=arm CROSS_COMPILE=${CCPREFIX} make"
 +
# Set an environment variable, MODULES_TEMP, to point to the location of the source (for example, MODULES_TEMP=/home/me/modules/ )
 +
# Set aside the new kernel modules by using "ARCH=arm CROSS_COMPILE=${CCPREFIX} INSTALL_MOD_PATH=${MODULES_TEMP} make modules_install"
 +
# From the tools clone location, in the mkimage directory, run "./imagetool-uncompressed.py ${KERNEL_SRC}/arch/arm/boot/zImage"
 +
# Move the resulting kernel.img to the Raspberry Pi's /boot/ directory
 +
# Package up the modules into an archive such that at the top level, the structure looks like this:
 +
#* ./firmware
 +
#* ./firmware/brcm
 +
#* ./firmware/edgeport
 +
#* ./firmware/emi26
 +
#* ...
 +
#* ./modules
 +
#* ./modules/3.6.11+
 +
#* ./modules/3.6.11+/kernel
 +
#* ./modules/3.6.11+/kernel/lib
 +
#* ./modules/3.6.11+/kernel/fs
 +
#* ...
 +
# Move the modules archive to the Raspberry Pi and extract them such that the aforementioned firmware and modules directories overwrite /lib/firmware and /lib/modules
 +
# Get the latest Raspberry Pi firmware (git://github.com/raspberrypi/firmware.git)
 +
# Transfer the following files from the firmware/boot directory to the Raspberry Pi /boot directory:
 +
#* bootcode.bin
 +
#* fixup.dat
 +
#* start.elf
 +
# Transfer the firmware/hardfp/opt directory to the Raspberry Pi /opt directory
 +
# Reboot the Raspberry Pi
 +
The Raspberry Pi should now boot with the newly configured/recompiled kernel.
  
== Compiling on the Raspberry pi itself ==
+
= Get the kernel source =
 +
The kernel source should be downloaded from the [https://github.com/raspberrypi/linux Raspberry Pi Linux section on GitHub]. Although you could just compile the vanilla kernel from [http://www.kernel.org/ Kernel.org], it will not have the necessary drivers and modules for the Broadcom SoC on the Raspberry Pi. You can however apply patches from the vanilla kernel to the Raspberry Pi one - be prepared for potential compiler grumbles though!
  
=== Arch Linux ===
+
On Jan 2014, the current is rpi-3.10.y. You can check this and other available versions by browsing [https://github.com/raspberrypi/linux Raspberry Pi Linux section on GitHub]
  
==== getting the compiler ====
+
You can download the source directly using Git. For the 3.10 branch:
You will need GIT to clone the kernel source tree from GitHub, compiler (gcc) and GNU Make:
+
<pre>
pacman -S git gcc make
+
git init
 +
git clone --depth 1 git://github.com/raspberrypi/linux.git
 +
</pre>
 +
And for the other stable code branch, change the numbers in the following to suit:
 +
<pre>
 +
git init
 +
git fetch git://github.com/raspberrypi/linux.git rpi-3.6.y:refs/remotes/origin/rpi-3.6.y
 +
git checkout rpi-3.6.y
 +
</pre>
  
(NOTE: git might be omitted if you decide to download sources in compressed format; this is far faster)
+
Or you can download a tarball from the same website:
  
==== getting the sources ====
+
= Get a compiler =
 +
Next, you will need to get a version of GCC in order to build the kernel.
  
create a directory where you can work on  the raspberry pi software. I called mine "raspberrypi". Then clone the git repository.
+
== 1. On the Raspberry Pi ==
  
mkdir raspberrypi
+
=== Raspbian and PiBang ===
cd raspberrypi
+
<pre>
git clone https://github.com/raspberrypi/linux.git
+
apt-get update
(NOTE: git might fail due to memory constraints; in this case creation of swap file might help. Be warned - this takes ages! To omit the revision history and reduce the download, you can add "--depth 1" to the end of the git clone command.)
+
apt-get -y dist-upgrade
 +
apt-get -y install gcc make bc screen ncurses-dev
 +
</pre>
  
Alternatively, download ZIP or TAR.GZ version of the sources from:
+
=== Arch Linux ===
https://github.com/raspberrypi/linux/downloads
+
<pre>
unpack and enter the extracted directory (this is your kernel directory - its sources to be precise)
+
pacman -Syu
 +
pacman -S gcc make
 +
</pre>
  
==== configuring the kernel ====
+
=== openSUSE Linux ===
Next, the kernel options are configured.  Either copy the cut down Raspberry Pi .config file from the kernel source configs directory:
+
Detailed openSUSE Raspberry Pi 12.3 Image 20130407 + 3.8.8 kernel hack tutorial witten (2013-04-22 updated)
cp arch/arm/configs/bcmrpi_cutdown_defconfig .config
+
see: http://www.raspberrypi.org/phpBB3/viewtopic.php?f=87&t=40664&p=331953#p331953
 +
The kernel compile takes about 22 hours on Raspberry Pi Model B due massive module compiles. Include all IP_VS, ARPD, Fuse-zfs, Zram and more :-)
  
Or alternatively, to use the configuration from a currently running Raspberry Pi image, connect to the target and extract the .config file.  Then copy the resultant .config file into the Linux kernel source root directory:
+
This works as well for Debian, Fedora Remix and others (just the package install command differs):
  zcat /proc/config.gz > .config
+
  zypper install u-boot-tools sudo gcc automake autoconf bison gettext flex libncurses5 ncurses-devel
cp .config <path to linux source root directory>
+
  
If needed - manual/additional configuration:
+
<pre>
make menuconfig
+
cd /usr/src
 +
mkdir GIT; cd GIT; git init; D=`date +"%m-%d-%Y"`
 +
git fetch git://github.com/raspberrypi/linux.git rpi-3.8.y:refs/remotes/origin/rpi-3.8.y
 +
git checkout rpi-3.8.y
 +
tar cpf rpi-3.8.y.$D.tar  rpi-3.8.y
  
==== compile the kernel ====
+
cd /usr/src
  make
+
tar xpf GIT/rpi-3.8.y.$D.tar
 +
rm linux
 +
ln -s linux-rpi-3.8.y linux
  
(NOTE: this will take around 6h; You might find GNU Screen useful)
+
cd /usr/src/linux
 +
kversion=$(make -s kernelrelease)
 +
cp linux/.config .config_$kversion
  
==== build kernel.img so your RPi can boot from it ====
+
cd /usr/src/
 +
# Get config-3.8.7.ipvs+krb5+arpd.tar.bz2 from the tutorial:
 +
wget http://www.raspberrypi.org/phpBB3/download/file.php?id=3174
 +
# Copy the .config file to /usr/src/linux:
 +
tar xpfj config-3.8.7.ipvs+krb5+arpd.tar.bz2
  
Finally you need to build a kernel.img for your Pi to boot from. For this, you need the mkimage tool from the raspberrypi github repository:
 
  
git clone https://github.com/raspberrypi/tools
+
#Make the kernel and go sleep :-)
 +
cd linux
 +
make oldconfig
 +
nohup make zImage dep modules &
  
Alternatively, download 'imagetool-uncompressed.py' and its dependencies from (this takes far less time and resources):
+
#The next day: Install it.
  https://github.com/raspberrypi/tools/tree/master/mkimage
+
cd /usr/src/linux
 +
kversion=$(make -s kernelrelease)
 +
echo $kversion
 +
mkdir -p /boot/$kversion
 +
make ARCH=arm INSTALL_PATH=/boot/ install
 +
cp System.map /boot/System.map-$kversion
 +
cp System.map-$kversion /boot/System.map
 +
make ARCH=arm modules_install INSTALL_MOD_PATH=/
 +
make ARCH=arm INSTALL_PATH=/boot/ zinstall
 +
cp .config /boot/config-$kversion
 +
cp ./Module.symvers  /boot/symvers-$kversion
 +
cp arch/arm/boot/Image /boot/kernel.img
 +
</pre>
  
Before you can use this script you need Python v2 to be installed:
+
== 2. Cross compiling from Linux ==
pacman -S python2
+
Please note that when cross-compiling, your compiler may not target the correct ARM processor by default. This will at best reduce performance, or worse, compile for a much newer processor resulting in illegal instructions in your code. The pre-built compiler or a custom-built compiler are recommended because of this. (For example, the latest GCC Linaro binary targets armv7-a by default, whereas the Raspberry Pi requires armv6kz). It is possible to add extra compiler options to the <tt>HOSTCFLAGS</tt> line in <tt>Makefile</tt>. The correct flags are shown on the [[RPi_Software#Compiler|software page]] - note that you may also need to add <tt>-marm</tt> if your compiler produces Thumb code by default.
  
Once all above is set up you should have the following files (checklist):
+
=== Use the provided compiler ===
* in the kernel folder you compiled a file: linux/arch/arm/boot/Image
+
Download the pre-built bmc2708 compiler from the [https://github.com/raspberrypi/tools/tree/master/arm-bcm2708/arm-bcm2708hardfp-linux-gnueabi Raspberry Pi tools section on GitHub].
* python2 executable (it should be located by default in /usr/bin/python2)
+
<pre>
* imagetool-uncompressed.py script
+
git clone git://github.com/raspberrypi/tools.git --depth 1
 +
</pre>
  
 +
Or you can download a tarball from the website using [https://github.com/raspberrypi/tools/archive/master.tar.gz this link].
  
If this is a case (you have all the above) convert your kernel image with the script:
+
=== Custom-built Linaro GCC ===
 +
See [[RPi_Linaro_GCC_Compilation|Linaro GCC Compilation]].
  
python2 imagetool-uncompressed.py path/to/linux/arch/arm/boot/Image
+
=== Ubuntu ===
 
+
<pre>
This will create a file called kernel.img. Transfer this file into /boot directory (make sure the existing kernel.img in /boot directory gets replaced).
+
apt-get install gcc-arm-linux-gnueabi make ncurses-dev
 
+
</pre>
The last thing is to install kernel modules. To do this navigate to your kernel folder and execute:
+
make modules_install
+
 
+
This will install all compiled modules into /lib/modules and possibly some additional files into /lib/firmware folders.
+
 
+
Reboot your RPi and pray :)
+
reboot
+
 
+
TODO: verify & consolidate
+
 
+
== Cross compiling on a foreign machine==
+
 
+
=== Ubuntu Linux ===
+
 
+
==== getting the compiler ====
+
 
+
On Ubuntu Oneiric getting the arm cross compiler can be as easy as:
+
+
sudo apt-get install gcc-arm-linux-gnueabi make
+
sudo apt-get install git-core  #jhauser14905 -- might as well state the obvious, you need git installed! -- it's git-core on ubuntu. --REW
+
sudo apt-get install ncurses-dev #MatthewEveritt -- Had to install this to use menuconfig.
+
 
+
 
+
(TODO: Is this the right one? More packages required? I did this a while ago! TODO: Other distributions?)
+
 
+
==== getting the sources ====
+
 
+
create a directory where you can work on  the raspberry pi software. I called mine "raspberrypi". Then clone the git repository.
+
 
+
mkdir raspberrypi
+
cd raspberrypi
+
git clone https://github.com/raspberrypi/linux.git
+
cd linux
+
 
+
==== compiling ====
+
 
+
Next, the kernel options are configured.  Either copy the cut down Raspberry Pi .config file from the kernel source configs directory:
+
cp arch/arm/configs/bcmrpi_cutdown_defconfig .config
+
 
+
Or alternatively, to use the configuration from a currently running Raspberry Pi image, connect to the target and extract the .config file.  Then copy the resultant .config file into the Linux kernel source root directory:
+
zcat /proc/config.gz > .config
+
cp .config <path to linux source root directory>
+
 
+
Configure the kernel with the copied .config file by running oldconfig:
+
make ARCH=arm CROSS_COMPILE=/usr/bin/arm-linux-gnueabi- oldconfig
+
 
+
If manual/additional configuration of kernel options are needed run menuconfig:
+
make ARCH=arm CROSS_COMPILE=/usr/bin/arm-linux-gnueabi- menuconfig
+
 
+
Then build the kernel:
+
make ARCH=arm CROSS_COMPILE=/usr/bin/arm-linux-gnueabi- -k
+
 
+
You can use the "-j" flag to improve compilation time. If you have a dual core machine you can use "-j 3", for a quad core machine you can use "-j 6", and so on.
+
 
+
If you get the error messages that arm-linux-gnueabi-gcc cannot be found when running make, run the following command:
+
 
+
sudo apt-get install gcc-arm-linux-gnueabi
+
  
 
=== Gentoo Linux ===
 
=== Gentoo Linux ===
 +
<pre>
 +
crossdev -S -v -t arm-unknown-linux-gnueabi
 +
</pre>
  
==== getting the compiler ====
+
Crossdev should create a cross-toolchain using the latest stable versions of the required packages. If it fails, you can specify exact versions by removing the "-S" flag and adding the "--b", "--g", "--k" and "--l" flags. On 2012-05-06, <tt>cross -S -v -A gnueabi arm</tt> works just fine.
 
+
Build the cross toolchain:
+
crossdev -S -v -t arm-unknown-linux-gnueabi
+
 
+
theBuell: on 2012-05-06, cross -S -v -A gnueabi arm works just fine
+
 
+
This command should create a cross-toolchain using the latest stable versions of the required packages. If it fails, you can specify exact versions by removing the "-S" flag and adding the "--b", "--g", "--k" and "--l" flags. For the exact usage refer to the crossdev manpage. A good starting point for figuring out the right versions are those which are stable for the arm architecture.
+
 
+
==== getting the sources ====
+
 
+
create a directory where you can work on  the raspberry pi software. I called mine "raspberrypi". Then clone the git repository.
+
 
+
mkdir raspberrypi
+
cd raspberrypi
+
git clone https://github.com/raspberrypi/linux.git
+
cd linux
+
 
+
==== compiling ====
+
 
+
Next you have to configure the kernel:
+
cp arch/arm/configs/bcmrpi_cutdown_defconfig .config
+
make ARCH=arm CROSS_COMPILE=/usr/bin/arm-linux-gnueabi- oldconfig
+
 
+
Then building the kernel:
+
make ARCH=arm CROSS_COMPILE=/usr/bin/arm-linux-gnueabi- -k
+
 
+
You can use the "-j" flag to improve compilation time. If you have a dual core machine you can use "-j 3", for a quad core machine you can use "-j 6", and so on.
+
  
 
=== Arch Linux ===
 
=== Arch Linux ===
 +
<pre>
 +
yaourt -S arm-linux-gnueabi-gcc
 +
</pre>
  
==== getting the compiler ====
+
== Cross compiling from OS X ==
You will need GIT to clone the kernel source tree from GitHub:
+
=== Macports ===
pacman -S git
+
The kernel source requires a case-sensitive filesystem. If you do not have a HFS+ case-sensitive partition that can be used, create a disk image with the appropriate format.
 
+
Ensure the latest versin of Xcode and command line tools are installed from [http://developer.apple.com/downloads Apple Developer Connection]
Build the cross toolchain:
+
Install [http://guide.macports.org/#installing macports]
arm-linux-gnueabi-gcc is on the AUR. If you use yaourt:
+
<pre>
 
+
port install arm-none-eabi-gcc
yaourt -S arm-linux-gnueabi-gcc
+
port install arm-none-eabi-binutils
 
+
</pre>
Yaourt is recommended as it will build all dependencies.
+
 
+
==== getting the sources ====
+
 
+
create a directory where you can work on  the raspberry pi software. I called mine "raspberrypi". Then clone the git repository.
+
 
+
mkdir raspberrypi
+
cd raspberrypi
+
git clone https://github.com/raspberrypi/linux.git
+
cd linux
+
 
+
==== compiling ====
+
 
+
Next you have to configure the kernel:
+
cp arch/arm/configs/bcmrpi_cutdown_defconfig .config
+
make ARCH=arm CROSS_COMPILE=/usr/bin/arm-linux-gnueabi- oldconfig
+
 
+
Then building the kernel:
+
make ARCH=arm CROSS_COMPILE=/usr/bin/arm-linux-gnueabi- -k
+
 
+
You can use the "-j" flag to improve compilation time. If you have a dual core machine you can use "-j 3", for a quad core machine you can use "-j 6", and so on.
+
 
+
=== Windows ===
+
 
+
TODO
+
 
+
=== OS X ===
+
 
+
==== getting the compiler ====
+
Ensure latest Xcode and command line tools are installed from [http://developer.apple.com/downloads Apple Developer Connection] then
+
Downoad and install an GNU ARM toolchain such as [http://www.yagarto.de/#downloadmac yagarto]
+
 
+
Another option is the MacPorts arm-none-eabi-*:
+
 
+
ARM gcc:
+
 
+
port install arm-none-eabi-gcc
+
 
+
binutils:
+
 
+
port install arm-none-eabi-binutils
+
 
+
==== getting the sources ====
+
 
+
The Kernel source requires a case-sensitive filesystem. If you do not have a HFS+ Case-sensitive partition that can be used, create a disk image with the appropriate format then clone the repository into the mounted image.
+
 
+
Otherwise, create a directory where you can work on  the raspberry pi software. I called mine "raspberrypi". Then clone the git repository.
+
 
+
mkdir raspberrypi
+
cd raspberrypi
+
git clone https://github.com/raspberrypi/linux.git
+
cd linux
+
 
+
==== compiling ====
+
 
+
Next you have to configure the kernel: (the running kernel config can be found in <code>/proc/config.gz</code> on your RPi)
+
cp arch/arm/configs/bcmrpi_cutdown_defconfig .config
+
make ARCH=arm CROSS_COMPILE=/path/to/yagarto/bin/arm-none-eabi- oldconfig
+
 
+
or if you used the MacPorts
+
make ARCH=arm CROSS_COMPILE=/opt/local/bin/arm-none-eabi- oldconfig
+
 
+
Then building the kernel:
+
make ARCH=arm CROSS_COMPILE=/path/to/yagarto/bin/arm-none-eabi- -k
+
 
+
or if you used the MacPorts
+
make ARCH=arm CROSS_COMPILE=/opt/local/bin/arm-none-eabi- -k
+
 
+
You can use the "-j" flag to improve compilation time. If you have a dual core machine you can use "-j 3", for a quad core machine you can use "-j 6", and so on. (Don't use these for the oldconfig option because it messes up the input and output).
+
  
 
'''If you get an error message that elf.h is missing'''
 
'''If you get an error message that elf.h is missing'''
 
install [http://guide.macports.org/#installing macports]
 
install libelf and symlink to /usr/libelf:
 
 
  sudo port install libelf && sudo ln -s /opt/local/include/libelf /usr/include/libelf
 
  sudo port install libelf && sudo ln -s /opt/local/include/libelf /usr/include/libelf
copy [http://opensource.apple.com/source/dtrace/dtrace-48/sys/elf.h?txt elf.h] and [http://opensource.apple.com/source/dtrace/dtrace-48/sys/elftypes.h?txt elftypes.h] to /usr/include
+
From opensource.apple.com, download and copy [http://opensource.apple.com/source/dtrace/dtrace-48/sys/elf.h?txt elf.h] and [http://opensource.apple.com/source/dtrace/dtrace-48/sys/elftypes.h?txt elftypes.h] to /usr/include
  
 
Edit elf.h and add
 
Edit elf.h and add
 +
#define EM_S390          22   
 
  #define R_386_NONE        0
 
  #define R_386_NONE        0
 
  #define R_386_32          1
 
  #define R_386_32          1
Line 266: Line 197:
 
  #define R_MIPS_HI16      5
 
  #define R_MIPS_HI16      5
 
  #define R_MIPS_LO16      6
 
  #define R_MIPS_LO16      6
 
 
'''If you get a "SEGMENT_SIZE is undeclared" error'''
 
'''If you get a "SEGMENT_SIZE is undeclared" error'''
 
 
open the Makefile and change the line:
 
open the Makefile and change the line:
 
 
  NOSTDINC_FLAGS += -nostdinc -isystem $(shell $(CC) -print-file-name=include)
 
  NOSTDINC_FLAGS += -nostdinc -isystem $(shell $(CC) -print-file-name=include)
 
 
to
 
to
 +
NOSTDINC_FLAGS += -nostdinc -isystem $(shell $(CC) -print-file-name=include) -Dlinux
 +
 +
'''Complete script''' requires raspberrypi.config to be in the same folder that you execute from.
 +
<pre>
 +
sudo port install arm-none-eabi-gcc
 +
sudo port install arm-none-eabi-binutils
 +
sudo port install libelf && sudo ln -s /opt/local/include/libelf /usr/include/libelf
 +
sudo curl http://opensource.apple.com/source/dtrace/dtrace-48/sys/elftypes.h?txt -o  /usr/include/elftypes.h
 +
sudo curl http://opensource.apple.com/source/dtrace/dtrace-48/sys/elf.h?txt -o /usr/include/elf.h
 +
#code to append to elf.h
 +
echo "
 +
#define EM_S390 22   
 +
#define R_386_NONE 0
 +
#define R_386_32 1
 +
#define R_386_PC32 2
 +
#define R_ARM_NONE 0
 +
#define R_ARM_PC24 1
 +
#define R_ARM_ABS32 2
 +
#define R_MIPS_NONE 0
 +
#define R_MIPS_16 1
 +
#define R_MIPS_32 2
 +
#define R_MIPS_REL32 3
 +
#define R_MIPS_26 4
 +
#define R_MIPS_HI16 5
 +
#define R_MIPS_LO16 6" > elf-append.h
 +
sudo -s 'cat elf-append.h >> /usr/include/elf.h'
 +
 +
#Make a case sensitive 3&nbsp;GB disk image, raspberrypi-kernel, and attach it:
 +
hdiutil create -size 10g -type SPARSEBUNDLE -nospotlight -volname raspberrypi-kernel -fs "Case-sensitive Journaled HFS+" -attach ./raspberrypi-kernel.dmg
 +
cp raspberrypi.config /Volumes/raspberrypi-kernel/
 +
mkdir /Volumes/raspberrypi-kernel/src
 +
cd /Volumes/raspberrypi-kernel/src
 +
 +
#Get source, either 1. from a ZIP file (faster), or 2. from Git
 +
#1. From a ZIP file
 +
curl https://codeload.github.com/raspberrypi/linux/zip/rpi-3.6.y -o ./rpi-3.6.y.zip
 +
unzip rpi-3.6.y.zip
 +
#2. From Git (disabled)
 +
#git init
 +
#git fetch git://github.com/raspberrypi/linux.git rpi-3.6.y:refs/remotes/origin/rpi-3.6.y
 +
#git checkout rpi-3.6.y
 +
 +
cpu=$(sysctl hw.ncpu | awk '{print $2}')
 +
cpup1=$((cpu+1))
 +
 +
cd /Volumes/raspberrypi-kernel/src/linux-rpi-3.6.y/
 +
export CCPREFIX=/opt/local/bin/arm-none-eabi-
 +
make mrproper
 +
cp /Volumes/raspberrypi-kernel/raspberrypi.config .config
 +
#Answer yes to all config options
 +
#yes "" | make ARCH=arm CROSS_COMPILE=${CCPREFIX} oldconfig
 +
make ARCH=arm CROSS_COMPILE=${CCPREFIX} -j$cpup1
 +
#make ARCH=arm CROSS_COMPILE=${CCPREFIX} modules -j$cpup1
 +
</pre>
  
NOSTDINC_FLAGS += -nostdinc -isystem $(shell $(CC) -print-file-name=include) -Dlinux
+
=== Yagarto ===
 +
Download and install from [http://www.yagarto.de/#downloadmac here].
 +
 
 +
= Perform the compilation =
 +
Firstly, ensure your build directory is clean:
 +
<pre>
 +
make mrproper
 +
</pre>
 +
 
 +
Next, in all cases, you will want to get a working kernel configuration to start from. You can get the one running on the Raspberry Pi by typing the following (on the Raspberry Pi):
 +
<pre>
 +
zcat /proc/config.gz > .config
 +
</pre>
 +
Then copy <tt>.config</tt> into your build directory.
 +
 
 +
Alternatively, the default configuration is available in the downloaded kernel source in <tt>arch/arm/configs/bcmrpi_defconfig</tt>. Just copy this to <tt>.config</tt> in the build directory.
 +
 
 +
From this point on, if you are cross-compiling, set an environment variable <tt>CCPREFIX</tt> that points to the prefix of your compiler binary as each compiler will be named slightly differently.
 +
<pre>
 +
export CCPREFIX=/path/to/your/compiler/binary/prefix-of-binary-
 +
</pre>
 +
 
 +
If you are building on the Raspberry Pi, remove <tt>ARCH=arm CROSS_COMPILE=${CCPREFIX}</tt> from each command.
 +
 
 +
Ensure that your configuration file is up-to-date:
 +
<pre>
 +
make ARCH=arm CROSS_COMPILE=${CCPREFIX} oldconfig
 +
</pre>
 +
If any configuration options have been added, you will be asked what set each option to. If you don't know the answer, just press enter to accept the default.
 +
 
 +
Optionally, if you want to make changes to the configuration, run this next:
 +
<pre>
 +
make ARCH=arm CROSS_COMPILE=${CCPREFIX} menuconfig
 +
</pre>
 +
 
 +
Now you are ready to build:<br>
 +
(On the Raspberry Pi, type 'screen' to open a virtual screen. If you use it you can disconnect from the Raspberry Pi and compile overnight...)
 +
<pre>
 +
make ARCH=arm CROSS_COMPILE=${CCPREFIX}
 +
</pre>
 +
If you are on a multi-core system, you can make the build faster by appending <tt>-j<N></tt> where <tt><N></tt> is the number of cores on your system plus one (that is, -j3 for two cores).
 +
 
 +
Find something else to get on with while the compilation takes place. On an average PC with the default configuration, this should take about 15 minutes.
  
= Final step: Making the 'kernel.img' for your Pi =
+
The modules will be build with the following command.
 +
<pre>
 +
make ARCH=arm CROSS_COMPILE=${CCPREFIX} modules
 +
</pre>
  
Finally you need to build a kernel.img for your Pi to boot from. The next two sections describe how to do this, depending on which firmware/bootloader version you're using.
+
= Transfer the build =
 +
The fully built kernel will be <tt>arch/arm/boot/Image</tt>. Copy your new kernel file into the Raspberry Pi boot partition, though preferably as a new file (such as <tt>kernel_new.img</tt>) just in case it doesn't work. If you're building on the Raspberry Pi, just copy the file to <tt>/boot</tt>. If you use a different filename, edit <tt>config.txt</tt> change the kernel line:
 +
<pre>
 +
kernel=kernel_new.img
 +
#kernel=kernel.img
 +
</pre>
  
== Image Generation For Latest Firmware ==
+
Now you need to transfer the modules. Set an environment variable that points to a temporary module path.
 +
<pre>
 +
export MODULES_TEMP=~/modules
 +
</pre>
  
With the latest firmware (available from https://github.com/raspberrypi/firmware), you no longer need to create an explicit kernel image; you can directly use Image (not zImage) from the kernel build process (under 'arch/arm/boot/' of the linux directory) as /boot/kernel.img.
+
In the build directory, run the following command:
 +
<pre>
 +
make ARCH=arm CROSS_COMPILE=${CCPREFIX} INSTALL_MOD_PATH=${MODULES_TEMP} modules_install
 +
</pre>
  
cp linux/arch/arm/boot/Image /media/<boot-partition-of-SD-card>/kernel.img
+
The contents of this directory, a single <pre>lib</pre> directory, should then be copied into the Raspberry Pi root directory, merging or overwriting <pre>/lib</pre>
 +
NOTE: If you have rebuilt the new kernel with exactly the same version as the one that's running, you'll need to remove the old modules first. Ideally this should be done offline by mounting the SD card on another system.
  
If you just copied the "Image" file to "kernel.img" in the boot partition of your SD card and the Raspberry Pi doesn't boot (black screen, only red powerled on), then this might help:
+
NOTE: The lib directory will have symlinks back to the kernel sources (lib/modules/<kernel-version>/source and lib/modules/<kernel-version>/build). If you have limited space on the SD card and don't intend to compile modules on the Raspberry Pi itself, you will probably want to remove those links before you transfer the lib directory. The size difference can be many hundreds of MB.
* get the most recent firmware from github:
+
  
git clone https://github.com/raspberrypi/firmware/
+
Your Raspberry Pi should now be ready to boot the new kernel. However, at this point it's recommended that you update your GPU firmware and libraries. '''This is required if you've just moved from 3.2 to 3.6 as the firmware interface has changed'''.
  
* copy the files from ''firmware/boot/'' to the boot partition of your SD card
+
= Get the firmware =
+
The firmware and boot files should be updated at the same time to ensure that your new kernel works properly. Again, two branches are available:
cd firmware/boot
+
* '''master''' - This is the version of firmware currently used in Raspbian (that is, it works with the 3.2 kernel).
cp arm128_start.elf arm192_start.elf arm224_start.elf bootcode.bin loader.bin start.elf /media/<boot-partition-of-SD-card>/
+
* '''next''' - This is a development branch which provides a newer GPU firmware to work with the updated drivers in the 3.6 kernel.
  
== Image Generation For Older Firmware ==
+
You can either download the source directly using Git:
 +
You can download the firmware directly using Git. For the master branch:
 +
<pre>
 +
git clone git://github.com/raspberrypi/firmware.git
 +
</pre>
 +
And for the next branch:
 +
<pre>
 +
git fetch git://github.com/raspberrypi/firmware.git next:refs/remotes/origin/next
 +
</pre>
 +
Or you can download a tarball from the website using these links: [https://github.com/raspberrypi/firmware/archive/master.tar.gz master] [https://github.com/raspberrypi/firmware/archive/next.tar.gz next]
  
For this, you need the mkimage tool from the raspberrypi github repository:
+
= Transfer the firmware =
 +
Firstly, update the required boot files in the Raspberry Pi <tt>boot</tt> directory with those you've downloaded. These are:
 +
* bootcode.bin
 +
* fixup.dat
 +
* start.elf
  
git clone https://github.com/raspberrypi/tools
+
Next, you need to copy the VC libraries over. There are two copies of this: one for hard float and one for soft float. To find the correct one, run the following command:
 +
<pre>
 +
${CCPREFIX}gcc -v 2>&1 | grep hard
 +
</pre>
  
In tools/mkimage, you'll find a python script called 'imagetool-uncompressed.py':
+
If something prints out, and you can see <tt>--with-float=hard</tt>, you need the hard float ones. NOTE: The current version of Raspbian uses hard float.
  
usage : imagetool-uncompressed.py <kernel image>
+
Remove the <tt>/opt/vc</tt> directory from the Raspberry Pi root, then:
 +
* For hard float, copy <tt>vc</tt> from the <tt>hardfp/opt</tt> directory into <tt>/opt</tt> in the Raspberry Pi root directory
 +
* Otherwise copy <tt>vc</tt> from the top-level <tt>opt</tt> directory into <tt>/opt</tt> in the Raspberry Pi root directory.
  
After building your linux kernel, you'll find the kernel image you require in 'arch/arm/boot/Image' of the linux directory. Convert your kernel image with the script:
+
Note: The hard float vs soft float here refers only to the kernel itself, not the functionality it provides. Your applications will still be able to use hard floats. The kernel doesn't use floats anyway, so it is not something to worry about as long as you select the correct <tt>vc</tt> directory to copy.
  
python imagetool-uncompressed.py path/to/linux/arch/arm/boot/Image
+
= Test your build =
 +
Power cycle your Raspberry Pi and check the following:
 +
* If you have the serial port on the GPIO expander wired up, you should see the kernel booting.
 +
* The screen works - the kernel boots and you get a login prompt.
 +
* The VC interface is working - if the 'OK' LED flashes regularly eight or so times every few seconds once the OS has booted, it's not. You can also test this by running <tt>vcgencmd measure_temp</tt>. If it prints "VCHI initialization failed", you have the a mismatch between the firmware, the VC libraries, and the kernel driver.
 +
* Run <tt>uname -a</tt> and check that your new kernel is the one that's running.
 +
* Make sure you don't have any odd error messages during boot that may indicate a module isn't working properly. If you see <tt>missed completion of cmd 18</tt> regarding DMA transfers to the SD card, you can safely ignore it.
  
= Transferring The Image To The Raspberry Pi =
+
= Build modules for the running kernel =
 +
[https://github.com/notro/rpi-source/wiki rpi-source] downloads a matching source for the running kernel.
 +
It supports rpi-update kernels and Raspian kernels.
  
Then you have to transfer this img file to the /boot directory and install the compiled modules. Unfortunately the compiled modules are not in a single place, there are two options of installing them.
+
Examples: https://github.com/notro/rpi-source/wiki/Examples-on-how-to-build-various-modules
  
Boot your RaspberryPi and mount the <code>linux</code> directory over the network using sshfs:
+
= Easy kernel building with rpi-build =
cd /mnt
+
Now it's easy for everyone to build, install and distribute Linux kernels for the Raspberry Pi.
mkdir linux
+
sshfs <user>@<host>:<path/to/linux> linux
+
cd linux
+
make modules_install
+
  
If you got "Permission denied" when doing <code>cd linux</code>, try:
+
rpi-build installs all prerequisites and downloads all necessary source files.
sudo sh -c "cd linux ; make modules_install"
+
  
If that is not an option, you can also install the modules into a temporary folder:
+
Wiki with examples: https://github.com/notro/rpi-build/wiki
mkdir /tmp/modules
+
make ARCH=arm modules_install INSTALL_MOD_PATH=/tmp/modules
+
  
Now you have to copy the contents of that directory to /lib/modules on the SD card.
+
Build and install the latest Raspberry Pi/Linux kernel on the Raspberry Pi (~11 hours)
 +
<pre>
 +
rpi-build use[stdlib] rpi_linux build
 +
rpi-build use[stdlib] rpi_linux install
 +
</pre>
 +
From a build machine (cross compiling)
 +
<pre>
 +
rpi-build use[stdlib] rpi_linux build
 +
rpi-build use[stdlib] rpi_linux install SSHIP=<Raspberry Pi IP address>
 +
</pre>
 +
Upload the kernel to GitHub
 +
<pre>
 +
rpi-build use[stdlib] rpi_linux commit COMMIT_MESSAGE="First release" FW_REPO=<path to Git repository>
 +
rpi-build use[stdlib] rpi_linux push
 +
</pre>
 +
Install the kernel from GitHub
 +
<pre>
 +
sudo REPO_URI=<github repo url> rpi-update
 +
</pre>
  
Once you've done those two steps, you are ready to put the SD card in and try booting your new system!
 
  
 
{{Template:Raspberry Pi}}
 
{{Template:Raspberry Pi}}
[[Category: RaspberryPi]]
+
[[Category:RaspberryPi]]
 +
[[Category:Linux-kernel]]

Latest revision as of 07:52, 6 November 2014

Back to the Hub.


Software & Distributions:

Software - an overview.

Distributions - operating systems and development environments for the Raspberry Pi.

Kernel Compilation - advice on compiling a kernel.

Performance - measures of the Raspberry Pi's performance.

Programming - programming languages that might be used on the Raspberry Pi.

Overview

This page explains how to rebuild the kernel image for the Raspberry Pi. There are two possible routes available:

  1. Compile on the Raspberry Pi itself
  2. Cross compile on another Linux system

Both of these routes are covered below, however, you are strongly recommended to follow the cross-compilation route. The low processing power of the Raspberry Pi means that a local compile will take many hours. A compilation of the latest kernel and modules took about 752 minutes (12h30m)!

If you want to compile an upstream kernel, rather than the Raspberry Pi Foundation's downstream kernel, please see RPi_Upstream_Kernel_Compilation for a few tips.

Example Checklist/Roadmap

This section serves to hold a new user's hand just a bit more than some of the other more generic information below in the document. To get more information on the steps in the roadmap, search this page for additional details. It assumes you can navigate filesystems, move files across systems, and have a general understanding of compiling linux kernels, filesystems, partitions, and block devices.

This series of steps yielded a successful custom/updated hardfp kernel to a stock Raspbian installation, cross compiled from an AMD 64-bit Debian system without regression on any kernel configuration options or requiring modified boot parameters. Be aware that in the worst case, you may need to overlay a stock set of kernel/modules/firmware on the Raspberry Pi if something fails. If you do not know how to do this, then a reimage of the SD card may be necessary. Assuming this is not an issue for your configuration, continue onward:

  1. Get the latest Raspberry Pi kernel source (https://github.com/raspberrypi/linux)
  2. Set an environment variable KERNEL_SRC to point to the location of the source (for example, KERNEL_SRC=/home/me/linux/ )
  3. Get the latest Raspberry Pi compiler (git clone https://github.com/raspberrypi/tools)
  4. Set an environment variable CCPREFIX to point to the location of tools (for example, CCPREFIX=/home/me/tools/arm-bcm2708/arm-bcm2708-linux-gnueabi/bin/arm-bcm2708-linux-gnueabi- )
  5. From the kernel clone location, clean the kernel source with "make mrproper"
  6. Pull the /proc/config.gz from the running Raspbian installation
  7. Prime the kernel with the old configuration by running "ARCH=arm CROSS_COMPILE=${CCPREFIX} make oldconfig"
  8. Modify the kernel configuration by either modifying the .config file or using "ARCH=arm CROSS_COMPILE=${CCPREFIX} make menuconfig"
  9. Build the new kernel by using "ARCH=arm CROSS_COMPILE=${CCPREFIX} make"
  10. Set an environment variable, MODULES_TEMP, to point to the location of the source (for example, MODULES_TEMP=/home/me/modules/ )
  11. Set aside the new kernel modules by using "ARCH=arm CROSS_COMPILE=${CCPREFIX} INSTALL_MOD_PATH=${MODULES_TEMP} make modules_install"
  12. From the tools clone location, in the mkimage directory, run "./imagetool-uncompressed.py ${KERNEL_SRC}/arch/arm/boot/zImage"
  13. Move the resulting kernel.img to the Raspberry Pi's /boot/ directory
  14. Package up the modules into an archive such that at the top level, the structure looks like this:
    • ./firmware
    • ./firmware/brcm
    • ./firmware/edgeport
    • ./firmware/emi26
    • ...
    • ./modules
    • ./modules/3.6.11+
    • ./modules/3.6.11+/kernel
    • ./modules/3.6.11+/kernel/lib
    • ./modules/3.6.11+/kernel/fs
    • ...
  15. Move the modules archive to the Raspberry Pi and extract them such that the aforementioned firmware and modules directories overwrite /lib/firmware and /lib/modules
  16. Get the latest Raspberry Pi firmware (git://github.com/raspberrypi/firmware.git)
  17. Transfer the following files from the firmware/boot directory to the Raspberry Pi /boot directory:
    • bootcode.bin
    • fixup.dat
    • start.elf
  18. Transfer the firmware/hardfp/opt directory to the Raspberry Pi /opt directory
  19. Reboot the Raspberry Pi

The Raspberry Pi should now boot with the newly configured/recompiled kernel.

Get the kernel source

The kernel source should be downloaded from the Raspberry Pi Linux section on GitHub. Although you could just compile the vanilla kernel from Kernel.org, it will not have the necessary drivers and modules for the Broadcom SoC on the Raspberry Pi. You can however apply patches from the vanilla kernel to the Raspberry Pi one - be prepared for potential compiler grumbles though!

On Jan 2014, the current is rpi-3.10.y. You can check this and other available versions by browsing Raspberry Pi Linux section on GitHub

You can download the source directly using Git. For the 3.10 branch:

git init
git clone --depth 1 git://github.com/raspberrypi/linux.git

And for the other stable code branch, change the numbers in the following to suit:

git init
git fetch git://github.com/raspberrypi/linux.git rpi-3.6.y:refs/remotes/origin/rpi-3.6.y
git checkout rpi-3.6.y

Or you can download a tarball from the same website:

Get a compiler

Next, you will need to get a version of GCC in order to build the kernel.

1. On the Raspberry Pi

Raspbian and PiBang

apt-get update
apt-get -y dist-upgrade
apt-get -y install gcc make bc screen ncurses-dev

Arch Linux

pacman -Syu
pacman -S gcc make

openSUSE Linux

Detailed openSUSE Raspberry Pi 12.3 Image 20130407 + 3.8.8 kernel hack tutorial witten (2013-04-22 updated) see: http://www.raspberrypi.org/phpBB3/viewtopic.php?f=87&t=40664&p=331953#p331953 The kernel compile takes about 22 hours on Raspberry Pi Model B due massive module compiles. Include all IP_VS, ARPD, Fuse-zfs, Zram and more :-)

This works as well for Debian, Fedora Remix and others (just the package install command differs):

zypper install u-boot-tools sudo gcc automake autoconf bison gettext flex libncurses5 ncurses-devel
cd /usr/src
mkdir GIT; cd GIT; git init; D=`date +"%m-%d-%Y"`
git fetch git://github.com/raspberrypi/linux.git rpi-3.8.y:refs/remotes/origin/rpi-3.8.y
git checkout rpi-3.8.y
tar cpf rpi-3.8.y.$D.tar   rpi-3.8.y

cd /usr/src
tar xpf  GIT/rpi-3.8.y.$D.tar
rm linux
ln -s linux-rpi-3.8.y linux

cd /usr/src/linux
kversion=$(make -s kernelrelease)
cp linux/.config .config_$kversion

cd /usr/src/
# Get config-3.8.7.ipvs+krb5+arpd.tar.bz2 from the tutorial:
wget http://www.raspberrypi.org/phpBB3/download/file.php?id=3174
# Copy the .config file to /usr/src/linux: 
tar xpfj config-3.8.7.ipvs+krb5+arpd.tar.bz2


#Make the kernel and go sleep :-)
cd linux
make oldconfig
nohup make zImage dep modules &

#The next day: Install it.
cd /usr/src/linux
kversion=$(make -s kernelrelease)
echo $kversion
mkdir -p  /boot/$kversion
make ARCH=arm INSTALL_PATH=/boot/ install
cp System.map /boot/System.map-$kversion
cp System.map-$kversion /boot/System.map
make ARCH=arm modules_install INSTALL_MOD_PATH=/
make ARCH=arm INSTALL_PATH=/boot/ zinstall
cp .config /boot/config-$kversion
cp ./Module.symvers  /boot/symvers-$kversion
cp arch/arm/boot/Image /boot/kernel.img

2. Cross compiling from Linux

Please note that when cross-compiling, your compiler may not target the correct ARM processor by default. This will at best reduce performance, or worse, compile for a much newer processor resulting in illegal instructions in your code. The pre-built compiler or a custom-built compiler are recommended because of this. (For example, the latest GCC Linaro binary targets armv7-a by default, whereas the Raspberry Pi requires armv6kz). It is possible to add extra compiler options to the HOSTCFLAGS line in Makefile. The correct flags are shown on the software page - note that you may also need to add -marm if your compiler produces Thumb code by default.

Use the provided compiler

Download the pre-built bmc2708 compiler from the Raspberry Pi tools section on GitHub.

git clone git://github.com/raspberrypi/tools.git --depth 1

Or you can download a tarball from the website using this link.

Custom-built Linaro GCC

See Linaro GCC Compilation.

Ubuntu

apt-get install gcc-arm-linux-gnueabi make ncurses-dev

Gentoo Linux

crossdev -S -v -t arm-unknown-linux-gnueabi

Crossdev should create a cross-toolchain using the latest stable versions of the required packages. If it fails, you can specify exact versions by removing the "-S" flag and adding the "--b", "--g", "--k" and "--l" flags. On 2012-05-06, cross -S -v -A gnueabi arm works just fine.

Arch Linux

yaourt -S arm-linux-gnueabi-gcc

Cross compiling from OS X

Macports

The kernel source requires a case-sensitive filesystem. If you do not have a HFS+ case-sensitive partition that can be used, create a disk image with the appropriate format. Ensure the latest versin of Xcode and command line tools are installed from Apple Developer Connection Install macports

port install arm-none-eabi-gcc
port install arm-none-eabi-binutils

If you get an error message that elf.h is missing

sudo port install libelf && sudo ln -s /opt/local/include/libelf /usr/include/libelf

From opensource.apple.com, download and copy elf.h and elftypes.h to /usr/include

Edit elf.h and add

#define EM_S390           22    
#define R_386_NONE        0
#define R_386_32          1
#define R_386_PC32        2
#define R_ARM_NONE        0
#define R_ARM_PC24        1
#define R_ARM_ABS32       2
#define R_MIPS_NONE       0
#define R_MIPS_16         1
#define R_MIPS_32         2
#define R_MIPS_REL32      3
#define R_MIPS_26         4
#define R_MIPS_HI16       5
#define R_MIPS_LO16       6

If you get a "SEGMENT_SIZE is undeclared" error open the Makefile and change the line:

NOSTDINC_FLAGS += -nostdinc -isystem $(shell $(CC) -print-file-name=include)

to

NOSTDINC_FLAGS += -nostdinc -isystem $(shell $(CC) -print-file-name=include) -Dlinux

Complete script requires raspberrypi.config to be in the same folder that you execute from.

sudo port install arm-none-eabi-gcc
sudo port install arm-none-eabi-binutils
sudo port install libelf && sudo ln -s /opt/local/include/libelf /usr/include/libelf
sudo curl http://opensource.apple.com/source/dtrace/dtrace-48/sys/elftypes.h?txt -o  /usr/include/elftypes.h
sudo curl http://opensource.apple.com/source/dtrace/dtrace-48/sys/elf.h?txt -o /usr/include/elf.h
#code to append to elf.h
echo "
#define EM_S390 22    
#define R_386_NONE 0
#define R_386_32 1
#define R_386_PC32 2
#define R_ARM_NONE 0
#define R_ARM_PC24 1
#define R_ARM_ABS32 2
#define R_MIPS_NONE 0
#define R_MIPS_16 1
#define R_MIPS_32 2
#define R_MIPS_REL32 3
#define R_MIPS_26 4
#define R_MIPS_HI16 5
#define R_MIPS_LO16 6" > elf-append.h
sudo -s 'cat elf-append.h >> /usr/include/elf.h'

#Make a case sensitive 3 GB disk image, raspberrypi-kernel, and attach it:
hdiutil create -size 10g -type SPARSEBUNDLE -nospotlight -volname raspberrypi-kernel -fs "Case-sensitive Journaled HFS+" -attach ./raspberrypi-kernel.dmg
cp raspberrypi.config /Volumes/raspberrypi-kernel/
mkdir /Volumes/raspberrypi-kernel/src
cd /Volumes/raspberrypi-kernel/src

#Get source, either 1. from a ZIP file (faster), or 2. from Git
#1. From a ZIP file
curl https://codeload.github.com/raspberrypi/linux/zip/rpi-3.6.y -o ./rpi-3.6.y.zip
unzip rpi-3.6.y.zip
#2. From Git (disabled)
#git init
#git fetch git://github.com/raspberrypi/linux.git rpi-3.6.y:refs/remotes/origin/rpi-3.6.y
#git checkout rpi-3.6.y

cpu=$(sysctl hw.ncpu | awk '{print $2}')
cpup1=$((cpu+1))

cd /Volumes/raspberrypi-kernel/src/linux-rpi-3.6.y/
export CCPREFIX=/opt/local/bin/arm-none-eabi-
make mrproper
cp /Volumes/raspberrypi-kernel/raspberrypi.config .config
#Answer yes to all config options
#yes "" | make ARCH=arm CROSS_COMPILE=${CCPREFIX} oldconfig
make ARCH=arm CROSS_COMPILE=${CCPREFIX} -j$cpup1
#make ARCH=arm CROSS_COMPILE=${CCPREFIX} modules -j$cpup1

Yagarto

Download and install from here.

Perform the compilation

Firstly, ensure your build directory is clean:

make mrproper

Next, in all cases, you will want to get a working kernel configuration to start from. You can get the one running on the Raspberry Pi by typing the following (on the Raspberry Pi):

zcat /proc/config.gz > .config

Then copy .config into your build directory.

Alternatively, the default configuration is available in the downloaded kernel source in arch/arm/configs/bcmrpi_defconfig. Just copy this to .config in the build directory.

From this point on, if you are cross-compiling, set an environment variable CCPREFIX that points to the prefix of your compiler binary as each compiler will be named slightly differently.

export CCPREFIX=/path/to/your/compiler/binary/prefix-of-binary-

If you are building on the Raspberry Pi, remove ARCH=arm CROSS_COMPILE=${CCPREFIX} from each command.

Ensure that your configuration file is up-to-date:

make ARCH=arm CROSS_COMPILE=${CCPREFIX} oldconfig

If any configuration options have been added, you will be asked what set each option to. If you don't know the answer, just press enter to accept the default.

Optionally, if you want to make changes to the configuration, run this next:

make ARCH=arm CROSS_COMPILE=${CCPREFIX} menuconfig

Now you are ready to build:
(On the Raspberry Pi, type 'screen' to open a virtual screen. If you use it you can disconnect from the Raspberry Pi and compile overnight...)

make ARCH=arm CROSS_COMPILE=${CCPREFIX}

If you are on a multi-core system, you can make the build faster by appending -j<N> where <N> is the number of cores on your system plus one (that is, -j3 for two cores).

Find something else to get on with while the compilation takes place. On an average PC with the default configuration, this should take about 15 minutes.

The modules will be build with the following command.

make ARCH=arm CROSS_COMPILE=${CCPREFIX} modules

Transfer the build

The fully built kernel will be arch/arm/boot/Image. Copy your new kernel file into the Raspberry Pi boot partition, though preferably as a new file (such as kernel_new.img) just in case it doesn't work. If you're building on the Raspberry Pi, just copy the file to /boot. If you use a different filename, edit config.txt change the kernel line:

kernel=kernel_new.img
#kernel=kernel.img

Now you need to transfer the modules. Set an environment variable that points to a temporary module path.

export MODULES_TEMP=~/modules

In the build directory, run the following command:

make ARCH=arm CROSS_COMPILE=${CCPREFIX} INSTALL_MOD_PATH=${MODULES_TEMP} modules_install
The contents of this directory, a single
lib
directory, should then be copied into the Raspberry Pi root directory, merging or overwriting
/lib

NOTE: If you have rebuilt the new kernel with exactly the same version as the one that's running, you'll need to remove the old modules first. Ideally this should be done offline by mounting the SD card on another system.

NOTE: The lib directory will have symlinks back to the kernel sources (lib/modules/<kernel-version>/source and lib/modules/<kernel-version>/build). If you have limited space on the SD card and don't intend to compile modules on the Raspberry Pi itself, you will probably want to remove those links before you transfer the lib directory. The size difference can be many hundreds of MB.

Your Raspberry Pi should now be ready to boot the new kernel. However, at this point it's recommended that you update your GPU firmware and libraries. This is required if you've just moved from 3.2 to 3.6 as the firmware interface has changed.

Get the firmware

The firmware and boot files should be updated at the same time to ensure that your new kernel works properly. Again, two branches are available:

  • master - This is the version of firmware currently used in Raspbian (that is, it works with the 3.2 kernel).
  • next - This is a development branch which provides a newer GPU firmware to work with the updated drivers in the 3.6 kernel.

You can either download the source directly using Git: You can download the firmware directly using Git. For the master branch:

git clone git://github.com/raspberrypi/firmware.git

And for the next branch:

git fetch git://github.com/raspberrypi/firmware.git next:refs/remotes/origin/next

Or you can download a tarball from the website using these links: master next

Transfer the firmware

Firstly, update the required boot files in the Raspberry Pi boot directory with those you've downloaded. These are:

  • bootcode.bin
  • fixup.dat
  • start.elf

Next, you need to copy the VC libraries over. There are two copies of this: one for hard float and one for soft float. To find the correct one, run the following command:

${CCPREFIX}gcc -v 2>&1 | grep hard

If something prints out, and you can see --with-float=hard, you need the hard float ones. NOTE: The current version of Raspbian uses hard float.

Remove the /opt/vc directory from the Raspberry Pi root, then:

  • For hard float, copy vc from the hardfp/opt directory into /opt in the Raspberry Pi root directory
  • Otherwise copy vc from the top-level opt directory into /opt in the Raspberry Pi root directory.

Note: The hard float vs soft float here refers only to the kernel itself, not the functionality it provides. Your applications will still be able to use hard floats. The kernel doesn't use floats anyway, so it is not something to worry about as long as you select the correct vc directory to copy.

Test your build

Power cycle your Raspberry Pi and check the following:

  • If you have the serial port on the GPIO expander wired up, you should see the kernel booting.
  • The screen works - the kernel boots and you get a login prompt.
  • The VC interface is working - if the 'OK' LED flashes regularly eight or so times every few seconds once the OS has booted, it's not. You can also test this by running vcgencmd measure_temp. If it prints "VCHI initialization failed", you have the a mismatch between the firmware, the VC libraries, and the kernel driver.
  • Run uname -a and check that your new kernel is the one that's running.
  • Make sure you don't have any odd error messages during boot that may indicate a module isn't working properly. If you see missed completion of cmd 18 regarding DMA transfers to the SD card, you can safely ignore it.

Build modules for the running kernel

rpi-source downloads a matching source for the running kernel. It supports rpi-update kernels and Raspian kernels.

Examples: https://github.com/notro/rpi-source/wiki/Examples-on-how-to-build-various-modules

Easy kernel building with rpi-build

Now it's easy for everyone to build, install and distribute Linux kernels for the Raspberry Pi.

rpi-build installs all prerequisites and downloads all necessary source files.

Wiki with examples: https://github.com/notro/rpi-build/wiki

Build and install the latest Raspberry Pi/Linux kernel on the Raspberry Pi (~11 hours)

rpi-build use[stdlib] rpi_linux build
rpi-build use[stdlib] rpi_linux install

From a build machine (cross compiling)

rpi-build use[stdlib] rpi_linux build
rpi-build use[stdlib] rpi_linux install SSHIP=<Raspberry Pi IP address>

Upload the kernel to GitHub

rpi-build use[stdlib] rpi_linux commit COMMIT_MESSAGE="First release" FW_REPO=<path to Git repository>
rpi-build use[stdlib] rpi_linux push

Install the kernel from GitHub

sudo REPO_URI=<github repo url> rpi-update