tools: imager: Add make-pi4-rpiboot-gpio-sd

Add new utility which creates a SD card image for programming
the rpiboot GPIO OTP option on a Pi 4 or Pi 400.

Example:
sudo imager/make-pi4-rpiboot-gpio-sd 6

Creates images-2711/pi4-program-rpiboot-gpio6.zip which can
be flashed to a spared SD card with Raspberry Pi Imager. This
will select GPIO 6 for use as the rpiboot GPIO.
This commit is contained in:
Tim Gover
2025-11-24 15:41:07 +00:00
committed by Tim Gover
parent 801aeb77c5
commit eed4273686

133
imager/make-pi4-rpiboot-gpio-sd Executable file
View File

@@ -0,0 +1,133 @@
#!/bin/sh
set -e
script_dir=$(cd "$(dirname "$0")" && pwd)
TMP_DIR=""
die() {
echo "$@" >&2
exit 1
}
cleanup() {
if [ -d "${TMP_DIR}" ]; then
rm -rf "${TMP_DIR}"
fi
}
usage() {
cat <<EOF
Usage:
sudo $(basename $0): <gpio_num>
Creates and SD card image which programs the OTP on a Pi 4B or Pi 400
to select a GPIO on the 40-pin header for use as the rpiboot GPIO.
Once programmed, if this GPIO is pulled to ground at power on the SoC
bootrom will boot into rpiboot provisioning mode.
This setting permenantely modifies the device confiuration and cannot
be undone or changed.
The SD image will be written to images-2711/pi4-program-rpiboot-gpioN.zip
and can be flashed using Raspberry Pi Imager to a spare SD card.
As with programming the bootloader EEPROM insert the card in the
Raspberry Pi, power on and wait for the green LED to flash.
gpio_num: Select the rpiboot GPIO number from 2,4,5,6,7 or 8.
EOF
exit 1
}
trap cleanup EXIT
[ "$(id -u)" = "0" ] || die "$(basename $0) must be run as root"
[ -n "${SUDO_UID}" ] || die "SUDO_UID not defined"
[ -n "${SUDO_GID}" ] || die "SUDO_GID not defined"
build_image()
{
chip="${1}"
gpio="${2}"
img="pi4-program-rpiboot-gpio${gpio}"
zip="${img}.zip"
img="${img}.img"
TMP_DIR="$(mktemp -d)"
(
mkdir "${TMP_DIR}/files"
cd "${TMP_DIR}/files"
cp "${script_dir}/../firmware-${chip}/latest/recovery.bin" .
cat <<EOF > config.txt
uart_2ndstage=1
recovery_wait=1
program_rpiboot_gpio=${gpio}
EOF
echo "Generated config.txt file"
cat config.txt
cd "${TMP_DIR}"
dd if=/dev/zero bs=1M count=258 of=temp.img > /dev/null 2>&1
/sbin/sfdisk temp.img <<EOF
label: dos
label-id: 0x0a7b5ac5
device: temp.img
unit: sectors
./test.img1 : start= 2048, size= 524288, type=c
EOF
file temp.img
LOOP="/dev/mapper/$(kpartx -lv temp.img | head -n1 | awk '{print $1}')"
kpartx -a temp.img
/sbin/mkfs.fat -F 32 -s 1 "${LOOP}" > /dev/null
mkdir fs
mount "${LOOP}" fs
cp -v files/* fs
sync
sleep 5
umount fs
# Delay before calling kpartx otherwise it's sometimes possible to get orphaned loopback devices
sleep 5
kpartx -d temp.img
)
image_dir="images-${chip}"
mkdir -p "${image_dir}"
chown "${SUDO_UID}:${SUDO_GID}" "${image_dir}"
mv "${TMP_DIR}/temp.img" "${image_dir}/${img}"
file "${image_dir}/${img}"
cd "${image_dir}"
zip "${zip}" "${img}"
cd ..
rm "${image_dir}/${img}"
chown "${SUDO_UID}:${SUDO_GID}" "${image_dir}/${zip}"
echo "Wrote $(pwd)/${image_dir}/${zip}"
}
if ! command -v kpartx > /dev/null; then
die "kpartx not found: Try installing the kpartx package"
fi
[ -n "${1}" ] || usage
gpio_num="$1"
case "${gpio_num}" in
2)
;;
4)
;;
5)
;;
6)
;;
7)
;;
8)
;;
*)
echo "GPIO ${gpio_num} is not supported"
echo
usage
;;
esac
build_image 2711 "${gpio_num}"