diff --git a/firmware-2712/default/pieeprom-2023-11-20.bin b/firmware-2712/default/pieeprom-2023-11-20.bin new file mode 100644 index 0000000..6959ff5 Binary files /dev/null and b/firmware-2712/default/pieeprom-2023-11-20.bin differ diff --git a/firmware-2712/latest/pieeprom-2023-11-20.bin b/firmware-2712/latest/pieeprom-2023-11-20.bin new file mode 100644 index 0000000..6959ff5 Binary files /dev/null and b/firmware-2712/latest/pieeprom-2023-11-20.bin differ diff --git a/firmware-2712/release-notes.md b/firmware-2712/release-notes.md index 5c3c742..db57e74 100644 --- a/firmware-2712/release-notes.md +++ b/firmware-2712/release-notes.md @@ -1,5 +1,16 @@ # Raspberry Pi5 bootloader EEPROM release notes +2023-11-20: Auto-detect support for PCIe expansion HAT (default + latest) + +* Add autodetect support for PCIe expansion HATs +* Add PCIE_PROBE=1 to the EEPROM config for custom PCIe exapansion + designs that do not support the upcoming HAT spec. This gives + similar behaviour to CM4 where PCIe x1 is enumerated to discover NVMe + devices. +* Fix loading of multiple initramfs images that are not 32-bit aligned sizes + https://github.com/raspberrypi/firmware/issues/1843 +* Kernel load performance improvement - remove a memcpy + 2023-10-30: UPG watchdog support + SD reset fixes (default + latest) * Fix SDIO / WiFi clock-setup for BOOT_ORDER=0xf14 diff --git a/rpi-eeprom-config b/rpi-eeprom-config index ccfc538..9c4f5f5 100755 --- a/rpi-eeprom-config +++ b/rpi-eeprom-config @@ -109,7 +109,7 @@ def exit_error(msg): sys.stderr.write("ERROR: %s\n" % msg) sys.exit(1) -def shell_cmd(args): +def shell_cmd(args, timeout=5, echo=False): """ Executes a shell command waits for completion returning STDOUT. If an error occurs then exit and output the subprocess stdout, stderr messages @@ -117,9 +117,14 @@ def shell_cmd(args): """ start = time.time() arg_str = ' '.join(args) - result = subprocess.Popen(args, stdout=subprocess.PIPE, stderr=subprocess.PIPE) + bufsize = 0 if echo else -1 + result = subprocess.Popen(args, bufsize=bufsize, stdout=subprocess.PIPE, stderr=subprocess.PIPE) - while time.time() - start < 5: + while time.time() - start < timeout: + if echo: + s = result.stdout.read(80).decode('utf-8') + if s != "": + sys.stdout.write(s) if result.poll() is not None: break @@ -128,8 +133,8 @@ def shell_cmd(args): if result.returncode != 0: exit_error("%s failed: %d\n %s\n %s\n" % - (arg_str, result.returncode, result.stdout.read(), result.stderr.read())) - else: + (arg_str, result.returncode, result.stdout.read().decode('utf-8'), result.stderr.read().decode('utf-8'))) + elif not echo: return result.stdout.read().decode('utf-8') def get_latest_eeprom(): @@ -170,8 +175,10 @@ def apply_update(config, eeprom=None, config_src=None): # with EEPROMs with configs delivered outside of APT. # The checksums are really just a safety check for automatic updates. args = ['rpi-eeprom-update', '-d', '-i', '-f', tmp_update] - resp = shell_cmd(args) - sys.stdout.write(resp) + + # If flashrom is used then the command will not return until the EEPROM + # has been updated so use a larger timeout. + shell_cmd(args, timeout=20, echo=True) def edit_config(eeprom=None): """ @@ -377,6 +384,15 @@ class BootloaderImage(object): % (src_filename, len(src_bytes), MAX_FILE_SIZE)) self.update(src_bytes, dst_filename) + def set_timestamp(self, timestamp): + """ + Sets the self-update timestamp in an EEPROM image file. This is useful when + using flashrom to write to SPI flash instead of using the bootloader self-update mode. + """ + ts = int(timestamp) + struct.pack_into(' "${FLASHROM_LOG}"; 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 @@ -269,6 +305,25 @@ applyUpdate() { ) || 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 + echo "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 + echo "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 } @@ -334,14 +389,21 @@ checkDependencies() { BCM_CHIP=2711 EEPROM_SIZE=524288 BOOTLOADER_AUTO_UPDATE_MIN_VERSION="${BOOTLOADER_AUTO_UPDATE_MIN_VERSION:-1599135103}" + + 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:-1697650217}" + SPIDEV=/dev/spidev10.0 else chipNotSupported fi + # Default to off - in the future Raspberry Pi 5 may default to using flashrom if + # flashrom is available. + [ -z "${RPI_EEPROM_USE_FLASHROM}" ] && RPI_EEPROM_USE_FLASHROM=0 + FIRMWARE_IMAGE_DIR="${FIRMWARE_ROOT}-${BCM_CHIP}/${FIRMWARE_RELEASE_STATUS}" if ! [ -d "${FIRMWARE_IMAGE_DIR}" ]; then # Use unadorned name for backwards compatiblity @@ -358,6 +420,18 @@ checkDependencies() { 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 @@ -404,6 +478,10 @@ checkDependencies() { if [ "${BCM_CHIP}" = 2711 ] && [ ! -f "${RECOVERY_BIN}" ]; then die "${RECOVERY_BIN} not found." fi + + if ! command -v flashrom > /dev/null; then + RPI_EEPROM_USE_FLASHROM=0 + fi } usage() { @@ -542,6 +620,22 @@ N.B. If there is a power failure during SELF_UPDATE the EEPROM write may fail an usbboot must be used to flash the bootloader EEPROM. SELF_UPDATE is not recommended for updating the bootloader on remote systems. +FLASHROM: + +If the RPI_EEPROM_USE_FLASHROM variable is set to 1 then flashrom is used to perform +an immediate update to the SPI flash rather than installing the recovery.bin plus +pieeprom.upd files. The power must not be disconnected during this update otherwise the +EEPROM will need to be re-flashed using the Rasberry Pi Imager bootloader restore feature. + +On Raspberry Pi 4, CM4, CM4-S and Pi400 flashrom updates are not enabled by default +because the SPI GPIOs are shared with analog audio. To enable this add the following +entries to config.txt. This moves analog audio to GPIO pins 12,13 and may not be +compatible with some HATS / CM4 IO boards. + +dtparam=spi=on +dtoverlay=audremap +dtoverlay=spi-gpio40-45 + EOF exit ${EXIT_SUCCESS} } @@ -595,7 +689,9 @@ findBootFS() elif [ -z "$BOOTFS" ]; then if ! BOOTFS=$(/usr/lib/raspberrypi-sys-mods/get_fw_loc 2> /dev/null); then for BOOTFS in /boot/firmware /boot; do - if findmnt --fstab "$BOOTFS" > /dev/null; then + if [ -f "${BOOTFS}/config.txt" ]; then + break + elif findmnt --fstab "$BOOTFS" > /dev/null; then break fi done @@ -714,7 +810,7 @@ checkAndApply() fi if [ "${ACTION_UPDATE_BOOTLOADER}" = 1 ] || [ "${ACTION_UPDATE_VL805}" = 1 ]; then - echo "*** INSTALLING EEPROM UPDATES ***" + echo "*** PREPARING EEPROM UPDATES ***" echo "" printVersions @@ -727,7 +823,7 @@ checkAndApply() fileUpdate() { removePreviousUpdates - echo "*** INSTALLING ${BOOTLOADER_UPDATE_IMAGE} ${VL805_UPDATE_IMAGE} ***" + echo "*** CREATED UPDATE ${BOOTLOADER_UPDATE_IMAGE} ${VL805_UPDATE_IMAGE} ***" echo if [ -n "${BOOTLOADER_UPDATE_IMAGE}" ]; then diff --git a/rpi-eeprom-update-default b/rpi-eeprom-update-default index ef02791..a31d288 100644 --- a/rpi-eeprom-update-default +++ b/rpi-eeprom-update-default @@ -2,8 +2,10 @@ FIRMWARE_ROOT=/lib/firmware/raspberrypi/bootloader FIRMWARE_RELEASE_STATUS="default" FIRMWARE_BACKUP_DIR="/var/lib/raspberrypi/bootloader/backup" -USE_FLASHROM=0 EEPROM_CONFIG_HOOK= # BOOTFS can be set here to override auto-detection in rpi-eeprom-update #BOOTFS=/boot + +# Use flashrom if available to update the bootloader without rebooting - Raspberry Pi 5 +#RPI_EEPROM_USE_FLASHROM=1