@@ -89,6 +89,9 @@ cleanup() {
8989 if [ -f " ${NEW_EEPROM_CONFIG} " ]; then
9090 rm -f " ${NEW_EEPROM_CONFIG} "
9191 fi
92+ if [ -f " ${FLASHROM_LOG} " ]; then
93+ rm -f " ${FLASHROM_LOG} "
94+ fi
9295 if [ -d " ${TMP_BOOTFS_MNT} " ]; then
9396 umount " ${TMP_BOOTFS_MNT} "
9497 rmdir " ${TMP_BOOTFS_MNT} "
@@ -97,6 +100,7 @@ cleanup() {
97100 TMP_EEPROM_IMAGE=
98101 TMP_EEPROM_CONFIG=
99102 NEW_EEPROM_CONFIG=
103+ FLASHROM_LOG=
100104}
101105trap cleanup EXIT
102106
@@ -169,7 +173,14 @@ prepareImage()
169173 if [ " ${OVERWRITE_CONFIG} " = 0 ]; then
170174 " ${script_dir} /rpi-eeprom-config" \
171175 --out " ${TMP_EEPROM_IMAGE} " \
172- --config " ${NEW_EEPROM_CONFIG} " " ${BOOTLOADER_UPDATE_IMAGE} "
176+ --config " ${NEW_EEPROM_CONFIG} " \
177+ --timestamp " $( date -u +%s) " \
178+ " ${BOOTLOADER_UPDATE_IMAGE} "
179+ else
180+ " ${script_dir} /rpi-eeprom-config" \
181+ --out " ${TMP_EEPROM_IMAGE} " \
182+ --timestamp " $( date -u +%s) " \
183+ " ${BOOTLOADER_UPDATE_IMAGE} "
173184 fi
174185}
175186
@@ -200,7 +211,7 @@ applyRecoveryUpdate()
200211 # and the current timestamp.
201212 rpi-eeprom-digest -i " ${TMP_EEPROM_IMAGE} " -o " ${BOOTFS} /pieeprom.sig"
202213
203- cp -f " ${TMP_EEPROM_IMAGE} " " ${BOOTFS} /pieeprom.upd" \
214+ cp -fv " ${TMP_EEPROM_IMAGE} " " ${BOOTFS} /pieeprom.upd" \
204215 || die " Failed to copy ${TMP_EEPROM_IMAGE} to ${BOOTFS} "
205216
206217 # For NFS mounts ensure that the files are readable to the TFTP user
@@ -225,7 +236,7 @@ applyRecoveryUpdate()
225236 RPI_EEPROM_SELF_UPDATE=0
226237 fi
227238
228- # Setting bootlaoder_update =0 was really intended for use with network-boot with shared
239+ # Setting bootloader_update =0 was really intended for use with network-boot with shared
229240 # config.txt files. However, if it looks as though self-update has been disabled then
230241 # assume recovery.bin is required.
231242 config_txt=" ${BOOTFS} /config.txt"
@@ -237,8 +248,33 @@ applyRecoveryUpdate()
237248
238249 [ " ${BOOTLOADER_CURRENT_VERSION} " -ge " ${RPI_EEPROM_SELF_UPDATE_MIN_VER} " ] || RPI_EEPROM_SELF_UPDATE=0
239250
240- if [ " ${RPI_EEPROM_SELF_UPDATE} " != " 1" ]; then
241- echo " Using recovery.bin for EEPROM update"
251+ # For immediate updates via flash the recovery.bin update is created and then discarded if the
252+ # flashrom update was successful. For SD boot (most common) this provides a rollback in the event
253+ # of power loss.
254+ if [ " ${RPI_EEPROM_USE_FLASHROM} " = 1 ]; then
255+ echo
256+ echo " UPDATING bootloader."
257+ echo
258+ echo " *** WARNING: Do not disconnect the power until the update is complete ***"
259+ echo " If a problem occurs then the Raspberry Pi Imager may be used to create"
260+ echo " a bootloader rescue SD card image which restores the default bootloader image."
261+ echo
262+ FLASHROM_LOG=" $( mktemp) "
263+ echo " flashrom -p linux_spi:dev=${SPIDEV} ,spispeed=16000 -w ${BOOTFS} /pieeprom.upd"
264+ if flashrom -p linux_spi:dev=${SPIDEV} ,spispeed=16000 -w " ${BOOTFS} /pieeprom.upd" > " ${FLASHROM_LOG} " ; then
265+ # Success - remove update files from the boot partition
266+ removePreviousUpdates
267+ echo " UPDATE SUCCESSFUL"
268+ else
269+ # Leave the recovery files in case the EEPROM has been partially updated
270+ cat " ${FLASHROM_LOG} "
271+ die " UPDATE FAILED"
272+ fi
273+ return
274+ elif [ " ${RPI_EEPROM_SELF_UPDATE} " = " 1" ]; then
275+ echo " Using self-update"
276+ else
277+ echo " Copying recovery.bin to ${BOOTFS} for EEPROM update"
242278 cp -f " ${RECOVERY_BIN} " " ${BOOTFS} /recovery.bin" || die " Failed to copy ${RECOVERY_BIN} to ${BOOTFS} "
243279 fi
244280
@@ -269,6 +305,25 @@ applyUpdate() {
269305 ) || die " Unable to validate EEPROM image package checksums"
270306 fi
271307
308+ # Disable flashrom if the SPI device is not found
309+ if [ " ${RPI_EEPROM_USE_FLASHROM} " = 1 ]; then
310+ flashrom_probe_ok=0
311+ if ! [ -e " ${SPIDEV} " ]; then
312+ echo " WARNING: SPI device ${SPIDEV} not found. Setting RPI_EEPROM_USE_FLASHROM to 0"
313+ fi
314+
315+ if ! flashrom -p linux_spi:dev=${SPIDEV} ,spispeed=16000 > /dev/null 2>&1 ; then
316+ echo " WARNING: Flashrom probe of ${SPIDEV} failed"
317+ else
318+ flashrom_probe_ok=1
319+ fi
320+ if [ " ${flashrom_probe_ok} " != 1 ]; then
321+ echo " Setting RPI_EEPROM_USE_FLASHROM to 0"
322+ echo
323+ export RPI_EEPROM_USE_FLASHROM=0
324+ fi
325+ fi
326+
272327 applyRecoveryUpdate
273328}
274329
@@ -334,14 +389,21 @@ checkDependencies() {
334389 BCM_CHIP=2711
335390 EEPROM_SIZE=524288
336391 BOOTLOADER_AUTO_UPDATE_MIN_VERSION=" ${BOOTLOADER_AUTO_UPDATE_MIN_VERSION:- 1599135103} "
392+
393+ SPIDEV=/dev/spidev0.0
337394 elif [ $(( (0 x$BOARD_INFO >> 12 ) & 15 )) = 4 ]; then
338395 BCM_CHIP=2712
339396 EEPROM_SIZE=2097152
340397 BOOTLOADER_AUTO_UPDATE_MIN_VERSION=" ${BOOTLOADER_AUTO_UPDATE_MIN_VERSION:- 1697650217} "
398+ SPIDEV=/dev/spidev10.0
341399 else
342400 chipNotSupported
343401 fi
344402
403+ # Default to off - in the future Raspberry Pi 5 may default to using flashrom if
404+ # flashrom is available.
405+ [ -z " ${RPI_EEPROM_USE_FLASHROM} " ] && RPI_EEPROM_USE_FLASHROM=0
406+
345407 FIRMWARE_IMAGE_DIR=" ${FIRMWARE_ROOT} -${BCM_CHIP} /${FIRMWARE_RELEASE_STATUS} "
346408 if ! [ -d " ${FIRMWARE_IMAGE_DIR} " ]; then
347409 # Use unadorned name for backwards compatiblity
@@ -358,6 +420,18 @@ checkDependencies() {
358420 echo " The recommended method for flashing the EEPROM is rpiboot."
359421 echo " See: https://github.com/raspberrypi/usbboot/blob/master/Readme.md"
360422 echo " Run with -h for more information."
423+ echo
424+ echo " To enable flashrom programming of the EEPROM"
425+ echo " Add these the following entries to /etc/default/rpi-eeprom-update"
426+ echo " RPI_EEPROM_USE_FLASHROM=1"
427+ echo " CM4_ENABLE_RPI_EEPROM_UPDATE=1"
428+ echo
429+ echo " and these entries to config.txt and reboot"
430+ echo " [cm4]"
431+ echo " dtparam=spi=on"
432+ echo " dtoverlay=audremap"
433+ echo " dtoverlay=spi-gpio40-45"
434+ echo
361435 exit ${EXIT_SUCCESS}
362436 fi
363437
@@ -404,6 +478,10 @@ checkDependencies() {
404478 if [ " ${BCM_CHIP} " = 2711 ] && [ ! -f " ${RECOVERY_BIN} " ]; then
405479 die " ${RECOVERY_BIN} not found."
406480 fi
481+
482+ if ! command -v flashrom > /dev/null; then
483+ RPI_EEPROM_USE_FLASHROM=0
484+ fi
407485}
408486
409487usage () {
@@ -542,6 +620,22 @@ N.B. If there is a power failure during SELF_UPDATE the EEPROM write may fail an
542620usbboot must be used to flash the bootloader EEPROM. SELF_UPDATE is not recommended
543621for updating the bootloader on remote systems.
544622
623+ FLASHROM:
624+
625+ If the RPI_EEPROM_USE_FLASHROM variable is set to 1 then flashrom is used to perform
626+ an immediate update to the SPI flash rather than installing the recovery.bin plus
627+ pieeprom.upd files. The power must not be disconnected during this update otherwise the
628+ EEPROM will need to be re-flashed using the Rasberry Pi Imager bootloader restore feature.
629+
630+ On Raspberry Pi 4, CM4, CM4-S and Pi400 flashrom updates are not enabled by default
631+ because the SPI GPIOs are shared with analog audio. To enable this add the following
632+ entries to config.txt. This moves analog audio to GPIO pins 12,13 and may not be
633+ compatible with some HATS / CM4 IO boards.
634+
635+ dtparam=spi=on
636+ dtoverlay=audremap
637+ dtoverlay=spi-gpio40-45
638+
545639EOF
546640 exit ${EXIT_SUCCESS}
547641}
@@ -595,7 +689,9 @@ findBootFS()
595689 elif [ -z " $BOOTFS " ]; then
596690 if ! BOOTFS=$( /usr/lib/raspberrypi-sys-mods/get_fw_loc 2> /dev/null) ; then
597691 for BOOTFS in /boot/firmware /boot; do
598- if findmnt --fstab " $BOOTFS " > /dev/null; then
692+ if [ -f " ${BOOTFS} /config.txt" ]; then
693+ break
694+ elif findmnt --fstab " $BOOTFS " > /dev/null; then
599695 break
600696 fi
601697 done
@@ -714,7 +810,7 @@ checkAndApply()
714810 fi
715811
716812 if [ " ${ACTION_UPDATE_BOOTLOADER} " = 1 ] || [ " ${ACTION_UPDATE_VL805} " = 1 ]; then
717- echo " *** INSTALLING EEPROM UPDATES ***"
813+ echo " *** PREPARING EEPROM UPDATES ***"
718814 echo " "
719815
720816 printVersions
@@ -727,7 +823,7 @@ checkAndApply()
727823fileUpdate ()
728824{
729825 removePreviousUpdates
730- echo " *** INSTALLING ${BOOTLOADER_UPDATE_IMAGE} ${VL805_UPDATE_IMAGE} ***"
826+ echo " *** CREATED UPDATE ${BOOTLOADER_UPDATE_IMAGE} ${VL805_UPDATE_IMAGE} ***"
731827 echo
732828
733829 if [ -n " ${BOOTLOADER_UPDATE_IMAGE} " ]; then
0 commit comments