diff --git a/rpi-eeprom-config b/rpi-eeprom-config index 02f01b21..96b2ca4d 100755 --- a/rpi-eeprom-config +++ b/rpi-eeprom-config @@ -349,15 +349,23 @@ class BootloaderImage(object): """ if bootcode: hdr_offset, length, is_last, next_offset = self.find_file(dst_filename, partition_start=0, partition_end=READ_ONLY_SIZE) - struct.pack_into('>L', self._bytes, hdr_offset + 4, len(src_bytes)) - struct.pack_into(("%ds" % len(src_bytes)), self._bytes, hdr_offset + 8, src_bytes) - pad_start = hdr_offset + len(src_bytes) + 8 is_last = False debug("bootcode padded to %d" % next_offset); + + # The new bootcode plus its section header must fit in the space + # before the next non-padding section + if next_offset <= hdr_offset: + raise Exception("update-bootcode: Failed to find next section") if not self._is_ab_image and next_offset < 128 * 1024: raise Exception("update-bootcode: Can't update image - 128K must be reserved for bootcode") - if next_offset < 0: - raise Exception("update-bootcode: Failed to find next section") + max_len = next_offset - hdr_offset - 8 + if len(src_bytes) > max_len: + raise Exception("update-bootcode: %s is too large (%d bytes). The maximum size for this image is %d bytes." + % (dst_filename, len(src_bytes), max_len)) + + struct.pack_into('>L', self._bytes, hdr_offset + 4, len(src_bytes)) + struct.pack_into(("%ds" % len(src_bytes)), self._bytes, hdr_offset + 8, src_bytes) + pad_start = hdr_offset + len(src_bytes) + 8 else: hdr_offset, length, is_last, next_offset = self.find_file(dst_filename, partition_start=READ_ONLY_SIZE, partition_end=READ_ONLY_SIZE + PARTITION_SIZE) diff --git a/test/test-rpi-eeprom-config b/test/test-rpi-eeprom-config index b0af3c1a..170bcb79 100755 --- a/test/test-rpi-eeprom-config +++ b/test/test-rpi-eeprom-config @@ -12,11 +12,18 @@ die() { TMP_CONFIG="" TMP_EEPROM="" TMP_EEPROM2="" +TMP_BOOTCODE="" +TMP_DIR="" cleanup() { - rm -f "${TMP_CONFIG}" -f "${TMP_EEPROM}" "${TMP_EEPROM2}" + rm -f "${TMP_CONFIG}" -f "${TMP_EEPROM}" "${TMP_EEPROM2}" "${TMP_BOOTCODE}" + if [ -n "${TMP_DIR}" ]; then + rm -rf "${TMP_DIR}" + fi TMP_CONFIG="" TMP_EEPROM="" TMP_EEPROM2="" + TMP_BOOTCODE="" + TMP_DIR="" } trap cleanup EXIT @@ -164,6 +171,47 @@ check_conf_size_too_large() fi } +# Verify that rpi-eeprom-config can replace the bootcode +check_bootcode_update() +{ + echo "check bootcode update $1" + image="${script_dir}/$1" + + TMP_DIR="$(mktemp -d)" + (cd "${TMP_DIR}" && "${script_dir}/../rpi-eeprom-config" -x "${image}") + [ -f "${TMP_DIR}/bootcode.bin" ] || die "bootcode.bin was not extracted from ${image}" + TMP_BOOTCODE="$(mktemp)" + cp -f "${TMP_DIR}/bootcode.bin" "${TMP_BOOTCODE}" + expected_md5="$(md5sum "${TMP_BOOTCODE}" | awk '{print $1}')" + + TMP_EEPROM="$(mktemp)" + "${script_dir}/../rpi-eeprom-config" \ + "${image}" \ + --bootcode "${TMP_BOOTCODE}" \ + --out "${TMP_EEPROM}" + + rm -f "${TMP_DIR}/bootcode.bin" + (cd "${TMP_DIR}" && "${script_dir}/../rpi-eeprom-config" -x "${TMP_EEPROM}") + actual_md5="$(md5sum "${TMP_DIR}/bootcode.bin" | awk '{print $1}')" + [ "${actual_md5}" = "${expected_md5}" ] || die "EEPROM bootcode update: checksum mismatch" +} + +# Verify that rpi-eeprom-config rejects a bootcode which does not fit in the +# space before the next section +check_bootcode_too_large() +{ + echo "check bootcode which exceeds the available space $1 $2" + image="${script_dir}/$1" + + TMP_BOOTCODE="$(mktemp)" + head -c "$2" /dev/zero > "${TMP_BOOTCODE}" + + TMP_EEPROM="$(mktemp)" + if "${script_dir}/../rpi-eeprom-config" "${image}" --bootcode "${TMP_BOOTCODE}" --out "${TMP_EEPROM}" > /dev/null 2>&1; then + die "bootcode of $2 bytes should have been rejected" + fi +} + echo "Check config read and loopback read/write against reference config files" versions="$(cd configs; ls *.txt | sed 's/bootconf-//g' | sed 's/.txt//g')" for ver in ${versions}; do @@ -192,3 +240,19 @@ cleanup check_conf_size_too_large "../firmware-2711/old/beta/pieeprom-2019-07-15.bin" cleanup + +echo "Test bootcode replacement in BCM2712 images (AB and non-AB layouts)" +check_bootcode_update "../firmware-2712/old/latest/pieeprom-2026-05-13.bin" +cleanup + +check_bootcode_update "../firmware-2712/old/latest/pieeprom-2025-12-08.bin" +cleanup + +check_bootcode_too_large "../firmware-2712/old/latest/pieeprom-2026-05-13.bin" 70000 +cleanup + +check_bootcode_too_large "../firmware-2712/old/latest/pieeprom-2026-05-13.bin" 3145728 +cleanup + +check_bootcode_too_large "../firmware-2712/old/latest/pieeprom-2025-12-08.bin" 200000 +cleanup