-
-
Save satmandu/a507c59d84737f6d29ff353395819d51 to your computer and use it in GitHub Desktop.
#!/bin/bash -x | |
# make_arm64_rpi_kernel_debs.sh | |
# Builds arm64 debian packages from the CURRENT rpi firmware repository kernel which is installed by: | |
# sudo rpi-update | |
# This runs on an arm64 host with arm64 compilation tools... | |
# or with some sort of cross-compilation setup. | |
# Debs are put in $workdir/build | |
# | |
# This will NOT work in Raspbian unless you have an arm64 compilation | |
# environment setup. Appears to work on | |
# Raspberry Pi OS (64 bit) beta test version | |
# | |
# | |
# | |
# Install packages you should probably have if you are needing to install kernel headers. | |
arch=$(uname -m) | |
if [[ $arch == 'aarch64' ]]; then | |
echo "" | |
else | |
echo "This needs to be run when booted into 64-bit mode." | |
exit 1 | |
fi | |
# sudo apt install -f -y build-essential flex gawk bison libssl-dev bc dkms autoconf libtool || (sudo apt install -f -y || true) | |
workdir="${HOME}/workdir" | |
[[ ! -d "$workdir" ]] && ( mkdir -p "$workdir" || exit 1) | |
[[ ! -d "$workdir"/tmp ]] && ( mkdir -p "$workdir"/tmp || exit 1) | |
[[ ! -d "$workdir"/build ]] && ( mkdir -p "$workdir"/build || exit 1) | |
echo "workdir is ${workdir}" | |
tmpdir=$(mktemp -d deb_XXXX -p "$workdir"/tmp) | |
echo "tmpdir is ${tmpdir}" | |
dhpath="$tmpdir/headers" | |
dipath="$tmpdir/image" | |
src_temp=$(mktemp -d rpi_src_XXXi -p "$workdir"/tmp) | |
git_base="https://github.com/raspberrypi/rpi-firmware" | |
git_branch="master" | |
FIRMWARE_REV=$(git ls-remote "https://github.com/raspberrypi/rpi-firmware" refs/heads/$git_branch | awk '{print $1}') | |
cd "$src_temp" && curl -OLf https://github.com/raspberrypi/rpi-firmware/raw/$git_branch/git_hash | |
KERNEL_REV=$(cat "$src_temp"/git_hash) | |
SHORT_HASH=$(echo ${KERNEL_REV:0:7}) | |
setup_git_fw() { | |
if [[ -d "$workdir/rpi-firmware" ]]; then | |
( sudo rm -rf "$workdir"/rpi-firmware.old || true ) | |
( sudo mv "$workdir"/rpi-firmware "$workdir"/rpi-firmware.old || true ) | |
( sudo rm -rf "$workdir"/rpi-firmware.old || true ) | |
fi | |
cd "$workdir" && git clone --depth=1 -b $git_branch $git_base | |
} | |
update_git_fw() { | |
[[ ! -d "$workdir/rpi-firmware" ]] && setup_git_fw | |
( cd "$workdir"/rpi-firmware && git fetch && git reset --hard origin/$git_branch ) || setup_git_fw | |
cd "$workdir"/rpi-firmware && git config pull.ff only | |
cd "$workdir"/rpi-firmware && git pull | |
#cd "$workdir"/rpi-firmware && git_hash=$(git rev-parse origin/$git_branch) | |
} | |
check_zfs() { | |
# Install zfs prerequisites | |
sudo apt install -f -y autoconf libtool uuid-dev libudev-dev \ | |
libssl-dev zlib1g-dev libaio-dev libattr1-dev python3 python3-dev \ | |
python3-setuptools autoconf automake libtool gawk dkms libblkid-dev \ | |
uuid-dev libudev-dev libssl-dev libelf-dev python3-cffi libffi-dev || true | |
} | |
make_headers_deb_files() { | |
installed_size_headers=$(du -a "$dhpath" | tail -n 1 | awk '{print $1}') | |
mkdir -p "$dhpath"/DEBIAN | |
chmod 777 "$dhpath"/DEBIAN | |
cat <<-EOF | dd status=none of="$dhpath"/DEBIAN/control | |
Source: linux-$kver | |
Section: kernel | |
Priority: optional | |
Maintainer: root <root@$SHORT_HASH> | |
Standards-Version: 4.1.3 | |
Homepage: http://www.kernel.org/ | |
Package: linux-headers-$kver | |
Architecture: all | |
Version: $kver-1 | |
Depends: build-essential, flex, bison, bc | |
Installed-Size: $installed_size_headers | |
Description: Linux kernel headers for $kver on arm64 | |
This package provides kernel header files for $kver on arm64 | |
built from: | |
https://github.com/raspberrypi/linux/tree/$FIRMWARE_REV | |
This is useful for people who need to build external modules | |
EOF | |
cat <<-EOF | dd status=none of="$dhpath"/DEBIAN/preinst | |
#!/bin/sh | |
set -e | |
version=$kver | |
if [ "\$1" = abort-upgrade ]; then | |
exit 0 | |
fi | |
if [ "\$1" = install ]; then | |
mkdir -p /lib/modules/\$version | |
mkdir -p /usr/src/linux-headers-\$version || true | |
cd /lib/modules/\$version && ln -snrvf /usr/src/linux-headers-\$version build | |
fi | |
if [ -d /etc/kernel/header_preinst.d ]; then | |
DEB_MAINT_PARAMS="\$*" run-parts --report --exit-on-error --arg=\$version \\ | |
--arg=\$image_path /etc/kernel/header_preinst.d | |
fi | |
exit 0 | |
EOF | |
chmod +x "$dhpath"/DEBIAN/preinst | |
cat <<-EOF | dd status=none of="$dhpath"/DEBIAN/postinst | |
#!/bin/bash | |
set -e | |
version=$kver | |
[[ -f /etc/environment ]] && . /etc/environment | |
if [ "\$1" != configure ]; then | |
exit 0 | |
fi | |
if [ -d /etc/kernel/header_postinst.d ]; then | |
DEB_MAINT_PARAMS="\$*" run-parts --report --exit-on-error --arg=\$version \\ | |
/etc/kernel/header_postinst.d | |
fi | |
exit 0 | |
EOF | |
chmod +x "$dhpath"/DEBIAN/postinst | |
chmod -R 0755 "$dhpath"/DEBIAN | |
cd "$tmpdir" && sudo nice -n 20 dpkg-deb -b headers/ | |
sudo mv "$tmpdir"/headers.deb "$workdir"/build/linux-headers-"${kver}"_all.deb | |
} | |
make_image_deb_files() { | |
installed_size_image=$(du -a "$dipath" | tail -n 1 | awk '{print $1}') | |
mkdir -p "$dipath"/DEBIAN | |
chmod 777 "$dipath"/DEBIAN | |
cat <<-EOF | dd status=none of="$dipath"/DEBIAN/control | |
Package: linux-image-$kver | |
Source: linux-$kver | |
Version: $kver-1 | |
Architecture: arm64 | |
Maintainer: root <root@$SHORT_HASH> | |
Installed-Size: $installed_size_image | |
Section: kernel | |
Priority: optional | |
Homepage: http://www.kernel.org/ | |
Description: Linux kernel, version $kver | |
This package contains the Linux kernel, modules and corresponding other | |
files, version: $kver. | |
EOF | |
cat <<-EOFF | dd status=none of="$dipath"/DEBIAN/postinst | |
#!/bin/bash | |
set -e | |
version=$kver | |
image_path=/boot/vmlinuz-\$version | |
bootfsmount=\$(mount | grep boot | awk '{print \$3}') | |
[[ \$(echo \$bootfsmount | wc -w) == "1" ]] && BOOTFS=\${bootfsmount} | |
BOOTFS=\${BOOTFS:-/boot} | |
# Install kernel (This avoids an issue if /boot is fat32.) | |
mount -o remount,rw /boot 2>/dev/null || true | |
cp /usr/share/rpikernelhack/vmlinuz-"$kver" \$image_path || true | |
# If custom kernel= line is being used don't replace kernel8.img, | |
# overlays, or dtb files. | |
if ! vcgencmd get_config str | grep -q kernel ; then | |
cp /usr/share/rpikernelhack/vmlinuz-"$kver" /boot/kernel8.img | |
fi | |
cp /usr/lib/linux-image-"$kver"/broadcom/*.dtb \$BOOTFS/ | |
cp /usr/lib/linux-image-"$kver"/overlays/* \$BOOTFS/overlays/ | |
# This is needed to keep flash-kernel from throwing an error. | |
cp /usr/lib/linux-image-"$kver"/broadcom/*.dtb /etc/flash-kernel/dtbs/ | |
# Make sure flash-kernel db allows for any kernel flavor | |
if ! grep -q 'Kernel-Flavors: any' /etc/flash-kernel/db ; then | |
mkdir -p /etc/flash-kernel/ | |
cat <<FLASHDBRPI4 >> /etc/flash-kernel/db | |
Machine: Raspberry Pi 4 Model B | |
Machine: Raspberry Pi 4 Model B Rev 1.1 | |
Machine: Raspberry Pi 4 Model B Rev 1.2 | |
Machine: Raspberry Pi 4 Model B Rev 1.4 | |
Machine: Raspberry Pi Compute Module 4 Rev 1.0 | |
Machine: Raspberry Pi 400 Rev 1.0 | |
Machine: Raspberry Pi 400 Rev 1.1 | |
Machine: Raspberry Pi * | |
Kernel-Flavors: any | |
FLASHDBRPI4 | |
fi | |
# | |
# When we install linux-image we have to run kernel postinst.d support to | |
# generate the initramfs, create links etc. Should it have an associated | |
# linux-image-extra package and we install that we also need to run kernel | |
# postinst.d, to regenerate the initramfs. If we are installing both at the | |
# same time, we necessarily trigger kernel postinst.d twice. As this includes | |
# rebuilding the initramfs and reconfiguring the boot loader this is very time | |
# consuming. | |
# | |
# Similarly for removal when we remove the linux-image-extra package we need to | |
# run kernel postinst.d handling in order to pare down the initramfs to | |
# linux-image contents only. When we remove the linux-image need to remove the | |
# now redundant initramfs. If we are removing both at the same time, then | |
# we will rebuilt the initramfs and then immediatly remove it. | |
# | |
# Switches to using a trigger against the linux-image package for all | |
# postinst.d and postrm.d handling. On installation postinst.d gets triggered | |
# twice once by linux-image and once by linux-image-extra. As triggers are | |
# non-cumulative we will only run this processing once. When removing both | |
# packages we will trigger postinst.d from linux-image-extra and then in | |
# linux-image postrm.d we effectivly ignore the pending trigger and simply run | |
# the postrm.d. This prevents us from rebuilding the initramfs. | |
# | |
if [ "\$1" = triggered ]; then | |
trigger=/usr/lib/linux/triggers/\$version | |
if [ -f "\$trigger" ]; then | |
sh "\$trigger" | |
rm -f "\$trigger" | |
fi | |
exit 0 | |
fi | |
if [ "\$1" != configure ]; then | |
exit 0 | |
fi | |
depmod \$version | |
if [ -f /lib/modules/\$version/.fresh-install ]; then | |
change=install | |
else | |
change=upgrade | |
fi | |
# linux-update-symlinks \$change \$version \$image_path | |
rm -f /lib/modules/\$version/.fresh-install | |
if [ -d /etc/kernel/postinst.d ]; then | |
mkdir -p /usr/lib/linux/triggers | |
cat - >/usr/lib/linux/triggers/\$version <<EOF | |
DEB_MAINT_PARAMS="\$*" run-parts --report --exit-on-error --arg=\$version \\ | |
--arg=\$image_path /etc/kernel/postinst.d | |
EOF | |
dpkg-trigger --no-await linux-update-\$version | |
fi | |
exit 0 | |
EOFF | |
chmod +x "$dipath"/DEBIAN/postinst | |
cat <<-EOF | dd status=none of="$dipath"/DEBIAN/triggers | |
interest linux-update-$kver | |
EOF | |
cat <<-EOF | dd status=none of="$dipath"/DEBIAN/postrm | |
#!/bin/sh | |
set -e | |
version=$kver | |
image_path=/boot/vmlinuz-\$version | |
rm -f /lib/modules/\$version/.fresh-install | |
#if [ "\$1" != upgrade ] && command -v linux-update-symlinks >/dev/null; then | |
# linux-update-symlinks remove \$version \$image_path | |
#fi | |
if [ -d /etc/kernel/postrm.d ]; then | |
# We cannot trigger ourselves as at the end of this we will no longer | |
# exist and can no longer respond to the trigger. The trigger would | |
# then become lost. Therefore we clear any pending trigger and apply | |
# postrm directly. | |
if [ -f /usr/lib/linux/triggers/\$version ]; then | |
echo "\$0 ... removing pending trigger" | |
rm -f /usr/lib/linux/triggers/\$version | |
fi | |
DEB_MAINT_PARAMS="\$*" run-parts --report --exit-on-error --arg=\$version \\ | |
--arg=\$image_path /etc/kernel/postrm.d | |
fi | |
if [ "\$1" = purge ]; then | |
for extra_file in modules.dep modules.isapnpmap modules.pcimap \\ | |
modules.usbmap modules.parportmap \\ | |
modules.generic_string modules.ieee1394map \\ | |
modules.ieee1394map modules.pnpbiosmap \\ | |
modules.alias modules.ccwmap modules.inputmap \\ | |
modules.symbols modules.ofmap \\ | |
modules.seriomap modules.\\*.bin \\ | |
modules.softdep modules.devname; do | |
eval rm -f /lib/modules/\$version/\$extra_file | |
done | |
rmdir /lib/modules/\$version || true | |
fi | |
exit 0 | |
EOF | |
chmod +x "$dipath"/DEBIAN/postrm | |
cat <<-EOF | dd status=none of="$dipath"/DEBIAN/preinst | |
#!/bin/sh | |
set -e | |
version=$kver | |
image_path=/boot/vmlinuz-\$version | |
if [ "\$1" = abort-upgrade ]; then | |
exit 0 | |
fi | |
if [ "\$1" = install ]; then | |
# Create a flag file for postinst | |
mkdir -p /lib/modules/\$version | |
touch /lib/modules/\$version/.fresh-install | |
fi | |
if [ -d /etc/kernel/preinst.d ]; then | |
DEB_MAINT_PARAMS="\$*" run-parts --report --exit-on-error --arg=\$version \\ | |
--arg=\$image_path /etc/kernel/preinst.d | |
fi | |
if [ ! -e /lib/modules/\$version/build ]; then | |
mkdir -p /usr/src/linux-headers-\$version || true | |
cd /lib/modules/\$version && ln -snrvf /usr/src/linux-headers-\$version build || true | |
fi | |
exit 0 | |
EOF | |
chmod +x "$dipath"/DEBIAN/preinst | |
cat <<-EOF | dd status=none of="$dipath"/DEBIAN/prerm | |
#!/bin/sh | |
set -e | |
version=$kver | |
image_path=/boot/vmlinuz-\$version | |
if [ "\$1" != remove ]; then | |
exit 0 | |
fi | |
linux-check-removal \$version | |
if [ -d /etc/kernel/prerm.d ]; then | |
DEB_MAINT_PARAMS="\$*" run-parts --report --exit-on-error --arg=\$version \\ | |
--arg=\$image_path /etc/kernel/prerm.d | |
fi | |
exit 0 | |
EOF | |
chmod +x "$dipath"/DEBIAN/prerm | |
chmod -R 0755 "$dipath"/DEBIAN | |
cd "$tmpdir" && sudo nice -n 20 dpkg-deb -b image/ | |
sudo mv "$tmpdir"/image.deb "$workdir"/build/linux-image-"${kver}"_arm64.deb | |
} | |
make_debs() { | |
cd "$src_temp" && curl -L https://github.com/raspberrypi/linux/archive/"${KERNEL_REV}".tar.gz >rpi-linux.tar.gz | |
cd "$src_temp" && curl --retry 3 -OL "https://github.com/raspberrypi/rpi-firmware/raw/${FIRMWARE_REV}/Module8.symvers" | |
mv $src_temp/Module8.symvers $src_temp/Module.symvers | |
kver=$(find "$workdir"/rpi-firmware/modules/ -type d -name '*v8+' -printf "%P\n") | |
l=$kver | |
# Build kernel header package | |
# Adapted from scripts/package/builddeb | |
mkdir -p $src_temp/header_tmp/debian | |
cd $src_temp/header_tmp && tar --strip-components 1 -xf "${src_temp}"/rpi-linux.tar.gz | |
SRCARCH=arm64 | |
(cd $src_temp/header_tmp; cp $src_temp/header_tmp/arch/arm64/configs/bcm2711_defconfig $src_temp/header_tmp/.config) # copy .config manually to be where it's expected to be | |
cd "$src_temp/header_tmp" && (yes "" | sudo make oldconfig) | |
mkdir -p "$dhpath"/boot | |
cp "$src_temp/header_tmp"/.config "$dhpath"/boot/config-"${kver}" | |
cd "$src_temp/header_tmp" && (yes "" | sudo make modules_prepare) && sudo chown -R `id -u` . | |
#cd "$src_temp/header_tmp" && (yes "" | sudo make scripts) && sudo chown -R `id -u` . | |
(cd $src_temp/header_tmp; find . -name Makefile\* -o -name Kconfig\* -o -name \*.pl) > "$src_temp/header_tmp/debian/hdrsrcfiles" | |
(cd $src_temp/header_tmp; find arch/*/include include scripts -type f -o -type l) >> "$src_temp/header_tmp/debian/hdrsrcfiles" | |
(cd $src_temp/header_tmp; find arch/$SRCARCH -name module.lds -o -name Kbuild.platforms -o -name Platform) >> "$src_temp/header_tmp/debian/hdrsrcfiles" | |
(cd $src_temp/header_tmp; find $(find arch/$SRCARCH -name include -o -name scripts -type d) -type f) >> "$src_temp/header_tmp/debian/hdrsrcfiles" | |
(cd $src_temp/header_tmp; find tools/objtool -type f -executable) >> "$src_temp/header_tmp/debian/hdrobjfiles" | |
(cd $src_temp/header_tmp; find arch/$SRCARCH/include modules.builtin.modinfo Module.symvers include scripts -type f) >> "$src_temp/header_tmp/debian/hdrobjfiles" | |
(cd $src_temp/header_tmp; find scripts/gcc-plugins -name \*.so -o -name gcc-common.h) >> "$src_temp/header_tmp/debian/hdrobjfiles" | |
destdir="$dhpath"/usr/src/linux-headers-$kver | |
mkdir -p "$destdir" | |
(cd $src_temp/header_tmp; tar -c -f - -T -) < "$src_temp/header_tmp/debian/hdrsrcfiles" | (cd $destdir; tar -xf -) | |
(cd $src_temp/header_tmp; tar -c -f - -T -) < "$src_temp/header_tmp/debian/hdrobjfiles" | (cd $destdir; tar -xf -) | |
(cd $src_temp/header_tmp; cp $src_temp/header_tmp/arch/arm64/configs/bcm2711_defconfig $destdir/.config) # copy .config manually to be where it's expected to be | |
rm -rf "$src_temp/header_tmp/debian/hdrsrcfiles" "$src_temp/header_tmp/debian/hdrobjfiles" | |
cp "$src_temp"/Module.symvers "$destdir"/Module.symvers | |
make_headers_deb_files | |
mkdir -p "$dipath"/usr/share/rpikernelhack/ | |
cp "$workdir"/rpi-firmware/kernel8.img "$dipath"/usr/share/rpikernelhack/vmlinuz-"$l" | |
mkdir -p "$dipath"/lib/modules/ | |
cp -r "$workdir"/rpi-firmware/modules/"$l" "$dipath"/lib/modules/ | |
mkdir -p "$dipath"/usr/lib/linux-image-"$l"/broadcom && mkdir -p "$dipath"/usr/lib/linux-image-"$l"/overlays | |
cp -f "$workdir"/rpi-firmware/*.dtb "$dipath"/usr/lib/linux-image-"$l"/broadcom/ | |
cp -f "$workdir"/rpi-firmware/overlays/* "$dipath"/usr/lib/linux-image-"$l"/overlays/ | |
[[ ! -e "$dipath/lib/firmware/$l/device-tree" ]] && mkdir -p "$dipath"/lib/firmware/"$l"/device-tree | |
make_image_deb_files | |
# Clean up. | |
cd "$workdir" | |
sudo rm -rf "$src_temp" | |
sudo rm -rf "$tmpdir" | |
} | |
install_headers() { | |
if [[ $(uname -m) == "aarch64" ]]; then | |
bootfsmount=$(mount | grep boot | awk '{print $3}') | |
[[ $(echo $bootfsmount | wc -w) == "1" ]] && BOOTFS=${bootfsmount} | |
BOOTFS=${BOOTFS:-/boot} | |
sudo mount -o remount,rw $BOOTFS | |
fi | |
sudo nice -n 20 dpkg -i "$workdir"/build/linux-headers-"${kver}"*.deb || sudo apt install -f -y | |
} | |
install_image() { | |
if [[ $(uname -m) == "aarch64" ]]; then | |
bootfsmount=$(mount | grep boot | awk '{print $3}') | |
[[ $(echo $bootfsmount | wc -w) == "1" ]] && BOOTFS=${bootfsmount} | |
BOOTFS=${BOOTFS:-/boot} | |
sudo mount -o remount,rw $BOOTFS | |
fi | |
sudo nice -n 20 dpkg -i "$workdir"/build/linux-image-"${kver}"*.deb || sudo apt install -f -y | |
} | |
update_git_fw | |
make_debs | |
mkdir -p "$workdir"/kernel-test | |
cp "$workdir"/build/linux-image-"${kver}"*.deb "$workdir"/kernel-test/ | |
cp "$workdir"/build/linux-headers-"${kver}"*.deb "$workdir"/kernel-test/ | |
install_headers | |
install_image | |
#sudo flash-image --force ${kver} | |
#trap '' HUP | |
#if [[ $(uname -m) == "aarch64" ]]; then | |
#bootfsmount=$(mount | grep boot | awk '{print $3}') | |
#[[ $(echo $bootfsmount | wc -w) == "1" ]] && BOOTFS=${bootfsmount} | |
#BOOTFS=${BOOTFS:-/boot} | |
#sudo mount -o remount,rw $BOOTFS | |
#fi | |
#mkdir "$workdir"/bin | |
#curl -Lf https://github.com/raspberrypi/rpi-update/raw/master/rpi-update -o "$workdir"/bin/rpi-update && chmod +x "$workdir"/bin/rpi-update | |
#sudo touch $BOOTFS/kernel7l.img && sudo WANT_32BIT=0 WANT_64BIT=1 WANT_PI4=1 SKIP_WARNING=1 BOOT_PATH=$BOOTFS ROOT_PATH=/ BRANCH=master "$workdir"/bin/rpi-update | |
echo "done." |
OK. Thanks a lot for clarifying.
Script works fine, btw. Could finally install openafs-modules-dkms.
NIce. I was also successful in getting openafs-modules-dkms to install.
FYI, if you're using 64-bit beta Pi OS 'lite' version, you have to manually install git
before running this gist script... that was tripping me up as there aren't any obvious errors in the script and it completes with some strange errors caused the the initial clone not working.
FYI, if you're using 64-bit beta Pi OS 'lite' version, you have to manually install
git
before running this gist script... that was tripping me up as there aren't any obvious errors in the script and it completes with some strange errors caused the the initial clone not working.
Thanks! I'll add that!
Hey, this script seems to do what I need. I want to install v4l2-loopback but 'am missing header files.
As I understand it this script builds headers for the most current version. My problem is that uname -r
shows I'm running 5.10.103-v8+
however the script builds headers for 5.10.73-v8+
which to me seems like a lower version.
Is this a bug or does this mean the script is outdated?
Any help would be greatly appriciated!
Secondly I was wondering, if it is relativly simple to build these headers shouldn't it be possible to make these available through a raspberrypi-kernel-headers style package for 64-bit raspbian?
EDIT: welp I'm an idiot. I didn't install the image.deb along with the headers. v4l2loopback now shows up in modprobe. However the raspberrypi-camera is gone. Anyway I belive this isn't really the solution to my problem since I think I just changed kernels (which is an older version than before)
Here is my current version, which builds the 5.15 kernel images...
#!/bin/bash -x
# make_arm64_rpi_kernel_debs.sh
# Builds arm64 debian packages from the CURRENT rpi firmware repository kernel which is installed by:
# sudo rpi-update
# This runs on an arm64 host with arm64 compilation tools...
# or with some sort of cross-compilation setup.
# Debs are put in $workdir/build
#
# This will NOT work in Raspbian unless you have an arm64 compilation
# environment setup. Appears to work on
# Raspberry Pi OS (64 bit) beta test version
#
#
#
# Install packages you should probably have if you are needing to install kernel headers.
arch=$(uname -m)
if [[ $arch == 'aarch64' ]]; then
echo ""
else
echo "This needs to be run when booted into 64-bit mode."
exit 1
fi
# sudo apt install -f -y build-essential flex gawk bison libssl-dev bc dkms autoconf libtool || (sudo apt install -f -y || true)
workdir="${HOME}/workdir"
[[ ! -d "$workdir" ]] && ( mkdir -p "$workdir" || exit 1)
[[ ! -d "$workdir"/tmp ]] && ( mkdir -p "$workdir"/tmp || exit 1)
[[ ! -d "$workdir"/build ]] && ( mkdir -p "$workdir"/build || exit 1)
echo "workdir is ${workdir}"
tmpdir=$(mktemp -d deb_XXXX -p "$workdir"/tmp)
echo "tmpdir is ${tmpdir}"
dhpath="$tmpdir/headers"
dipath="$tmpdir/image"
src_temp=$(mktemp -d rpi_src_XXXi -p "$workdir"/tmp)
git_base="https://github.com/raspberrypi/rpi-firmware"
git_branch="master"
FIRMWARE_REV=$(git ls-remote "https://github.com/raspberrypi/rpi-firmware" refs/heads/$git_branch | awk '{print $1}')
cd "$src_temp" && curl -OLf https://github.com/raspberrypi/rpi-firmware/raw/$git_branch/git_hash
KERNEL_REV=$(cat "$src_temp"/git_hash)
SHORT_HASH=$(echo ${KERNEL_REV:0:7})
setup_git_fw() {
if [[ -d "$workdir/rpi-firmware" ]]; then
( sudo rm -rf "$workdir"/rpi-firmware.old || true )
( sudo mv "$workdir"/rpi-firmware "$workdir"/rpi-firmware.old || true )
( sudo rm -rf "$workdir"/rpi-firmware.old || true )
fi
cd "$workdir" && git clone --depth=1 -b $git_branch $git_base
}
update_git_fw() {
[[ ! -d "$workdir/rpi-firmware" ]] && setup_git_fw
( cd "$workdir"/rpi-firmware && git fetch && git reset --hard origin/$git_branch ) || setup_git_fw
cd "$workdir"/rpi-firmware && git config pull.ff only
cd "$workdir"/rpi-firmware && git pull
#cd "$workdir"/rpi-firmware && git_hash=$(git rev-parse origin/$git_branch)
}
check_zfs() {
# Install zfs prerequisites
sudo apt install -f -y autoconf libtool uuid-dev libudev-dev \
libssl-dev zlib1g-dev libaio-dev libattr1-dev python3 python3-dev \
python3-setuptools autoconf automake libtool gawk dkms libblkid-dev \
uuid-dev libudev-dev libssl-dev libelf-dev python3-cffi libffi-dev || true
}
make_headers_deb_files() {
installed_size_headers=$(du -a "$dhpath" | tail -n 1 | awk '{print $1}')
mkdir -p "$dhpath"/DEBIAN
chmod 777 "$dhpath"/DEBIAN
cat <<-EOF | dd status=none of="$dhpath"/DEBIAN/control
Source: linux-$kver
Section: kernel
Priority: optional
Maintainer: root <root@$SHORT_HASH>
Standards-Version: 4.1.3
Homepage: http://www.kernel.org/
Package: linux-headers-$kver
Architecture: all
Version: $kver-1
Depends: build-essential, flex, bison, bc
Installed-Size: $installed_size_headers
Description: Linux kernel headers for $kver on arm64
This package provides kernel header files for $kver on arm64
built from:
https://github.com/raspberrypi/linux/tree/$FIRMWARE_REV
This is useful for people who need to build external modules
EOF
cat <<-EOF | dd status=none of="$dhpath"/DEBIAN/preinst
#!/bin/sh
set -e
version=$kver
if [ "\$1" = abort-upgrade ]; then
exit 0
fi
if [ "\$1" = install ]; then
mkdir -p /lib/modules/\$version
mkdir -p /usr/src/linux-headers-\$version || true
cd /lib/modules/\$version && ln -snrvf /usr/src/linux-headers-\$version build
fi
if [ -d /etc/kernel/header_preinst.d ]; then
DEB_MAINT_PARAMS="\$*" run-parts --report --exit-on-error --arg=\$version \\
--arg=\$image_path /etc/kernel/header_preinst.d
fi
exit 0
EOF
chmod +x "$dhpath"/DEBIAN/preinst
cat <<-EOF | dd status=none of="$dhpath"/DEBIAN/postinst
#!/bin/bash
set -e
version=$kver
[[ -f /etc/environment ]] && . /etc/environment
if [ "\$1" != configure ]; then
exit 0
fi
if [ -d /etc/kernel/header_postinst.d ]; then
DEB_MAINT_PARAMS="\$*" run-parts --report --exit-on-error --arg=\$version \\
/etc/kernel/header_postinst.d
fi
exit 0
EOF
chmod +x "$dhpath"/DEBIAN/postinst
chmod -R 0755 "$dhpath"/DEBIAN
cd "$tmpdir" && sudo nice -n 20 dpkg-deb -b headers/
sudo mv "$tmpdir"/headers.deb "$workdir"/build/linux-headers-"${kver}"_all.deb
}
make_image_deb_files() {
installed_size_image=$(du -a "$dipath" | tail -n 1 | awk '{print $1}')
mkdir -p "$dipath"/DEBIAN
chmod 777 "$dipath"/DEBIAN
cat <<-EOF | dd status=none of="$dipath"/DEBIAN/control
Package: linux-image-$kver
Source: linux-$kver
Version: $kver-1
Architecture: arm64
Maintainer: root <root@$SHORT_HASH>
Installed-Size: $installed_size_image
Section: kernel
Priority: optional
Homepage: http://www.kernel.org/
Description: Linux kernel, version $kver
This package contains the Linux kernel, modules and corresponding other
files, version: $kver.
EOF
cat <<-EOFF | dd status=none of="$dipath"/DEBIAN/postinst
#!/bin/sh
set -e
version=$kver
image_path=/boot/vmlinuz-\$version
# Install kernel (This avoids an issue if /boot is fat32.)
mount -o remount,rw /boot 2>/dev/null || true
cp /usr/share/rpikernelhack/vmlinuz-"$kver" \$image_path || true
# If custom kernel= line is being used don't replace kernel8.img,
# overlays, or dtb files.
if ! vcgencmd get_config str | grep -q kernel ; then
cp /usr/share/rpikernelhack/vmlinuz-"$kver" /boot/kernel8.img
cp /usr/lib/linux-image-"$kver"/broadcom/*.dtb /boot/
cp /usr/lib/linux-image-"$kver"/overlays/* /boot/overlays/
fi
#
# When we install linux-image we have to run kernel postinst.d support to
# generate the initramfs, create links etc. Should it have an associated
# linux-image-extra package and we install that we also need to run kernel
# postinst.d, to regenerate the initramfs. If we are installing both at the
# same time, we necessarily trigger kernel postinst.d twice. As this includes
# rebuilding the initramfs and reconfiguring the boot loader this is very time
# consuming.
#
# Similarly for removal when we remove the linux-image-extra package we need to
# run kernel postinst.d handling in order to pare down the initramfs to
# linux-image contents only. When we remove the linux-image need to remove the
# now redundant initramfs. If we are removing both at the same time, then
# we will rebuilt the initramfs and then immediatly remove it.
#
# Switches to using a trigger against the linux-image package for all
# postinst.d and postrm.d handling. On installation postinst.d gets triggered
# twice once by linux-image and once by linux-image-extra. As triggers are
# non-cumulative we will only run this processing once. When removing both
# packages we will trigger postinst.d from linux-image-extra and then in
# linux-image postrm.d we effectivly ignore the pending trigger and simply run
# the postrm.d. This prevents us from rebuilding the initramfs.
#
if [ "\$1" = triggered ]; then
trigger=/usr/lib/linux/triggers/\$version
if [ -f "\$trigger" ]; then
sh "\$trigger"
rm -f "\$trigger"
fi
exit 0
fi
if [ "\$1" != configure ]; then
exit 0
fi
depmod \$version
if [ -f /lib/modules/\$version/.fresh-install ]; then
change=install
else
change=upgrade
fi
# linux-update-symlinks \$change \$version \$image_path
rm -f /lib/modules/\$version/.fresh-install
if [ -d /etc/kernel/postinst.d ]; then
mkdir -p /usr/lib/linux/triggers
cat - >/usr/lib/linux/triggers/\$version <<EOF
DEB_MAINT_PARAMS="\$*" run-parts --report --exit-on-error --arg=\$version \\
--arg=\$image_path /etc/kernel/postinst.d
EOF
dpkg-trigger --no-await linux-update-\$version
fi
exit 0
EOFF
chmod +x "$dipath"/DEBIAN/postinst
cat <<-EOF | dd status=none of="$dipath"/DEBIAN/triggers
interest linux-update-$kver
EOF
cat <<-EOF | dd status=none of="$dipath"/DEBIAN/postrm
#!/bin/sh
set -e
version=$kver
image_path=/boot/vmlinuz-\$version
rm -f /lib/modules/\$version/.fresh-install
#if [ "\$1" != upgrade ] && command -v linux-update-symlinks >/dev/null; then
# linux-update-symlinks remove \$version \$image_path
#fi
if [ -d /etc/kernel/postrm.d ]; then
# We cannot trigger ourselves as at the end of this we will no longer
# exist and can no longer respond to the trigger. The trigger would
# then become lost. Therefore we clear any pending trigger and apply
# postrm directly.
if [ -f /usr/lib/linux/triggers/\$version ]; then
echo "\$0 ... removing pending trigger"
rm -f /usr/lib/linux/triggers/\$version
fi
DEB_MAINT_PARAMS="\$*" run-parts --report --exit-on-error --arg=\$version \\
--arg=\$image_path /etc/kernel/postrm.d
fi
if [ "\$1" = purge ]; then
for extra_file in modules.dep modules.isapnpmap modules.pcimap \\
modules.usbmap modules.parportmap \\
modules.generic_string modules.ieee1394map \\
modules.ieee1394map modules.pnpbiosmap \\
modules.alias modules.ccwmap modules.inputmap \\
modules.symbols modules.ofmap \\
modules.seriomap modules.\\*.bin \\
modules.softdep modules.devname; do
eval rm -f /lib/modules/\$version/\$extra_file
done
rmdir /lib/modules/\$version || true
fi
exit 0
EOF
chmod +x "$dipath"/DEBIAN/postrm
cat <<-EOF | dd status=none of="$dipath"/DEBIAN/preinst
#!/bin/sh
set -e
version=$kver
image_path=/boot/vmlinuz-\$version
if [ "\$1" = abort-upgrade ]; then
exit 0
fi
if [ "\$1" = install ]; then
# Create a flag file for postinst
mkdir -p /lib/modules/\$version
touch /lib/modules/\$version/.fresh-install
fi
if [ -d /etc/kernel/preinst.d ]; then
DEB_MAINT_PARAMS="\$*" run-parts --report --exit-on-error --arg=\$version \\
--arg=\$image_path /etc/kernel/preinst.d
fi
if [ ! -e /lib/modules/\$version/build ]; then
mkdir -p /usr/src/linux-headers-\$version || true
cd /lib/modules/\$version && ln -snrvf /usr/src/linux-headers-\$version build || true
fi
exit 0
EOF
chmod +x "$dipath"/DEBIAN/preinst
cat <<-EOF | dd status=none of="$dipath"/DEBIAN/prerm
#!/bin/sh
set -e
version=$kver
image_path=/boot/vmlinuz-\$version
if [ "\$1" != remove ]; then
exit 0
fi
linux-check-removal \$version
if [ -d /etc/kernel/prerm.d ]; then
DEB_MAINT_PARAMS="\$*" run-parts --report --exit-on-error --arg=\$version \\
--arg=\$image_path /etc/kernel/prerm.d
fi
exit 0
EOF
chmod +x "$dipath"/DEBIAN/prerm
chmod -R 0755 "$dipath"/DEBIAN
cd "$tmpdir" && sudo nice -n 20 dpkg-deb -b image/
sudo mv "$tmpdir"/image.deb "$workdir"/build/linux-image-"${kver}"_arm64.deb
}
make_debs() {
cd "$src_temp" && curl -L https://github.com/raspberrypi/linux/archive/"${KERNEL_REV}".tar.gz >rpi-linux.tar.gz
cd "$src_temp" && curl --retry 3 -OL "https://github.com/raspberrypi/rpi-firmware/raw/${FIRMWARE_REV}/Module8.symvers"
mv $src_temp/Module8.symvers $src_temp/Module.symvers
kver=$(find "$workdir"/rpi-firmware/modules/ -type d -name '*v8+' -printf "%P\n")
l=$kver
# Build kernel header package
# Adapted from scripts/package/builddeb
mkdir -p $src_temp/header_tmp/debian
cd $src_temp/header_tmp && tar --strip-components 1 -xf "${src_temp}"/rpi-linux.tar.gz
SRCARCH=arm64
(cd $src_temp/header_tmp; cp $src_temp/header_tmp/arch/arm64/configs/bcm2711_defconfig $src_temp/header_tmp/.config) # copy .config manually to be where it's expected to be
cd "$src_temp/header_tmp" && (yes "" | sudo make modules_prepare) && sudo chown -R `id -u` .
#cd "$src_temp/header_tmp" && (yes "" | sudo make scripts) && sudo chown -R `id -u` .
(cd $src_temp/header_tmp; find . -name Makefile\* -o -name Kconfig\* -o -name \*.pl) > "$src_temp/header_tmp/debian/hdrsrcfiles"
(cd $src_temp/header_tmp; find arch/*/include include scripts -type f -o -type l) >> "$src_temp/header_tmp/debian/hdrsrcfiles"
(cd $src_temp/header_tmp; find arch/$SRCARCH -name module.lds -o -name Kbuild.platforms -o -name Platform) >> "$src_temp/header_tmp/debian/hdrsrcfiles"
(cd $src_temp/header_tmp; find $(find arch/$SRCARCH -name include -o -name scripts -type d) -type f) >> "$src_temp/header_tmp/debian/hdrsrcfiles"
(cd $src_temp/header_tmp; find tools/objtool -type f -executable) >> "$src_temp/header_tmp/debian/hdrobjfiles"
(cd $src_temp/header_tmp; find arch/$SRCARCH/include modules.builtin.modinfo Module.symvers include scripts -type f) >> "$src_temp/header_tmp/debian/hdrobjfiles"
(cd $src_temp/header_tmp; find scripts/gcc-plugins -name \*.so -o -name gcc-common.h) >> "$src_temp/header_tmp/debian/hdrobjfiles"
destdir="$dhpath"/usr/src/linux-headers-$kver
mkdir -p "$destdir"
(cd $src_temp/header_tmp; tar -c -f - -T -) < "$src_temp/header_tmp/debian/hdrsrcfiles" | (cd $destdir; tar -xf -)
(cd $src_temp/header_tmp; tar -c -f - -T -) < "$src_temp/header_tmp/debian/hdrobjfiles" | (cd $destdir; tar -xf -)
(cd $src_temp/header_tmp; cp $src_temp/header_tmp/arch/arm64/configs/bcm2711_defconfig $destdir/.config) # copy .config manually to be where it's expected to be
rm -rf "$src_temp/header_tmp/debian/hdrsrcfiles" "$src_temp/header_tmp/debian/hdrobjfiles"
cp "$src_temp"/Module.symvers "$destdir"/Module.symvers
make_headers_deb_files
mkdir -p "$dipath"/usr/share/rpikernelhack/
cp "$workdir"/rpi-firmware/kernel8.img "$dipath"/usr/share/rpikernelhack/vmlinuz-"$l"
mkdir -p "$dipath"/lib/modules/
cp -r "$workdir"/rpi-firmware/modules/"$l" "$dipath"/lib/modules/
mkdir -p "$dipath"/usr/lib/linux-image-"$l"/broadcom && mkdir -p "$dipath"/usr/lib/linux-image-"$l"/overlays
cp -f "$workdir"/rpi-firmware/*.dtb "$dipath"/usr/lib/linux-image-"$l"/broadcom/
cp -f "$workdir"/rpi-firmware/overlays/* "$dipath"/usr/lib/linux-image-"$l"/overlays/
[[ ! -e "$dipath/lib/firmware/$l/device-tree" ]] && mkdir -p "$dipath"/lib/firmware/"$l"/device-tree
make_image_deb_files
# Clean up.
cd "$workdir"
sudo rm -rf "$src_temp"
sudo rm -rf "$tmpdir"
}
install_headers() {
if [[ $(uname -m) == "aarch64" ]]; then
bootfsmount=$(mount | grep boot | awk '{print $3}')
[[ $(echo $bootfsmount | wc -w) == "1" ]] && BOOTFS=${bootfsmount}
BOOTFS=${BOOTFS:-/boot}
sudo mount -o remount,rw $BOOTFS
fi
sudo nice -n 20 dpkg -i "$workdir"/build/linux-headers-"${kver}"*.deb || sudo apt install -f -y
}
install_image() {
if [[ $(uname -m) == "aarch64" ]]; then
bootfsmount=$(mount | grep boot | awk '{print $3}')
[[ $(echo $bootfsmount | wc -w) == "1" ]] && BOOTFS=${bootfsmount}
BOOTFS=${BOOTFS:-/boot}
sudo mount -o remount,rw $BOOTFS
fi
sudo nice -n 20 dpkg -i "$workdir"/build/linux-image-"${kver}"*.deb || sudo apt install -f -y
}
update_git_fw
make_debs
install_headers
install_image
sudo flash-image --force ${kver}
echo "done."
@satmandu Would you script be okay to generate the image/headers/tools etc for use in a Ubuntu aarch64 20.04 build running on a Pi4? I've been keeping a look out for a 5.15 kernel to come to 20.04 aarch64 like how it's coming to the x86_64 version, but so far all I see is 5.4
I installed a 5.15 kernel from Ubuntu 22.04 aarch64 for testing, which is fine, but the headers/tools can't be installed to do a dependency being to low a version in 20.04.
I have your script running now, so I guess I'll see what happens. I'm not sure how different a Pi OS Kernel vs a Ubuntu aarch64 kernel.
edit: I think I answered my own question as the script doesn't appear to work. It states the following "Ignoring old or unknown version 5.15.43-v8+ (latest is 5.15.0-1008-raspi)" towards the end.
Here is the current version I use with Ubuntu 22.04:
@alphafox02 I updated the script to the version I use for generating kernels for Ubuntu 22.04.
I’ll check it out here shortly. I’m super curious to see if it’ll work on 20.04 Ubuntu aarch64. Thank you for sharing.
@satmandu both the kernel and headers built and installed and no immediate problem booting. Should I be looking for a way to build the Linux-modules/Linux/modules-extra and Linux-raspi-tools/Linux-tools that typically accompany the kernel and header install on the Pi w/ aarch64 20.04?
@alphafox02 I have never bothered with those packages.
OK. Thanks a lot for clarifying.
Script works fine, btw. Could finally install openafs-modules-dkms.