|
| 1 | +#!/bin/sh |
| 2 | + |
| 3 | +set -e |
| 4 | + |
| 5 | +# deps: |
| 6 | +# - dpkg (dpkg-deb) |
| 7 | +# - openssl |
| 8 | +# - zstd |
| 9 | +# - cpio |
| 10 | +# - findutils (xargs) |
| 11 | + |
| 12 | +. /usr/local/bin/terminal-functions.sh |
| 13 | + |
| 14 | +read_config |
| 15 | + |
| 16 | +TMPDIR="${TMPDIR:=/tmp}" |
| 17 | + |
| 18 | +if [ -z "${1}" ]; then |
| 19 | + >&2 echo "No linux image specified" |
| 20 | + exit 1 |
| 21 | +fi |
| 22 | + |
| 23 | +if [ -z "${RPI_DEVICE_FAMILY}" ]; then |
| 24 | + >&2 echo "'RPI_DEVICE_FAMILY' not specified" |
| 25 | + exit 1 |
| 26 | +fi |
| 27 | + |
| 28 | +if [ -z "${BOOT_IMAGE_VENDOR}" ]; then |
| 29 | + >&2 echo "'BOOT_IMAGE_VENDOR' not specified" |
| 30 | + exit 1 |
| 31 | +fi |
| 32 | + |
| 33 | +if [ -z "${BOOT_IMAGE_MAINTAINER}" ]; then |
| 34 | + >&2 echo "'BOOT_IMAGE_MAINTAINER' not specified" |
| 35 | + exit 1 |
| 36 | +fi |
| 37 | + |
| 38 | +if [ -z "${OPENSSL}" ] || [ ! -f "${OPENSSL}" ]; then |
| 39 | + >&2 echo "'OPENSSL' not set or binary does not exist" |
| 40 | + exit 1 |
| 41 | +fi |
| 42 | + |
| 43 | +LINUX_IMAGE="${1}" |
| 44 | + |
| 45 | +# Should be set by systemd |
| 46 | +SERVICE_NAME="make-boot-image@$(systemd-escape "$LINUX_IMAGE").service" |
| 47 | +CACHE_DIRECTORY="${CACHE_DIRECTORY:=/var/cache/${SERVICE_NAME}}" |
| 48 | + |
| 49 | +# TODO: Might be interesting to start rpi-package-download with --no-block to |
| 50 | +# allow multiple simultaneous downloads. |
| 51 | +download_package() { |
| 52 | + systemctl start \ |
| 53 | + --wait \ |
| 54 | + rpi-package-download@"$(systemd-escape "${1}")".service |
| 55 | +} |
| 56 | + |
| 57 | +KERNEL_2711="linux-image-${LINUX_IMAGE}" |
| 58 | +>&2 echo "Downloading ${KERNEL_2711}" |
| 59 | +download_package "$KERNEL_2711" |
| 60 | + |
| 61 | +PACKAGE_NAME="boot-image-${BOOT_IMAGE_VENDOR}-${LINUX_IMAGE}" |
| 62 | + |
| 63 | +# Temp directory cleanup |
| 64 | +TEMP_DIRS_LIST=$(mktemp make_boot_image_temp_dirs_list.XXX) |
| 65 | +:> "${TEMP_DIRS_LIST}" |
| 66 | +remove_temp_dirs() { |
| 67 | + >&2 echo "Removing temporary directories" |
| 68 | + xargs --null rm -rf < "${TEMP_DIRS_LIST}" |
| 69 | + rm -f "${TEMP_DIRS_LIST}" |
| 70 | +} |
| 71 | +trap remove_temp_dirs EXIT |
| 72 | + |
| 73 | +>&2 printf "Creating filesystem hierarchy for deb package: " |
| 74 | +DEB_HIER="$(mktemp --directory --tmpdir debhier.XXX)" |
| 75 | +printf "%s\0" "${DEB_HIER}" >> "${TEMP_DIRS_LIST}" |
| 76 | +>&2 echo "${DEB_HIER}" |
| 77 | + |
| 78 | +>&2 printf "Create rootfs working directory: " |
| 79 | +WORK_DIR="$(mktemp --directory --tmpdir boot-image-rootfs.XXX)" |
| 80 | +printf "%s\0" "${WORK_DIR}" >> "${TEMP_DIRS_LIST}" |
| 81 | +>&2 echo "${WORK_DIR}" |
| 82 | + |
| 83 | +latest_pkg_dir() { |
| 84 | + echo /var/cache/rpi-package-download@"$(systemd-escape "${1}")".service/latest |
| 85 | +} |
| 86 | + |
| 87 | +>&2 echo "Extracting package contents" |
| 88 | +dpkg-deb --raw-extract "$(latest_pkg_dir "$KERNEL_2711")/package.deb" "${WORK_DIR}" |
| 89 | + |
| 90 | +get_dctrl_field() { |
| 91 | + grep-dctrl \ |
| 92 | + --field=Package \ |
| 93 | + --exact-match "${2}" \ |
| 94 | + --no-field-names \ |
| 95 | + --show-field="${3}" \ |
| 96 | + "${1}" |
| 97 | +} |
| 98 | + |
| 99 | +# Determine package version for later reuse |
| 100 | +KERNEL_2711_VERSION="$(get_dctrl_field "${WORK_DIR}/DEBIAN/control" "${KERNEL_2711}" Version)" |
| 101 | +>&2 echo "Extracted ${KERNEL_2711}, version ${KERNEL_2711_VERSION}" |
| 102 | + |
| 103 | +# rootfs kernel modules |
| 104 | +>&2 echo "Copy kernel modules into deb package" |
| 105 | +mkdir -p "${DEB_HIER}/lib/modules" |
| 106 | +rsync -crt "${WORK_DIR}/lib/modules/"* "${DEB_HIER}/lib/modules" |
| 107 | + |
| 108 | +>&2 printf "Create ramdisk working directory: " |
| 109 | +BFS_DIR="$(mktemp --directory --tmpdir boot-image-bootfs.XXX)" |
| 110 | +printf "%s\0" "${BFS_DIR}" >> "${TEMP_DIRS_LIST}" |
| 111 | +>&2 echo "${BFS_DIR}" |
| 112 | + |
| 113 | +# Kernel Images |
| 114 | +>&2 echo "Copy kernel to ramdisk" |
| 115 | +cp "${WORK_DIR}/boot/vmlinuz-${LINUX_IMAGE}" "${BFS_DIR}/zImage" |
| 116 | + |
| 117 | +# Overlays |
| 118 | +>&2 echo "Copy overlays to ramdisk" |
| 119 | +OVERLAY_PATH="${WORK_DIR}/usr/lib/${KERNEL_2711}/overlays" |
| 120 | +rsync -crt "${OVERLAY_PATH}"/*.dtb* "${OVERLAY_PATH}/README" "${BFS_DIR}/overlays" |
| 121 | + |
| 122 | +# DTBs |
| 123 | +>&2 echo "Copy DTBs to ramdisk" |
| 124 | +DTB_PATH="${WORK_DIR}/usr/lib/${KERNEL_2711}/broadcom" |
| 125 | +rsync -crt "${DTB_PATH}"/bcm27*.dtb "${BFS_DIR}" |
| 126 | + |
| 127 | +# Insert an initramfs |
| 128 | +>&2 echo "Add cryptoot initramfs to ramdisk (with necessary kernel modules)" |
| 129 | +INITRAMFS_EXTRACT="$(mktemp --directory --tmpdir initramfs-extract.XXX)" |
| 130 | +printf "%s\0" "${INITRAMFS_EXTRACT}" >> "${TEMP_DIRS_LIST}" |
| 131 | +zstd -q -d "$(get_cryptroot)" -o "${INITRAMFS_EXTRACT}/initramfs.cpio" |
| 132 | +mkdir -p "${INITRAMFS_EXTRACT}/initramfs" |
| 133 | +cd "${INITRAMFS_EXTRACT}/initramfs" |
| 134 | +RETURN_DIR="${OLDPWD}" |
| 135 | +cpio --quiet -id < ../initramfs.cpio > /dev/null |
| 136 | +rm ../initramfs.cpio |
| 137 | +cd "${WORK_DIR}" |
| 138 | +find lib/modules \ |
| 139 | + \( \ |
| 140 | + -name 'dm-mod.*' \ |
| 141 | + -o \ |
| 142 | + -name 'dm-crypt.*' \ |
| 143 | + -o \ |
| 144 | + -name 'af_alg.*' \ |
| 145 | + -o \ |
| 146 | + -name 'algif_skcipher.*' \ |
| 147 | + -o \ |
| 148 | + -name 'libaes.*' \ |
| 149 | + -o \ |
| 150 | + -name 'aes_generic.*' \ |
| 151 | + -o \ |
| 152 | + -name 'aes-arm64.*' \ |
| 153 | + \) \ |
| 154 | + -exec cp -r --parents "{}" "${INITRAMFS_EXTRACT}/initramfs/usr/" \; |
| 155 | +cd - |
| 156 | +find . -print0 | cpio --quiet --null -ov --format=newc > ../initramfs.cpio 2> /dev/null |
| 157 | +cd "${RETURN_DIR}" |
| 158 | +unset RETURN_DIR |
| 159 | +zstd -q -6 "${INITRAMFS_EXTRACT}/initramfs.cpio" -o "${BFS_DIR}/rootfs.cpio.zst" |
| 160 | + |
| 161 | +# raspi-firmware |
| 162 | +>&2 echo "Downloading raspi-firmware" |
| 163 | +download_package raspi-firmware |
| 164 | + |
| 165 | +>&2 printf "Create temp directory to extract firmware: " |
| 166 | +FW_EXTRACT_DIR="$(mktemp --directory --tmpdir boot-image-firmware.XXX)" |
| 167 | +printf "%s\0" "${FW_EXTRACT_DIR}" >> "${TEMP_DIRS_LIST}" |
| 168 | +>&2 echo "${FW_EXTRACT_DIR}" |
| 169 | + |
| 170 | +>&2 echo "Extracting firmware package contents" |
| 171 | +dpkg-deb --raw-extract "$(latest_pkg_dir raspi-firmware)/package.deb" "${FW_EXTRACT_DIR}" |
| 172 | + |
| 173 | +>&2 echo "Add firmware to ramdisk" |
| 174 | +rsync -v -crt "${FW_EXTRACT_DIR}/usr/lib/raspi-firmware/" "${BFS_DIR}" |
| 175 | + |
| 176 | +# cmdline.txt |
| 177 | +>&2 echo "Add cmdline.txt to ramdisk" |
| 178 | +cp "$(get_ramdisk_cmdline_file)" "${BFS_DIR}/cmdline.txt" |
| 179 | + |
| 180 | +# Inner config.txt |
| 181 | +>&2 echo "Add config.txt to ramdisk" |
| 182 | +cp "$(get_internal_config_file)" "${BFS_DIR}/config.txt" |
| 183 | + |
| 184 | +# Invoke make-boot-image |
| 185 | +>&2 echo "Finalise ramdisk in deb package (boot.img)" |
| 186 | +mkdir -p "${DEB_HIER}/boot/firmware" |
| 187 | +make-boot-image \ |
| 188 | + -b "pi${RPI_DEVICE_FAMILY}" \ |
| 189 | + -d "${BFS_DIR}" \ |
| 190 | + -o "${DEB_HIER}/boot/firmware/boot.img" > /dev/null |
| 191 | + |
| 192 | +# Outer config.txt |
| 193 | +>&2 echo "Add config.txt to deb package (ensure boot.img is used)" |
| 194 | +cp "$(get_fastboot_config_file)" "${DEB_HIER}/boot/firmware/config.txt" |
| 195 | + |
| 196 | +# boot.sig generation |
| 197 | +>&2 echo "Signing ramdisk image" |
| 198 | +sha256sum "${DEB_HIER}/boot/firmware/boot.img" | awk '{print $1}' > "${DEB_HIER}/boot/firmware/boot.sig" |
| 199 | +printf "rsa2048: " >> "${DEB_HIER}/boot/firmware/boot.sig" |
| 200 | +${OPENSSL} dgst \ |
| 201 | + -sign "$(get_signing_directives)" \ |
| 202 | + -keyform PEM \ |
| 203 | + -sha256 \ |
| 204 | + "${DEB_HIER}/boot/firmware/boot.img" \ |
| 205 | + | xxd -c 4096 -p >> "${DEB_HIER}/boot/firmware/boot.sig" |
| 206 | + |
| 207 | +# Insert control file |
| 208 | +mkdir "${DEB_HIER}/DEBIAN" |
| 209 | +echo \ |
| 210 | +"Package: ${PACKAGE_NAME} |
| 211 | +Source: linux |
| 212 | +Version: ${KERNEL_2711_VERSION} |
| 213 | +Architecture: arm64 |
| 214 | +Maintainer: ${BOOT_IMAGE_MAINTAINER} |
| 215 | +Section: kernel |
| 216 | +Priority: optional |
| 217 | +Homepage: https://github.com/raspberrypi/linux/ |
| 218 | +Provides: ${KERNEL_2711} |
| 219 | +Conflicts: ${KERNEL_2711} |
| 220 | +Replaces: ${KERNEL_2711} |
| 221 | +Description: Repackaged ${KERNEL_2711} for signed/cryptroot boot" \ |
| 222 | +> "${DEB_HIER}/DEBIAN/control" |
| 223 | + |
| 224 | +# Create Debian package |
| 225 | +dpkg-deb --build "${DEB_HIER}" "${CACHE_DIRECTORY}" |
0 commit comments