Skip to content

Instantly share code, notes, and snippets.

@MartyMacGyver
Last active May 12, 2021 06:45
Show Gist options
  • Save MartyMacGyver/2ed99ec1e56d60c22519 to your computer and use it in GitHub Desktop.
Save MartyMacGyver/2ed99ec1e56d60c22519 to your computer and use it in GitHub Desktop.
Building the kernel for the Raspberry Pi/Pi2/Pi3 using a cross-compiler
###############################################################################
###############################################################################
###############################################################################
###############################################################################
###############################################################################
###############################################################################
###############################################################################
###############################################################################
###############################################################################
###############################################################################
###############################################################################
#
#
#
#
# Bottom line: Because ultimately the tools don't get built for the target arch,
# it may be easier to build the headers on the RPi itself.
#
#
#
#
###############################################################################
###############################################################################
###############################################################################
###############################################################################
###############################################################################
###############################################################################
###############################################################################
###############################################################################
###############################################################################
###############################################################################
###############################################################################
###############################################################################
###############################################################################
# Compiling the RPi kernel using a cross-compiler
#
# Updates http://www.raspberrypi.org/documentation/linux/kernel/building.md
# Eventually merge into https://github.com/raspberrypi/documentation/blob/master/linux/kernel/building.md
# Inputs from https://www.raspberrypi.org/forums/viewtopic.php?f=66&t=57401
# Especially https://www.raspberrypi.org/forums/viewtopic.php?f=66&t=90276
###############################################################################
# Install Ubuntu 14.04 server (I did this in a VM with 2 vCPUs)
# Create a local admin (e.g., 'localadmin')
sudo apt-get update # Fetches the list of available updates
sudo apt-get dist-upgrade -y # Installs updates
sudo apt-get install -y build-essential git bc
alias dir="ls -alF" # Optional but handy
MYBASE=~/pibuild
KERNEL_SRC=${MYBASE}/linux
PI_LOGIN=pi@192.168.1.176 # Whatever your RPi's login and IP are
PI_CMD_PREFIX='' # Works if you are building on the Pi or remotely
mkdir -p ${MYBASE}
# Jobs should be 1.5x the number of CPUs. My VM has 2 CPUs allocated to it.
# Took me 15 minutes to build the kernel
CPUS=`grep 'processor\s*:' /proc/cpuinfo | wc -l` # A decent approximation
JOBS=`echo $CPUS*1.5/1 | bc`
echo Running $JOBS jobs over $CPUS cpus
#VERSION=CUSTOM-`git rev-parse --short=16 HEAD`
VERSION=99002 # Your choice... you might want to use what you already have
echo Custom kernel version ${VERSION}
#=== METHOD 1: Determine the kernel you have now via the RPi!
# This will depend on how you maintain your RPi (e.g., Raspbian, Hexxeh's firmware, etc.)
# If you are based on the regular Raspberry Pi firmware, get the commit ID as follows:
FIRMWARE_HASH=$(ssh ${PI_LOGIN} 'zgrep "* firmware as of" /usr/share/doc/raspberrypi-bootloader/changelog.Debian.gz' | head -1 | awk '{ print $5 }') ; \
KERNEL_HASH=$(wget -nv https://raw.github.com/raspberrypi/firmware/${FIRMWARE_HASH}/extra/git_hash -O -) ; \
echo FIRMWARE_HASH = $FIRMWARE_HASH ; \
echo KERNEL_HASH = $KERNEL_HASH
# If you are based on Hexxeh's firmware, get the commit ID as follows:
FIRMWARE_HASH=$(ssh ${PI_LOGIN} 'cat /boot/.firmware_revision') ; \
KERNEL_HASH=$(wget -nv https://raw.githubusercontent.com/Hexxeh/rpi-firmware/${FIRMWARE_HASH}/git_hash -O -) ; \
echo FIRMWARE_HASH = $FIRMWARE_HASH ; \
echo KERNEL_HASH = $KERNEL_HASH
# Clone the kernel sources
# You cannot clone a specific commit only: you will need to clone a lot of data!
# git clone --branch rpi-4.1.y ... # Get only this branch of the kernel - doesn't save space either.
# git clone --depth=1 ... # Get only the latest commit on the default branch
cd ${MYBASE}
git clone https://github.com/raspberrypi/linux ${KERNEL_SRC}
cd ${KERNEL_SRC}
git clean -f
git pull --ff-only
git checkout ${KERNEL_HASH}
# Get the current kernel config from the RPi
ssh ${PI_LOGIN} sudo modprobe configs # Or run this directly on the RPi
scp ${PI_LOGIN}:/proc/config.gz ${MYBASE}/.
#=== METHOD 2: ON THE RPI: use rpi-source to get the kernel sources for your kernel
# More info at https://github.com/notro/rpi-source/wiki
sudo wget https://raw.githubusercontent.com/notro/rpi-source/master/rpi-source -O /usr/bin/rpi-source && \
sudo chmod +x /usr/bin/rpi-source && \
/usr/bin/rpi-source -q --tag-update
rpi-source --skip-gcc
#=== Clone the tools
cd ${MYBASE}
git clone https://github.com/raspberrypi/tools
cd ${MYBASE}/tools
git clean -f
git pull --ff-only
# Tools for building the RPi1 kernel:
export CCPREFIX=${MYBASE}/tools/arm-bcm2708/arm-bcm2708-linux-gnueabi/bin/arm-bcm2708-linux-gnueabi-
# Tools for building the RPi2 kernel via 32-bit host:
export CCPREFIX=${MYBASE}/tools/arm-bcm2708/gcc-linaro-arm-linux-gnueabihf-raspbian/bin/arm-linux-gnueabihf-
# Tools for building the RPi2 kernel via 64-bit host:
export CCPREFIX=${MYBASE}/tools/arm-bcm2708/gcc-linaro-arm-linux-gnueabihf-raspbian-x64/bin/arm-linux-gnueabihf-
# For consistency add to the path (the x64 CC works without this step, but the others don't for some reason)
#PATH=`dirname ${CCPREFIX}`:$PATH
#export PATH
#echo $PATH
#`basename ${CCPREFIX}`gcc # For some reason this only works for the x64 CCs.
#=== Ready to build
cd ${KERNEL_SRC}
make help # Shows us all the targets
make mrproper # Clean
# OBSOLETE
# Create the config (all configs are found in arch/arm/configs)
# # For the Pi:
# make V=1 ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- bcmrpi_defconfig
# # For the Pi2:
# make V=1 ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- bcm2709_defconfig
zcat ${MYBASE}/config.gz > .config
echo ${VERSION} > .version
make ARCH=arm CROSS_COMPILE=${CCPREFIX} oldconfig
# OPTIONAL tweaks (this shouldn't be needed unless you did't have config.gz)
# make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf menuconfig
# Build the kernel and the modules (V=1 is verbose per https://www.kernel.org/doc/makehelp.txt)
make V=1 -j${JOBS} ARCH=arm CROSS_COMPILE=${CCPREFIX} | tee build_main.log
# ???????
make V=1 -j${JOBS} ARCH=arm CROSS_COMPILE=${CCPREFIX} zImage modules dtbs | tee build_alt.log
# Directly on the Pi: make headers_install
# Build the kernel debians
KBUILD_DEBARCH=armhf make V=1 ARCH=arm CROSS_COMPILE=${CCPREFIX} deb-pkg | tee build_pkg.log
VERSION=`cat ${KERNEL_SRC}/.version`
cp .version ../linux-buildversion
#scp -p ../linux-buildversion ../linux-*${VERSION}*.deb ${PI_LOGIN}:.
scp -p ../linux-headers-*${VERSION}*.deb ${PI_LOGIN}:.
#=== On the Pi
# At this point you can just install the headers package on the RPi:
sudo dpkg --purge linux-headers-4.1.15-v7+
sudo dpkg -i linux-headers-*${VERSION}*.deb
#=== On the Pi
#=============================================================================================================#
# # ###### ###### ##### #### ##### ###### # # # #### # #### # #
## # # # # # # # # # # # # # # # # ## #
# # # ##### ##### # # #### # # ##### # # # #### # # # # # #
# # # # # # # # ##### # # # # # # # # # # #
# ## # # # # # # # # # # # # # # # # # # ##
# # ###### ###### ##### #### # # ###### ## # #### # #### # #
#=============================================================================================================#
# BEFORE installing make a backup!
VERSION=`cat linux-buildversion`
sudo dpkg --purge linux-image-4.1.15-v7+ # Otherwise we may get "unable to make backup link" errors
sudo dpkg -i linux-image-4.1.15-v7+_4.1.15-v7+-${VERSION}_armhf.deb
sudo dpkg -i linux-firmware-image-4.1.15-v7+_4.1.15-v7+-${VERSION}_armhf.deb
sudo dpkg -i linux-libc-dev_4.1.15-v7+-${VERSION}_armhf.deb
sudo dpkg -i linux-headers-4.1.15-v7+_4.1.15-v7+-${VERSION}_armhf.deb
dpkg -c foo.deb # To see contents
dpkg -l *linux-headers*
# If it's not already in there:
sudo bash -c "echo 'kernel=vmlinuz-4.1.15-v7+' >> /boot/config.txt"
sudo reboot # Reboot the Pi
exit
# It boots and works, but the binaries in the scripts folder are "ELF 64-bit LSB executable"
# (Any scripts used during the header build end up being the native version, not cross-compiled)
# This is pretty much why: https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=563376
# https://bugs.launchpad.net/ubuntu/+source/linux-ti-omap4/+bug/666267
#
# No workaround is available.
cd /usr/src/linux-headers-4.1.15-v7+/scripts
find . -type f -exec file '{}' \; | grep ELF
find . -type f -exec file '{}' \; | grep x86-64
~/pibuild/linux$ find . -type f -exec file '{}' \; | grep x86-64
./usr/gen_init_cpio: ELF 64-bit LSB executable, x86-64, version 1 (SYSV), dynamically linked (uses shared libs), for GNU/Linux 2.6.24, BuildID[sha1]=22d7fcb6e747f8a3d215d2d70b81ee2844eddc0c, not stripped
./firmware/ihex2fw: ELF 64-bit LSB executable, x86-64, version 1 (SYSV), dynamically linked (uses shared libs), for GNU/Linux 2.6.24, BuildID[sha1]=35bb9cd2776e23a5b3be74db9b0d7138373dfc0d, not stripped
./lib/raid6/mktables: ELF 64-bit LSB executable, x86-64, version 1 (SYSV), dynamically linked (uses shared libs), for GNU/Linux 2.6.24, BuildID[sha1]=9e89c9c002ebb8e468b1e2a73d131be4c792e743, not stripped
./lib/gen_crc32table: ELF 64-bit LSB executable, x86-64, version 1 (SYSV), dynamically linked (uses shared libs), for GNU/Linux 2.6.24, BuildID[sha1]=28c5b5c8eb12e5e41c003f637809b2cc95739954, not stripped
./scripts/recordmcount: ELF 64-bit LSB executable, x86-64, version 1 (SYSV), dynamically linked (uses shared libs), for GNU/Linux 2.6.24, BuildID[sha1]=e899c0b15e7032d77b28f8a466ed95b19208805a, not stripped
./scripts/mod/file2alias.o: ELF 64-bit LSB relocatable, x86-64, version 1 (SYSV), not stripped
./scripts/mod/modpost.o: ELF 64-bit LSB relocatable, x86-64, version 1 (SYSV), not stripped
./scripts/mod/sumversion.o: ELF 64-bit LSB relocatable, x86-64, version 1 (SYSV), not stripped
./scripts/mod/modpost: ELF 64-bit LSB executable, x86-64, version 1 (SYSV), dynamically linked (uses shared libs), for GNU/Linux 2.6.24, BuildID[sha1]=3cc94cef6e8632c4dd2c7d8571d46b9fb3a8aeb1, not stripped
./scripts/mod/mk_elfconfig: ELF 64-bit LSB executable, x86-64, version 1 (SYSV), dynamically linked (uses shared libs), for GNU/Linux 2.6.24, BuildID[sha1]=a751faa912ed6a50043ad6a90912ac2c898b5b81, not stripped
./scripts/pnmtologo: ELF 64-bit LSB executable, x86-64, version 1 (SYSV), dynamically linked (uses shared libs), for GNU/Linux 2.6.24, BuildID[sha1]=9755b51958a5a74753b0376a23cbab356fe2184c, not stripped
./scripts/genksyms/parse.tab.o: ELF 64-bit LSB relocatable, x86-64, version 1 (SYSV), not stripped
./scripts/genksyms/genksyms: ELF 64-bit LSB executable, x86-64, version 1 (SYSV), dynamically linked (uses shared libs), for GNU/Linux 2.6.24, BuildID[sha1]=93a713d766faa4dc98ed76e19b34eabb86a1759b, not stripped
./scripts/genksyms/lex.lex.o: ELF 64-bit LSB relocatable, x86-64, version 1 (SYSV), not stripped
./scripts/genksyms/genksyms.o: ELF 64-bit LSB relocatable, x86-64, version 1 (SYSV), not stripped
./scripts/kallsyms: ELF 64-bit LSB executable, x86-64, version 1 (SYSV), dynamically linked (uses shared libs), for GNU/Linux 2.6.24, BuildID[sha1]=19d6d1db123870773395432366d7edef2d5db286, not stripped
./scripts/conmakehash: ELF 64-bit LSB executable, x86-64, version 1 (SYSV), dynamically linked (uses shared libs), for GNU/Linux 2.6.24, BuildID[sha1]=a622a9c7938f06b31c2f15cf53877404ef739104, not stripped
./scripts/basic/fixdep: ELF 64-bit LSB executable, x86-64, version 1 (SYSV), dynamically linked (uses shared libs), for GNU/Linux 2.6.24, BuildID[sha1]=f3bbd37d59004620fe42f02aa00faf3bda3107c5, not stripped
./scripts/basic/bin2c: ELF 64-bit LSB executable, x86-64, version 1 (SYSV), dynamically linked (uses shared libs), for GNU/Linux 2.6.24, BuildID[sha1]=bd022e6ac54d63b3dac7d0ce77230a5a4227ac94, not stripped
./scripts/sortextable: ELF 64-bit LSB executable, x86-64, version 1 (SYSV), dynamically linked (uses shared libs), for GNU/Linux 2.6.24, BuildID[sha1]=dcdb50ffafb2a0f9f8ee7993842da7648da4f481, not stripped
./scripts/kconfig/conf: ELF 64-bit LSB executable, x86-64, version 1 (SYSV), dynamically linked (uses shared libs), for GNU/Linux 2.6.24, BuildID[sha1]=acffeb12b0914bc83c85efad7424dadadf2fc938, not stripped
./scripts/kconfig/zconf.tab.o: ELF 64-bit LSB relocatable, x86-64, version 1 (SYSV), not stripped
./scripts/kconfig/conf.o: ELF 64-bit LSB relocatable, x86-64, version 1 (SYSV), not stripped
./scripts/dtc/fstree.o: ELF 64-bit LSB relocatable, x86-64, version 1 (SYSV), not stripped
./scripts/dtc/dtc.o: ELF 64-bit LSB relocatable, x86-64, version 1 (SYSV), not stripped
./scripts/dtc/dtc-parser.tab.o: ELF 64-bit LSB relocatable, x86-64, version 1 (SYSV), not stripped
./scripts/dtc/flattree.o: ELF 64-bit LSB relocatable, x86-64, version 1 (SYSV), not stripped
./scripts/dtc/dtc-lexer.lex.o: ELF 64-bit LSB relocatable, x86-64, version 1 (SYSV), not stripped
./scripts/dtc/treesource.o: ELF 64-bit LSB relocatable, x86-64, version 1 (SYSV), not stripped
./scripts/dtc/util.o: ELF 64-bit LSB relocatable, x86-64, version 1 (SYSV), not stripped
./scripts/dtc/data.o: ELF 64-bit LSB relocatable, x86-64, version 1 (SYSV), not stripped
./scripts/dtc/checks.o: ELF 64-bit LSB relocatable, x86-64, version 1 (SYSV), not stripped
./scripts/dtc/livetree.o: ELF 64-bit LSB relocatable, x86-64, version 1 (SYSV), not stripped
./scripts/dtc/dtc: ELF 64-bit LSB executable, x86-64, version 1 (SYSV), dynamically linked (uses shared libs), for GNU/Linux 2.6.24, BuildID[sha1]=953078812a77ac923e532b346d4460af99eab40c, not stripped
./scripts/dtc/srcpos.o: ELF 64-bit LSB relocatable, x86-64, version 1 (SYSV), not stripped
# Testing this out
sudo apt-get install build-essential bc ncurses-dev tmux git
git clone https://github.com/xxorde/librekinect
cd librekinect
make
#! Doesn't work on the RPI2!
git clone https://github.com/lwfinger/rtl8723bu
cd rtl8723bu
make
#! Doesn't work on the RPI2 either... because the toolchain problem above
@MartyMacGyver
Copy link
Author

I've learned that gist has a major old bug wherein you don't get notifications for comments to gists.

If you leave a comment, it would be appreciated if you ping me elsewhere so I know to find it!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment