Foundation
Raspberry Pi
Documentation
Computers
Accessories
Microcontrollers
Services
Pico C SDK
The Linux kernel
Kernel
Edit this on GitHub
The Raspberry Pi kernel is stored in GitHub and can be
viewed at github.com/raspberrypi/linux; it follows behind
the main Linux kernel. The main Linux kernel is
continuously updating; we take long-term releases of the
kernel, which are mentioned on the front page, and
integrate the changes into the Raspberry Pi kernel. We
then create a 'next' branch which contains an unstable
port of the kernel; after extensive testing and discussion,
we push this to the main branch.
Updating your Kernel
If you use the standard Raspberry Pi OS update and
upgrade process, this will automatically update the kernel
to the latest stable version. This is the recommended
procedure. However, in certain circumstances, you may
wish to update to the latest 'bleeding edge' or test kernel.
You should only do this if recommended to do so by a
Raspberry Pi engineer, or if there is a speciVc feature only
available in this latest software.
Getting your Code into the Kernel
There are many reasons you may want to put something
into the kernel:
You’ve written some Raspberry Pi-speciVc code
that you want everyone to beneVt from
You’ve written a generic Linux kernel driver for a
device and want everyone to use it
You’ve Vxed a generic kernel bug
You’ve Vxed a Raspberry Pi-speciVc kernel bug
Initially, you should fork the Linux repository and clone
that on your build system; this can be either on the
Raspberry Pi or on a Linux machine you’re using for
cross-compiling. You can then make your changes, test
them, and commit them into your fork.
Next, depending upon whether the code is Raspberry Pi-
speciVc or not:
For Raspberry Pi-speciVc changes or bug Vxes,
submit a pull request to the kernel.
For general Linux kernel changes (i.e. a new driver),
these need to be submitted upstream Vrst. Once
they’ve been submitted upstream and accepted,
submit the pull request and we’ll receive it.
Building the Kernel
Edit this on GitHub
The default compilers and linkers that come with an OS
are conVgured to build executables to run on that OS -
they are native tools - but that doesn’t have to be the
case. A cross-compiler is conVgured to build code for a
target other than the one running the build process, and
using it is called cross-compilation.
Cross-compilation of the Raspberry Pi kernel is useful for
two reasons:
it allows a 64-bit kernel to be built using a 32-bit OS,
and vice versa, and
even a modest laptop can cross-compile a
Raspberry Pi kernel signiVcantly faster than the
Raspberry Pi itself.
The instructions below are divided into native builds and
cross-compilation; choose the section appropriate for
your situation - although there are many common steps
between the two, there are also some important
differences.
Building the Kernel Locally
On a Raspberry Pi, Vrst install the latest version of
Raspberry Pi OS. Then boot your Raspberry Pi, log in, and
ensure you’re connected to the internet to give you
access to the sources.
First install Git and the build dependencies:
sudo apt install git bc bison flex libssl-dev make
Next get the sources, which will take some time:
git clone --depth=1 https://github.com/raspberrypi
Choosing Sources
The git clone command above will download the
current active branch (the one we are building Raspberry
Pi OS images from) without any history. Omitting the --
depth=1 will download the entire repository, including the
full history of all branches, but this takes much longer and
occupies much more storage.
To download a different branch (again with no history),
use the --branch option:
git clone --depth=1 --branch <branch> https://gith
where <branch> is the name of the branch that you wish
to download.
Refer to the original GitHub repository for information
about the available branches.
Kernel ConIguration
ConVgure the kernel; as well as the default conVguration,
you may wish to conVgure your kernel in more detail or
apply patches from another source, to add or remove
required functionality.
Apply the Default ConIguration
First, prepare the default conVguration by running the
following commands, depending on your Raspberry Pi
model:
For Raspberry Pi 1, Zero and Zero W, and Raspberry Pi
Compute Module 1 default (32-bit only) build
conVguration
cd linux
KERNEL=kernel
make bcmrpi_defconfig
For Raspberry Pi 2, 3, 3+ and Zero 2 W, and Raspberry Pi
Compute Modules 3 and 3+ default 32-bit build
conVguration
cd linux
KERNEL=kernel7
make bcm2709_defconfig
For Raspberry Pi 4 and 400, and Raspberry Pi Compute
Module 4 default 32-bit build conVguration
cd linux
KERNEL=kernel7l
make bcm2711_defconfig
For Raspberry Pi 3, 3+, 4, 400 and Zero 2 W, and
Raspberry Pi Compute Modules 3, 3+ and 4 default 64-bit
build conVguration
cd linux
KERNEL=kernel8
make bcm2711_defconfig
Customising the Kernel Version Using LOCALVERSION
In addition to your kernel conVguration changes, you may
wish to adjust the LOCALVERSION to ensure your new
kernel does not receive the same version string as the
upstream kernel. This both clariVes you are running your
own kernel in the output of uname and ensures existing
modules in /lib/modules are not overwritten.
To do so, change the following line in .config:
CONFIG_LOCALVERSION="-v7l-MY_CUSTOM_KERNEL"
You can also change that setting graphically as shown in
the kernel conVguration instructions. It is located in
"General setup" => "Local version - append to kernel
release".
Building the Kernel
Build and install the kernel, modules, and Device Tree
blobs; this step can take a long time depending on the
Raspberry Pi model in use. For the 32-bit kernel:
make -j4 zImage modules dtbs
sudo make modules_install
sudo cp arch/arm/boot/dts/*.dtb /boot/
sudo cp arch/arm/boot/dts/overlays/*.dtb* /boot/ov
sudo cp arch/arm/boot/dts/overlays/README /boot/ov
sudo cp arch/arm/boot/zImage /boot/$KERNEL.img
For the 64-bit kernel:
make -j4 Image.gz modules dtbs
sudo make modules_install
sudo cp arch/arm64/boot/dts/broadcom/*.dtb /boot/
sudo cp arch/arm64/boot/dts/overlays/*.dtb* /boot/
sudo cp arch/arm64/boot/dts/overlays/README /boot/
sudo cp arch/arm64/boot/Image.gz /boot/$KERNEL.img
NOTE
On a Raspberry Pi 2/3/4, the -j4 eag splits the work
between all four cores, speeding up compilation
signiVcantly.
If you now reboot, your Raspberry Pi should be running
your freshly-compiled kernel!
Cross-Compiling the Kernel
First, you will need a suitable Linux cross-compilation
host. We tend to use Ubuntu; since Raspberry Pi OS is
also a Debian distribution, it means many aspects are
similar, such as the command lines.
You can either do this using VirtualBox (or VMWare) on
Windows, or install it directly onto your computer. For
reference, you can follow instructions online at Wikihow.
Install Required Dependencies and Toolchain
To build the sources for cross-compilation, make sure you
have the dependencies needed on your machine by
executing:
sudo apt install git bc bison flex libssl-dev make
If you Vnd you need other things, please submit a pull
request to change the documentation.
Install the 32-bit Toolchain for a 32-bit Kernel
sudo apt install crossbuild-essential-armhf
Install the 64-bit Toolchain for a 64-bit Kernel
sudo apt install crossbuild-essential-arm64
Get the Kernel Sources
To download the minimal source tree for the current
branch, run:
git clone --depth=1 https://github.com/raspberrypi
See Choosing sources above for instructions on how to
choose a different branch.
Build sources
Enter the following commands to build the sources and
Device Tree Vles:
32-bit ConIgs
For Raspberry Pi 1, Zero and Zero W, and Raspberry Pi
Compute Module 1:
cd linux
KERNEL=kernel
make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- b
For Raspberry Pi 2, 3, 3+ and Zero 2 W, and Raspberry Pi
Compute Modules 3 and 3+:
cd linux
KERNEL=kernel7
make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- b
For Raspberry Pi 4 and 400, and Raspberry Pi Compute
Module 4:
cd linux
KERNEL=kernel7l
make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- b
64-bit ConIgs
For Raspberry Pi 3, 3+, 4, 400 and Zero 2 W, and
Raspberry Pi Compute Modules 3, 3+ and 4:
cd linux
KERNEL=kernel8
make ARCH=arm64 CROSS_COMPILE=aarch64-linux-gnu- b
Build with ConIgs
NOTE
To speed up compilation on multiprocessor systems,
and get some improvement on single processor ones,
use -j n, where n is the number of processors * 1.5.
You can use the nproc command to see how many
processors you have. Alternatively, feel free to
experiment and see what works!
For all 32-bit Builds
make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- z
For all 64-bit Builds
NOTE
Note the difference between Image target between 32
and 64-bit.
make ARCH=arm64 CROSS_COMPILE=aarch64-linux-gnu- I
Install Directly onto the SD Card
Having built the kernel, you need to copy it onto your
Raspberry Pi and install the modules; this is best done
directly using an SD card reader.
First, use lsblk before and after plugging in your SD card
to identify it. You should end up with something a lot like
this:
sdb
sdb1
sdb2
with sdb1 being the FAT Vlesystem (boot) partition, and
sdb2 being the ext4 Vlesystem (root) partition.
Mount these Vrst, adjusting the partition letter as
necessary:
mkdir mnt
mkdir mnt/fat32
mkdir mnt/ext4
sudo mount /dev/sdb1 mnt/fat32
sudo mount /dev/sdb2 mnt/ext4
NOTE
You should adjust the drive letter appropriately for
your setup, e.g. if your SD card appears as /dev/sdc
instead of /dev/sdb.
Next, install the kernel modules onto the SD card:
For 32-bit
sudo env PATH=$PATH make ARCH=arm CROSS_COMPILE=ar
For 64-bit
sudo env PATH=$PATH make ARCH=arm64 CROSS_COMPILE=
Finally, copy the kernel and Device Tree blobs onto the SD
card, making sure to back up your old kernel:
For 32-bit
sudo cp mnt/fat32/$KERNEL.img mnt/fat32/$KERNEL-ba
sudo cp arch/arm/boot/zImage mnt/fat32/$KERNEL.img
sudo cp arch/arm/boot/dts/*.dtb mnt/fat32/
sudo cp arch/arm/boot/dts/overlays/*.dtb* mnt/fat3
sudo cp arch/arm/boot/dts/overlays/README mnt/fat3
sudo umount mnt/fat32
sudo umount mnt/ext4
For 64-bit
sudo cp mnt/fat32/$KERNEL.img mnt/fat32/$KERNEL-ba
sudo cp arch/arm64/boot/Image mnt/fat32/$KERNEL.im
sudo cp arch/arm64/boot/dts/broadcom/*.dtb mnt/fat
sudo cp arch/arm64/boot/dts/overlays/*.dtb* mnt/fa
sudo cp arch/arm64/boot/dts/overlays/README mnt/fa
sudo umount mnt/fat32
sudo umount mnt/ext4
Another option is to copy the kernel into the same place,
but with a different Vlename - for instance, kernel-
myconfig.img - rather than overwriting the kernel.img
Vle. You can then edit the config.txt Vle to select the
kernel that the Raspberry Pi will boot:
kernel=kernel-myconfig.img
This has the advantage of keeping your custom kernel
separate from the stock kernel image managed by the
system and any automatic update tools, and allowing you
to easily revert to a stock kernel in the event that your
kernel cannot boot.
Finally, plug the card into the Raspberry Pi and boot it!
ConIguring the Kernel
Edit this on GitHub
The Linux kernel is highly conVgurable; advanced users
may wish to modify the default conVguration to
customise it to their needs, such as enabling a new or
experimental network protocol, or enabling support for
new hardware.
ConVguration is most commonly done through the make
menuconfig interface. Alternatively, you can modify your
.config Vle manually, but this can be more dikcult for
new users.
Preparing to ConIgure
The menuconfig tool requires the ncurses development
headers to compile properly. These can be installed with
the following command:
sudo apt install libncurses5-dev
You’ll also need to download and prepare your kernel
sources, as described in the build guide. In particular,
ensure you have installed the default conVguration.
Using menuconfig
Once you’ve got everything set up and ready to go, you
can compile and run the menuconfig utility as follows:
make menuconfig
If you’re cross-compiling a 32-bit kernel:
make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- m
Or, if you are cross-compiling a 64-bit kernel:
make ARCH=arm64 CROSS_COMPILE=aarch64-linux-gnu- m
The menuconfig utility has simple keyboard navigation.
After a brief compilation, you’ll be presented with a list of
submenus containing all the options you can conVgure;
there’s a lot, so take your time to read through them and
get acquainted.
Use the arrow keys to navigate, the Enter key to enter a
submenu (indicated by --->), Escape twice to go up a
level or exit, and the space bar to cycle the state of an
option. Some options have multiple choices, in which
case they’ll appear as a submenu and the Enter key will
select an option. You can press h on most entries to get
help about that speciVc option or menu.
Resist the temptation to enable or disable a lot of things
on your Vrst attempt; it’s relatively easy to break your
conVguration, so start small and get comfortable with the
conVguration and build process.
Saving your Changes
Once you’re done making the changes you want, press
Escape until you’re prompted to save your new
conVguration. By default, this will save to the .config
Vle. You can save and load conVgurations by copying this
Vle around.
Patching the Kernel
Edit this on GitHub
When building your custom kernel you may wish to apply
patches, or collections of patches ('patchsets'), to the
Linux kernel.
Patchsets are often provided with newer hardware as a
temporary measure, before the patches are applied to the
upstream Linux kernel ('mainline') and then propagated
down to the Raspberry Pi kernel sources. However,
patchsets for other purposes exist, for instance to enable
a fully pre-emptible kernel for real-time usage.
Version IdentiIcation
It’s important to check what version of the kernel you
have when downloading and applying patches. In a kernel
source directory, running head Makefile -n 3 will
show you the version the sources relate to:
VERSION = 3
PATCHLEVEL = 10
SUBLEVEL = 25
In this instance, the sources are for a 3.10.25 kernel. You
can see what version you’re running on your system with
the uname -r command.
Applying Patches
How you apply patches depends on the format in which
the patches are made available. Most patches are a
single Vle, and applied with the patch utility. For example,
let’s download and patch our example kernel version with
the real-time kernel patches:
wget https://www.kernel.org/pub/linux/kernel/proj
gunzip patch-3.10.25-rt23.patch.gz
cat patch-3.10.25-rt23.patch | patch -p1
In our example we simply download the Vle, uncompress
it, and then pass it to the patch utility using the cat tool
and a Unix pipe.
Some patchsets come as mailbox-format patchsets,
arranged as a folder of patch Vles. We can use Git to
apply these patches to our kernel, but Vrst we must
conVgure Git to let it know who we are when we make
these changes:
git config --global user.name "Your name"
git config --global user.email "your email in her
Once we’ve done this we can apply the patches:
git am -3 /path/to/patches/*
If in doubt, consult with the distributor of the patches,
who should tell you how to apply them. Some patchsets
will require a speciVc commit to patch against; follow the
details provided by the patch distributor.
Kernel Headers
Edit this on GitHub
If you are compiling a kernel module or similar, you will
need the Linux Kernel headers. These provide the various
function and structure deVnitions required when
compiling code that interfaces with the kernel.
If you have cloned the entire kernel from github, the
headers are already included in the source tree. If you
don’t need all the extra Vles, it is possible to install only
the kernel headers from the Raspberry Pi OS repo.
sudo apt install raspberrypi-kernel-headers
NOTE
It can take quite a while for this command to
complete, as it installs a lot of small Vles. There is no
progress indicator.
When a new kernel release is made, you will need the
headers that match that kernel version. It can take several
weeks for the repo to be updated to reeect the latest
kernel version. If this happens, the best approach is to
clone the kernel as described in the Build Section.
Raspberry Pi documentation is copyright © 2012-2023 Raspberry Pi
Ltd and is licensed under a Creative Commons Attribution-ShareAlike
4.0 International (CC BY-SA) licence.
Some content originates from the eLinux wiki, and is licensed under a
Creative Commons Attribution-ShareAlike 3.0 Unported licence.
Follow us
Sign up to newsletter
Twitter
Mastodon
YouTube
Instagram
LinkedIn
Facebook
About Raspberry Pi
News
Contact us
Trademark
About us
Our Approved Resellers