Last active
September 25, 2024 03:44
-
-
Save satmandu/a507c59d84737f6d29ff353395819d51 to your computer and use it in GitHub Desktop.
Make arm64 deb packages for the offical Raspberry Pi Foundation arm64 kernels, tested with ubuntu 23.04
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/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." |
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.
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
@alphafox02 I updated the script to the version I use for generating kernels for Ubuntu 22.04.