#!/bin/sh # Raspberry Pi bootloader EEPROM updater. set -e script_dir=$(cd "$(dirname "$0")" && pwd) if [ -f /etc/default/rpi-eeprom-update ]; then . /etc/default/rpi-eeprom-update fi LOCAL_MODE=0 if [ -n "$FIRMWARE_ROOT" ]; then # Provided by environment true elif [ -d /usr/lib/firmware/raspberrypi/bootloader ] || [ -d /usr/lib/firmware/raspberrypi/bootloader-2711 ] || [ -d /usr/lib/firmware/raspberrypi/bootloader-2712 ]; then FIRMWARE_ROOT=/usr/lib/firmware/raspberrypi/bootloader elif [ -d /lib/firmware/raspberrypi/bootloader ] || [ -d /lib/firmware/raspberrypi/bootloader-2711 ] || [ -d /lib/firmware/raspberrypi/bootloader-2712 ]; then FIRMWARE_ROOT=/lib/firmware/raspberrypi/bootloader else # Work from local git checkout LOCAL_MODE=1 IGNORE_DPKG_CHECKSUMS=1 FIRMWARE_ROOT="${script_dir}/firmware" fi # Selects the release sub-directory FIRMWARE_RELEASE_STATUS=${FIRMWARE_RELEASE_STATUS:-default} FIRMWARE_BACKUP_DIR=${FIRMWARE_BACKUP_DIR:-/var/lib/raspberrypi/bootloader/backup} ENABLE_VL805_UPDATES=${ENABLE_VL805_UPDATES:-1} CM4_ENABLE_RPI_EEPROM_UPDATE=${CM4_ENABLE_RPI_EEPROM_UPDATE:-0} RPI_EEPROM_UPDATE_CONFIG_TOOL="${RPI_EEPROM_UPDATE_CONFIG_TOOL:-raspi-config}" # Self-update is preferred to using recovery.bin because it avoids modifiy the # boot partition in order to rename recovery.bin after use. Since the 2711 ROM # does not support network or USB MSD loading of recovery.bin self-update has to # be used with other boot modes anyway. # If RPI_EEPROM_SELF_UPDATE=1 then avoid installing recovery.bin so long as the # current bootloader version supports self-update from SD/MMC and that doesn't # look as though SELF_UPDATE has been disable in the EEPROM config or config.txt. RPI_EEPROM_SELF_UPDATE="${RPI_EEPROM_SELF_UPDATE:-0}" RPI_EEPROM_SELF_UPDATE_MIN_VER=1650968668 DT_BOOTLOADER_TS=${DT_BOOTLOADER_TS:-/proc/device-tree/chosen/bootloader/build-timestamp} EXIT_SUCCESS=0 EXIT_UPDATE_REQUIRED=1 EXIT_FAILED=2 EXIT_EEPROM_FROZEN=3 # Reserved # EXIT_PREVIOUS_UPDATE_FAILED=4 OVERWRITE_CONFIG=0 # Timestamp for first release which doesn't have a timestamp field BOOTLOADER_FIRST_VERSION=1557513636 EEPROM_SIZE=524288 BOARD_INFO= BOARD_REVISION= BOARD_TYPE= BCM_CHIP= # Newer board revisions embed the VLI firmware in the bootloader EEPROM and # there is no way to separately update the VLI firmware. Consequently, # standalone vl805 update files do not trigger automatic updates. # recovery.bin and the SPI bootloader ignore vl805.bin files on boards # without a dedicated VL805 EEPROM. HAVE_VL805_EEPROM=0 TMP_EEPROM_IMAGE="" TMP_BOOTFS_MNT="" VL805_CURRENT_VERSION= VL805_UPDATE_VERSION= # The update actions selected by the version check ACTION_UPDATE_BOOTLOADER=0 ACTION_UPDATE_VL805=0 CHECKSUMS='' cleanup() { if [ -f "${CHECKSUMS}" ]; then rm -f "${CHECKSUMS}" fi if [ -f "${TMP_EEPROM_IMAGE}" ]; then rm -f "${TMP_EEPROM_IMAGE}" fi if [ -f "${TMP_EEPROM_CONFIG}" ]; then rm -f "${TMP_EEPROM_CONFIG}" fi if [ -f "${NEW_EEPROM_CONFIG}" ]; then rm -f "${NEW_EEPROM_CONFIG}" fi if [ -f "${FLASHROM_LOG}" ]; then rm -f "${FLASHROM_LOG}" fi if [ -d "${TMP_BOOTFS_MNT}" ]; then umount "${TMP_BOOTFS_MNT}" rmdir "${TMP_BOOTFS_MNT}" fi TMP_BOOTFS_MNT= TMP_EEPROM_IMAGE= TMP_EEPROM_CONFIG= NEW_EEPROM_CONFIG= FLASHROM_LOG= } trap cleanup EXIT die() { echo "$@" >&2 exit ${EXIT_FAILED} } warn() { echo "$@" >&2 } getBootloaderConfig() { # Prefer extracting bootloader's config from DT. # # In order to find the right nvmem device, we build the sysfs path of the # bootloader reserved memory DT node to then match that path against all # nvmem device's ofnode path. # # If the path isn't there, default to using vcgencmd. local blconfig_alias="/sys/firmware/devicetree/base/aliases/blconfig" local blconfig_nvmem_path="" if [ -f "${blconfig_alias}" ]; then local blconfig_ofnode_path="/sys/firmware/devicetree/base"$(strings "${blconfig_alias}")"" local blconfig_ofnode_link=$(find -L /sys/bus/nvmem -maxdepth 3 -samefile "${blconfig_ofnode_path}" 2>/dev/null) if [ -e "${blconfig_ofnode_link}" ]; then blconfig_nvmem_path=$(dirname "${blconfig_ofnode_link}") fi fi if [ -n "${blconfig_nvmem_path}" ]; then cat "${blconfig_nvmem_path}"/nvmem else vcgencmd bootloader_config fi } prepareImage() { [ -f "${BOOTLOADER_UPDATE_IMAGE}" ] || die "EEPROM image '${BOOTLOADER_UPDATE_IMAGE}' not found" TMP_EEPROM_IMAGE="$(mktemp)" TMP_EEPROM_CONFIG="$(mktemp)" NEW_EEPROM_CONFIG="$(mktemp)" mkdir -p "${FIRMWARE_BACKUP_DIR}" # Backup the configuration of the currently loaded bootloader getBootloaderConfig > "${TMP_EEPROM_CONFIG}" backup="${FIRMWARE_BACKUP_DIR}/pieeprom-backup-$(date +%Y%m%d-%H%M%S).conf" cp -f "${TMP_EEPROM_CONFIG}" "${backup}" if [ -x "${EEPROM_CONFIG_HOOK}" ]; then echo "Running EEPROM config hook ${EEPROM_CONFIG_HOOK}" if ! "${EEPROM_CONFIG_HOOK}" -u "${BOOTLOADER_UPDATE_IMAGE}" < "${TMP_EEPROM_CONFIG}" > "${NEW_EEPROM_CONFIG}"; then echo "EEPROM config hook \"${EEPROM_CONFIG_HOOK}\" failed. Using original configuration" cp -f "${TMP_EEPROM_CONFIG}" "${NEW_EEPROM_CONFIG}" fi else cp -f "${TMP_EEPROM_CONFIG}" "${NEW_EEPROM_CONFIG}" fi if [ "$(wc -l "${NEW_EEPROM_CONFIG}" | awk '{print $1}')" -lt 3 ]; then # Don't propagate empty EEPROM config files and also prevent the initial # bootloader config with WAKE_ON_GPIO=0 propgating to newer versions by # accident. OVERWRITE_CONFIG=1 fi cp -f "${BOOTLOADER_UPDATE_IMAGE}" "${TMP_EEPROM_IMAGE}" if [ "${OVERWRITE_CONFIG}" = 0 ]; then "${script_dir}/rpi-eeprom-config" \ --out "${TMP_EEPROM_IMAGE}" \ --config "${NEW_EEPROM_CONFIG}" \ --timestamp "$(date -u +%s)" \ "${BOOTLOADER_UPDATE_IMAGE}" else "${script_dir}/rpi-eeprom-config" \ --out "${TMP_EEPROM_IMAGE}" \ --timestamp "$(date -u +%s)" \ "${BOOTLOADER_UPDATE_IMAGE}" fi } runFlashrom() { attempts=5 freq=16000 # If flashrom fails then retry at a lower speed. while [ ${attempts} -gt 0 ]; do echo "flashrom -p linux_spi:dev=${SPIDEV},spispeed=${freq} -w ${BOOTFS}/pieeprom.upd" if flashrom -p linux_spi:dev=${SPIDEV},spispeed=${freq} -w "${BOOTFS}/pieeprom.upd" >> "${FLASHROM_LOG}"; then echo "Verifying update" if flashrom -p linux_spi:dev=${SPIDEV},spispeed=${freq} -v "${BOOTFS}/pieeprom.upd" >> "${FLASHROM_LOG}"; then echo "VERIFY: SUCCESS" return 0 else echo "VERIFY: FAIL" fi fi freq=8000 attempts=$((attempts - 1)) if [ ${attempts} -gt 0 ]; then echo "Failed to update bootloader using flashrom. Retrying." fi done return 1 } applyRecoveryUpdate() { [ -n "${BOOTLOADER_UPDATE_IMAGE}" ] || [ -n "${VL805_UPDATE_IMAGE}" ] || die "No update images specified" getBootloaderCurrentVersion BOOTLOADER_UPDATE_VERSION=$(strings "${BOOTLOADER_UPDATE_IMAGE}" | grep BUILD_TIMESTAMP | sed 's/.*=//g') if [ "${BOOTLOADER_CURRENT_VERSION}" -gt "${BOOTLOADER_UPDATE_VERSION}" ]; then warn " WARNING: Installing an older bootloader version." warn " Update the rpi-eeprom package to fetch the latest bootloader images." warn fi echo " CURRENT: $(date -u "-d@${BOOTLOADER_CURRENT_VERSION}") (${BOOTLOADER_CURRENT_VERSION})" echo " UPDATE: $(date -u "-d@${BOOTLOADER_UPDATE_VERSION}") (${BOOTLOADER_UPDATE_VERSION})" findBootFS echo " BOOTFS: ${BOOTFS}" if [ -n "${BOOTLOADER_UPDATE_IMAGE}" ]; then [ -f "${BOOTLOADER_UPDATE_IMAGE}" ] || die "${BOOTLOADER_UPDATE_IMAGE} not found" TMP_EEPROM_IMAGE="$(mktemp)" prepareImage # Generate a .sig file containing the sha256 hash of the EEPROM image # and the current timestamp. rpi-eeprom-digest -i "${TMP_EEPROM_IMAGE}" -o "${BOOTFS}/pieeprom.sig" cp -fv "${TMP_EEPROM_IMAGE}" "${BOOTFS}/pieeprom.upd" \ || die "Failed to copy ${TMP_EEPROM_IMAGE} to ${BOOTFS}" # For NFS mounts ensure that the files are readable to the TFTP user chmod -f go+r "${BOOTFS}/pieeprom.upd" "${BOOTFS}/pieeprom.sig" \ || die "Failed to set permissions on eeprom update files" fi if [ -n "${VL805_UPDATE_IMAGE}" ]; then rpi-eeprom-digest -i "${VL805_UPDATE_IMAGE}" -o "${BOOTFS}/vl805.sig" cp -f "${VL805_UPDATE_IMAGE}" "${BOOTFS}/vl805.bin" \ || die "Failed to copy ${VL805_UPDATE_IMAGE} to ${BOOTFS}/vl805.bin" # For NFS mounts ensure that the files are readable to the TFTP user chmod -f go+r "${BOOTFS}/vl805.bin" "${BOOTFS}/vl805.sig" \ || die "Failed to set permissions on eeprom update files" fi if getBootloaderConfig | grep -q ENABLE_SELF_UPDATE=0; then # Self update has been disabled in the EEPROM config so recovery.bin # must be used to clear this. RPI_EEPROM_SELF_UPDATE=0 fi # Setting bootloader_update=0 was really intended for use with network-boot with shared # config.txt files. However, if it looks as though self-update has been disabled then # assume recovery.bin is required. config_txt="${BOOTFS}/config.txt" if [ -f "${config_txt}" ]; then if grep -q "bootloader_update=0" "${config_txt}"; then RPI_EEPROM_SELF_UPDATE=0 fi fi [ "${BOOTLOADER_CURRENT_VERSION}" -ge "${RPI_EEPROM_SELF_UPDATE_MIN_VER}" ] || RPI_EEPROM_SELF_UPDATE=0 # For immediate updates via flash the recovery.bin update is created and then discarded if the # flashrom update was successful. For SD boot (most common) this provides a rollback in the event # of power loss. if [ "${RPI_EEPROM_USE_FLASHROM}" = 1 ]; then echo echo "UPDATING bootloader. This could take up to a minute. Please wait" echo echo "*** Do not disconnect the power until the update is complete ***" echo echo "If a problem occurs then the Raspberry Pi Imager may be used to create" echo "a bootloader rescue SD card image which restores the default bootloader image." echo FLASHROM_LOG="$(mktemp)" if runFlashrom; then # Success - remove update files from the boot partition removePreviousUpdates echo "UPDATE SUCCESSFUL" else # Leave the recovery files in case the EEPROM has been partially updated cat "${FLASHROM_LOG}" die "UPDATE FAILED" fi return elif [ "${RPI_EEPROM_SELF_UPDATE}" = "1" ]; then echo "Using self-update" else echo "Copying recovery.bin to ${BOOTFS} for EEPROM update" cp -f "${RECOVERY_BIN}" "${BOOTFS}/recovery.bin" || die "Failed to copy ${RECOVERY_BIN} to ${BOOTFS}" fi echo "" echo "EEPROM updates pending. Please reboot to apply the update." if [ "${RPI_EEPROM_USE_FLASHROM}" = 0 ]; then echo "To cancel a pending update run \"sudo rpi-eeprom-update -r\"." fi } applyUpdate() { [ "$(id -u)" = "0" ] || die "* Must be run as root - try 'sudo rpi-eeprom-update'" if [ "${IGNORE_DPKG_CHECKSUMS}" = 0 ]; then ( package_checksums_file="${PACKAGE_INFO_DIR}/rpi-eeprom.md5sums" if ! grep -qE '\.bin$' "${PACKAGE_INFO_DIR}/rpi-eeprom.md5sums"; then # Try the old rpi-eeprom-images package package_checksums_file="${PACKAGE_INFO_DIR}/rpi-eeprom-images.md5sums" fi CHECKSUMS=$(mktemp) grep -E '\.bin$' "${package_checksums_file}" > "${CHECKSUMS}" cd / if ! md5sum -c "${CHECKSUMS}" > /dev/null 2>&1; then md5sum -c "${CHECKSUMS}" die "rpi-eeprom checksums failed - try reinstalling this package" fi ) || die "Unable to validate EEPROM image package checksums" fi # Disable flashrom if the SPI device is not found if [ "${RPI_EEPROM_USE_FLASHROM}" = 1 ]; then flashrom_probe_ok=0 if ! [ -e "${SPIDEV}" ]; then warn "WARNING: SPI device ${SPIDEV} not found. Setting RPI_EEPROM_USE_FLASHROM to 0" fi if ! flashrom -p linux_spi:dev=${SPIDEV},spispeed=16000 > /dev/null 2>&1; then warn "WARNING: Flashrom probe of ${SPIDEV} failed" else flashrom_probe_ok=1 fi if [ "${flashrom_probe_ok}" != 1 ]; then echo "Setting RPI_EEPROM_USE_FLASHROM to 0" echo export RPI_EEPROM_USE_FLASHROM=0 fi fi applyRecoveryUpdate } BOOTLOADER_CURRENT_VERSION= getBootloaderCurrentVersion() { if [ -f "${DT_BOOTLOADER_TS}" ]; then # Prefer device-tree to vcgencmd BOOTLOADER_CURRENT_VERSION=$(printf "%d" "0x$(od "${DT_BOOTLOADER_TS}" -v -An -t x1 | tr -d ' ' )") elif vcgencmd bootloader_version | grep -q timestamp; then BOOTLOADER_CURRENT_VERSION=$(vcgencmd bootloader_version | grep timestamp | awk '{print $2}') if [ "${BOOTLOADER_CURRENT_VERSION}" = "0" ]; then # If a timestamp of zero is returned then it's new firmware but an # old bootloader. Assume bootloader v0 BOOTLOADER_CURRENT_VERSION="${BOOTLOADER_FIRST_VERSION}" fi else # New bootloader / old firmware ? Try to parse the date BOOTLOADER_CURRENT_VERSION=$(date -u +%s --date "$(vcgencmd bootloader_version | head -n1)" 2>/dev/null || true) fi # Failed to parse the version. Default to the initial production release. if [ -z "${BOOTLOADER_CURRENT_VERSION}" ]; then BOOTLOADER_CURRENT_VERSION="${BOOTLOADER_FIRST_VERSION}" fi } # Find latest applicable update version BOOTLOADER_UPDATE_IMAGE="" BOOTLOADER_UPDATE_VERSION=0 getBootloaderUpdateVersion() { BOOTLOADER_UPDATE_VERSION=0 match=".*/pieeprom-[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9].bin" latest="$(find "${FIRMWARE_IMAGE_DIR}/" -maxdepth 1 -type f -follow -size "${EEPROM_SIZE}c" -regex "${match}" | sort -r | head -n1)" if [ -f "${latest}" ]; then BOOTLOADER_UPDATE_VERSION=$(strings "${latest}" | grep BUILD_TIMESTAMP | sed 's/.*=//g') BOOTLOADER_UPDATE_IMAGE="${latest}" fi } chipNotSupported() { echo "Device does not a have a Raspberry Pi bootloader EEPROM (e.g. Pi 4 or Pi 5). Skipping bootloader update." exit ${EXIT_SUCCESS} } checkDependencies() { if [ -f "/sys/firmware/devicetree/base/system/linux,revision" ]; then BOARD_INFO="$(od -v -An -t x1 /sys/firmware/devicetree/base/system/linux,revision | tr -d ' \n')" elif grep -q Revision /proc/cpuinfo; then BOARD_INFO="$(sed -n '/^Revision/s/^.*: \(.*\)/\1/p' < /proc/cpuinfo)" elif command -v vcgencmd > /dev/null; then BOARD_INFO="$(vcgencmd otp_dump | grep '30:' | sed 's/.*://')" else echo "No Raspberry Pi board info found" exit ${EXIT_SUCCESS} fi if [ $(((0x$BOARD_INFO >> 23) & 1)) = 0 ]; then chipNotSupported fi if [ $(((0x$BOARD_INFO >> 12) & 15)) = 3 ]; then BCM_CHIP=2711 EEPROM_SIZE=524288 BOOTLOADER_AUTO_UPDATE_MIN_VERSION="${BOOTLOADER_AUTO_UPDATE_MIN_VERSION:-1746717695}" SPIDEV=/dev/spidev0.0 elif [ $(((0x$BOARD_INFO >> 12) & 15)) = 4 ]; then BCM_CHIP=2712 EEPROM_SIZE=2097152 BOOTLOADER_AUTO_UPDATE_MIN_VERSION="${BOOTLOADER_AUTO_UPDATE_MIN_VERSION:-1746713597}" SPIDEV=/dev/spidev10.0 # Default is to use flashrom if availableon BCM2712 RPI_EEPROM_USE_FLASHROM=${RPI_EEPROM_USE_FLASHROM:-1} else chipNotSupported fi # Default to off - in the future Raspberry Pi 5 may default to using flashrom if # flashrom is available. if [ "${AUTO_UPDATE_BOOTLOADER}" = 1 ] || [ -n "${BOOTLOADER_UPDATE_IMAGE}" ]; then [ -z "${RPI_EEPROM_USE_FLASHROM}" ] && RPI_EEPROM_USE_FLASHROM=0 if [ "${RPI_EEPROM_USE_FLASHROM}" -eq 1 ] && ! command -v flashrom > /dev/null; then warn "WARNING: flashrom not found. Setting RPI_EEPROM_USE_FLASHROM to 0" RPI_EEPROM_USE_FLASHROM=0 fi fi FIRMWARE_IMAGE_DIR="${FIRMWARE_ROOT}-${BCM_CHIP}/${FIRMWARE_RELEASE_STATUS}" if ! [ -d "${FIRMWARE_IMAGE_DIR}" ]; then # Use unadorned name for backwards compatiblity FIRMWARE_IMAGE_DIR="${FIRMWARE_ROOT}/${FIRMWARE_RELEASE_STATUS}" fi RECOVERY_BIN=${RECOVERY_BIN:-${FIRMWARE_IMAGE_DIR}/recovery.bin} BOARD_TYPE=$(((0x$BOARD_INFO >> 4) & 0xff)) BOARD_REVISION=$((0x$BOARD_INFO & 0xf)) if [ ${BOARD_TYPE} -eq 20 ] && [ "${CM4_ENABLE_RPI_EEPROM_UPDATE}" != '1' ]; then # For CM4, USB device boot is the recommended method for EEPROM updates. echo "rpi-eeprom-update is not enabled by default on CM4." echo "The recommended method for flashing the EEPROM is rpiboot." echo "See: https://github.com/raspberrypi/usbboot/blob/master/Readme.md" echo "Run with -h for more information." echo echo "To enable flashrom programming of the EEPROM" echo "Add these the following entries to /etc/default/rpi-eeprom-update" echo "RPI_EEPROM_USE_FLASHROM=1" echo "CM4_ENABLE_RPI_EEPROM_UPDATE=1" echo echo "and these entries to config.txt and reboot" echo "[cm4]" echo "dtparam=spi=on" echo "dtoverlay=audremap" echo "dtoverlay=spi-gpio40-45" echo exit ${EXIT_SUCCESS} fi if [ ${BOARD_TYPE} -eq 17 ] && [ ${BOARD_REVISION} -lt 4 ]; then HAVE_VL805_EEPROM=1 else HAVE_VL805_EEPROM=0 fi if ! command -v rpi-eeprom-digest > /dev/null; then die "rpi-eeprom-digest not found. Try re-installing the rpi-eeprom package" fi if ! command -v lspci > /dev/null; then die "lspci not found. Try installing the pciutils package." fi if ! command -v strings > /dev/null; then die "strings not found. Try installing the binutils package." fi # vcgencmd bootloader_version is deprecated. Use device-tree if available to # reduce the number of dependencies on VCHI. if ! [ -f "${DT_BOOTLOADER_TS}" ]; then if ! command -v vcgencmd > /dev/null; then die "vcgencmd not found. Try installing the raspi-utils package." fi fi if [ ! -e "${FIRMWARE_IMAGE_DIR}" ]; then die "EEPROM updates directory ${FIRMWARE_IMAGE_DIR} not found." fi # If a board revision specific firmware directory is defined then use that # in preference to the generic directory. if [ -e "${FIRMWARE_IMAGE_DIR}-${BOARD_INFO}" ]; then FIRMWARE_IMAGE_DIR="${FIRMWARE_IMAGE_DIR}-${BOARD_INFO}" fi if ! getBootloaderConfig > /dev/null; then die "Unable to get bootloader config, please update VC firmware and reboot." fi if ! command -v sha256sum > /dev/null; then die "sha256sum not found. Try installing the coreutils package." fi if [ "${BCM_CHIP}" = 2711 ] && [ ! -f "${RECOVERY_BIN}" ]; then die "${RECOVERY_BIN} not found." fi } usage() { cat < /dev/null); then for BOOTFS in /boot/firmware /boot; do if [ -f "${BOOTFS}/config.txt" ]; then break elif findmnt --fstab "$BOOTFS" > /dev/null; then break fi done fi fi # If BOOTFS is not a directory or doesn't contain any .elf files then # it's probably not the boot partition. [ -d "${BOOTFS}" ] || die "BOOTFS: \"${BOOTFS}\" is not a directory" if [ "${BCM_CHIP}" = 2712 ]; then if ! [ -e "${BOOTFS}/config.txt" ]; then warn "WARNING: BOOTFS: \"${BOOTFS}/config.txt\" not found. Please check boot directory" fi else if [ "$(find "${BOOTFS}/" -name "*.elf" | wc -l)" = 0 ]; then warn "WARNING: BOOTFS: \"${BOOTFS}\" contains no .elf files. Please check boot directory" fi fi } getVL805CurrentVersion() { # The version number is obtained by examing a section of PCI config # space which is only accessible as root. If the command is not run as # root then treat the version as unknown and skip VLI updates. VL805_CURRENT_VERSION="" if [ "${BCM_CHIP}" = 2711 ]; then if [ "$(id -u)" = "0" ]; then vlver="$(lspci -d 1106:3483 -xxx | awk '/^50:/ { print "VL805 FW version: " $5 $4 $3 $2 }')" if [ -n "${vlver}" ]; then VL805_CURRENT_VERSION="${vlver#*: }" fi fi fi } getVL805UpdateVersion() { # The VL805 version number is an eight character hex string. Select the # largest number for the newest version. # The vl805.latest version is retained for backwards compatibility with # thirdparty scripts (are there any?) but it not used by this script and # is deprecated. VL805_UPDATE_VERSION="" match='.*/vl805-.*.bin' ver=$(find "${FIRMWARE_IMAGE_DIR}" -maxdepth 1 -type f -follow -regex "${match}" | sed 's/.*\/vl805-\([0-9a-f]*\)\.bin/\1/' | sort -r | head -n1) if [ -f "${FIRMWARE_IMAGE_DIR}/vl805-${ver}.bin" ]; then VL805_UPDATE_VERSION="${ver}" VL805_UPDATE_IMAGE="${FIRMWARE_IMAGE_DIR}/vl805-${ver}.bin" fi } # Retrieve the version information and determine whether newer # versions are available. lookupVersionInfo() { getBootloaderCurrentVersion getBootloaderUpdateVersion getVL805CurrentVersion ACTION_UPDATE_BOOTLOADER=0 ACTION_UPDATE_VL805=0 if [ "${BOOTLOADER_UPDATE_VERSION}" -gt "${BOOTLOADER_CURRENT_VERSION}" ]; then ACTION_UPDATE_BOOTLOADER=1 else BOOTLOADER_UPDATE_IMAGE="" fi # If the '-s' flag for silent updates is specified then only update the # bootloader if the current version is older than the minimum version. if [ "${SILENT_UPDATE}" = 1 ] && [ -n "${BOOTLOADER_AUTO_UPDATE_MIN_VERSION}" ] && [ "${ACTION_UPDATE_BOOTLOADER}" = 1 ]; then if [ "${FIRMWARE_RELEASE_STATUS}" = "critical" ] || [ "${FIRMWARE_RELEASE_STATUS}" = "default" ]; then if [ "${BOOTLOADER_CURRENT_VERSION}" -ge "${BOOTLOADER_AUTO_UPDATE_MIN_VERSION}" ]; then echo "Skipping automatic bootloader upgrade. current ${BOOTLOADER_CURRENT_VERSION} >= min ${BOOTLOADER_AUTO_UPDATE_MIN_VERSION}" echo "" # Clear the update requried flag ACTION_UPDATE_BOOTLOADER=0 BOOTLOADER_UPDATE_IMAGE="" fi fi fi if [ "${HAVE_VL805_EEPROM}" = 1 ]; then getVL805UpdateVersion if [ -n "${VL805_CURRENT_VERSION}" ] && [ -n "${VL805_UPDATE_VERSION}" ]; then if [ "$((0x${VL805_CURRENT_VERSION}))" -lt "$((0x${VL805_UPDATE_VERSION}))" ]; then ACTION_UPDATE_VL805=1 else VL805_UPDATE_IMAGE="" fi fi else VL805_UPDATE_VERSION="${VL805_CURRENT_VERSION}" ACTION_UPDATE_VL805=0 fi } checkAndApply() { lookupVersionInfo removePreviousUpdates # Restrict the automatic updates to the EEPROM types selected by the -A option. if [ "${AUTO_UPDATE_VL805}" != 1 ]; then ACTION_UPDATE_VL805=0 VL805_UPDATE_IMAGE="" fi if [ "${AUTO_UPDATE_BOOTLOADER}" != 1 ]; then ACTION_UPDATE_BOOTLOADER=0 BOOTLOADER_UPDATE_IMAGE="" fi if [ "${ACTION_UPDATE_BOOTLOADER}" = 1 ] || [ "${ACTION_UPDATE_VL805}" = 1 ]; then echo "*** PREPARING EEPROM UPDATES ***" echo "" printVersions applyUpdate else printVersions fi } fileUpdate() { removePreviousUpdates echo "*** CREATED UPDATE ${BOOTLOADER_UPDATE_IMAGE} ${VL805_UPDATE_IMAGE} ***" echo if [ -n "${BOOTLOADER_UPDATE_IMAGE}" ]; then [ -f "${BOOTLOADER_UPDATE_IMAGE}" ] || die "Bootloader image \"${BOOTLOADER_UPDATE_IMAGE}\" not found" fi if [ -n "${VL805_UPDATE_IMAGE}" ]; then [ -f "${VL805_UPDATE_IMAGE}" ] || die "VL805 image \"${VL805_UPDATE_IMAGE}\" not found" fi applyUpdate } removePreviousUpdates() { if [ "$(id -u)" = "0" ]; then findBootFS ( # Remove any stale recovery.bin files or EEPROM images # N.B. recovery.bin is normally ignored by the ROM if is not a valid # executable but it's best to not have the file at all. rm -f "${BOOTFS}/recovery.bin" rm -f "${BOOTFS}/pieeprom.bin" "${BOOTFS}/pieeprom.upd" "${BOOTFS}/pieeprom.sig" rm -f "${BOOTFS}/vl805.bin" "${BOOTFS}/vl805.sig" # Case insensitive for FAT bootfs find "${BOOTFS}" -maxdepth 1 -type f -follow -iname "recovery.*" -regex '.*\.[0-9][0-9][0-9]$' -exec rm -f {} \; ) || die "Failed to remove previous update files" fi } checkVersion() { lookupVersionInfo if [ "${ACTION_UPDATE_BOOTLOADER}" = 1 ] || [ "${ACTION_UPDATE_VL805}" = 1 ]; then echo "*** UPDATE AVAILABLE ***" echo "" echo "Run \"sudo rpi-eeprom-update -a\" to install this update now." echo echo "To configure the bootloader update policy run \"sudo ${RPI_EEPROM_UPDATE_CONFIG_TOOL}\"" echo "" printVersions write_status_info "EXIT_UPDATE_REQUIRED" exit ${EXIT_UPDATE_REQUIRED} else printVersions write_status_info "EXIT_SUCCESS" exit ${EXIT_SUCCESS} fi } write_status_info() { [ -z "${MACHINE_OUTPUT}" ] && return 0 exit_code="${1:-EXIT_FAILED}" bootloader_cur="${BOOTLOADER_CURRENT_VERSION:-0}" bootloader_new="${BOOTLOADER_UPDATE_VERSION:-0}" vl805_cur="${VL805_CURRENT_VERSION}" vl805_new="${VL805_UPDATE_VERSION}" min_ver=${BOOTLOADER_AUTO_UPDATE_MIN_VERSION:-0} if [ "${JSON_OUTPUT}" = "no" ]; then [ "${HAVE_VL805_EEPROM}" = "0" ] && vl805_eeprom="no" || vl805_eeprom="yes" cat > "${MACHINE_OUTPUT}" < "${MACHINE_OUTPUT}" <