From 2aa97029fd221c70abd285987fe1eba3895c1c97 Mon Sep 17 00:00:00 2001 From: Nicolas Saenz Julienne Date: Thu, 21 Jan 2021 12:57:27 +0100 Subject: [PATCH 1/2] rpi-eeprom-update: Get bootloader configuration from DT Signed-off-by: Nicolas Saenz Julienne --- rpi-eeprom-config | 18 ++++++++++++++---- rpi-eeprom-update | 36 ++++++++++++++++++++++++++++++++---- 2 files changed, 46 insertions(+), 8 deletions(-) diff --git a/rpi-eeprom-config b/rpi-eeprom-config index 7a5f632..0a6ce5e 100755 --- a/rpi-eeprom-config +++ b/rpi-eeprom-config @@ -138,8 +138,7 @@ def edit_config(eeprom=None): image = BootloaderImage(pending) current_config = image.get_config().decode('utf-8') else: - config_src = 'vcgencmd bootloader_config' - current_config = read_current_config() + current_config, config_src = read_current_config() create_tempdir() tmp_conf = os.path.join(TEMP_DIR, 'boot.conf') @@ -160,7 +159,17 @@ def read_current_config(): """ Reads the configuration used by the current bootloader. """ - return shell_cmd(['vcgencmd', 'bootloader_config']) + fw_base = "/sys/firmware/devicetree/base/" + nvmem_base = "/sys/bus/nvmem/devices/" + + if os.path.exists(fw_base + "/aliases/blconfig"): + with open(fw_base + "/aliases/blconfig") as f: + nvmem_ofnode_path = fw_base + f.read().encode('ascii') + for d in os.listdir(nvmem_base): + if os.path.realpath(nvmem_base + d + "/of_node") in os.path.normpath(nvmem_ofnode_path): + return (open(nvmem_base + d + "/nvmem").read(), "blconfig device") + + return (shell_cmd(['vcgencmd', 'bootloader_config']), "vcgencmd bootloader_config") class BootloaderImage(object): def __init__(self, filename, output=None): @@ -293,6 +302,7 @@ Operating modes: it must be run as root. The configuration file will be taken from: + * The blconfig reserved memory nvmem device * The cached bootloader configuration 'vcgencmd bootloader_config' * The current pending update - typically /boot/pieeprom.upd @@ -336,7 +346,7 @@ images. else: image.read() elif args.config is None and args.eeprom is None: - current_config = read_current_config() + current_config, config_src = read_current_config() if args.out is not None: open(args.out, 'w').write(current_config) else: diff --git a/rpi-eeprom-update b/rpi-eeprom-update index a0643b8..09ccda8 100755 --- a/rpi-eeprom-update +++ b/rpi-eeprom-update @@ -104,6 +104,34 @@ die() { exit ${EXIT_FAILED} } +getBootloaderConfig() { + # Prefer extracting bootloader's config from DT. + # + # In order to find the right nvmem device, we build the sysfs path of the + # bootloader reserved memory DT node to then match that path against all + # nvmem device's ofnode path. + # + # If the path isn't there, default to using vcgencmd. + + local blconfig_alias="/sys/firmware/devicetree/base/aliases/blconfig" + local blconfig_nvmem_path="" + + if [ -f "${blconfig_alias}" ]; then + local blconfig_ofnode_path="/sys/firmware/devicetree/base"$(strings "${blconfig_alias}")"" + local blconfig_ofnode_link=$(find -L /sys/bus/nvmem -samefile "${blconfig_ofnode_path}" 2>/dev/null) + + if [ -e "${blconfig_ofnode_link}" ]; then + blconfig_nvmem_path=$(dirname "${blconfig_ofnode_link}") + fi + fi + + if [ -n "${blconfig_nvmem_path}" ]; then + cat "${blconfig_nvmem_path}"/nvmem + else + vcgencmd bootloader_config + fi +} + prepareImage() { [ -f "${BOOTLOADER_UPDATE_IMAGE}" ] || die "EEPROM image '${BOOTLOADER_UPDATE_IMAGE}' not found" @@ -114,7 +142,7 @@ prepareImage() mkdir -p "${FIRMWARE_BACKUP_DIR}" # Backup the configuration of the currently loaded bootloader - vcgencmd bootloader_config > "${TMP_EEPROM_CONFIG}" + getBootloaderConfig > "${TMP_EEPROM_CONFIG}" backup="${FIRMWARE_BACKUP_DIR}/pieeprom-backup-$(date +%Y%m%d-%H%M%S).conf" cp -f "${TMP_EEPROM_CONFIG}" "${backup}" @@ -355,8 +383,8 @@ checkDependencies() { 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." + if ! getBootloaderConfig > /dev/null; then + die "Unable to get bootloader config, please update VC firmware and reboot." fi if ! command -v sha256sum > /dev/null; then @@ -800,7 +828,7 @@ done checkDependencies if [ "${AUTO_UPDATE_BOOTLOADER}" = 1 ] || [ "${AUTO_UPDATE_VL805}" = 1 ]; then - if vcgencmd bootloader_config | grep FREEZE_VERSION=1; then + if getBootloaderConfig | grep FREEZE_VERSION=1; then echo "EEPROM version is frozen. Skipping update" exit ${EXIT_EEPROM_FROZEN} else From eeb4a19c7f9d108660728310f602bdaf784fee07 Mon Sep 17 00:00:00 2001 From: Nicolas Saenz Julienne Date: Tue, 26 Jan 2021 12:48:25 +0100 Subject: [PATCH 2/2] rpi-eeprom-config: Properly decode sysfs binary files The previous implementation was reading the sysfs files as plain text and encoding them as 'ascii' to remove all the trailing zeros. This is wrong twofold. To start with, the sysfs file we're querying are binary files[1], and we're reading it as a string. On top of that we're benefiting that *some* python implementations of string.encode() will deal with trailing zeros. Fix this by marking the files as binary and decoding them as strings before consuming them. [1] sysfs files are generally text based, but there is also the option to output binary data. Our configuration file does the later. Signed-off-by: Nicolas Saenz Julienne --- rpi-eeprom-config | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/rpi-eeprom-config b/rpi-eeprom-config index 0a6ce5e..6ce96a4 100755 --- a/rpi-eeprom-config +++ b/rpi-eeprom-config @@ -163,11 +163,11 @@ def read_current_config(): nvmem_base = "/sys/bus/nvmem/devices/" if os.path.exists(fw_base + "/aliases/blconfig"): - with open(fw_base + "/aliases/blconfig") as f: - nvmem_ofnode_path = fw_base + f.read().encode('ascii') + with open(fw_base + "/aliases/blconfig", "rb") as f: + nvmem_ofnode_path = fw_base + f.read().decode('utf-8') for d in os.listdir(nvmem_base): if os.path.realpath(nvmem_base + d + "/of_node") in os.path.normpath(nvmem_ofnode_path): - return (open(nvmem_base + d + "/nvmem").read(), "blconfig device") + return (open(nvmem_base + d + "/nvmem", "rb").read().decode('utf-8'), "blconfig device") return (shell_cmd(['vcgencmd', 'bootloader_config']), "vcgencmd bootloader_config")