mirror of
https://github.com/raspberrypi/rpi-eeprom.git
synced 2026-01-20 21:13:36 +08:00
609 lines
20 KiB
Bash
Executable File
609 lines
20 KiB
Bash
Executable File
#!/bin/sh
|
|
|
|
# Raspberry Pi4 boot EEPROM updater.
|
|
|
|
set -e
|
|
|
|
script_dir=$(cd "$(dirname "$0")" && pwd)
|
|
|
|
if [ -f /etc/default/rpi-eeprom-update ]; then
|
|
. /etc/default/rpi-eeprom-update
|
|
fi
|
|
|
|
FIRMWARE_ROOT=${FIRMWARE_ROOT:-/lib/firmware/raspberrypi/bootloader}
|
|
# May be used to select beta releases instead of the default critical
|
|
# updates.
|
|
FIRMWARE_RELEASE_STATUS=${FIRMWARE_RELEASE_STATUS:-critical}
|
|
FIRMWARE_IMAGE_DIR=${FIRMWARE_IMAGE_DIR:-${FIRMWARE_ROOT}/${FIRMWARE_RELEASE_STATUS}}
|
|
FIRMWARE_BACKUP_DIR=${FIRMWARE_BACKUP_DIR:-/var/lib/raspberrypi/bootloader/backup}
|
|
ENABLE_VL805_UPDATES=${ENABLE_VL805_UPDATES:-1}
|
|
USE_FLASHROM=${USE_FLASHROM:-0}
|
|
RECOVERY_BIN=${RECOVERY_BIN:-${FIRMWARE_ROOT}/${FIRMWARE_RELEASE_STATUS}/recovery.bin}
|
|
BOOTFS=${BOOTFS:-/boot}
|
|
VCMAILBOX=${VCMAILBOX:-/opt/vc/bin/vcmailbox}
|
|
|
|
EXIT_SUCCESS=0
|
|
EXIT_UPDATE_REQUIRED=1
|
|
EXIT_FAILED=2
|
|
EXIT_EEPROM_FROZEN=3
|
|
# Reserved
|
|
# EXIT_PREVIOUS_UPDATE_FAILED=4
|
|
|
|
OVERWRITE_CONFIG=0
|
|
# Maximum safe SPI speed for EEPROM access 16000, slower is ok.
|
|
SPI_SPEED=16000
|
|
# Timestamp for first release which doesn't have a timestamp field
|
|
BOOTLOADER_FIRST_VERSION=1557513636
|
|
EEPROM_SIZE=524288
|
|
|
|
# Simple bootloader which is able to load start.elf in the event of a power
|
|
# cut. This runs SDRAM at low speed and may have reduced functionality but
|
|
# should be enough to run flashrom again.
|
|
|
|
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
|
|
|
|
cleanup() {
|
|
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 [ -d "${TMP_BOOTFS_MNT}" ]; then
|
|
umount "${TMP_BOOTFS_MNT}"
|
|
rmdir "${TMP_BOOTFS_MNT}"
|
|
fi
|
|
TMP_BOOTFS_MNT=
|
|
TMP_EEPROM_IMAGE=
|
|
TMP_EEPROM_CONFIG=
|
|
}
|
|
trap cleanup EXIT
|
|
|
|
die() {
|
|
echo "$@" >&2
|
|
exit ${EXIT_FAILED}
|
|
}
|
|
|
|
prepareImage()
|
|
{
|
|
[ -f "${BOOTLOADER_UPDATE_IMAGE}" ] || die "EEPROM image \'${BOOTLOADER_UPDATE_IMAGE}\' not found"
|
|
TMP_EEPROM_IMAGE="$(mktemp)"
|
|
TMP_EEPROM_CONFIG="$(mktemp)"
|
|
|
|
mkdir -p "${FIRMWARE_BACKUP_DIR}"
|
|
|
|
# Backup the configuration of the currently loaded bootloader
|
|
vcgencmd bootloader_config > "${TMP_EEPROM_CONFIG}"
|
|
backup="${FIRMWARE_BACKUP_DIR}/pieeprom-backup-$(date +%Y%m%d-%H%M%S).conf"
|
|
cp -f "${TMP_EEPROM_CONFIG}" "${backup}"
|
|
|
|
if [ "$(wc -l "${TMP_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 "${TMP_EEPROM_CONFIG}" "${BOOTLOADER_UPDATE_IMAGE}"
|
|
fi
|
|
}
|
|
|
|
applyRecoveryUpdate()
|
|
{
|
|
[ -n "${BOOTLOADER_UPDATE_IMAGE}" ] || [ -n "${VL805_UPDATE_IMAGE}" ] || die "No update images specified"
|
|
|
|
findBootFS
|
|
|
|
# A '.sig' file is created so that recovery.bin can check that the
|
|
# EEPROM image has not been created (e.g. SD card corruption).
|
|
# The .sig file format is currently just a SHA256 in ASCII hex. In future,
|
|
# if an actual public key signature is required then that plus any other
|
|
# data would be appended after the SHA256 signature.
|
|
if [ -n "${BOOTLOADER_UPDATE_IMAGE}" ]; then
|
|
[ -f "${BOOTLOADER_UPDATE_IMAGE}" ] || die "${BOOTLOADER_UPDATE_IMAGE} not found"
|
|
|
|
TMP_EEPROM_IMAGE="$(mktemp)"
|
|
prepareImage
|
|
# If recovery.bin encounters pieeprom.upd then it will select it in
|
|
# preference to pieeprom.bin. The .upd file also causes recovery.bin
|
|
# to rename itself to recovery.000 and reboot if the update is successful.
|
|
# The rename causes the ROM to ignore this file and use the newly flashed
|
|
# EEPROM image instead.
|
|
sha256sum "${TMP_EEPROM_IMAGE}" | awk '{print $1}' > "${BOOTFS}/pieeprom.sig" \
|
|
|| die "Failed to create ${BOOTFS}/pieeprom.sig"
|
|
|
|
cp -f "${TMP_EEPROM_IMAGE}" "${BOOTFS}/pieeprom.upd" \
|
|
|| die "Failed to copy ${TMP_EEPROM_IMAGE} to ${BOOTFS}"
|
|
fi
|
|
|
|
if [ -n "${VL805_UPDATE_IMAGE}" ]; then
|
|
sha256sum "${VL805_UPDATE_IMAGE}" | awk '{print $1}' > "${BOOTFS}/vl805.sig" \
|
|
|| die "Failed to create ${BOOTFS}/vl805.sig"
|
|
cp -f "${VL805_UPDATE_IMAGE}" "${BOOTFS}/vl805.bin"
|
|
fi
|
|
|
|
cp -f "${RECOVERY_BIN}" "${BOOTFS}/recovery.bin" \
|
|
|| die "Failed to copy ${RECOVERY_BIN} to ${BOOTFS}"
|
|
}
|
|
|
|
applyUpdate() {
|
|
checksums_file="/var/lib/dpkg/info/rpi-eeprom-images.md5sums"
|
|
|
|
[ "$(id -u)" = "0" ] || die "* Must be run as root - try 'sudo rpi-eeprom-update'"
|
|
|
|
if [ "${IGNORE_DPKG_CHECKSUMS}" = 0 ] && [ -f "${checksums_file}" ]; then
|
|
(
|
|
cd /
|
|
if ! md5sum -c "${checksums_file}" > /dev/null 2>&1; then
|
|
md5sum -c "${checksums_file}"
|
|
die "rpi-eeprom-images checksums failed - try reinstalling this package"
|
|
fi
|
|
)
|
|
fi
|
|
|
|
if [ "${USE_FLASHROM}" = 0 ]; then
|
|
applyRecoveryUpdate
|
|
return
|
|
fi
|
|
|
|
if [ -f "${BOOTLOADER_UPDATE_IMAGE}" ]; then
|
|
# Bootloader EEPROM chip-select is muxed with audio pin so disable audio
|
|
# LDO first to avoid sending noise to analog audio.
|
|
"${VCMAILBOX}" 0x00030056 4 4 0 > /dev/null || true
|
|
dtparam audio=off
|
|
|
|
# Switch the SPI pins to boot EEPROM
|
|
dtoverlay spi-gpio40-45
|
|
modprobe spidev
|
|
modprobe spi-bcm2835
|
|
|
|
prepareImage "${BOOTLOADER_UPDATE_IMAGE}"
|
|
|
|
echo "Applying bootloaer update ${BOOTLOADER_UPDATE_IMAGE}"
|
|
flashrom -p "linux_spi:dev=/dev/spidev0.0,spispeed=${SPI_SPEED}" -w "${TMP_EEPROM_IMAGE}" || die "flashrom EEPROM update failed"
|
|
|
|
dtparam -R spi-gpio40-45
|
|
dtparam audio=on
|
|
${VCMAILBOX} 0x00030056 4 4 1 > /dev/null || true
|
|
fi
|
|
|
|
if [ -f "${VL805_UPDATE_IMAGE}" ]; then
|
|
echo "Applying VL805 image ${VL805_UPDATE_IMAGE}"
|
|
vl805 -w "${VL805_UPDATE_IMAGE}"
|
|
fi
|
|
|
|
echo "Applying bootloader update ${BOOTLOADER_UPDATE_IMAGE}"
|
|
}
|
|
|
|
# Use the version reported by the loaded EEPROM instead of attempting to retrieve
|
|
# this via flashrom to avoid unnecessary audio glitches.
|
|
BOOTLOADER_CURRENT_VERSION=
|
|
getBootloaderCurrentVersion() {
|
|
if 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 -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
|
|
}
|
|
|
|
checkDependencies() {
|
|
if ! command -v vcgencmd > /dev/null; then
|
|
die "vcgencmd not found. On Debian, try installing the libraspberrypi-bin package."
|
|
fi
|
|
|
|
CPU_VER="$(vcgencmd otp_dump | grep 30: | cut -c8)"
|
|
|
|
if [ "${CPU_VER}" != "3" ]; then
|
|
# Not a BCM2711, no EEPROMs to update.
|
|
exit ${EXIT_SUCCESS}
|
|
fi
|
|
|
|
if [ ! -d "${FIRMWARE_IMAGE_DIR}" ]; then
|
|
die "EEPROM updates directory ${FIRMWARE_IMAGE_DIR} not found."
|
|
fi
|
|
|
|
if ! command -v vl805 > /dev/null; then
|
|
die "vl805 command not found. On Debian, try reinstalling the rpi-eeprom package."
|
|
fi
|
|
|
|
if vcgencmd bootloader_config | grep -qi "Command not registered"; then
|
|
die "vcgencmd: 'bootloader_config' command not supported. Please update VC firmware and reboot."
|
|
fi
|
|
|
|
if ! command -v sha256sum > /dev/null; then
|
|
die "sha256sum not found. On Debian, try installing the coreutilities package"
|
|
fi
|
|
|
|
if ! command -v flashrom > /dev/null && [ "${USE_FLASHROM}" = 1 ]; then
|
|
die "flashrom not found. On Debian, try installing the flashrom package."
|
|
fi
|
|
|
|
if [ ! -x "${VCMAILBOX}" ] && [ "${USE_FLASHROM}" = 1 ]; then
|
|
die "vcmailbox not found. On Debian, try installing the libraspberrypi-bin package."
|
|
fi
|
|
|
|
if ! command -v dtparam > /dev/null && [ "${USE_FLASHROM}" = 1 ]; then
|
|
die "dtparam not found. On Debian, try installing the libraspberrypi-bin package."
|
|
fi
|
|
|
|
if ! command -v dtoverlay > /dev/null && [ "${USE_FLASHROM}" = 1 ]; then
|
|
die "dtoverlay not found. On Debian, try installing the libraspberrypi-bin package."
|
|
fi
|
|
|
|
if [ "${USE_FLASHROM}" = 0 ] && [ ! -f "${RECOVERY_BIN}" ]; then
|
|
die "${RECOVERY_BIN} not found."
|
|
fi
|
|
}
|
|
|
|
usage() {
|
|
cat <<EOF
|
|
rpi-eeprom-update [options]... [FILE]
|
|
Checks whether the Raspberry Pi bootloader and the VL805 USB controller
|
|
EEPROMs are up-to-date and optionally updates the EEPROMs at the next reboot.
|
|
|
|
The default update mechanism writes recovery.bin and the EEPROM update
|
|
image(s) (pieeprom.upd and vl805.bin) to the boot partition on the sd-card.
|
|
The SHA256 hash of the corresponding images are written to pieeprom.sig
|
|
and/or vl805.sig. This guards against file system corruption which could
|
|
cause the EEPROM to be flashed with an invalid image. This is not a
|
|
security check.
|
|
|
|
At the next reboot the ROM runs recovery.bin which updates EEPROM(s).
|
|
If the update was successful recovery.bin renames itself to recovery.000
|
|
to prevent it from running a second time then resets the system.
|
|
The system should then boot normally.
|
|
|
|
If /boot does not correspond to the boot partition on the sd-card and this
|
|
is not a NOOBS system then the mount point for BOOTFS should be defined
|
|
in /etc/default/rpi-eeprom-update by defining the BOOTFS variable.
|
|
|
|
For reference, the flashrom update mechanism may be enabled by defining
|
|
USE_FLASHROM=1 in /etc/default/rpi-eeprom-update. This not recommended
|
|
because the SPI pins are muxed with audio and other device drivers may
|
|
be using SPI (e.g. HATs). This is also not safe in the event of a power
|
|
failure during the update of the EEPROM.
|
|
|
|
A backup of the current EEPROM config file is written to ${FIRMWARE_BACKUP_DIR}
|
|
before applying the update.
|
|
|
|
-a Automatically install bootloader and USB (VLI) EEPROM updates.
|
|
-A Specify which type of EEPROM to automatically update (vl805 or bootloader)
|
|
-d Use the default bootloader config instead of migrating the current settings
|
|
-f Install the given file instead of the latest applicable update
|
|
Ignores the FREEZE_VERSION flag in bootloader and is intended for manual
|
|
firmware updates.
|
|
WARNING: This command should only be run from console mode in order to
|
|
avoid conflicts/deadlock with dtoverlay/dtparam settings.
|
|
-h Display help text and exit
|
|
-i Ignore package checksums - for rpi-eeprom developers.
|
|
-j Write status information using JSON notation
|
|
-m Write status information to the given file when run without -a or -f
|
|
-r Removes temporary EEPROM update files from the boot partition.
|
|
-u Install the specified VL805 (USB EEPROM) image file.
|
|
|
|
To extract the configuration file from an EEPROM image:
|
|
rpi-eeprom-config pieeprom.bin --out bootconf.txt
|
|
|
|
To update the configuration file in an EEPROM image:
|
|
rpi-eeprom-config pieeprom.bin --config bootconf.txt --out pieeprom-new.bin
|
|
|
|
To flash the new image:
|
|
sudo rpi-eeprom-update -d -f ./pieeprom-new.bin
|
|
|
|
The syntax is the same as config.txt but section filters etc are not supported. See
|
|
online documentation for the list of parameters.
|
|
|
|
The official documentation for the Raspberry Pi bootloader EEPROM is available at
|
|
https://www.raspberrypi.org/documentation/hardware/raspberrypi/booteeprom.md
|
|
|
|
EOF
|
|
exit ${EXIT_SUCCESS}
|
|
}
|
|
|
|
printVersions()
|
|
{
|
|
if [ "${ACTION_UPDATE_BOOTLOADER}" = 1 ]; then
|
|
echo "BOOTLOADER: update required"
|
|
else
|
|
echo "BOOTLOADER: up-to-date"
|
|
fi
|
|
|
|
echo "CURRENT: $(date -u "-d@${BOOTLOADER_CURRENT_VERSION}") (${BOOTLOADER_CURRENT_VERSION})"
|
|
echo " LATEST: $(date -u "-d@${BOOTLOADER_UPDATE_VERSION}") (${BOOTLOADER_UPDATE_VERSION})"
|
|
|
|
if [ "${ACTION_UPDATE_VL805}" = 1 ]; then
|
|
echo "VL805: update required"
|
|
else
|
|
if [ "$(id -u)" = "0" ]; then
|
|
echo "VL805: up-to-date"
|
|
else
|
|
echo "VL805: version unknown. Try sudo rpi-eeprom-update"
|
|
fi
|
|
fi
|
|
|
|
echo "CURRENT: ${VL805_CURRENT_VERSION}"
|
|
echo " LATEST: ${VL805_UPDATE_VERSION}"
|
|
}
|
|
|
|
findBootFS()
|
|
{
|
|
# recovery.bin is loaded by the ROM from the boot partition, this is normally
|
|
# ${BOOTFS} but on NOOBS this is /dev/mmcblk0p1 with volume label RECOVERY
|
|
# If ${BOOTFS} is not writable OR is not on /dev/mmcblk0 then error because the ROM
|
|
# can only load recovery.bin from the on-board SD-CARD slot or the EEPROM.
|
|
|
|
if blkid | grep -qE "/dev/mmcblk0p1.*LABEL_FATBOOT.*RECOVERY.*TYPE.*vfat"; then
|
|
TMP_BOOTFS_MNT="$(mktemp -d)"
|
|
mount /dev/mmcblk0p1 "${TMP_BOOTFS_MNT}"
|
|
BOOTFS="${TMP_BOOTFS_MNT}"
|
|
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"
|
|
[ "$(find "${BOOTFS}/" -name "*.elf" | wc -l)" -gt 0 ] || die "BOOTFS: \"${BOOTFS}\" contains no .elf files"
|
|
}
|
|
|
|
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 [ "$(id -u)" = "0" ]; then
|
|
if command -v lspci >/dev/null; then
|
|
vlver="$(lspci -d 1106:3483 -xxx | awk '/^50:/ { print "VL805 FW version: " $5 $4 $3 $2 }')"
|
|
else
|
|
vlver="$(vl805 | grep "VL805 FW version")"
|
|
fi
|
|
if [ -n "${vlver}" ]; then
|
|
VL805_CURRENT_VERSION="${vlver#*: }"
|
|
fi
|
|
fi
|
|
}
|
|
|
|
getVL805UpdateVersion()
|
|
{
|
|
# The latest VL805 version is indicated by a file containing the version
|
|
# number. If the version file exists then verify that the corresponding
|
|
# VL805 binary exists before selecting it.
|
|
# There are no user modifiable sections in the VL805 firmware and there
|
|
# are unlikely to be many updates to it so just indicate the latest supported
|
|
# version. This also avoids making any assumptions about the VLI version numbers.
|
|
VL805_UPDATE_VERSION=""
|
|
if [ -f "${FIRMWARE_IMAGE_DIR}/vl805.latest" ]; then
|
|
ver="$(cat "${FIRMWARE_IMAGE_DIR}/vl805.latest")"
|
|
if [ -f "${FIRMWARE_IMAGE_DIR}/vl805-${ver}.bin" ]; then
|
|
VL805_UPDATE_VERSION="${ver}"
|
|
VL805_UPDATE_IMAGE="${FIRMWARE_IMAGE_DIR}/vl805-${ver}.bin"
|
|
fi
|
|
fi
|
|
}
|
|
|
|
# Retrieve the version information and determine whether newer
|
|
# versions are available.
|
|
lookupVersionInfo()
|
|
{
|
|
getBootloaderCurrentVersion
|
|
getBootloaderUpdateVersion
|
|
|
|
getVL805CurrentVersion
|
|
getVL805UpdateVersion
|
|
|
|
if [ "${BOOTLOADER_UPDATE_VERSION}" -gt "${BOOTLOADER_CURRENT_VERSION}" ]; then
|
|
ACTION_UPDATE_BOOTLOADER=1
|
|
else
|
|
BOOTLOADER_UPDATE_IMAGE=""
|
|
fi
|
|
|
|
if [ -n "${VL805_CURRENT_VERSION}" ] && [ -n "${VL805_UPDATE_VERSION}" ]; then
|
|
if [ "${VL805_CURRENT_VERSION}" != "${VL805_UPDATE_VERSION}" ]; then
|
|
ACTION_UPDATE_VL805=1
|
|
else
|
|
VL805_UPDATE_IMAGE=""
|
|
fi
|
|
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 "*** INSTALLING EEPROM UPDATES ***"
|
|
printVersions
|
|
applyUpdate
|
|
echo "EEPROM updates pending. Please reboot to apply the update."
|
|
else
|
|
printVersions
|
|
fi
|
|
}
|
|
|
|
fileUpdate()
|
|
{
|
|
removePreviousUpdates
|
|
echo "*** INSTALLING ${BOOTLOADER_UPDATE_IMAGE} ${VL805_UPDATE_IMAGE} ***"
|
|
|
|
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
|
|
echo "EEPROM update pending. Please reboot to apply the update."
|
|
}
|
|
|
|
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 -iname "recovery.*" -regex '.*\.[0-9][0-9][0-9]$' -exec rm -f {} \;
|
|
fi
|
|
}
|
|
|
|
checkVersion()
|
|
{
|
|
lookupVersionInfo
|
|
|
|
if [ "${BOOTLOADER_UPDATE_VERSION}" -gt "${BOOTLOADER_CURRENT_VERSION}" ]; then
|
|
echo "*** UPDATE REQUIRED ***"
|
|
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}"
|
|
|
|
if [ "${JSON_OUTPUT}" = "no" ]; then
|
|
cat > "${MACHINE_OUTPUT}" <<EOF
|
|
EXITCODE="${exit_code}"
|
|
BOOTLOADER_CURRENT=${bootloader_cur}
|
|
BOOTLOADER_LATEST=${bootloader_new}
|
|
VL805_CURRENT="${vl805_cur}"
|
|
VL805_LATEST="${vl805_new}"
|
|
EOF
|
|
else
|
|
cat > "${MACHINE_OUTPUT}" <<EOF
|
|
{
|
|
"EXITCODE": "${exit_code}",
|
|
"BOOTLOADER_CURRENT": ${bootloader_cur},
|
|
"BOOTLOADER_LATEST": ${bootloader_new},
|
|
"VL805_CURRENT": "${vl805_cur}",
|
|
"VL805_LATEST": "${vl805_new}"
|
|
}
|
|
EOF
|
|
fi
|
|
return 0
|
|
}
|
|
|
|
AUTO_UPDATE_BOOTLOADER=0
|
|
AUTO_UPDATE_VL805=0
|
|
MACHINE_OUTPUT=""
|
|
JSON_OUTPUT="no"
|
|
IGNORE_DPKG_CHECKSUMS=0
|
|
|
|
while getopts A:adhif:m:ju:r option; do
|
|
case "${option}" in
|
|
A)
|
|
if [ "${OPTARG}" = "bootloader" ]; then
|
|
AUTO_UPDATE_BOOTLOADER=1
|
|
elif [ "${OPTARG}" = "vl805" ]; then
|
|
AUTO_UPDATE_VL805=1
|
|
else
|
|
die "Unknown update mode: ${OPTARG}"
|
|
fi
|
|
;;
|
|
a) AUTO_UPDATE_BOOTLOADER=1
|
|
AUTO_UPDATE_VL805=1
|
|
;;
|
|
d) OVERWRITE_CONFIG=1
|
|
;;
|
|
f) BOOTLOADER_UPDATE_IMAGE="${OPTARG}"
|
|
;;
|
|
i) IGNORE_DPKG_CHECKSUMS=1
|
|
;;
|
|
j) JSON_OUTPUT="yes"
|
|
;;
|
|
m) MACHINE_OUTPUT="${OPTARG}"
|
|
;;
|
|
h) usage
|
|
;;
|
|
r) [ "$(id -u)" = "0" ] || die "* Must be run as root - try 'sudo rpi-eeprom-update -r'"
|
|
echo "Removing temporary files from previous EEPROM update"
|
|
removePreviousUpdates
|
|
exit 0
|
|
;;
|
|
u) VL805_UPDATE_IMAGE="${OPTARG}"
|
|
;;
|
|
*) echo "Unknown argument \"${option}\""
|
|
usage
|
|
;;
|
|
esac
|
|
done
|
|
|
|
checkDependencies
|
|
if [ "${AUTO_UPDATE_BOOTLOADER}" = 1 ] || [ "${AUTO_UPDATE_VL805}" = 1 ]; then
|
|
if vcgencmd bootloader_config | grep FREEZE_VERSION=1; then
|
|
echo "EEPROM version is frozen. Skipping update"
|
|
exit ${EXIT_EEPROM_FROZEN}
|
|
else
|
|
checkAndApply
|
|
fi
|
|
elif [ -n "${BOOTLOADER_UPDATE_IMAGE}" ] || [ -n "${VL805_UPDATE_IMAGE}" ]; then
|
|
fileUpdate
|
|
else
|
|
checkVersion
|
|
fi
|