Use these recipes as a complement to Beyond Linux From Scratch to expand your system.

1 The PiLFS Bootscripts

The PiLFS Bootscripts tarball is a small collection of scripts and fixes from various sources that are specific to the Raspberry Pi. The following scripts can be installed:

This little fix tells the kernel to keep 8MB of RAM free at all times for incoming network traffic. Without this fix, it's easy to hang the Pi when doing a lot of work over SSH. All it does is add vm.min_free_kbytes=8192 to /etc/sysctl.conf

The original LFS swap init script will try to enable swap space before the root file system is properly mounted. This won't work if you're using a swap file instead of a dedicated swap partition. This fix simply adjusts the timing of that init script.

The Pi doesn't have a way of keeping time between reboots. This script adds a save/restore function to set an approximate date until the exact date can be obtained via NTP.

Start/stop script for the Random Number Generator Daemon for use with the hardware RNG device present on the Pi.

Switches the cpufreq governor from the default "powersave" to "ondemand" which allows for overclocking the Pi.

Simple modification to the BLFS sshd init script that will generate new keys if missing.

Provides automatic control of the Fan SHIM on Raspberry Pi 4.

An empty init script in which to add your own autostart applications.

2 Adding a Swap File

To create a swap file where count is the number of megabytes you'd like:

dd if=/dev/zero of=/swapfile bs=1M count=512
mkswap /swapfile
swapon -v /swapfile

To activate the swap file on boot, add a line to /etc/fstab

/swapfile     swap         swap     pri=1               0     0

3 Tapping the Pi Hardware Random Number Generator

The BCM2835 chip on the Pi contains a hardware entropy source that can be tapped by crypto-heavy applications to improve the quality of randomness and might even help speed up some operations.

You'll need to build rngd which in turn will feed applications with random goodness from the hardware RNG:

./configure --prefix=/usr
make install

make install-rngd from the PiLFS Bootscripts takes care of starting the daemon.

4 Overclocking the Pi

On September 19 2012 the Raspberry Pi Foundation introduced a Pi "turbo mode", which dynamically enables overclock and overvolt under the control of a cpufreq driver, without affecting your warranty.

The first step is to add a set of overclock values to your /boot/config.txt. These are the preset values offered by Raspbian's raspi-config:

Variable No OC Modest Medium High Turbo
arm_freq 700 800 900 950 1000
core_freq 250 250 250 250 500
sdram_freq 400 400 450 450 600
over_voltage 0 0 2 6 6

The final step is to switch the cpufreq governor from the default "powersave" to "ondemand" with this command:

echo "ondemand" > /sys/devices/system/cpu/cpu0/cpufreq/scaling_governor

make install-switch-cpu-governor from the PiLFS Bootscripts takes care of this step for you on boot.

You can keep an eye on the current frequency and temperature with these commands:

cat /sys/devices/system/cpu/cpu0/cpufreq/scaling_cur_freq
/opt/vc/bin/vcgencmd measure_temp

5 Resizing Your ext4 Partition

When you write an image to your SD card, you'll usually want to resize the data partition to fit the free space available on the card.

Start fdisk and press 'p' to print the partition table:

fdisk /dev/mmcblk0

Note the Start sector (540672 on the PiLFS Base image) of the Linux partition.

Now press 'd' and '2' to delete it.

Then press 'n', 'p', '2', the Start sector, 'enter' and 'w'.

This re-creates the ext4 partition with the maximum size available.

Finally, reboot your Pi, then perform the actual resize:

resize2fs /dev/mmcblk0p2

6 Optimized Memcpy/Memset Replacement

These ARM-accelerated versions of selected functions from string.h replace the default routines of the glibc library. To use them, grab a copy from this github repository:

wget -O arm-mem.tar.gz

Then we compile them into a shared library, put it in place and make sure it gets used as a replacement for glibc's functions.

For Raspberry Pi 1 & 2:

cp -v /usr/lib
echo "/usr/lib/" >> /etc/

For Raspberry 3 & 4:

cp -v /usr/lib
echo "/usr/lib/" >> /etc/

7 Compiling the Kernel

First grab the latest kernel sources if you haven't got them already:


After unpacking, ensure the sources are in pristine condition:

make mrproper

Issue the following sed command if you want the kernel to appear exactly as the official one (with a 6.1.X+ version string):

sed -i 's/EXTRAVERSION =.*/EXTRAVERSION = +/' Makefile

Create a default kernel .config file for your Raspberry Pi model - for Raspberry Pi 1:

make bcmrpi_defconfig

For Raspberry Pi 2 & 3:

make bcm2709_defconfig

For Raspberry Pi 4:

make bcm2711_defconfig

If you want you can customize the kernel configuration:

make menuconfig

Now we can build our kernel, then install the kernel modules:

make zImage dtbs modules_install
cp arch/arm/boot/dts/*.dtb /boot/
cp arch/arm/boot/dts/overlays/*.dtb* /boot/overlays/

Finally copy the compressed kernel for your Pi model to the boot partition - for Raspberry Pi 1:

cp -v arch/arm/boot/zImage /boot/kernel.img

For Raspberry Pi 2 & 3:

cp -v arch/arm/boot/zImage /boot/kernel7.img

For Raspberry Pi 4:

cp -v arch/arm/boot/zImage /boot/kernel7l.img

8 Compiling External Kernel Modules

What if you just want to compile a third-party kernel module compatible with the latest official Raspberry Pi kernel? In my case I wanted to compile the DirectFB Fusion module without having to build a complete kernel.

You'll still need the complete kernel sources so grab them first:


After unpacking, ensure the sources are in pristine condition:

make mrproper

Issue the following sed command so that your module ends up in the correct place (/lib/modules/6.1.X+):

sed -i 's/EXTRAVERSION =.*/EXTRAVERSION = +/' Makefile

Create a default kernel .config file for your Raspberry Pi model - for Raspberry Pi 1:

make bcmrpi_defconfig

For Raspberry Pi 2 & 3:

make bcm2709_defconfig

For Raspberry Pi 4:

make bcm2711_defconfig

Now we need to grab an important file for your Pi model from the Firmware repo and put that in the root of the source tree - for Raspberry Pi 1:


For Raspberry Pi 2 & 3:


For Raspberry Pi 4:


Next we issue a command that will compile all the little extra kernel bits and pieces that are necessary to build modules:

make modules_prepare

And the last step needed is a build symlink pointing to the kernel sources:

ln -sv $PWD /lib/modules/6.1.X+/build

There, you should now be able to compile your third-party kernel module. And don't forget that you need to refresh your modules.dep file before you modprobe your new module, like so:


9 Building the Userland Source

Now that Broadcom has open sourced the ARM userland libraries, we can replace the contents of /opt/vc from the firmware repo with our own build.

You will need to have cmake installed to perform the build.

Let's start with obtaining the userland sources:

wget -O userland.tar.gz

And now we build and install (you might want to rename/backup your current /opt/vc before installing):

mkdir build
cd build
cmake -DCMAKE_BUILD_TYPE=Release ..
make install

You should build the included hello_pi examples to verify that your new libraries are working properly:

cd /opt/vc/src/hello_pi
chmod +x

Note that the hello_font example requires FreeType to build.

10 Building OMXPlayer

First install the following prerequisites (in order):

Download the latest OMXPlayer source from the github repo:

wget -O omxplayer.tar.gz

Since we're not cross-compiling, we need to massage the Makefile for our purposes:

sed -i '/include Makefile.include/d' Makefile
sed -i 's:INCLUDES+=*:&-I/opt/vc/include -I/opt/vc/include/interface/vcos/pthreads -I/opt/vc/include/interface/vmcs_host/linux -I/usr/include/freetype2 -I/usr/include/dbus-1.0 -I/usr/lib/dbus-1.0/include :' Makefile
sed -i 's:LDFLAGS+=*:&-L/opt/vc/lib :' Makefile
sed -i 's/$(STRIP)/strip/' Makefile
sed -i '/cp -a ffmpeg_compiled/d' Makefile

Now we can build and copy the binary somewhere nice:

cp -v omxplayer.bin /usr/bin/omxplayer
cp -v omxplayer.1 /usr/share/man/man1

OMXPlayer comes with a free font to be used for subtitles, put it where OMXPlayer expects it to be:

mkdir -p /usr/share/fonts/truetype/freefont
cp -v fonts/FreeSans* /usr/share/fonts/truetype/freefont

Sometimes the background console shines through while playing a video, or equally annoying, stays black after playing a video. This can be fixed with the fbset utility and a simple wrapper function in your ~/.profile:

function omxplay() { omxplayer -r -t1 "$@" ; fbset -depth 8 && fbset -depth 16 ;}

11 Building Quake3

First install the following prerequisites (in order):

Next we need to compile OpenAL using this CMake build procedure:

cd build
make install

Let's fetch the Quake3 source:

wget -O quake3.tar.gz

Now we can start the build:


Now you just have to decide where to install your Quake3 binaries, I chose /root/quake3 here:

cp -rv build/release-linux-arm ~/quake3

And the final step is to copy the pak#.pk3 files from the original Quake3 CD:

cp -v pak{0..8}.pk3 ~/quake3/baseq3

Start the game with ~/quake3/ioquake3.arm - Happy fragging!

12 Building Accelerated SDL + DGen Genesis Emulator

With all the fun software out there depending on the SDL multimedia library, wouldn't it be nice if SDL could take better advantage of the Pi's GPU?

Vanfanel thought so too and wrote a Dispmanx backend for SDL, which takes a small resolution (320x240) output from any SDL application and hardware-scales it to your monitor's native fullscreen resolution (like 1920x1080).

I tried it with DGen and really enjoyed watching Sonic frolic about in 1080p at 60FPS (with a bit of overclock) - smooth as silk!

Building SDL:

For SDL, the only prerequisites are ALSA-lib and ALSA-utils (to be able to adjust the volume with alsamixer). Let's build!

wget -O SDL12-dispmanx.tar.gz
sed -i 's:DISPMANX_INCLUDES="*:&-I/opt/vc/include/interface/vmcs_host/linux :' configure
./configure --prefix=/usr --disable-static --enable-video-dispmanx --disable-video-kms --disable-video-fbcon --disable-video-x11 --disable-video-directfb
make install

That's all there is to it really, but you'll need to ensure that your SDL application outputs to a small (320x240) plain resolution without any fancy scaling effects etc. so that when you start the application you should see something like this:

dispmanx: Opening display[0]...
Using internal program mode: width=320 height=240
Using physical mode: 1920 x 1080 16 bpp

Building DGen:

Now let's build DGen so we have something to play with (apparently, the largest HQX scaler doesn't compile on the Pi. You can either cross-compile it or live without it for now):

./configure --prefix=/usr --disable-hqx
make install

So, to get DGen to output in 320x240 you can either specify -S 1 on the command line, or put int_scale = 1 in your ~/.dgen/dgenrc.

Also, adding bool_screen_thread = yes to your ~/.dgen/dgenrc should give you better graphics performance on the Pi!

13 Building RetroArch Emulators

RetroArch is like an emulator framework to which you add one or more game system cores.

You need the following prerequisites to build RetroArch:

Grab the latest sources:

wget -O retroarch.tar.gz

Then configure and install. Add --enable-neon if compiling for Raspberry Pi 2.

./configure --prefix=/usr
make install
cp -v tools/retroarch-joyconfig /usr/bin

Next you might want to setup a joypad:


Paste the resulting output anywhere in /etc/retroarch.cfg or ~/.config/retroarch/retroarch.cfg. You can optionally bind a button to input_exit_emulator_btn to quit the emulator with the joypad. I also like to bind input_menu_toggle_btn to the joypad so that I can change games through a nifty menu system without having to exit RetroArch.

Now you'll want to grab one or more emulator cores, most of them can be found in the libretro github. Here's a list of some nice ones:

Game System Git Repository
Genesis / SMS / GG
Final Burn Alpha
Game Boy / Color

Building a core is usually pretty straight forward, you either just type make or point out which Makefile to build. Here's an example for FCEU:

wget -O fceu.tar.gz
cd fceumm-code
make -f Makefile.libretro

For every compiled core you'll end up with a file called something. If we do find . -name '*' for FCEU we'll find You should copy this file somewhere in an organized fashion that makes sense to you, for example:

mkdir -p ~/retroarch/cores
cp -v ~/retroarch/cores

Next we'll want to add some info files. These are required for RetroArch to pick a suitable core automatically for any given ROM file.

git clone
cp -rv dist/info ~/retroarch

Now add the following directives to your ~/.config/retroarch/retroarch.cfg:

libretro_path = "~/retroarch/cores/" # Set this to any core
libretro_directory = "~/retroarch/cores"
libretro_info_path = "~/retroarch/info"
rgui_browser_directory = "~/retroarch/roms"

Time to try out the emulation! Just type retroarch followed by the ROM file name to start. You can also specify a specific core to load using the -L argument. Or type retroarch --menu to browse ROMs through the spiffy menu system.

14 Building Kodi (XBMC)

Let's begin with the dependencies that are required for Kodi to build.

First of all, you need a Java runtime to build the interface files. Note that Java is not required to run Kodi, it's only used during the build. Head on over to the Java SE Embedded Downloads page and trade your soul in for ejdk-8u65-linux-arm-sflt.gz.

Untar and put it somewhere nice and make sure that the java executable is in your path:

cp -rv ejdk1.8.0_65/linux_arm_sflt/jre /opt/java
export PATH="$PATH:/opt/java/bin"

Now we can work our way down the list of dependencies:

We also need yajl, which compiles like this:

mkdir build
cd build
make install

And finally TinyXML which needs a patch to produce a shared library:

patch -Np1 -i ../tinyxml_2_6_2-shared_lib.patch
make install

Phew! So those are the bare minimum dependencies for building Kodi. You may want to add additional software that Kodi can make use of, like Samba and Avahi etc. In particular, I would recommend that you also install libgpg-error, libgcrypt and libmicrohttpd and remove --disable-webserver from the configure line below. You'll be able to remote-control Kodi from your browser or your phone which is a very convenient feature to have on the Pi.

If your TV supports CEC, you'll also want to build libCEC so that you can use your TV remote to control Kodi:

mkdir build
cd build
make install
mkdir build
cd build
cmake -DCMAKE_INSTALL_PREFIX=/usr -DCMAKE_BUILD_TYPE=Release -DRPI_INCLUDE_DIR=/opt/vc/include -DRPI_LIB_DIR=/opt/vc/lib ..
sed -i 's/#define LIB_INFO.*/#define LIB_INFO ("3.0.1")/' ../src/libcec/env.h
sed -i '/\\n, compiled on/d' ../src/libcec/env.h
make install

Alright, let's start building Kodi!

You will definitely need a swap file to build Kodi, so set that up first.

Now grab the latest stable Kodi release:


If you're building for Raspberry Pi 2, apply this patch to override the raspberry-pi platform target specs:

patch -Np1 -i ../xbmc-15.2-Isengard-rpi2-target.patch

Whip the sources into shape with a bootstrap:


Now we can run configure:

CFLAGS="-I/opt/vc/include -I/opt/vc/include/interface/vcos/pthreads -I/opt/vc/include/interface/vmcs_host/linux" CXXFLAGS="-I/opt/vc/include -I/opt/vc/include/interface/vcos/pthreads -I/opt/vc/include/interface/vmcs_host/linux" LDFLAGS="-L/opt/vc/lib" ./configure --prefix=/usr --disable-debug --disable-gl --enable-gles --disable-joystick --disable-x11 --disable-ssh --disable-samba --disable-dvdcss --disable-avahi --disable-mysql --disable-webserver --disable-optical-drive --with-platform=raspberry-pi --enable-player=omxplayer

Note that the configure script will pause mid-way and build Kodi's own version of FFMPEG as it will not currently build against the official release.

And we make and pray to His Noodly Appendage!

make install

Tada! Just fire it up with kodi.

15 Adding on-board Bluetooth support

The Raspberry Pi 3 and 4 come equipped with an on-board Bluetooth controller.

To make use of it, you'll need to build BlueZ - the Bluetooth protocol stack.

First build these dependencies (in order):

When it's time to build BlueZ, you need to apply this patch which contains various Pi specific fixes:

patch -Np1 -i ../bluez-5.40-rpi-fixes.patch

You'll also need to append --enable-deprecated to the configure line in order to build a few still necessary binaries.

Once BlueZ is installed, one last step is required to make the Bluetooth controller work.

For Raspberry Pi 3:

cat > /etc/bluetooth/uart.conf << "EOF"
# Start uart.conf
# Attach serial devices via UART HCI to BlueZ stack
# Use one line per device
# See the hciattach man page for options

ttyAMA0 bcm43xx 921600 noflow

# End of uart.conf

For Raspberry Pi 4:

cat > /etc/bluetooth/uart.conf << "EOF"
# Start uart.conf
# Attach serial devices via UART HCI to BlueZ stack
# Use one line per device
# See the hciattach man page for options

ttyAMA0 bcm43xx 3000000 flow

# End of uart.conf

After a reboot, your Bluetooth controller should be up and ready for action. Try pairing with a BT device like so:

power on
agent on
scan on

For more info on Bluetooth poking from the command line, including Obex FTP and such, check out the Arch Linux wiki

16 Building Wayland / Weston

The GPU accelerated desktop on the Pi that we've all been waiting for is inching ever closer each day.

These instructions will get you a "pure" Wayland / Weston environment free of X11 dependencies, which obviously means that the XWayland compatibility layer will not be built. If you need the ability to run X apps inside Weston, follow the Xorg BLFS guide to get your Xorg server up and running first.

The first thing you'll want to do is enable Eric Anholt's VC4 driver in /boot/config.txt by adding or uncommenting this line:


(Unfortunately, Eric Anholt's VC4 driver doesn't work on Raspberry Pi 1 or Zero due to memory constraints)

Once rebooted, you can make your way through this list of dependencies (in order):

Time to build Mesa for the VC4/V3D driver:

meson --prefix=/usr --sysconfdir=/etc -Dbuildtype=release -Dplatforms="wayland" -Dvulkan-drivers="broadcom" -Ddri-drivers="" -Dgallium-drivers="vc4,v3d,kmsro" -Dglx=disabled build
ninja -C build && ninja -C build install

And some more dependencies:

Next is libinput which uses meson and builds like so:

meson --prefix=/usr -Dudev-dir=/lib/udev -Ddocumentation=false -Dlibwacom=false -Ddebug-gui=false -Dtests=false build
ninja -C build && ninja -C build install
udevadm hwdb --update

On to the fun stuff! Now we can build Weston:

meson --prefix=/usr -Dbuildtype=release -Dxwayland=false -Dbackend-x11=false -Dweston-launch=false -Dimage-webp=false -Dlauncher-logind=false -Dbackend-drm-screencast-vaapi=false -Dbackend-rdp=false -Dcolor-management-colord=false -Dcolor-management-lcms=false -Dsystemd=false -Dremoting=false -Ddemo-clients=false -Dpipewire=false build
ninja -C build && ninja -C build install

Almost there, we just need to create a directory for Weston's socket and lock files, like so:

echo "/run/shm/wayland dir 1700 root root" >> /etc/sysconfig/createfiles

And set the environment variable XDG_RUNTIME_DIR to point there, like so:

echo "export XDG_RUNTIME_DIR=/run/shm/wayland" >> ~/.profile

One last environment variable for the Vulkan driver, like so:

echo "export VK_ICD_FILENAMES=/usr/share/vulkan/icd.d/broadcom_icd.armv7l.json" >> ~/.profile

Time to play! Reboot your Pi and run weston to give you an accelerated minimal desktop and a terminal.

For more details on Weston and a list of keyboard shortcuts, check out the Arch Linux wiki

17 Building QT / Falkon

QT is a comprehensive GUI toolkit that is easy to build and works well in Wayland and directly from the console.

It's also the fastest way to get Falkon, a decent Chromium based browser, running on the Pi.

The latest QT is v5.13.0, but it doesn't seem to work well with Wayland so we'll have to stick with v5.12.4 for now.

QT is highly modular - I usually grab the large single source tarball containing all the modules and build whatever bits I need.



First off is the QT base module:

cd qtbase
./configure -prefix /opt/qt5 -opensource -confirm-license -opengl es2 -no-pch -nomake examples -no-use-gold-linker -DMESA_EGL_NO_X11_HEADERS
make install

So our QT installation is going to live in /opt/qt5

Now we want to make sure the libraries and binaries can be found by other packages:

cat > /etc/ << "EOF"

export PATH="$PATH:/opt/qt5/bin"
export PKG_CONFIG_PATH="$PKG_CONFIG_PATH:/opt/qt5/lib/pkgconfig"

With the base libraries in place we can move on to build whatever QT modules are needed.
Here my goal is to get Falkon running under Wayland:

cd qtdeclarative && qmake && make && make install && cd ..
cd qtwebchannel && qmake && make && make install && cd ..
cd qtwayland && qmake && make && make install && cd ..
cd qttools/src/designer && qmake && make && make install && cd ..
cd qttools/src/linguist && qmake && make && make install && cd ..


The QT webengine module has a few dependencies:

Note that building qtwebengine is a particularly memory intensive affair, a large swap file is recommended.
You can also restrict the number of parallel compile jobs with export NINJAJOBS=1 prior to build.

cd qtwebengine && qmake -- -system-ffmpeg && make && make install

Whatever QT apps you build from here on can be started in either wayland or eglfs (direct console) mode.
You can specify the mode explicitly with an argument to the application - for example -platform wayland or you can set it in an environment variable like so:

echo "export QT_QPA_PLATFORM=wayland" >> ~/.profile


Just follow the BLFS Falkon recipe to build, with one exception to ditch the X dependency:

-DNO_X11=1 \

You'll definitely want to add a decent font for your browser to use.
I personally like the DejaVu font family:

tar xvf dejavu-fonts-ttf-2.37.tar.bz2 && cd dejavu-fonts-ttf-2.37
install -v -d -m755 /usr/share/fonts/dejavu
install -v -m644 ttf/*.ttf /usr/share/fonts/dejavu
fc-cache -v /usr/share/fonts/dejavu