mirror of
https://github.com/raspberrypi/rpi-eeprom.git
synced 2026-01-21 06:13:33 +08:00
Merge branch 'master' into debian/buster
This commit is contained in:
@@ -1,12 +1,17 @@
|
|||||||
#!/usr/bin/env python
|
#!/usr/bin/env python
|
||||||
|
|
||||||
# rpi-eeprom-config
|
"""
|
||||||
# Utility for reading and writing the configuration file in the
|
rpi-eeprom-config
|
||||||
# Raspberry Pi 4 bootloader EEPROM image.
|
"""
|
||||||
|
|
||||||
import argparse
|
import argparse
|
||||||
|
import atexit
|
||||||
|
import os
|
||||||
|
import subprocess
|
||||||
import struct
|
import struct
|
||||||
import sys
|
import sys
|
||||||
|
import tempfile
|
||||||
|
import time
|
||||||
|
|
||||||
IMAGE_SIZE = 512 * 1024
|
IMAGE_SIZE = 512 * 1024
|
||||||
|
|
||||||
@@ -22,18 +27,160 @@ MAGIC_MASK = 0xfffff00f
|
|||||||
FILE_MAGIC = 0x55aaf11f # id for modifiable file, currently only bootconf.txt
|
FILE_MAGIC = 0x55aaf11f # id for modifiable file, currently only bootconf.txt
|
||||||
FILE_HDR_LEN = 20
|
FILE_HDR_LEN = 20
|
||||||
FILENAME_LEN = 12
|
FILENAME_LEN = 12
|
||||||
|
TEMP_DIR = None
|
||||||
|
|
||||||
|
def exit_handler():
|
||||||
|
"""
|
||||||
|
Delete any temporary files.
|
||||||
|
"""
|
||||||
|
if TEMP_DIR is not None and os.path.exists(TEMP_DIR):
|
||||||
|
tmp_image = os.path.join(TEMP_DIR, 'pieeprom.upd')
|
||||||
|
if os.path.exists(tmp_image):
|
||||||
|
os.remove(tmp_image)
|
||||||
|
tmp_conf = os.path.join(TEMP_DIR, 'boot.conf')
|
||||||
|
if os.path.exists(tmp_conf):
|
||||||
|
os.remove(tmp_conf)
|
||||||
|
os.rmdir(TEMP_DIR)
|
||||||
|
|
||||||
|
def create_tempdir():
|
||||||
|
global TEMP_DIR
|
||||||
|
if TEMP_DIR is None:
|
||||||
|
TEMP_DIR = tempfile.mkdtemp()
|
||||||
|
|
||||||
|
def exit_error(msg):
|
||||||
|
"""
|
||||||
|
Trapped a fatal arror, output message to stderr and exit with non-zero
|
||||||
|
return code.
|
||||||
|
"""
|
||||||
|
sys.stderr.write("ERROR: %s\n" % msg)
|
||||||
|
sys.exit(1)
|
||||||
|
|
||||||
|
def shell_cmd(args):
|
||||||
|
"""
|
||||||
|
Executes a shell command waits for completion returning STDOUT. If an
|
||||||
|
error occurs then exit and output the subprocess stdout, stderr messages
|
||||||
|
for debug.
|
||||||
|
"""
|
||||||
|
start = time.time()
|
||||||
|
arg_str = ' '.join(args)
|
||||||
|
result = subprocess.Popen(args, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
|
||||||
|
|
||||||
|
while time.time() - start < 5:
|
||||||
|
if result.poll() is not None:
|
||||||
|
break
|
||||||
|
|
||||||
|
if result.poll() is None:
|
||||||
|
exit_error("%s timeout" % arg_str)
|
||||||
|
|
||||||
|
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:
|
||||||
|
return result.stdout.read()
|
||||||
|
|
||||||
|
def get_latest_eeprom():
|
||||||
|
"""
|
||||||
|
Returns the path of the latest EEPROM image file if it exists.
|
||||||
|
"""
|
||||||
|
latest = shell_cmd(['rpi-eeprom-update', '-l']).rstrip()
|
||||||
|
if not os.path.exists(latest):
|
||||||
|
exit_error("EEPROM image '%s' not found" % latest)
|
||||||
|
return latest
|
||||||
|
|
||||||
|
def apply_update(config, eeprom=None, config_src=None):
|
||||||
|
"""
|
||||||
|
Applies the config file to the latest available EEPROM image and spawns
|
||||||
|
rpi-eeprom-update to schedule the update at the next reboot.
|
||||||
|
"""
|
||||||
|
if eeprom is not None:
|
||||||
|
eeprom_image = eeprom
|
||||||
|
else:
|
||||||
|
eeprom_image = get_latest_eeprom()
|
||||||
|
create_tempdir()
|
||||||
|
tmp_update = os.path.join(TEMP_DIR, 'pieeprom.upd')
|
||||||
|
image = BootloaderImage(eeprom_image, tmp_update)
|
||||||
|
image.write(config)
|
||||||
|
config_str = open(config).read()
|
||||||
|
if config_src is None:
|
||||||
|
config_src = ''
|
||||||
|
sys.stdout.write("Updating bootloader EEPROM\n image: %s\nconfig_src: %s\nconfig: %s\n%s\n" %
|
||||||
|
(eeprom_image, config_src, config, config_str))
|
||||||
|
|
||||||
|
# Ignore APT package checksums so that this doesn't fail when used
|
||||||
|
# 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)
|
||||||
|
|
||||||
|
def edit_config(eeprom=None):
|
||||||
|
"""
|
||||||
|
Implements something like visudo for editing EEPROM configs.
|
||||||
|
"""
|
||||||
|
# Default to nano if $EDITOR is not defined.
|
||||||
|
editor = 'nano'
|
||||||
|
if 'EDITOR' in os.environ:
|
||||||
|
editor = os.environ['EDITOR']
|
||||||
|
|
||||||
|
config_src = ''
|
||||||
|
if eeprom is None:
|
||||||
|
# If an EEPROM has not been specified but there is a pending
|
||||||
|
# update then use that as the current EEPROM image.
|
||||||
|
bootfs = shell_cmd(['rpi-eeprom-update', '-b']).rstrip()
|
||||||
|
pending = os.path.join(bootfs, 'pieeprom.upd')
|
||||||
|
if os.path.exists(pending):
|
||||||
|
config_src = pending
|
||||||
|
image = BootloaderImage(pending)
|
||||||
|
current_config = image.get_config()
|
||||||
|
else:
|
||||||
|
config_src = 'vcgencmd bootloader_config'
|
||||||
|
current_config = read_current_config()
|
||||||
|
else:
|
||||||
|
# If an EEPROM image is specified OR there is pending update
|
||||||
|
# then get the current config from there.
|
||||||
|
image = BootloaderImage(eeprom)
|
||||||
|
config_src = eeprom
|
||||||
|
current_config = image.get_config()
|
||||||
|
|
||||||
|
create_tempdir()
|
||||||
|
tmp_conf = os.path.join(TEMP_DIR, 'boot.conf')
|
||||||
|
out = open(tmp_conf, 'w')
|
||||||
|
out.write(current_config)
|
||||||
|
out.close()
|
||||||
|
cmd = "\'%s\' \'%s\'" % (editor, tmp_conf)
|
||||||
|
result = os.system(cmd)
|
||||||
|
if result != 0:
|
||||||
|
exit_error("Aborting update because \'%s\' exited with code %d." % (cmd, result))
|
||||||
|
|
||||||
|
new_config = open(tmp_conf, 'r').read()
|
||||||
|
if len(new_config.splitlines()) < 2:
|
||||||
|
exit_error("Aborting update because \'%s\' appears to be empty." % tmp_conf)
|
||||||
|
apply_update(tmp_conf, eeprom, config_src)
|
||||||
|
|
||||||
|
def read_current_config():
|
||||||
|
"""
|
||||||
|
Reads the configuration used by the current bootloader.
|
||||||
|
"""
|
||||||
|
return shell_cmd(['vcgencmd', 'bootloader_config'])
|
||||||
|
|
||||||
class BootloaderImage(object):
|
class BootloaderImage(object):
|
||||||
def __init__(self, filename, output):
|
def __init__(self, filename, output=None):
|
||||||
|
"""
|
||||||
|
Instantiates a Bootloader image writer with a source eeprom (filename)
|
||||||
|
and optionally an output filename.
|
||||||
|
"""
|
||||||
self._filename = filename
|
self._filename = filename
|
||||||
self._bytes = bytearray(open(filename, 'rb').read())
|
try:
|
||||||
|
self._bytes = bytearray(open(filename, 'rb').read())
|
||||||
|
except IOError as err:
|
||||||
|
exit_error("Failed to read \'%s\'\n%s\n" % (filename, str(err)))
|
||||||
self._out = None
|
self._out = None
|
||||||
if output is not None:
|
if output is not None:
|
||||||
self._out = open(output, 'wb')
|
self._out = open(output, 'wb')
|
||||||
|
|
||||||
if len(self._bytes) != IMAGE_SIZE:
|
if len(self._bytes) != IMAGE_SIZE:
|
||||||
raise Exception("%s: Expected size %d bytes actual size %d bytes" %
|
exit_error("%s: Expected size %d bytes actual size %d bytes" %
|
||||||
(filename, IMAGE_SIZE, len(self._bytes)))
|
(filename, IMAGE_SIZE, len(self._bytes)))
|
||||||
|
|
||||||
def find_config(self):
|
def find_config(self):
|
||||||
offset = 0
|
offset = 0
|
||||||
@@ -51,7 +198,7 @@ class BootloaderImage(object):
|
|||||||
offset += 8 + length # length + type
|
offset += 8 + length # length + type
|
||||||
offset = (offset + 7) & ~7
|
offset = (offset + 7) & ~7
|
||||||
|
|
||||||
raise Exception('Bootloader config not found')
|
raise Exception('EEPROM parse error: Bootloader config not found')
|
||||||
|
|
||||||
def write(self, new_config):
|
def write(self, new_config):
|
||||||
hdr_offset, length = self.find_config()
|
hdr_offset, length = self.find_config()
|
||||||
@@ -59,12 +206,13 @@ class BootloaderImage(object):
|
|||||||
new_len = len(new_config_bytes) + FILENAME_LEN + 4
|
new_len = len(new_config_bytes) + FILENAME_LEN + 4
|
||||||
if len(new_config_bytes) > MAX_BOOTCONF_SIZE:
|
if len(new_config_bytes) > MAX_BOOTCONF_SIZE:
|
||||||
raise Exception("Config is too large (%d bytes). The maximum size is %d bytes."
|
raise Exception("Config is too large (%d bytes). The maximum size is %d bytes."
|
||||||
% (len(new_config_bytes), MAX_BOOTCONF_SIZE))
|
% (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')
|
||||||
|
|
||||||
struct.pack_into('>L', self._bytes, hdr_offset + 4, new_len)
|
struct.pack_into('>L', self._bytes, hdr_offset + 4, new_len)
|
||||||
struct.pack_into(("%ds" % len(new_config_bytes)), self._bytes, hdr_offset + 4 + FILE_HDR_LEN, new_config_bytes)
|
struct.pack_into(("%ds" % len(new_config_bytes)), self._bytes,
|
||||||
|
hdr_offset + 4 + FILE_HDR_LEN, new_config_bytes)
|
||||||
|
|
||||||
# If the new config is smaller than the old config then set any old
|
# If the new config is smaller than the old config then set any old
|
||||||
# data which is now unused to all ones (erase value)
|
# data which is now unused to all ones (erase value)
|
||||||
@@ -83,10 +231,14 @@ class BootloaderImage(object):
|
|||||||
else:
|
else:
|
||||||
sys.stdout.write(self._bytes)
|
sys.stdout.write(self._bytes)
|
||||||
|
|
||||||
def read(self):
|
def get_config(self):
|
||||||
hdr_offset, length = self.find_config()
|
hdr_offset, length = self.find_config()
|
||||||
offset = hdr_offset + 4 + FILE_HDR_LEN
|
offset = hdr_offset + 4 + FILE_HDR_LEN
|
||||||
config_bytes = self._bytes[offset:offset+length-FILENAME_LEN-4]
|
config_bytes = self._bytes[offset:offset+length-FILENAME_LEN-4]
|
||||||
|
return config_bytes
|
||||||
|
|
||||||
|
def read(self):
|
||||||
|
config_bytes = self.get_config()
|
||||||
if self._out is not None:
|
if self._out is not None:
|
||||||
self._out.write(config_bytes)
|
self._out.write(config_bytes)
|
||||||
self._out.close()
|
self._out.close()
|
||||||
@@ -97,34 +249,99 @@ class BootloaderImage(object):
|
|||||||
sys.stdout.write(config_bytes)
|
sys.stdout.write(config_bytes)
|
||||||
|
|
||||||
def main():
|
def main():
|
||||||
parser = argparse.ArgumentParser(formatter_class=argparse.RawDescriptionHelpFormatter, \
|
"""
|
||||||
description='Bootloader EEPROM configuration tool for the Raspberry Pi 4. \
|
Utility for reading and writing the configuration file in the
|
||||||
\n\nThere are 3 operating modes: \
|
Raspberry Pi 4 bootloader EEPROM image.
|
||||||
\n\n1. Output the bootloader configuration stored in an EEPROM image file to \
|
"""
|
||||||
the screen (STDOUT): specify only the name of an EEPROM image file using the \
|
description = """\
|
||||||
\'eeprom\' option. \
|
Bootloader EEPROM configuration tool for the Raspberry Pi 4.
|
||||||
\n\n2. Output the bootloader configuration stored in an EEPROM image file to a \
|
Operating modes:
|
||||||
file: specify the EEPROM image file using the \'eeprom\' option, and the output \
|
|
||||||
file using the \'--out\' option.\
|
1. Outputs the current bootloader configuration to STDOUT if no arguments are
|
||||||
\n\n3. Insert a new bootloader configuration into an EEPROM image file: specify \
|
specified OR the given output file if --out is specified.
|
||||||
the source EEPROM image file using the \'eeprom\' option and the bootloader \
|
|
||||||
configuration file using the \'--config\' option. A new file which is a \
|
rpi-eeprom-config [--out boot.conf]
|
||||||
combination of the EEPROM image file, together with the new bootloader \
|
|
||||||
configuration file will be created - specify its name using the \'--out\' option. \
|
2. Extracts the configuration file from the given 'eeprom' file and outputs
|
||||||
The new bootloader configuration will replace any configuration present in the \
|
the result to STDOUT or the output file if --output is specified.
|
||||||
source EEPROM image.\
|
|
||||||
\n\nBootloader EEPROM images are contained in the \'rpi-eeprom-images\' package,\
|
rpi-eeprom-config pieeprom.bin [--out boot.conf]
|
||||||
which installs them to the /lib/firmware/raspberrypi/bootloader directory.')
|
|
||||||
parser.add_argument('--config', help='Name of bootloader configuration file')
|
3. Writes a new EEPROM image replacing the configuration file with the contents
|
||||||
parser.add_argument('--out', help='Name of output file')
|
of the file specified by --config.
|
||||||
parser.add_argument('eeprom', help='Name of EEPROM file to use as input')
|
|
||||||
|
rpi-eeprom-config --config boot.conf --out newimage.bin pieeprom.bin
|
||||||
|
|
||||||
|
The new image file can be installed via rpi-eeprom-update
|
||||||
|
rpi-eeprom-update -d -f newimage.bin
|
||||||
|
|
||||||
|
4. Applies a given config file to an EEPROM image and invokes rpi-eeprom-update
|
||||||
|
to schedule an update of the bootloader when the system is rebooted.
|
||||||
|
|
||||||
|
Since this command launches rpi-eeprom-update to schedule the EERPOM update
|
||||||
|
it must be run as root.
|
||||||
|
|
||||||
|
sudo rpi-eeprom-config --apply boot.conf [pieeprom.bin]
|
||||||
|
|
||||||
|
If the 'eeprom' argument is not specified then the latest available image
|
||||||
|
is selected by calling 'rpi-eeprom-update -l'.
|
||||||
|
|
||||||
|
5. The '--edit' parameter behaves the same as '--apply' except that instead of
|
||||||
|
applying a predefined configuration file a text editor is launched with the
|
||||||
|
contents of the current EEPROM configuration.
|
||||||
|
|
||||||
|
Since this command launches rpi-eeprom-update to schedule the EERPOM update
|
||||||
|
it must be run as root.
|
||||||
|
|
||||||
|
The configuration file will be taken from:
|
||||||
|
* The 'eeprom' file - if specified.
|
||||||
|
* The current pending update - typically /boot/pieeprom.upd
|
||||||
|
* The cached bootloader configuration 'vcgencmd bootloader_config'
|
||||||
|
|
||||||
|
sudo -E rpi-eeprom-config --edit [pieeprom.bin]
|
||||||
|
|
||||||
|
The default text editor is nano and may be overriden by setting the 'EDITOR'
|
||||||
|
environment variable and passing '-E' to 'sudo' to preserve the environment.
|
||||||
|
|
||||||
|
See 'rpi-eeprom-update -h' for more information about the available EEPROM
|
||||||
|
images.
|
||||||
|
"""
|
||||||
|
parser = argparse.ArgumentParser(formatter_class=argparse.RawDescriptionHelpFormatter,
|
||||||
|
description=description)
|
||||||
|
|
||||||
|
parser.add_argument('-a', '--apply', required=False,
|
||||||
|
help='Updates the bootloader to the given config plus latest available EEPROM release.')
|
||||||
|
parser.add_argument('-c', '--config', help='Name of bootloader configuration file', required=False)
|
||||||
|
parser.add_argument('-e', '--edit', action='store_true', default=False, help='Edit the current EEPROM config')
|
||||||
|
parser.add_argument('-o', '--out', help='Name of output file', required=False)
|
||||||
|
parser.add_argument('eeprom', nargs='?', help='Name of EEPROM file to use as input')
|
||||||
args = parser.parse_args()
|
args = parser.parse_args()
|
||||||
|
|
||||||
image = BootloaderImage(args.eeprom, args.out)
|
|
||||||
if args.config is not None:
|
if (args.edit or args.apply is not None) and os.getuid() != 0:
|
||||||
image.write(args.config)
|
exit_error("--edit/--apply must be run as root")
|
||||||
else:
|
|
||||||
image.read()
|
if args.edit:
|
||||||
|
edit_config(args.eeprom)
|
||||||
|
elif args.apply is not None:
|
||||||
|
if not os.path.exists(args.apply):
|
||||||
|
exit_error("config file '%s' not found" % args.apply)
|
||||||
|
apply_update(args.apply, args.eeprom, args.apply)
|
||||||
|
elif args.eeprom is not None:
|
||||||
|
image = BootloaderImage(args.eeprom, args.out)
|
||||||
|
if args.config is not None:
|
||||||
|
if not os.path.exists(args.config):
|
||||||
|
exit_error("config file '%s' not found" % args.config)
|
||||||
|
image.write(args.config)
|
||||||
|
else:
|
||||||
|
image.read()
|
||||||
|
elif args.config is None and args.eeprom is None:
|
||||||
|
current_config = read_current_config()
|
||||||
|
if args.out is not None:
|
||||||
|
open(args.out, 'w').write(current_config)
|
||||||
|
else:
|
||||||
|
sys.stdout.write(current_config)
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
|
atexit.register(exit_handler)
|
||||||
main()
|
main()
|
||||||
|
|||||||
@@ -71,8 +71,12 @@ VL805_UPDATE_VERSION=
|
|||||||
# The update actions selected by the version check
|
# The update actions selected by the version check
|
||||||
ACTION_UPDATE_BOOTLOADER=0
|
ACTION_UPDATE_BOOTLOADER=0
|
||||||
ACTION_UPDATE_VL805=0
|
ACTION_UPDATE_VL805=0
|
||||||
|
CHECKSUMS=''
|
||||||
|
|
||||||
cleanup() {
|
cleanup() {
|
||||||
|
if [ -f "${CHECKSUMS}" ]; then
|
||||||
|
rm -f "${CHECKSUMS}"
|
||||||
|
fi
|
||||||
if [ -f "${TMP_EEPROM_IMAGE}" ]; then
|
if [ -f "${TMP_EEPROM_IMAGE}" ]; then
|
||||||
rm -f "${TMP_EEPROM_IMAGE}"
|
rm -f "${TMP_EEPROM_IMAGE}"
|
||||||
fi
|
fi
|
||||||
@@ -143,6 +147,7 @@ applyRecoveryUpdate()
|
|||||||
[ -n "${BOOTLOADER_UPDATE_IMAGE}" ] || [ -n "${VL805_UPDATE_IMAGE}" ] || die "No update images specified"
|
[ -n "${BOOTLOADER_UPDATE_IMAGE}" ] || [ -n "${VL805_UPDATE_IMAGE}" ] || die "No update images specified"
|
||||||
|
|
||||||
findBootFS
|
findBootFS
|
||||||
|
echo "BOOTFS ${BOOTFS}"
|
||||||
|
|
||||||
# A '.sig' file is created so that recovery.bin can check that the
|
# A '.sig' file is created so that recovery.bin can check that the
|
||||||
# EEPROM image has not been created (e.g. SD card corruption).
|
# EEPROM image has not been created (e.g. SD card corruption).
|
||||||
@@ -166,16 +171,20 @@ applyRecoveryUpdate()
|
|||||||
|| die "Failed to copy ${TMP_EEPROM_IMAGE} to ${BOOTFS}"
|
|| die "Failed to copy ${TMP_EEPROM_IMAGE} to ${BOOTFS}"
|
||||||
|
|
||||||
# For NFS mounts ensure that the files are readable to the TFTP user
|
# For NFS mounts ensure that the files are readable to the TFTP user
|
||||||
chmod -f go+r "${BOOTFS}/pieeprom.upd" "${BOOTFS}/pieeprom.sig"
|
chmod -f go+r "${BOOTFS}/pieeprom.upd" "${BOOTFS}/pieeprom.sig" \
|
||||||
|
|| die "Failed to set permissions on eeprom update files"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if [ -n "${VL805_UPDATE_IMAGE}" ]; then
|
if [ -n "${VL805_UPDATE_IMAGE}" ]; then
|
||||||
sha256sum "${VL805_UPDATE_IMAGE}" | awk '{print $1}' > "${BOOTFS}/vl805.sig" \
|
sha256sum "${VL805_UPDATE_IMAGE}" | awk '{print $1}' > "${BOOTFS}/vl805.sig" \
|
||||||
|| die "Failed to create ${BOOTFS}/vl805.sig"
|
|| die "Failed to create ${BOOTFS}/vl805.sig"
|
||||||
cp -f "${VL805_UPDATE_IMAGE}" "${BOOTFS}/vl805.bin"
|
|
||||||
|
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
|
# For NFS mounts ensure that the files are readable to the TFTP user
|
||||||
chmod -f go+r "${BOOTFS}/vl805.bin" "${BOOTFS}/vl805.sig"
|
chmod -f go+r "${BOOTFS}/vl805.bin" "${BOOTFS}/vl805.sig" \
|
||||||
|
|| die "Failed to set permissions on eeprom update files"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
cp -f "${RECOVERY_BIN}" "${BOOTFS}/recovery.bin" \
|
cp -f "${RECOVERY_BIN}" "${BOOTFS}/recovery.bin" \
|
||||||
@@ -183,18 +192,26 @@ applyRecoveryUpdate()
|
|||||||
}
|
}
|
||||||
|
|
||||||
applyUpdate() {
|
applyUpdate() {
|
||||||
checksums_file="/var/lib/dpkg/info/rpi-eeprom.md5sums"
|
|
||||||
|
|
||||||
[ "$(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 [ "${IGNORE_DPKG_CHECKSUMS}" = 0 ] && [ -f "${checksums_file}" ]; then
|
if [ "${IGNORE_DPKG_CHECKSUMS}" = 0 ]; then
|
||||||
(
|
(
|
||||||
|
package_info_dir="/var/lib/dpkg/info/"
|
||||||
|
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)
|
||||||
|
cat "${package_checksums_file}" | grep -E '\.bin$' > "${CHECKSUMS}"
|
||||||
cd /
|
cd /
|
||||||
if ! md5sum -c "${checksums_file}" > /dev/null 2>&1; then
|
if ! md5sum -c "${CHECKSUMS}" > /dev/null 2>&1; then
|
||||||
md5sum -c "${checksums_file}"
|
md5sum -c "${CHECKSUMS}"
|
||||||
die "rpi-eeprom checksums failed - try reinstalling this package"
|
die "rpi-eeprom checksums failed - try reinstalling this package"
|
||||||
fi
|
fi
|
||||||
)
|
) || die "Unable to validate EEPROM image package checksums"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if [ "${USE_FLASHROM}" = 0 ]; then
|
if [ "${USE_FLASHROM}" = 0 ]; then
|
||||||
@@ -268,7 +285,15 @@ getBootloaderUpdateVersion() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
checkDependencies() {
|
checkDependencies() {
|
||||||
BOARD_INFO="$(od -v -An -t x1 /sys/firmware/devicetree/base/system/linux,revision | tr -d ' \n')"
|
|
||||||
|
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
|
if [ $(((0x$BOARD_INFO >> 23) & 1)) -ne 0 ] && [ $(((0x$BOARD_INFO >> 12) & 15)) -eq 3 ]; then
|
||||||
echo "BCM2711 detected"
|
echo "BCM2711 detected"
|
||||||
else
|
else
|
||||||
@@ -370,6 +395,7 @@ retained.
|
|||||||
Options:
|
Options:
|
||||||
-a Automatically install bootloader and USB (VLI) EEPROM updates.
|
-a Automatically install bootloader and USB (VLI) EEPROM updates.
|
||||||
-A Specify which type of EEPROM to automatically update (vl805 or bootloader)
|
-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
|
-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
|
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
|
bootloader EEPROM update is needed; if the bootloader EEPROM is up-to-date
|
||||||
@@ -380,6 +406,8 @@ Options:
|
|||||||
-h Display help text and exit
|
-h Display help text and exit
|
||||||
-i Ignore package checksums - for rpi-eeprom developers.
|
-i Ignore package checksums - for rpi-eeprom developers.
|
||||||
-j Write status information using JSON notation
|
-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
|
-m Write status information to the given file when run without -a or -f
|
||||||
-r Removes temporary EEPROM update files from the boot partition.
|
-r Removes temporary EEPROM update files from the boot partition.
|
||||||
-u Install the specified VL805 (USB EEPROM) image file.
|
-u Install the specified VL805 (USB EEPROM) image file.
|
||||||
@@ -493,9 +521,7 @@ findBootFS()
|
|||||||
# 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.
|
# it's probably not the boot partition.
|
||||||
[ -d "${BOOTFS}" ] || die "BOOTFS: \"${BOOTFS}\" is not a directory"
|
[ -d "${BOOTFS}" ] || die "BOOTFS: \"${BOOTFS}\" is not a directory"
|
||||||
if [ "$(find "${BOOTFS}/" -name "*.elf" | wc -l)" -gt 0 ]; then
|
if [ "$(find "${BOOTFS}/" -name "*.elf" | wc -l)" = 0 ]; then
|
||||||
echo "BOOTFS ${BOOTFS}"
|
|
||||||
else
|
|
||||||
echo "WARNING: BOOTFS: \"${BOOTFS}\" contains no .elf files. Please check boot directory"
|
echo "WARNING: BOOTFS: \"${BOOTFS}\" contains no .elf files. Please check boot directory"
|
||||||
fi
|
fi
|
||||||
}
|
}
|
||||||
@@ -611,14 +637,16 @@ removePreviousUpdates()
|
|||||||
if [ "$(id -u)" = "0" ]; then
|
if [ "$(id -u)" = "0" ]; then
|
||||||
findBootFS
|
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
|
# Remove any stale recovery.bin files or EEPROM images
|
||||||
# executable but it's best to not have the file at all.
|
# N.B. recovery.bin is normally ignored by the ROM if is not a valid
|
||||||
rm -f "${BOOTFS}/recovery.bin"
|
# executable but it's best to not have the file at all.
|
||||||
rm -f "${BOOTFS}/pieeprom.bin" "${BOOTFS}/pieeprom.upd" "${BOOTFS}/pieeprom.sig"
|
rm -f "${BOOTFS}/recovery.bin"
|
||||||
rm -f "${BOOTFS}/vl805.bin" "${BOOTFS}/vl805.sig"
|
rm -f "${BOOTFS}/pieeprom.bin" "${BOOTFS}/pieeprom.upd" "${BOOTFS}/pieeprom.sig"
|
||||||
# Case insensitive for FAT bootfs
|
rm -f "${BOOTFS}/vl805.bin" "${BOOTFS}/vl805.sig"
|
||||||
find "${BOOTFS}" -maxdepth 1 -type f -follow -iname "recovery.*" -regex '.*\.[0-9][0-9][0-9]$' -exec rm -f {} \;
|
# 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
|
fi
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -680,7 +708,7 @@ MACHINE_OUTPUT=""
|
|||||||
JSON_OUTPUT="no"
|
JSON_OUTPUT="no"
|
||||||
IGNORE_DPKG_CHECKSUMS=$LOCAL_MODE
|
IGNORE_DPKG_CHECKSUMS=$LOCAL_MODE
|
||||||
|
|
||||||
while getopts A:adhif:m:ju:r option; do
|
while getopts A:abdhilf:m:ju:r option; do
|
||||||
case "${option}" in
|
case "${option}" in
|
||||||
A)
|
A)
|
||||||
if [ "${OPTARG}" = "bootloader" ]; then
|
if [ "${OPTARG}" = "bootloader" ]; then
|
||||||
@@ -694,6 +722,11 @@ while getopts A:adhif:m:ju:r option; do
|
|||||||
a) AUTO_UPDATE_BOOTLOADER=1
|
a) AUTO_UPDATE_BOOTLOADER=1
|
||||||
AUTO_UPDATE_VL805=1
|
AUTO_UPDATE_VL805=1
|
||||||
;;
|
;;
|
||||||
|
b)
|
||||||
|
findBootFS
|
||||||
|
echo ${BOOTFS}
|
||||||
|
exit 0
|
||||||
|
;;
|
||||||
d) OVERWRITE_CONFIG=1
|
d) OVERWRITE_CONFIG=1
|
||||||
;;
|
;;
|
||||||
f) BOOTLOADER_UPDATE_IMAGE="${OPTARG}"
|
f) BOOTLOADER_UPDATE_IMAGE="${OPTARG}"
|
||||||
@@ -702,6 +735,11 @@ while getopts A:adhif:m:ju:r option; do
|
|||||||
;;
|
;;
|
||||||
j) JSON_OUTPUT="yes"
|
j) JSON_OUTPUT="yes"
|
||||||
;;
|
;;
|
||||||
|
l)
|
||||||
|
getBootloaderUpdateVersion
|
||||||
|
echo "${BOOTLOADER_UPDATE_IMAGE}"
|
||||||
|
exit 0
|
||||||
|
;;
|
||||||
m) MACHINE_OUTPUT="${OPTARG}"
|
m) MACHINE_OUTPUT="${OPTARG}"
|
||||||
;;
|
;;
|
||||||
h) usage
|
h) usage
|
||||||
|
|||||||
Reference in New Issue
Block a user