forked from raspberrypi/rpi-eeprom
-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathrpi-eeprom-update
executable file
·791 lines (667 loc) · 26.6 KB
/
rpi-eeprom-update
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
#!/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
LOCAL_MODE=0
if [ -n "$FIRMWARE_ROOT" ]; then
# Provided by environment
true
elif [ -d /lib/firmware/raspberrypi/bootloader ]; then
# Default firmware root exists
FIRMWARE_ROOT=/lib/firmware/raspberrypi/bootloader
else
# Work from local git checkout
LOCAL_MODE=1
FIRMWARE_ROOT="${script_dir}/firmware"
fi
# May be used to select beta or stable 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}
CM4_ENABLE_RPI_EEPROM_UPDATE=${CM4_ENABLE_RPI_EEPROM_UPDATE:-0}
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
BOARD_INFO=
BOARD_REVISION=
BOARD_TYPE=
# 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 the SPI bootloader ignore vl805.bin files on boards
# without a dedicate VL805 EEPROM.
HAVE_VL805_EEPROM=0
# 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
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 [ -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=
}
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)"
NEW_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 [ -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}" "${BOOTLOADER_UPDATE_IMAGE}"
fi
}
applyRecoveryUpdate()
{
[ -n "${BOOTLOADER_UPDATE_IMAGE}" ] || [ -n "${VL805_UPDATE_IMAGE}" ] || die "No update images specified"
findBootFS
echo "BOOTFS ${BOOTFS}"
# A '.sig' file is created so that recovery.bin can check that the
# EEPROM image has not been corrupted (e.g. SD card corruption).
# Format of the .sig file.
# --
# SHA256\n
# ts: UPDATE-TIMESTAMP\n
# --
# SHA256 is a 64 character hex string
# UPDATE-TIMESTAMP is an unsigned decimal.
#
# The 'filename' output from sha256 MUST be omitted.
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"
# Appends the update creation timestamp on a newline in pieeprom.sig
# During a self-update mode the bootloader examines the update-timestamp
# and will only update itself if it is newer than the current update
# timestamp.
#
# The update-timestamp is independent of the bootloader version and
# does not have to be timestamp.
echo "ts: $(date -u +%s)" >> "${BOOTFS}/pieeprom.sig"
cp -f "${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
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" \
|| 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
cp -f "${RECOVERY_BIN}" "${BOOTFS}/recovery.bin" \
|| die "Failed to copy ${RECOVERY_BIN} to ${BOOTFS}"
}
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
if [ "${USE_FLASHROM}" = 0 ]; then
applyRecoveryUpdate
return
fi
if [ -f "${BOOTLOADER_UPDATE_IMAGE}" ]; then
echo "WARNING: USE_FLASHROM is deprecated."
# 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 bootloader 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 [ -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)"
else
BOARD_INFO="$(vcgencmd otp_dump | grep '30:' | sed 's/.*://')"
fi
if [ $(((0x$BOARD_INFO >> 23) & 1)) -ne 0 ] && [ $(((0x$BOARD_INFO >> 12) & 15)) -eq 3 ]; then
echo "BCM2711 detected"
else
# Not a BCM2711, no EEPROMs to update.
exit ${EXIT_SUCCESS}
fi
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"
exit ${EXIT_SUCCESS}
fi
if [ ${BOARD_TYPE} -eq 17 ] && [ ${BOARD_REVISION} -lt 4 ]; then
echo "Dedicated VL805 EEPROM detected"
HAVE_VL805_EEPROM=1
else
echo "VL805 firmware in bootloader EEPROM"
HAVE_VL805_EEPROM=0
fi
if ! command -v vcgencmd > /dev/null; then
die "vcgencmd not found. On Debian, try installing the libraspberrypi-bin package."
fi
if [ ! -d "${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 [ -d "${FIRMWARE_IMAGE_DIR}-${BOARD_INFO}" ]; then
FIRMWARE_IMAGE_DIR="${FIRMWARE_IMAGE_DIR}-${BOARD_INFO}"
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]
Bootloader EEPROM update tool for the Raspberry Pi 4.
Checks whether the Raspberry Pi 4 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.
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 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.
A backup of the current EEPROM config file is written to ${FIRMWARE_BACKUP_DIR}
before applying the update.
Unless the -d flag is specified, the current bootloader configuration is
retained.
Options:
-a Automatically install bootloader and USB (VLI) EEPROM updates.
-A Specify which type of EEPROM to automatically update (vl805 or bootloader)
-b Outputs the path that pending EEPROM updates will be written to.
-d Use the default bootloader config, or if a file is specified using the -f
flag use the config in that file. This option only applies when a
bootloader EEPROM update is needed; if the bootloader EEPROM is up-to-date
then its config will not be changed.
-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.
-h Display help text and exit
-i Ignore package checksums - for rpi-eeprom developers.
-j Write status information using JSON notation
-l Returns the full path to the latest available EEPROM image file according
to the FIRMWARE_RELEASE_STATUS and FIRMWARE_IMAGE_DIR settings.
-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.
Environment:
Environment variables should be defined in /etc/default/rpi-eeprom-update
EEPROM_CONFIG_HOOK
Specifies the path of an optional script which post-processes the
configuration file before it is applied to the new image. The modified
output must contain at least 3 lines and should contain WAKE_ON_GPIO
and POWER_OFF_ON_HALT settings.
USE_FLASHROM
USE_FLASHROM is deprecated and there is no support for this. The muxing
of the SPI pins causes too many issues for this to ever be reliable.
The flashrom update mechanism may be enabled by setting USE_FLASHROM=1. This
also selects the vl805 tool instead of using recovery.bin to perform the
update. This may be desirable if an immediate update is required or if an
SD card is not present.
However, 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.
Changing the VL805 firmware whilst USB devices are attached may also cause
those devices to stop working until after the system is reboot.
FIRMWARE_RELEASE_STATUS
Specifies the release status of the firmware to apply. The default is 'critical'.
Before selecting a firmware release directory this script checks whether there
is a board revision specific variant e.g. critical-c03111. If present then the
board-revision specific version is used in preference.
Release status:
critical: The latest production release plus important security or hardware compatibility bug fixes.
stable: Contains new features that have already undergone some beta testing.
These are candidates for new production releases.
beta: New features, bug fixes for development/test purposes. Use at your own
risk!
As far as rpi-eeprom-update is concerned FIRMWARE_RELEASE_STATUS is just
the subdirectory mapping under ${FIRMWARE_ROOT}. Therefore, custom release
directories are supported by creating the relevant directory and changing
the FIRMWARE_RELEASE_STATUS environment variable.
Examples:
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 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 available"
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})"
echo " FW DIR: ${FIRMWARE_IMAGE_DIR}"
if [ "${ACTION_UPDATE_VL805}" = 1 ]; then
echo "VL805: update available"
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"
if [ "$(find "${BOOTFS}/" -name "*.elf" | wc -l)" = 0 ]; then
echo "WARNING: BOOTFS: \"${BOOTFS}\" contains no .elf files. Please check boot directory"
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 [ "$(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 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
if [ "${BOOTLOADER_UPDATE_VERSION}" -gt "${BOOTLOADER_CURRENT_VERSION}" ]; then
ACTION_UPDATE_BOOTLOADER=1
else
BOOTLOADER_UPDATE_IMAGE=""
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 "*** 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 -follow -iname "recovery.*" -regex '.*\.[0-9][0-9][0-9]$' -exec rm -f {} \;
) || die "Failed to remove previous update files"
fi
}
checkVersion()
{
lookupVersionInfo
if [ "${BOOTLOADER_UPDATE_VERSION}" -gt "${BOOTLOADER_CURRENT_VERSION}" ]; then
echo "*** UPDATE AVAILABLE ***"
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
[ "${HAVE_VL805_EEPROM}" = "0" ] && vl805_eeprom="no" || vl805_eeprom="yes"
cat > "${MACHINE_OUTPUT}" <<EOF
EXITCODE="${exit_code}"
BOOTLOADER_CURRENT=${bootloader_cur}
BOOTLOADER_LATEST=${bootloader_new}
VL805_CURRENT="${vl805_cur}"
VL805_LATEST="${vl805_new}"
VL805_EEPROM="${vl805_eeprom}"
EOF
else
[ "${HAVE_VL805_EEPROM}" = "0" ] && vl805_eeprom="false" || vl805_eeprom="true"
cat > "${MACHINE_OUTPUT}" <<EOF
{
"EXITCODE": "${exit_code}",
"BOOTLOADER_CURRENT": ${bootloader_cur},
"BOOTLOADER_LATEST": ${bootloader_new},
"VL805_CURRENT": "${vl805_cur}",
"VL805_LATEST": "${vl805_new}",
"VL805_EEPROM": ${vl805_eeprom}
}
EOF
fi
return 0
}
AUTO_UPDATE_BOOTLOADER=0
AUTO_UPDATE_VL805=0
MACHINE_OUTPUT=""
JSON_OUTPUT="no"
IGNORE_DPKG_CHECKSUMS=${LOCAL_MODE}
PACKAGE_INFO_DIR="/var/lib/dpkg/info/"
if [ ! -d "${PACKAGE_INFO_DIR}" ]; then
IGNORE_DPKG_CHECKSUMS=1
fi
while getopts A:abdhilf: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
;;
b)
findBootFS
echo "${BOOTFS}"
exit 0
;;
d) OVERWRITE_CONFIG=1
;;
f) BOOTLOADER_UPDATE_IMAGE="${OPTARG}"
;;
i) IGNORE_DPKG_CHECKSUMS=1
;;
j) JSON_OUTPUT="yes"
;;
l)
getBootloaderUpdateVersion
echo "${BOOTLOADER_UPDATE_IMAGE}"
exit 0
;;
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