Merge branch 'master' into debian/buster

This commit is contained in:
Serge Schneider
2019-10-22 14:02:27 +01:00
16 changed files with 408 additions and 108 deletions

Binary file not shown.

BIN
firmware/beta/recovery.bin Normal file

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@@ -0,0 +1 @@
000137ab

View File

@@ -127,3 +127,14 @@ Optional dotted decimal ip address (e.g. 192.169.1.99) for the TFTP server which
This maybe useful on home networks because tftpd-hpa can be used instead of dnsmasq where broadband router is the DHCP server. This maybe useful on home networks because tftpd-hpa can be used instead of dnsmasq where broadband router is the DHCP server.
Default: "" Default: ""
### TFTP_PREFIX (since 2019-10-08)
Configure the TFTP prefix string to probe
* 0 - The serial number
* 1 - The value of TFTP_PREFIX_STR
* 2 - The mac-address separated by dashes (lower case)
Default: 0
### TFTP_PREFIX_STR (since 2019-10-08)
The prefix string to use with TFTP_PREFIX=1 - up to 127 characters.
Default: ""

View File

@@ -1,5 +1,26 @@
# Raspberry Pi4 bootloader EEPROM release notes # Raspberry Pi4 bootloader EEPROM release notes
## 2019-10-17 - rpi-eeprom-update + recovery.bin
* New beta recovery.bin which can update the VLI EEPROM before
start.elf is loaded. This is the recommended and default method
because no USB devices will be in use at this stage.
* Extend the USE_FLASHROM configuration to use the vl805 tool
to program the VL805 directly.
* Generate SHA256 checksums in .sig files for the bootloader and
and VL805 images. This is required by the new recovery.bin to
guard against corrupted files being flashed to the EEPROM(s).
* Various variable renames to distinguish between the bootloader
and the VL805 images.
## 2019-10-16 - Git 18472066 (BETA)
* Ignore trailing characters when parsing in PXE boot menu option.
* Improve error handling with unformatted sd-cards.
## 2019-10-08 - Git 26dd3686c (BETA)
* TFTP now uses RFC2348 blksize option to get 1024 byte blocks if the server supports it.
* Fix DHCP handling of SI_ADDR
* TFTP_PREFIX and TFTP_PREFIX_STR options for mac-address or string literal prefix.
* Improved support for standard capacity and SDv1 cards.
## 2019-09-25 - Git 4d9824321 (BETA) ## 2019-09-25 - Git 4d9824321 (BETA)
* Increase TFTP timeout to 30s as default & bootconf.txt * Increase TFTP timeout to 30s as default & bootconf.txt
* Fix intermittent boot freeze/slowdown issue after loading start.elf * Fix intermittent boot freeze/slowdown issue after loading start.elf

View File

@@ -10,6 +10,8 @@ import sys
IMAGE_SIZE = 512 * 1024 IMAGE_SIZE = 512 * 1024
MAX_BOOTCONF_SIZE = 2024
# Each section starts with a magic number followed by a 32 bit offset to the # Each section starts with a magic number followed by a 32 bit offset to the
# next section (big-endian). # next section (big-endian).
# The number, order and size of the sections depends on the bootloader version # The number, order and size of the sections depends on the bootloader version
@@ -55,8 +57,9 @@ class BootloaderImage(object):
hdr_offset, length = self.find_config() hdr_offset, length = self.find_config()
new_config_bytes = open(new_config, 'rb').read() new_config_bytes = open(new_config, 'rb').read()
new_len = len(new_config_bytes) + FILENAME_LEN + 4 new_len = len(new_config_bytes) + FILENAME_LEN + 4
if new_len > length and new_len > 1024: if len(new_config_bytes) > MAX_BOOTCONF_SIZE:
raise Exception('Config is too large') raise Exception("Config is too large (%d bytes). The maximum size is %d bytes."
% (len(new_config_bytes), MAX_BOOTCONF_SIZE))
if hdr_offset + len(new_config_bytes) + FILE_HDR_LEN > IMAGE_SIZE: if hdr_offset + len(new_config_bytes) + FILE_HDR_LEN > IMAGE_SIZE:
raise Exception('EEPROM image size exceeded') raise Exception('EEPROM image size exceeded')

View File

@@ -16,8 +16,9 @@ FIRMWARE_ROOT=${FIRMWARE_ROOT:-/lib/firmware/raspberrypi/bootloader}
FIRMWARE_RELEASE_STATUS=${FIRMWARE_RELEASE_STATUS:-critical} FIRMWARE_RELEASE_STATUS=${FIRMWARE_RELEASE_STATUS:-critical}
FIRMWARE_IMAGE_DIR=${FIRMWARE_IMAGE_DIR:-${FIRMWARE_ROOT}/${FIRMWARE_RELEASE_STATUS}} FIRMWARE_IMAGE_DIR=${FIRMWARE_IMAGE_DIR:-${FIRMWARE_ROOT}/${FIRMWARE_RELEASE_STATUS}}
FIRMWARE_BACKUP_DIR=${FIRMWARE_BACKUP_DIR:-/var/lib/raspberrypi/bootloader/backup} FIRMWARE_BACKUP_DIR=${FIRMWARE_BACKUP_DIR:-/var/lib/raspberrypi/bootloader/backup}
ENABLE_VL805_UPDATES=${ENABLE_VL805_UPDATES:-1}
USE_FLASHROM=${USE_FLASHROM:-0} USE_FLASHROM=${USE_FLASHROM:-0}
RECOVERY_BIN=${RECOVERY_BIN:-${FIRMWARE_ROOT}/recovery.bin} RECOVERY_BIN=${RECOVERY_BIN:-${FIRMWARE_ROOT}/${FIRMWARE_RELEASE_STATUS}/recovery.bin}
BOOTFS=${BOOTFS:-/boot} BOOTFS=${BOOTFS:-/boot}
EXIT_SUCCESS=0 EXIT_SUCCESS=0
@@ -31,7 +32,7 @@ OVERWRITE_CONFIG=0
# Maximum safe SPI speed for EEPROM access 16000, slower is ok. # Maximum safe SPI speed for EEPROM access 16000, slower is ok.
SPI_SPEED=16000 SPI_SPEED=16000
# Timestamp for first release which doesn't have a timestamp field # Timestamp for first release which doesn't have a timestamp field
FIRST_VERSION=1557513636 BOOTLOADER_FIRST_VERSION=1557513636
EEPROM_SIZE=524288 EEPROM_SIZE=524288
# Simple bootloader which is able to load start.elf in the event of a power # Simple bootloader which is able to load start.elf in the event of a power
@@ -41,6 +42,13 @@ EEPROM_SIZE=524288
TMP_EEPROM_IMAGE="" TMP_EEPROM_IMAGE=""
TMP_BOOTFS_MNT="" 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() { cleanup() {
if [ -f "${TMP_EEPROM_IMAGE}" ]; then if [ -f "${TMP_EEPROM_IMAGE}" ]; then
rm -f "${TMP_EEPROM_IMAGE}" rm -f "${TMP_EEPROM_IMAGE}"
@@ -65,9 +73,7 @@ die() {
prepareImage() prepareImage()
{ {
eeprom_image="$1" [ -f "${BOOTLOADER_UPDATE_IMAGE}" ] || die "EEPROM image \'${BOOTLOADER_UPDATE_IMAGE}\' not found"
[ -f "${eeprom_image}" ] || die "EEPROM image \'${eeprom_image}\' not found"
TMP_EEPROM_IMAGE="$(mktemp)" TMP_EEPROM_IMAGE="$(mktemp)"
TMP_EEPROM_CONFIG="$(mktemp)" TMP_EEPROM_CONFIG="$(mktemp)"
@@ -85,46 +91,62 @@ prepareImage()
OVERWRITE_CONFIG=1 OVERWRITE_CONFIG=1
fi fi
cp -f "${eeprom_image}" "${TMP_EEPROM_IMAGE}" cp -f "${BOOTLOADER_UPDATE_IMAGE}" "${TMP_EEPROM_IMAGE}"
if [ "${OVERWRITE_CONFIG}" = 0 ]; then if [ "${OVERWRITE_CONFIG}" = 0 ]; then
"${script_dir}/rpi-eeprom-config" \ "${script_dir}/rpi-eeprom-config" \
--out "${TMP_EEPROM_IMAGE}" \ --out "${TMP_EEPROM_IMAGE}" \
--config "${TMP_EEPROM_CONFIG}" "${eeprom_image}" --config "${TMP_EEPROM_CONFIG}" "${BOOTLOADER_UPDATE_IMAGE}"
fi fi
} }
applyRecoveryUpdate() applyRecoveryUpdate()
{ {
eeprom_image="$1" [ -n "${BOOTLOADER_UPDATE_IMAGE}" ] || [ -n "${VL805_UPDATE_IMAGE}" ] || die "No update images specified"
[ -f "${eeprom_image}" ] || die "${eeprom_image} not found"
TMP_EEPROM_IMAGE="$(mktemp)"
findBootFS findBootFS
prepareImage "${eeprom_image}"
# 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 # If recovery.bin encounters pieeprom.upd then it will select it in
# preference to pieeprom.bin. The .upd file also causes recovery.bin # preference to pieeprom.bin. The .upd file also causes recovery.bin
# to rename itself to recovery.000 and reboot if the update is successful. # 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 # The rename causes the ROM to ignore this file and use the newly flashed
# EEPROM image instead. # 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" \ cp -f "${TMP_EEPROM_IMAGE}" "${BOOTFS}/pieeprom.upd" \
|| die "Failed to copy ${TMP_EEPROM_IMAGE} to ${BOOTFS}" || 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" \ cp -f "${RECOVERY_BIN}" "${BOOTFS}/recovery.bin" \
|| die "Failed to copy ${RECOVERY_BIN} to ${BOOTFS}" || die "Failed to copy ${RECOVERY_BIN} to ${BOOTFS}"
} }
applyUpdate() { applyUpdate() {
eeprom_image="$1"
[ "$(id -u)" = "0" ] || die "* Must be run as root - try 'sudo rpi-eeprom-update'" [ "$(id -u)" = "0" ] || die "* Must be run as root - try 'sudo rpi-eeprom-update'"
if [ "${USE_FLASHROM}" = 0 ]; then if [ "${USE_FLASHROM}" = 0 ]; then
applyRecoveryUpdate "${eeprom_image}" applyRecoveryUpdate
return return
fi fi
if [ -f "${BOOTLOADER_UPDATE_IMAGE}" ]; then
# Bootloader EEPROM chip-select is muxed with audio pin so disable audio # Bootloader EEPROM chip-select is muxed with audio pin so disable audio
# LDO first to avoid sending noise to analog audio. # LDO first to avoid sending noise to analog audio.
/opt/vc/bin/vcmailbox 0x00030056 4 4 0 > /dev/null || true /opt/vc/bin/vcmailbox 0x00030056 4 4 0 > /dev/null || true
@@ -135,48 +157,56 @@ applyUpdate() {
modprobe spidev modprobe spidev
modprobe spi-bcm2835 modprobe spi-bcm2835
prepareImage "${eeprom_image}" prepareImage "${BOOTLOADER_UPDATE_IMAGE}"
echo "Applying update ${eeprom_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" 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 -R spi-gpio40-45
dtparam audio=on dtparam audio=on
/opt/vc/bin/vcmailbox 0x00030056 4 4 1 > /dev/null || true /opt/vc/bin/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 # Use the version reported by the loaded EEPROM instead of attempting to retrieve
# this via flashrom to avoid unnecessary audio glitches. # this via flashrom to avoid unnecessary audio glitches.
CURRENT_VERSION= BOOTLOADER_CURRENT_VERSION=
getCurrentVersion() { getBootloaderCurrentVersion() {
if vcgencmd bootloader_version | grep -q timestamp; then if vcgencmd bootloader_version | grep -q timestamp; then
CURRENT_VERSION=$(vcgencmd bootloader_version | grep timestamp | awk '{print $2}') BOOTLOADER_CURRENT_VERSION=$(vcgencmd bootloader_version | grep timestamp | awk '{print $2}')
if [ "${CURRENT_VERSION}" = "0" ]; then if [ "${BOOTLOADER_CURRENT_VERSION}" = "0" ]; then
# If a timestamp of zero is returned then it's new firmware but an # If a timestamp of zero is returned then it's new firmware but an
# old bootloader. Assume bootloader v0 # old bootloader. Assume bootloader v0
CURRENT_VERSION="${FIRST_VERSION}" BOOTLOADER_CURRENT_VERSION="${BOOTLOADER_FIRST_VERSION}"
fi fi
else else
# New bootloader / old firmware ? Try to parse the date # New bootloader / old firmware ? Try to parse the date
CURRENT_VERSION=$(date -u +%s --date "$(vcgencmd bootloader_version | head -n1)") BOOTLOADER_CURRENT_VERSION=$(date -u +%s --date "$(vcgencmd bootloader_version | head -n1)" 2>/dev/null || true)
fi fi
# Failed to parse the version. Default to the initial production release. # Failed to parse the version. Default to the initial production release.
if [ -z "${CURRENT_VERSION}" ]; then if [ -z "${BOOTLOADER_CURRENT_VERSION}" ]; then
CURRENT_VERSION="${FIRST_VERSION}" BOOTLOADER_CURRENT_VERSION="${BOOTLOADER_FIRST_VERSION}"
fi fi
} }
# Find latest applicable update version # Find latest applicable update version
UPDATE_IMAGE="" BOOTLOADER_UPDATE_IMAGE=""
UPDATE_VERSION=0 BOOTLOADER_UPDATE_VERSION=0
getUpdateVersion() { getBootloaderUpdateVersion() {
UPDATE_VERSION=0 BOOTLOADER_UPDATE_VERSION=0
match=".*/pieeprom-[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9].bin" 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)" latest="$(find "${FIRMWARE_IMAGE_DIR}" -maxdepth 1 -type f -size "${EEPROM_SIZE}c" -regex "${match}" | sort -r | head -n1)"
if [ -f "${latest}" ]; then if [ -f "${latest}" ]; then
UPDATE_VERSION=$(strings "${latest}" | grep BUILD_TIMESTAMP | sed 's/.*=//g') BOOTLOADER_UPDATE_VERSION=$(strings "${latest}" | grep BUILD_TIMESTAMP | sed 's/.*=//g')
UPDATE_IMAGE="${latest}" BOOTLOADER_UPDATE_IMAGE="${latest}"
fi fi
} }
@@ -192,12 +222,20 @@ checkDependencies() {
die "Bootloader updates directory ${FIRMWARE_IMAGE_DIR} not found." die "Bootloader updates directory ${FIRMWARE_IMAGE_DIR} not found."
fi fi
if vcgencmd bootloader_config | grep -qi "Command not registered"; then if ! command -v vl805 -h > /dev/null 2>&1; then
die "vcgencmd: 'bootloader_config' command not supported. Please update VC firmware" die "vl805 command not found"
fi fi
if ! flashrom --version > /dev/null 2>&1; then if vcgencmd bootloader_config | grep -qi "Command not registered"; then
[ "${USE_FLASHROM}" = 0 ] || die "flashrom not found." die "vcgencmd: 'bootloader_config' command not supported. Please update VC firmware and reboot."
fi
if ! command -v sha256sum > /dev/null 2>&1; then
die "sha256sum not found. On Debian, try installing the coreutilities package"
fi
if ! command -v flashrom > /dev/null 2>&1; then
[ "${USE_FLASHROM}" = 0 ] || die "flashrom not found. On Debian, try installing the flashrom package."
fi fi
if [ "${USE_FLASHROM}" = 0 ]; then if [ "${USE_FLASHROM}" = 0 ]; then
@@ -208,18 +246,24 @@ checkDependencies() {
usage() { usage() {
cat <<EOF cat <<EOF
rpi-eeprom-update [options]... [FILE] rpi-eeprom-update [options]... [FILE]
Checks whether the Raspberry Pi bootloader EEPROM is up-to-date and Checks whether the Raspberry Pi bootloader and the VL805 USB controller
optionally updates the EEPROM at the next reboot. EEPROMs are up-to-date and optionally updates the EEPROMs at the next reboot.
The default update mechanism writes recovery.bin and pieeprom.upd to the The default update mechanism writes recovery.bin and the EEPROM update
boot partition on the sd-card. At the next reboot the ROM runs recovery.bin image(s) (pieeprom.upd and vl805.bin) to the boot partition on the sd-card.
which flashes pieeprom.upd to the EEPROM. If the EEPROM update was successful The SHA256 hash of the corresponding images are written to pieeprom.sig
recovery.bin renames itself to recovery.000 to prevent it from running a and/or vl805.sig. This guards against file system corruption which could
second time then resets the system. The system should then boot normally. cause the EEPROM to be flashed with an invalid image. This is 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 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 is not a NOOBS system then the mount point for BOOTFS should be defined
in /etc/default/rpi-eeprom-update in /etc/default/rpi-eeprom-update by defining the BOOTFS variable.
For reference, the flashrom update mechanism may be enabled by defining For reference, the flashrom update mechanism may be enabled by defining
USE_FLASHROM=1 in /etc/default/rpi-eeprom-update. This not recommended USE_FLASHROM=1 in /etc/default/rpi-eeprom-update. This not recommended
@@ -230,7 +274,8 @@ rpi-eeprom-update [options]... [FILE]
A backup of the current EEPROM config file is written to ${FIRMWARE_BACKUP_DIR} A backup of the current EEPROM config file is written to ${FIRMWARE_BACKUP_DIR}
before applying the update. before applying the update.
-a Install the latest update if necessary -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 -d Use the default bootloader config instead of migrating the current settings
-f Install the given file instead of the latest applicable update -f Install the given file instead of the latest applicable update
Ignores the FREEZE_VERSION flag in bootloader and is intended for manual Ignores the FREEZE_VERSION flag in bootloader and is intended for manual
@@ -240,7 +285,7 @@ rpi-eeprom-update [options]... [FILE]
-h Display help text and exit -h Display help text and exit
-j Write status information using JSON notation -j Write status information using JSON notation
-m Write status information to the given file when run without -a or -f -m Write status information to the given file when run without -a or -f
-u Install the specified VL805 (USB EEPROM) image file.
To extract the configuration file from an EEPROM image: To extract the configuration file from an EEPROM image:
rpi-eeprom-config pieeprom.bin --out bootconf.txt rpi-eeprom-config pieeprom.bin --out bootconf.txt
@@ -263,10 +308,12 @@ EOF
printVersions() printVersions()
{ {
cur="$1" echo "BOOTLOADER"
new="$2" echo "CURRENT: $(date -u "-d@${BOOTLOADER_CURRENT_VERSION}") (${BOOTLOADER_CURRENT_VERSION})"
echo "CURRENT: $(date -u "-d@${cur}") (${cur})" echo " LATEST: $(date -u "-d@${BOOTLOADER_UPDATE_VERSION}") (${BOOTLOADER_UPDATE_VERSION})"
echo " LATEST: $(date -u "-d@${new}") (${new})" echo "VL805"
echo "CURRENT: ${VL805_CURRENT_VERSION}"
echo " LATEST: ${VL805_UPDATE_VERSION}"
} }
findBootFS() findBootFS()
@@ -276,7 +323,6 @@ findBootFS()
# If ${BOOTFS} is not writable OR is not on /dev/mmcblk0 then error because the ROM # 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. # can only load recovery.bin from the on-board SD-CARD slot or the EEPROM.
# To skip installing the safe mode recovery.bin use the -s option
if blkid | grep -qE "/dev/mmcblk0p1.*LABEL_FATBOOT.*RECOVERY.*TYPE.*vfat"; then if blkid | grep -qE "/dev/mmcblk0p1.*LABEL_FATBOOT.*RECOVERY.*TYPE.*vfat"; then
TMP_BOOTFS_MNT="$(mktemp -d)" TMP_BOOTFS_MNT="$(mktemp -d)"
mount /dev/mmcblk0p1 "${TMP_BOOTFS_MNT}" mount /dev/mmcblk0p1 "${TMP_BOOTFS_MNT}"
@@ -284,33 +330,105 @@ findBootFS()
fi fi
# If BOOTFS is not a directory or doesn't contain any .elf files then # If BOOTFS is not a directory or doesn't contain any .elf files then
# it's probably not the boot partition so assume that it cannot be used for a # it's probably not the boot partition.
# safe mode recovery
[ -d "${BOOTFS}" ] || die "BOOTFS: \"${BOOTFS}\" is not a directory" [ -d "${BOOTFS}" ] || die "BOOTFS: \"${BOOTFS}\" is not a directory"
[ "$(find "${BOOTFS}/" -name "*.elf" | wc -l)" -gt 0 ] || die "BOOTFS: \"${BOOTFS}\" contains no .elf files" [ "$(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 vl805 | grep -q "VL805 FW version"; then
VL805_CURRENT_VERSION=$(vl805 | grep "VL805 FW version" | awk '{print $4}')
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() checkAndApply()
{ {
getCurrentVersion lookupVersionInfo
getUpdateVersion
if [ "${UPDATE_VERSION}" -gt "${CURRENT_VERSION}" ]; then # Restrict the automatic updates to the EEPROM types selected by the -A option.
printVersions "${CURRENT_VERSION}" "${UPDATE_VERSION}" if [ "${AUTO_UPDATE_VL805}" != 1 ]; then
echo "*** INSTALLING REQUIRED UPDATE ***" ACTION_UPDATE_VL805=0
applyUpdate "${UPDATE_IMAGE}" VL805_UPDATE_IMAGE=""
echo "Bootloader EEPROM update pending. Please reboot to apply the update." 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 "Bootloader and/or VL805 EEPROM update pending. Please reboot to apply the update."
else else
echo "Bootloader EEPROM is up to date. $(date -d@${CURRENT_VERSION})" echo "Bootloader and VL805 EEPROMs are up to date. $(date -d@${BOOTLOADER_CURRENT_VERSION})"
fi fi
} }
fileUpdate() fileUpdate()
{ {
echo "*** INSTALLING ${1} ***" echo "*** INSTALLING ${BOOTLOADER_UPDATE_IMAGE} ${VL805_UPDATE_IMAGE} ***"
[ -f "${1}" ] || die "\"${1}\" not found"
applyUpdate "$1" if [ -n "${BOOTLOADER_UPDATE_IMAGE}" ]; then
echo "Bootloader EEPROM update pending. Please reboot to apply the update." [ -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() removePreviousUpdates()
@@ -322,25 +440,26 @@ removePreviousUpdates()
# N.B. recovery.bin is normally ignored by the ROM if is not a valid # 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. # executable but it's best to not have the file at all.
rm -f "${BOOTFS}/recovery.bin" rm -f "${BOOTFS}/recovery.bin"
rm -f "${BOOTFS}/pieeprom.bin" "${BOOTFS}/pieeprom.upd" rm -f "${BOOTFS}/pieeprom.bin" "${BOOTFS}/pieeprom.upd" "${BOOTFS}/pieeprom.sig"
rm -f "${BOOTFS}/vl805.bin" "${BOOTFS}/vl805.sig"
# Case insensitive for FAT bootfs # Case insensitive for FAT bootfs
find "${BOOTFS}" -maxdepth 1 -type f -iname "recovery.*" -regex ".*\.[0-9][0-9][0-9]$" -exec rm -f {} \; find "${BOOTFS}" -maxdepth 1 -type f -iname "recovery.*" -regex '.*\.[0-9][0-9][0-9]$' -exec rm -f {} \;
fi fi
} }
checkVersion() checkVersion()
{ {
getCurrentVersion lookupVersionInfo
getUpdateVersion
if [ "${UPDATE_VERSION}" -gt "${CURRENT_VERSION}" ]; then if [ "${BOOTLOADER_UPDATE_VERSION}" -gt "${BOOTLOADER_CURRENT_VERSION}" ]; then
echo "*** UPDATE REQUIRED ***" echo "*** UPDATE REQUIRED ***"
printVersions "${CURRENT_VERSION}" "${UPDATE_VERSION}" printVersions
write_status_info EXIT_UPDATE_REQUIRED "${CURRENT_VERSION}" "${UPDATE_VERSION}" write_status_info "${EXIT_UPDATE_REQUIRED}"
exit ${EXIT_UPDATE_REQUIRED} exit ${EXIT_UPDATE_REQUIRED}
else else
echo "Bootloader EEPROM is up to date" echo "Bootloader EEPROM is up to date"
printVersions "${CURRENT_VERSION}" "${UPDATE_VERSION}" printVersions
write_status_info EXIT_SUCCESS "${CURRENT_VERSION}" "${UPDATE_VERSION}" write_status_info "${EXIT_SUCCESS}"
exit ${EXIT_SUCCESS} exit ${EXIT_SUCCESS}
fi fi
} }
@@ -349,40 +468,56 @@ write_status_info()
{ {
[ -z "${MACHINE_OUTPUT}" ] && return 0 [ -z "${MACHINE_OUTPUT}" ] && return 0
exit_code="${1}" exit_code="${1:-EXIT_FAILED}"
cur=${2} bootloader_cur="${BOOTLOADER_CURRENT_VERSION}"
new=${3} bootloader_new="${BOOTLOADER_UPDATE_VERSION}"
vl805_cur="${VL805_CURRENT_VERSION}"
vl805_new="${VL805_UPDATE_VERSION}"
if [ "${JSON_OUTPUT}" = "no" ]; then if [ "${JSON_OUTPUT}" = "no" ]; then
cat > "${MACHINE_OUTPUT}" <<EOF cat > "${MACHINE_OUTPUT}" <<EOF
EXITCODE="${exit_code}" EXITCODE="${exit_code}"
CURRENT_TS=${cur} BOOTLOADER_CURRENT=${bootloader_cur}
LATEST_TS=${new} BOOTLOADER_LATEST=${bootloader_new}
VL805_CURRENT="${vl805_cur}"
VL805_LATEST="${vl805_new}"
EOF EOF
else else
cat > "${MACHINE_OUTPUT}" <<EOF cat > "${MACHINE_OUTPUT}" <<EOF
{ {
"EXITCODE": "${exit_code}", "EXITCODE": ${exit_code},
"CURRENT_TS": ${cur}, "BOOTLOADER_CURRENT": ${bootloader_cur:-0},
"LATEST_TS": ${new} "BOOTLOADER_LATEST": ${bootloader_new:-0},
"VL805_CURRENT": "${vl805_cur}",
"VL805_LATEST": "${vl805_new}"
} }
EOF EOF
fi fi
return 0 return 0
} }
AUTO_UPDATE="" AUTO_UPDATE_BOOTLOADER=0
FILE_UPDATE="" AUTO_UPDATE_VL805=0
MACHINE_OUTPUT="" MACHINE_OUTPUT=""
JSON_OUTPUT="no" JSON_OUTPUT="no"
while getopts adhf:m:j option; do while getopts A:adhf:m:ju: option; do
case "${option}" in case "${option}" in
a) AUTO_UPDATE=1 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 d) OVERWRITE_CONFIG=1
;; ;;
f) FILE_UPDATE="${OPTARG}" f) BOOTLOADER_UPDATE_IMAGE="${OPTARG}"
;; ;;
j) JSON_OUTPUT="yes" j) JSON_OUTPUT="yes"
;; ;;
@@ -390,6 +525,8 @@ while getopts adhf:m:j option; do
;; ;;
h) usage h) usage
;; ;;
u) VL805_UPDATE_IMAGE="${OPTARG}"
;;
*) echo "Unknown argument \"${option}\"" *) echo "Unknown argument \"${option}\""
usage usage
;; ;;
@@ -398,15 +535,15 @@ done
checkDependencies checkDependencies
removePreviousUpdates removePreviousUpdates
if [ -n "${AUTO_UPDATE}" ]; then if [ "${AUTO_UPDATE_BOOTLOADER}" = 1 ] || [ "${AUTO_UPDATE_VL805}" = 1 ]; then
if vcgencmd bootloader_config | grep FREEZE_VERSION=1; then if vcgencmd bootloader_config | grep FREEZE_VERSION=1; then
echo "EEPROM version is frozen. Skipping update" echo "EEPROM version is frozen. Skipping update"
exit ${EXIT_EEPROM_FROZEN} exit ${EXIT_EEPROM_FROZEN}
else else
checkAndApply checkAndApply
fi fi
elif [ -n "${FILE_UPDATE}" ]; then elif [ -n "${BOOTLOADER_UPDATE_IMAGE}" ] || [ -n "${VL805_UPDATE_IMAGE}" ]; then
fileUpdate "${FILE_UPDATE}" fileUpdate
else else
checkVersion checkVersion
fi fi

28
test/bootconf-2024.txt Normal file
View File

@@ -0,0 +1,28 @@
[all]
BOOT_UART=0
WAKE_ON_GPIO=1
POWER_OFF_ON_HALT=0
[none]
userdata0=0x12345789
userdata1=0x12345789
userdata2=0x12345789
userdata3=0x12345789
userdata4=0x12345789
userdata5=0x12345789
userdata6=0x12345789
userdata7=0x12345789
userdata8=0x12345789
userdata9=0x12345789
usercert=ZZZZZZZZZZZZlhEAAAADAQABAAABAQDg2l41l7troIKOA0hk3p9y4KuITWBL/aaTMORoqmXfyqEONNULSMElaLWch/b8ScHmcS+kxkS5DtLmKFo1JI14IaQNL5fr4C6Dp23CyMGIgjp3ZFg9tXs/qWpw36Ge0MCxjabbFeKVcMXD10voMT0AHfJtQb2YfOl37ffzC4bR3phUnp0Ceqpl0Loe6hxUP/r4Jen1OKskdfjsldfjalAjn9ASdkjnkjbaAKjnLKJbaKJHDRDkllDAlciaIKSPX2b0uk2MJRJhfarMHDnmxZtEzqMgwLdLol9XVjiSu/7EUzR9Qtvs8xhf6XuUJPRD6OtJCb49L+bb/pXAej/GOk0f
# 0123456789 0123456789 0123456789 0123456789 0123456789 0123456789 0123456789 0123456789 0123456789 0123456789
# 0123456789 0123456789 0123456789 0123456789 0123456789 0123456789 0123456789 0123456789 0123456789 0123456789
# 0123456789 0123456789 0123456789 0123456789 0123456789 0123456789 0123456789 0123456789 0123456789 0123456789
# 0123456789 0123456789 0123456789 0123456789 0123456789 0123456789 0123456789 0123456789 0123456789 0123456789
# 0123456789 0123456789 0123456789 0123456789 0123456789 0123456789 0123456789 0123456789 0123456789 0123456789
# 0123456789 0123456789 0123456789 0123456789 0123456789 0123456789 0123456789 0123456789 0123456789 0123456789
# 0123456789 0123456789 0123456789 0123456789 0123456789 0123456789 0123456789 0123456789 0123456789 0123456789
# 0123456789 0123456789 0123456789 0123456789 0123456789 0123456789 0123456789 0123456789 0123456789 0123456789
# 0123456789 0123456789 0123456789 0123456789 0123456789 0123456789 0123456789 0123456789 0123456789 0123456789
# 0123456789 0123456789 0123456789 0123456789 0123456789 0123456789 0123456789 0123456789 0123456789 0123456789
# 0123456789 0123456789 0123456789 0123456789 0123456789 0123456789 0123456789 0123456789 0123456789 0123456789
# ++++++++++++++++++++++++++++++++++++++++++++++++

28
test/bootconf-2025.txt Normal file
View File

@@ -0,0 +1,28 @@
[all]
BOOT_UART=0
WAKE_ON_GPIO=1
POWER_OFF_ON_HALT=0
[none]
userdata0=0x12345789
userdata1=0x12345789
userdata2=0x12345789
userdata3=0x12345789
userdata4=0x12345789
userdata5=0x12345789
userdata6=0x12345789
userdata7=0x12345789
userdata8=0x12345789
userdata9=0x12345789
usercert=ZZZZZZZZZZZZlhEAAAADAQABAAABAQDg2l41l7troIKOA0hk3p9y4KuITWBL/aaTMORoqmXfyqEONNULSMElaLWch/b8ScHmcS+kxkS5DtLmKFo1JI14IaQNL5fr4C6Dp23CyMGIgjp3ZFg9tXs/qWpw36Ge0MCxjabbFeKVcMXD10voMT0AHfJtQb2YfOl37ffzC4bR3phUnp0Ceqpl0Loe6hxUP/r4Jen1OKskdfjsldfjalAjn9ASdkjnkjbaAKjnLKJbaKJHDRDkllDAlciaIKSPX2b0uk2MJRJhfarMHDnmxZtEzqMgwLdLol9XVjiSu/7EUzR9Qtvs8xhf6XuUJPRD6OtJCb49L+bb/pXAej/GOk0f
# 0123456789 0123456789 0123456789 0123456789 0123456789 0123456789 0123456789 0123456789 0123456789 0123456789
# 0123456789 0123456789 0123456789 0123456789 0123456789 0123456789 0123456789 0123456789 0123456789 0123456789
# 0123456789 0123456789 0123456789 0123456789 0123456789 0123456789 0123456789 0123456789 0123456789 0123456789
# 0123456789 0123456789 0123456789 0123456789 0123456789 0123456789 0123456789 0123456789 0123456789 0123456789
# 0123456789 0123456789 0123456789 0123456789 0123456789 0123456789 0123456789 0123456789 0123456789 0123456789
# 0123456789 0123456789 0123456789 0123456789 0123456789 0123456789 0123456789 0123456789 0123456789 0123456789
# 0123456789 0123456789 0123456789 0123456789 0123456789 0123456789 0123456789 0123456789 0123456789 0123456789
# 0123456789 0123456789 0123456789 0123456789 0123456789 0123456789 0123456789 0123456789 0123456789 0123456789
# 0123456789 0123456789 0123456789 0123456789 0123456789 0123456789 0123456789 0123456789 0123456789 0123456789
# 0123456789 0123456789 0123456789 0123456789 0123456789 0123456789 0123456789 0123456789 0123456789 0123456789
# 0123456789 0123456789 0123456789 0123456789 0123456789 0123456789 0123456789 0123456789 0123456789 0123456789
# ++++++++++++++++++++++++++++++++++++++++++++++++!

31
test/install Executable file
View File

@@ -0,0 +1,31 @@
#!/bin/sh
# Convenience script for updating the rpi-eeprom updater via a git
# clone instead of apt install.
# For test & debug only.
set -e
script_dir="$(cd "$(dirname "$0")" && pwd)"
die() {
echo "$@" >&2
exit 1
}
FIRMWARE_DIR="${script_dir}/../firmware"
CONFIG="/etc/default/rpi-eeprom-update"
[ "$(id -u)" = "0" ] || die "$0 Must be run as root - try 'sudo $0 [-b]'"
cp -rfv "${FIRMWARE_DIR}"/* /lib/firmware/raspberrypi/bootloader
cp -fv "${script_dir}/../rpi-eeprom-config" /usr/bin
cp -fv "${script_dir}/../rpi-eeprom-update" /usr/bin
cp -fv "${script_dir}/../vl805" /usr/bin
cp -fv "${script_dir}/../rpi-eeprom-update-default" /etc/default/rpi-eeprom-update
if [ "$1" = "-b" ]; then
sed -i -e 's/^FIRMWARE_RELEASE_STATUS=.*/FIRMWARE_RELEASE_STATUS=beta/' "${CONFIG}"
fi

View File

@@ -107,6 +107,40 @@ check_update()
fi fi
} }
# Verify that rpi-eeprom-config will apply and 2024 byte configuration file correctly.
check_conf_size_large()
{
echo "check maximum config file size"
image="${script_dir}/$1"
conf="bootconf-2024.txt"
expected_md5="$(md5sum "${conf}" | awk '{print $1}')"
TMP_EEPROM="$(mktemp)"
"${script_dir}/../rpi-eeprom-config" \
"${image}" \
--config "${conf}" \
--out "${TMP_EEPROM}"
actual_md5="$("${script_dir}/../rpi-eeprom-config" "${TMP_EEPROM}" | md5sum | awk '{print $1}')"
[ "${actual_md5}" = "${expected_md5}" ] || die "EEPROM check large config: checksum mismatch"
}
# Verify that rpi-eeprom-config will reject files exceeding 2024 bytes
check_conf_size_too_large()
{
echo "check config file which exceeds the maximum size"
image="${script_dir}/$1"
conf="bootconf-2025.txt"
expected_md5="$(md5sum "${conf}" | awk '{print $1}')"
TMP_EEPROM="$(mktemp)"
if "${script_dir}/../rpi-eeprom-config" "${image}" --config "${conf}" --out "${TMP_EEPROM}" > /dev/null 2>&1; then
die "$config should have been rejected"
fi
}
check_loopback "../firmware/critical/pieeprom-2019-05-10.bin" "bootconf-2019-05-10.txt" check_loopback "../firmware/critical/pieeprom-2019-05-10.bin" "bootconf-2019-05-10.txt"
cleanup cleanup
@@ -118,3 +152,9 @@ cleanup
check_reduce_size "../firmware/critical/pieeprom-2019-05-10.bin" "bootconf-2019-05-10.txt" check_reduce_size "../firmware/critical/pieeprom-2019-05-10.bin" "bootconf-2019-05-10.txt"
cleanup cleanup
check_conf_size_large "../firmware/critical/pieeprom-2019-05-10.bin"
cleanup
check_conf_size_too_large "../firmware/critical/pieeprom-2019-05-10.bin"
cleanup

BIN
vl805 Executable file

Binary file not shown.