From bc4478c9467186d01d0987d50ebefbc250572c73 Mon Sep 17 00:00:00 2001 From: Karambite <01sudesh.e@gmail.com> Date: Tue, 19 Nov 2024 08:50:26 -0600 Subject: [PATCH 01/15] IAR compiler compatibility break in image.h Signed-off-by: Karambite <01sudesh.e@gmail.com> --- boot/bootutil/include/bootutil/image.h | 22 ++++++++++++---------- 1 file changed, 12 insertions(+), 10 deletions(-) diff --git a/boot/bootutil/include/bootutil/image.h b/boot/bootutil/include/bootutil/image.h index 05e04438b..243910815 100644 --- a/boot/bootutil/include/bootutil/image.h +++ b/boot/bootutil/include/bootutil/image.h @@ -36,8 +36,10 @@ extern "C" { #endif -#ifndef __packed -#define __packed __attribute__((__packed__)) +#if defined(__IAR_SYSTEMS_ICC__) + #define STRUCT_PACKED __packed struct +#else + #define STRUCT_PACKED struct __attribute__((__packed__)) #endif struct flash_area; @@ -136,12 +138,12 @@ struct flash_area; */ #define IMAGE_TLV_ANY 0xffff /* Used to iterate over all TLV */ -struct image_version { +STRUCT_PACKED image_version { uint8_t iv_major; uint8_t iv_minor; uint16_t iv_revision; uint32_t iv_build_num; -} __packed; +}; struct image_dependency { uint8_t image_id; /* Image index (from 0) */ @@ -154,7 +156,7 @@ struct image_dependency { }; /** Image header. All fields are in little endian byte order. */ -struct image_header { +STRUCT_PACKED image_header { uint32_t ih_magic; uint32_t ih_load_addr; uint16_t ih_hdr_size; /* Size of image header (bytes). */ @@ -163,19 +165,19 @@ struct image_header { uint32_t ih_flags; /* IMAGE_F_[...]. */ struct image_version ih_ver; uint32_t _pad1; -} __packed; +}; /** Image TLV header. All fields in little endian. */ -struct image_tlv_info { +STRUCT_PACKED image_tlv_info { uint16_t it_magic; uint16_t it_tlv_tot; /* size of TLV area (including tlv_info header) */ -} __packed; +}; /** Image trailer TLV format. All fields in little endian. */ -struct image_tlv { +STRUCT_PACKED image_tlv { uint16_t it_type; /* IMAGE_TLV_[...]. */ uint16_t it_len; /* Data length (not including TLV header). */ -} __packed; +}; #define ENCRYPTIONFLAGS (IMAGE_F_ENCRYPTED_AES128 | IMAGE_F_ENCRYPTED_AES256) #define IS_ENCRYPTED(hdr) (((hdr)->ih_flags & IMAGE_F_ENCRYPTED_AES128) \ From 95773edf33082a1689795e0278c14b2da1e6ab74 Mon Sep 17 00:00:00 2001 From: TOKITA Hiroshi Date: Sun, 22 Dec 2024 08:33:12 +0900 Subject: [PATCH 02/15] boot: zephyr: boards: add support for M5stack CoreS3/CoreS3SE Add m5stack_cores3/esp32s3/procpu and m5stack_cores3/esp32s3/procpu/se board targets. Adds an overlay to disable devices that cause dependency conflicts. Signed-off-by: TOKITA Hiroshi --- .../m5stack_cores3_esp32s3_procpu.overlay | 17 +++++++++++++++++ .../m5stack_cores3_esp32s3_procpu_se.overlay | 17 +++++++++++++++++ 2 files changed, 34 insertions(+) create mode 100644 boot/zephyr/boards/m5stack_cores3_esp32s3_procpu.overlay create mode 100644 boot/zephyr/boards/m5stack_cores3_esp32s3_procpu_se.overlay diff --git a/boot/zephyr/boards/m5stack_cores3_esp32s3_procpu.overlay b/boot/zephyr/boards/m5stack_cores3_esp32s3_procpu.overlay new file mode 100644 index 000000000..f0740c854 --- /dev/null +++ b/boot/zephyr/boards/m5stack_cores3_esp32s3_procpu.overlay @@ -0,0 +1,17 @@ +/* + * Copyright (c) 2024 TOKITA Hiroshi + * + * SPDX-License-Identifier: Apache-2.0 + */ + +&aw9523b { + status = "disabled"; +}; + +&aw9523b_gpio { + status = "disabled"; +}; + +&ft6336_touch { + status = "disabled"; +}; diff --git a/boot/zephyr/boards/m5stack_cores3_esp32s3_procpu_se.overlay b/boot/zephyr/boards/m5stack_cores3_esp32s3_procpu_se.overlay new file mode 100644 index 000000000..f0740c854 --- /dev/null +++ b/boot/zephyr/boards/m5stack_cores3_esp32s3_procpu_se.overlay @@ -0,0 +1,17 @@ +/* + * Copyright (c) 2024 TOKITA Hiroshi + * + * SPDX-License-Identifier: Apache-2.0 + */ + +&aw9523b { + status = "disabled"; +}; + +&aw9523b_gpio { + status = "disabled"; +}; + +&ft6336_touch { + status = "disabled"; +}; From 1c04eac60b3bc2552023d9276850d19d5f343ea1 Mon Sep 17 00:00:00 2001 From: Dominik Ermel Date: Thu, 12 Sep 2024 19:37:40 +0000 Subject: [PATCH 03/15] imgtool: Add pure signature support Adds PureEdDSA signature support. The change includes implementation of SIG_PURE TLV that, when present, indicates the signature that is present is Pure type. Signed-off-by: Dominik Ermel Signed-off-by: Mateusz Michalek --- scripts/imgtool/image.py | 74 ++++++++++++++++++++++++++++++++-------- scripts/imgtool/main.py | 26 ++++++++++---- 2 files changed, 80 insertions(+), 20 deletions(-) diff --git a/scripts/imgtool/image.py b/scripts/imgtool/image.py index 5fec3c1b7..88ef7b90c 100644 --- a/scripts/imgtool/image.py +++ b/scripts/imgtool/image.py @@ -190,7 +190,15 @@ def tlv_sha_to_sha(tlv): keys.X25519 : ['256', '512'] } -def key_and_user_sha_to_alg_and_tlv(key, user_sha): +ALLOWED_PURE_KEY_SHA = { + keys.Ed25519 : ['512'] +} + +ALLOWED_PURE_SIG_TLVS = [ + TLV_VALUES['ED25519'] +] + +def key_and_user_sha_to_alg_and_tlv(key, user_sha, is_pure = False): """Matches key and user requested sha to sha alogrithm and TLV name. The returned tuple will contain hash functions and TVL name. @@ -204,12 +212,16 @@ def key_and_user_sha_to_alg_and_tlv(key, user_sha): # If key is not None, then we have to filter hash to only allowed allowed = None + allowed_key_ssh = ALLOWED_PURE_KEY_SHA if is_pure else ALLOWED_KEY_SHA try: - allowed = ALLOWED_KEY_SHA[type(key)] + allowed = allowed_key_ssh[type(key)] + except KeyError: raise click.UsageError("Colud not find allowed hash algorithms for {}" .format(type(key))) - if user_sha == 'auto': + + # Pure enforces auto, and user selection is ignored + if user_sha == 'auto' or is_pure: return USER_SHA_TO_ALG_AND_TLV[allowed[0]] if user_sha in allowed: @@ -447,12 +459,13 @@ def ecies_hkdf(self, enckey, plainkey): def create(self, key, public_key_format, enckey, dependencies=None, sw_type=None, custom_tlvs=None, compression_tlvs=None, compression_type=None, encrypt_keylen=128, clear=False, - fixed_sig=None, pub_key=None, vector_to_sign=None, user_sha='auto'): + fixed_sig=None, pub_key=None, vector_to_sign=None, + user_sha='auto', is_pure=False): self.enckey = enckey # key decides on sha, then pub_key; of both are none default is used check_key = key if key is not None else pub_key - hash_algorithm, hash_tlv = key_and_user_sha_to_alg_and_tlv(check_key, user_sha) + hash_algorithm, hash_tlv = key_and_user_sha_to_alg_and_tlv(check_key, user_sha, is_pure) # Calculate the hash of the public key if key is not None: @@ -592,9 +605,17 @@ def create(self, key, public_key_format, enckey, dependencies=None, sha = hash_algorithm() sha.update(self.payload) digest = sha.digest() - message = digest; tlv.add(hash_tlv, digest) self.image_hash = digest + # Unless pure, we are signing digest. + message = digest + + if is_pure: + # Note that when Pure signature is used, hash TLV is not present. + message = bytes(self.payload) + e = STRUCT_ENDIAN_DICT[self.endian] + sig_pure = struct.pack(e + '?', True) + tlv.add('SIG_PURE', sig_pure) if vector_to_sign == 'payload': # Stop amending data to the image @@ -786,7 +807,7 @@ def verify(imgfile, key): version = struct.unpack('BBHI', b[20:28]) if magic != IMAGE_MAGIC: - return VerifyResult.INVALID_MAGIC, None, None + return VerifyResult.INVALID_MAGIC, None, None, None tlv_off = header_size + img_size tlv_info = b[tlv_off:tlv_off + TLV_INFO_SIZE] @@ -797,11 +818,27 @@ def verify(imgfile, key): magic, tlv_tot = struct.unpack('HH', tlv_info) if magic != TLV_INFO_MAGIC: - return VerifyResult.INVALID_TLV_INFO_MAGIC, None, None + return VerifyResult.INVALID_TLV_INFO_MAGIC, None, None, None + + # This is set by existence of TLV SIG_PURE + is_pure = False prot_tlv_size = tlv_off hash_region = b[:prot_tlv_size] + tlv_end = tlv_off + tlv_tot + tlv_off += TLV_INFO_SIZE # skip tlv info + + # First scan all TLVs in search of SIG_PURE + while tlv_off < tlv_end: + tlv = b[tlv_off:tlv_off + TLV_SIZE] + tlv_type, _, tlv_len = struct.unpack('BBH', tlv) + if tlv_type == TLV_VALUES['SIG_PURE']: + is_pure = True + break + tlv_off += TLV_SIZE + tlv_len + digest = None + tlv_off = header_size + img_size tlv_end = tlv_off + tlv_tot tlv_off += TLV_INFO_SIZE # skip tlv info while tlv_off < tlv_end: @@ -809,15 +846,15 @@ def verify(imgfile, key): tlv_type, _, tlv_len = struct.unpack('BBH', tlv) if is_sha_tlv(tlv_type): if not tlv_matches_key_type(tlv_type, key): - return VerifyResult.KEY_MISMATCH, None, None + return VerifyResult.KEY_MISMATCH, None, None, None off = tlv_off + TLV_SIZE digest = get_digest(tlv_type, hash_region) if digest == b[off:off + tlv_len]: if key is None: - return VerifyResult.OK, version, digest + return VerifyResult.OK, version, digest, None else: - return VerifyResult.INVALID_HASH, None, None - elif key is not None and tlv_type == TLV_VALUES[key.sig_tlv()]: + return VerifyResult.INVALID_HASH, None, None, None + elif not is_pure and key is not None and tlv_type == TLV_VALUES[key.sig_tlv()]: off = tlv_off + TLV_SIZE tlv_sig = b[off:off + tlv_len] payload = b[:prot_tlv_size] @@ -826,9 +863,18 @@ def verify(imgfile, key): key.verify(tlv_sig, payload) else: key.verify_digest(tlv_sig, digest) - return VerifyResult.OK, version, digest + return VerifyResult.OK, version, digest, None + except InvalidSignature: + # continue to next TLV + pass + elif is_pure and key is not None and tlv_type in ALLOWED_PURE_SIG_TLVS: + off = tlv_off + TLV_SIZE + tlv_sig = b[off:off + tlv_len] + try: + key.verify_digest(tlv_sig, hash_region) + return VerifyResult.OK, version, None, tlv_sig except InvalidSignature: # continue to next TLV pass tlv_off += TLV_SIZE + tlv_len - return VerifyResult.INVALID_SIGNATURE, None, None + return VerifyResult.INVALID_SIGNATURE, None, None, None diff --git a/scripts/imgtool/main.py b/scripts/imgtool/main.py index e0f70945c..434530c7a 100755 --- a/scripts/imgtool/main.py +++ b/scripts/imgtool/main.py @@ -226,11 +226,14 @@ def getpriv(key, minimal, format): @click.command(help="Check that signed image can be verified by given key") def verify(key, imgfile): key = load_key(key) if key else None - ret, version, digest = image.Image.verify(imgfile, key) + ret, version, digest, signature = image.Image.verify(imgfile, key) if ret == image.VerifyResult.OK: print("Image was correctly validated") print("Image version: {}.{}.{}+{}".format(*version)) - print("Image digest: {}".format(digest.hex())) + if digest: + print("Image digest: {}".format(digest.hex())) + if signature and digest is None: + print("Image signature over image: {}".format(signature.hex())) return elif ret == image.VerifyResult.INVALID_MAGIC: print("Invalid image magic; is this an MCUboot image?") @@ -423,6 +426,10 @@ def convert(self, value, param, ctx): 'the signature calculated using the public key') @click.option('--fix-sig-pubkey', metavar='filename', help='public key relevant to fixed signature') +@click.option('--pure', 'is_pure', is_flag=True, default=False, show_default=True, + help='Expected Pure variant of signature; the Pure variant is ' + 'expected to be signature done over an image rather than hash of ' + 'that image.') @click.option('--sig-out', metavar='filename', help='Path to the file to which signature will be written. ' 'The image signature will be encoded as base64 formatted string') @@ -441,8 +448,8 @@ def sign(key, public_key_format, align, version, pad_sig, header_size, endian, encrypt_keylen, encrypt, compression, infile, outfile, dependencies, load_addr, hex_addr, erased_val, save_enctlv, security_counter, boot_record, custom_tlv, rom_fixed, max_align, - clear, fix_sig, fix_sig_pubkey, sig_out, user_sha, vector_to_sign, - non_bootable): + clear, fix_sig, fix_sig_pubkey, sig_out, user_sha, is_pure, + vector_to_sign, non_bootable): if confirm: # Confirmed but non-padded images don't make much sense, because @@ -509,9 +516,15 @@ def sign(key, public_key_format, align, version, pad_sig, header_size, 'value': raw_signature } + if is_pure and user_sha != 'auto': + raise click.UsageError( + 'Pure signatures, currently, enforces preferred hash algorithm, ' + 'and forbids sha selection by user.') + img.create(key, public_key_format, enckey, dependencies, boot_record, custom_tlvs, compression_tlvs, None, int(encrypt_keylen), clear, - baked_signature, pub_key, vector_to_sign, user_sha) + baked_signature, pub_key, vector_to_sign, user_sha=user_sha, + is_pure=is_pure) if compression in ["lzma2", "lzma2armthumb"]: compressed_img = image.Image(version=decode_version(version), @@ -552,7 +565,8 @@ def sign(key, public_key_format, align, version, pad_sig, header_size, compressed_img.create(key, public_key_format, enckey, dependencies, boot_record, custom_tlvs, compression_tlvs, compression, int(encrypt_keylen), clear, baked_signature, - pub_key, vector_to_sign, user_sha=user_sha) + pub_key, vector_to_sign, user_sha=user_sha, + is_pure=is_pure) img = compressed_img img.save(outfile, hex_addr) if sig_out is not None: From 1c32c9b1015c42dfe12bf1aa4bd9a113d25bf1c4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20J=C3=A4ger?= Date: Sun, 5 Jan 2025 13:35:32 +0100 Subject: [PATCH 04/15] boot: espressif: add support for upgrade modes w/o scratch MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Upgrade using move decreases flash wear and is now the default mode used by Zephyr. The implementation is done by MCUboot itself, so it is just a matter of setting the correct define to enable it. Swap using move was successfully tested with ESP32C6. Signed-off-by: Martin Jäger --- .../include/mcuboot_config/mcuboot_config.h | 34 +++++++++++++++---- boot/espressif/hal/src/flash_encrypt.c | 3 ++ .../port/esp32/bootloader-multi.conf | 4 +++ boot/espressif/port/esp32/bootloader.conf | 4 +++ boot/espressif/port/esp32c2/bootloader.conf | 4 +++ boot/espressif/port/esp32c3/bootloader.conf | 4 +++ boot/espressif/port/esp32c6/bootloader.conf | 4 +++ boot/espressif/port/esp32h2/bootloader.conf | 4 +++ boot/espressif/port/esp32s2/bootloader.conf | 4 +++ .../port/esp32s3/bootloader-multi.conf | 4 +++ boot/espressif/port/esp32s3/bootloader.conf | 4 +++ boot/espressif/port/esp_mcuboot.c | 12 +++++-- 12 files changed, 76 insertions(+), 9 deletions(-) diff --git a/boot/espressif/hal/include/mcuboot_config/mcuboot_config.h b/boot/espressif/hal/include/mcuboot_config/mcuboot_config.h index a299e3cfc..345ca57b8 100644 --- a/boot/espressif/hal/include/mcuboot_config/mcuboot_config.h +++ b/boot/espressif/hal/include/mcuboot_config/mcuboot_config.h @@ -45,23 +45,43 @@ * the default upgrade mode. */ -/* Uncomment to enable the overwrite-only code path. */ -/* #define MCUBOOT_OVERWRITE_ONLY */ +/* Define to enable the swap-using-move code path. */ +#if defined(CONFIG_ESP_BOOT_SWAP_USING_MOVE) +#define MCUBOOT_SWAP_USING_MOVE 1 +#endif -#ifdef MCUBOOT_OVERWRITE_ONLY +/* Define to enable the overwrite-only code path. */ +#if defined(CONFIG_ESP_BOOT_UPGRADE_ONLY) +#define MCUBOOT_OVERWRITE_ONLY /* Uncomment to only erase and overwrite those primary slot sectors needed * to install the new image, rather than the entire image slot. */ /* #define MCUBOOT_OVERWRITE_ONLY_FAST */ #endif -/* Uncomment to enable the direct-xip code path. */ -/* #define MCUBOOT_DIRECT_XIP */ +/* Define to enable the direct-xip code path (CURRENTLY UNSUPPORTED!). */ +#if defined(CONFIG_ESP_BOOT_DIRECT_XIP) +#define MCUBOOT_DIRECT_XIP +#endif -/* Define to enable the ram-load code path. */ -#if defined(CONFIG_BOOT_RAM_LOAD) +/* Define to enable the ram-load code path (CURRENTLY UNSUPPORTED!). */ +#if defined(CONFIG_ESP_BOOT_RAM_LOAD) #define MCUBOOT_RAM_LOAD #endif +/* If none of the above paths is defined, define CONFIG_ESP_BOOT_SWAP_USING_SCRATCH. + * + * Note: MCUBOOT_SWAP_USING_SCRATCH does not have to be defined, as it will be defined + * by MCUboot in bootutil_priv.h. + */ +#if !defined(CONFIG_ESP_BOOT_SWAP_USING_SCRATCH) && \ + !defined(CONFIG_ESP_BOOT_SWAP_USING_MOVE) && \ + !defined(CONFIG_ESP_BOOT_UPGRADE_ONLY) && \ + !defined(CONFIG_ESP_BOOT_DIRECT_XIP) && \ + !defined(CONFIG_ESP_BOOT_RAM_LOAD) +#define CONFIG_ESP_BOOT_SWAP_USING_SCRATCH +#endif + + /* * Cryptographic settings * diff --git a/boot/espressif/hal/src/flash_encrypt.c b/boot/espressif/hal/src/flash_encrypt.c index d064d8b7b..3996d0e7a 100644 --- a/boot/espressif/hal/src/flash_encrypt.c +++ b/boot/espressif/hal/src/flash_encrypt.c @@ -307,12 +307,15 @@ esp_err_t esp_flash_encrypt_contents(void) if (err != ESP_OK) { return err; } + +#ifdef CONFIG_ESP_BOOT_SWAP_USING_SCRATCH region_addr = CONFIG_ESP_SCRATCH_OFFSET; region_size = CONFIG_ESP_SCRATCH_SIZE; err = esp_flash_encrypt_region(region_addr, region_size); if (err != ESP_OK) { return err; } +#endif #if defined(CONFIG_ESP_IMAGE_NUMBER) && (CONFIG_ESP_IMAGE_NUMBER == 2) region_addr = CONFIG_ESP_IMAGE1_PRIMARY_START_ADDRESS; diff --git a/boot/espressif/port/esp32/bootloader-multi.conf b/boot/espressif/port/esp32/bootloader-multi.conf index ad3355ec2..29e2073f6 100644 --- a/boot/espressif/port/esp32/bootloader-multi.conf +++ b/boot/espressif/port/esp32/bootloader-multi.conf @@ -2,6 +2,10 @@ # # SPDX-License-Identifier: Apache-2.0 +# Define upgrade mode (default is CONFIG_ESP_BOOT_SWAP_USING_SCRATCH) +# CONFIG_ESP_BOOT_SWAP_USING_MOVE=y +# CONFIG_ESP_BOOT_UPGRADE_ONLY=y + CONFIG_ESP_FLASH_SIZE=4MB CONFIG_ESP_BOOTLOADER_SIZE=0xF000 CONFIG_ESP_BOOTLOADER_OFFSET=0x1000 diff --git a/boot/espressif/port/esp32/bootloader.conf b/boot/espressif/port/esp32/bootloader.conf index 8f555ec57..5a59a422a 100644 --- a/boot/espressif/port/esp32/bootloader.conf +++ b/boot/espressif/port/esp32/bootloader.conf @@ -2,6 +2,10 @@ # # SPDX-License-Identifier: Apache-2.0 +# Define upgrade mode (default is CONFIG_ESP_BOOT_SWAP_USING_SCRATCH) +# CONFIG_ESP_BOOT_SWAP_USING_MOVE=y +# CONFIG_ESP_BOOT_UPGRADE_ONLY=y + CONFIG_ESP_FLASH_SIZE=4MB CONFIG_ESP_BOOTLOADER_SIZE=0xF000 CONFIG_ESP_BOOTLOADER_OFFSET=0x1000 diff --git a/boot/espressif/port/esp32c2/bootloader.conf b/boot/espressif/port/esp32c2/bootloader.conf index 54f797e71..8f6886023 100644 --- a/boot/espressif/port/esp32c2/bootloader.conf +++ b/boot/espressif/port/esp32c2/bootloader.conf @@ -2,6 +2,10 @@ # # SPDX-License-Identifier: Apache-2.0 +# Define upgrade mode (default is CONFIG_ESP_BOOT_SWAP_USING_SCRATCH) +# CONFIG_ESP_BOOT_SWAP_USING_MOVE=y +# CONFIG_ESP_BOOT_UPGRADE_ONLY=y + CONFIG_ESP_FLASH_SIZE=4MB CONFIG_ESP_BOOTLOADER_SIZE=0xF000 CONFIG_ESP_BOOTLOADER_OFFSET=0x0000 diff --git a/boot/espressif/port/esp32c3/bootloader.conf b/boot/espressif/port/esp32c3/bootloader.conf index 88954eea0..8ebd1b40e 100644 --- a/boot/espressif/port/esp32c3/bootloader.conf +++ b/boot/espressif/port/esp32c3/bootloader.conf @@ -2,6 +2,10 @@ # # SPDX-License-Identifier: Apache-2.0 +# Define upgrade mode (default is CONFIG_ESP_BOOT_SWAP_USING_SCRATCH) +# CONFIG_ESP_BOOT_SWAP_USING_MOVE=y +# CONFIG_ESP_BOOT_UPGRADE_ONLY=y + CONFIG_ESP_FLASH_SIZE=4MB CONFIG_ESP_BOOTLOADER_SIZE=0xF000 CONFIG_ESP_BOOTLOADER_OFFSET=0x0000 diff --git a/boot/espressif/port/esp32c6/bootloader.conf b/boot/espressif/port/esp32c6/bootloader.conf index 5c5307c9c..e92ddcc22 100644 --- a/boot/espressif/port/esp32c6/bootloader.conf +++ b/boot/espressif/port/esp32c6/bootloader.conf @@ -2,6 +2,10 @@ # # SPDX-License-Identifier: Apache-2.0 +# Define upgrade mode (default is CONFIG_ESP_BOOT_SWAP_USING_SCRATCH) +# CONFIG_ESP_BOOT_SWAP_USING_MOVE=y +# CONFIG_ESP_BOOT_UPGRADE_ONLY=y + CONFIG_ESP_FLASH_SIZE=4MB CONFIG_ESP_BOOTLOADER_SIZE=0xF000 CONFIG_ESP_BOOTLOADER_OFFSET=0x0000 diff --git a/boot/espressif/port/esp32h2/bootloader.conf b/boot/espressif/port/esp32h2/bootloader.conf index 5c5307c9c..e92ddcc22 100644 --- a/boot/espressif/port/esp32h2/bootloader.conf +++ b/boot/espressif/port/esp32h2/bootloader.conf @@ -2,6 +2,10 @@ # # SPDX-License-Identifier: Apache-2.0 +# Define upgrade mode (default is CONFIG_ESP_BOOT_SWAP_USING_SCRATCH) +# CONFIG_ESP_BOOT_SWAP_USING_MOVE=y +# CONFIG_ESP_BOOT_UPGRADE_ONLY=y + CONFIG_ESP_FLASH_SIZE=4MB CONFIG_ESP_BOOTLOADER_SIZE=0xF000 CONFIG_ESP_BOOTLOADER_OFFSET=0x0000 diff --git a/boot/espressif/port/esp32s2/bootloader.conf b/boot/espressif/port/esp32s2/bootloader.conf index 485ba77e1..981be59a1 100644 --- a/boot/espressif/port/esp32s2/bootloader.conf +++ b/boot/espressif/port/esp32s2/bootloader.conf @@ -2,6 +2,10 @@ # # SPDX-License-Identifier: Apache-2.0 +# Define upgrade mode (default is CONFIG_ESP_BOOT_SWAP_USING_SCRATCH) +# CONFIG_ESP_BOOT_SWAP_USING_MOVE=y +# CONFIG_ESP_BOOT_UPGRADE_ONLY=y + CONFIG_ESP_FLASH_SIZE=4MB CONFIG_ESP_BOOTLOADER_SIZE=0xF000 CONFIG_ESP_BOOTLOADER_OFFSET=0x1000 diff --git a/boot/espressif/port/esp32s3/bootloader-multi.conf b/boot/espressif/port/esp32s3/bootloader-multi.conf index 21c3457a4..f82b5e235 100644 --- a/boot/espressif/port/esp32s3/bootloader-multi.conf +++ b/boot/espressif/port/esp32s3/bootloader-multi.conf @@ -2,6 +2,10 @@ # # SPDX-License-Identifier: Apache-2.0 +# Define upgrade mode (default is CONFIG_ESP_BOOT_SWAP_USING_SCRATCH) +# CONFIG_ESP_BOOT_SWAP_USING_MOVE=y +# CONFIG_ESP_BOOT_UPGRADE_ONLY=y + CONFIG_ESP_FLASH_SIZE=4MB CONFIG_ESP_BOOTLOADER_SIZE=0xF000 CONFIG_ESP_BOOTLOADER_OFFSET=0x0000 diff --git a/boot/espressif/port/esp32s3/bootloader.conf b/boot/espressif/port/esp32s3/bootloader.conf index 138737dfb..a45c0cd19 100644 --- a/boot/espressif/port/esp32s3/bootloader.conf +++ b/boot/espressif/port/esp32s3/bootloader.conf @@ -2,6 +2,10 @@ # # SPDX-License-Identifier: Apache-2.0 +# Define upgrade mode (default is CONFIG_ESP_BOOT_SWAP_USING_SCRATCH) +# CONFIG_ESP_BOOT_SWAP_USING_MOVE=y +# CONFIG_ESP_BOOT_UPGRADE_ONLY=y + CONFIG_ESP_FLASH_SIZE=4MB CONFIG_ESP_BOOTLOADER_SIZE=0xF000 CONFIG_ESP_BOOTLOADER_OFFSET=0x0000 diff --git a/boot/espressif/port/esp_mcuboot.c b/boot/espressif/port/esp_mcuboot.c index 0ee9e388b..9bbd5a9f2 100644 --- a/boot/espressif/port/esp_mcuboot.c +++ b/boot/espressif/port/esp_mcuboot.c @@ -15,6 +15,7 @@ #include "esp_err.h" #include "bootloader_flash_priv.h" #include "esp_flash_encrypt.h" +#include "mcuboot_config/mcuboot_config.h" #include "flash_map_backend/flash_map_backend.h" #include "sysflash/sysflash.h" @@ -49,16 +50,19 @@ _Static_assert(IS_ALIGNED(FLASH_BUFFER_SIZE, 4), "Buffer size for SPI Flash oper #define BOOTLOADER_START_ADDRESS CONFIG_BOOTLOADER_OFFSET_IN_FLASH #define BOOTLOADER_SIZE CONFIG_ESP_BOOTLOADER_SIZE + #define IMAGE0_PRIMARY_START_ADDRESS CONFIG_ESP_IMAGE0_PRIMARY_START_ADDRESS #define IMAGE0_SECONDARY_START_ADDRESS CONFIG_ESP_IMAGE0_SECONDARY_START_ADDRESS -#define SCRATCH_OFFSET CONFIG_ESP_SCRATCH_OFFSET #if (MCUBOOT_IMAGE_NUMBER == 2) #define IMAGE1_PRIMARY_START_ADDRESS CONFIG_ESP_IMAGE1_PRIMARY_START_ADDRESS #define IMAGE1_SECONDARY_START_ADDRESS CONFIG_ESP_IMAGE1_SECONDARY_START_ADDRESS #endif - #define APPLICATION_SIZE CONFIG_ESP_APPLICATION_SIZE + +#ifdef CONFIG_ESP_BOOT_SWAP_USING_SCRATCH +#define SCRATCH_OFFSET CONFIG_ESP_SCRATCH_OFFSET #define SCRATCH_SIZE CONFIG_ESP_SCRATCH_SIZE +#endif extern int ets_printf(const char *fmt, ...); @@ -99,12 +103,14 @@ static const struct flash_area secondary_img1 = { }; #endif +#ifdef CONFIG_ESP_BOOT_SWAP_USING_SCRATCH static const struct flash_area scratch_img0 = { .fa_id = FLASH_AREA_IMAGE_SCRATCH, .fa_device_id = FLASH_DEVICE_INTERNAL_FLASH, .fa_off = SCRATCH_OFFSET, .fa_size = SCRATCH_SIZE, }; +#endif static const struct flash_area *s_flash_areas[] = { &bootloader, @@ -114,7 +120,9 @@ static const struct flash_area *s_flash_areas[] = { &primary_img1, &secondary_img1, #endif +#ifdef CONFIG_ESP_BOOT_SWAP_USING_SCRATCH &scratch_img0, +#endif }; static const struct flash_area *prv_lookup_flash_area(uint8_t id) { From d3080f10e5c72187c7c0d3f4e83455ac2c6ba04e Mon Sep 17 00:00:00 2001 From: Jamie Smith Date: Wed, 4 Dec 2024 00:44:09 -0800 Subject: [PATCH 05/15] Update Mbed CMakeLists.txt for Mbed CE Signed-off-by: Jamie Smith --- boot/mbed/CMakeLists.txt | 60 +++-- .../flash_map_backend/flash_map_backend.h | 5 + .../include/mcuboot_config/mcuboot_logging.h | 3 + boot/mbed/mbed_lib.json | 9 +- boot/mbed/mcuboot_imgtool.cmake | 219 ++++++++++++++++++ boot/mbed/mcuboot_main.cpp | 3 +- boot/mbed/src/flash_map_backend.cpp | 12 +- 7 files changed, 273 insertions(+), 38 deletions(-) create mode 100644 boot/mbed/mcuboot_imgtool.cmake diff --git a/boot/mbed/CMakeLists.txt b/boot/mbed/CMakeLists.txt index 8baa2628e..05199c380 100644 --- a/boot/mbed/CMakeLists.txt +++ b/boot/mbed/CMakeLists.txt @@ -1,10 +1,11 @@ # Copyright (c) 2021 ARM Limited. All rights reserved. # SPDX-License-Identifier: Apache-2.0 -# Mbed-MCUboot Port +# Pull in functions for working with imgtool +include(mcuboot_imgtool.cmake) +# Mbed-MCUboot Port cmake_minimum_required(VERSION 3.19.0 FATAL_ERROR) - get_filename_component(BOOT_UTIL_DIR ${CMAKE_CURRENT_SOURCE_DIR}/../bootutil REALPATH) set(LIB_TARGET mbed-mcuboot) @@ -13,49 +14,46 @@ set(LIB_BOOTUTIL bootutil) add_library(${LIB_TARGET} STATIC) target_include_directories(${LIB_TARGET} - PUBLIC - include - ${BOOT_UTIL_DIR}/include - ${BOOT_UTIL_DIR}/src + PUBLIC + include + ${BOOT_UTIL_DIR}/src ) target_sources(${LIB_TARGET} - PRIVATE - mcuboot_main.cpp - app_enc_keys.c - src/flash_map_backend.cpp - src/secondary_bd.cpp + PRIVATE + mcuboot_main.cpp + app_enc_keys.c + src/flash_map_backend.cpp + src/secondary_bd.cpp ) target_link_libraries(${LIB_TARGET} - PUBLIC - bootutil # Cross-dependency - mbed-mbedtls - mbed-storage-flashiap - mbed-storage-blockdevice + PUBLIC + bootutil # Cross-dependency + mbed-mbedtls + mbed-storage-flashiap + mbed-storage-blockdevice + mbed-core-flags ) -if("_RTE_" IN_LIST MBED_CONFIG_DEFINITIONS) - target_link_libraries(${LIB_TARGET} - PUBLIC - mbed-os - ) -else() - target_link_libraries(${LIB_TARGET} - PUBLIC - mbed-baremetal - ) +# Add signing key generated source file +mcuboot_generate_signing_keys_file(${CMAKE_CURRENT_BINARY_DIR}/signing_keys.c) +target_sources(${LIB_TARGET} PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/signing_keys.c) + +if("MCUBOOT_ENCRYPT_RSA=1" IN_LIST MBED_CONFIG_DEFINITIONS) + mcuboot_generate_encryption_key_file(${CMAKE_CURRENT_BINARY_DIR}/enc_keys.c) + target_sources(${LIB_TARGET} PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/enc_keys.c) endif() # The cross-dependency requires that bootutil have access to the mbed port's # include directory and is linked with the appropriate mbed-specific libraries. target_include_directories(${LIB_BOOTUTIL} - PUBLIC - include + PUBLIC + include ) target_link_libraries(${LIB_BOOTUTIL} - PUBLIC - mbed-mcuboot - mbed-mbedtls + PUBLIC + mbed-mcuboot + mbed-mbedtls ) diff --git a/boot/mbed/include/flash_map_backend/flash_map_backend.h b/boot/mbed/include/flash_map_backend/flash_map_backend.h index d526c5cfa..c8a9e3745 100644 --- a/boot/mbed/include/flash_map_backend/flash_map_backend.h +++ b/boot/mbed/include/flash_map_backend/flash_map_backend.h @@ -152,6 +152,11 @@ uint8_t flash_area_erased_val(const struct flash_area * fap); /* * Given flash area ID, return info about sectors within the area. + * + * Note: the sectors array has size MCUBOOT_MAX_IMG_SECTORS, and only that many elements should + * be stored into it. However, if the flash area has more than MCUBOOT_MAX_IMG_SECTORS sectors, + * the count variable should be set to indicate the real sector count. This will trigger the appropriate + * warning to be printed. */ int flash_area_get_sectors(int fa_id, uint32_t *count, struct flash_sector *sectors); diff --git a/boot/mbed/include/mcuboot_config/mcuboot_logging.h b/boot/mbed/include/mcuboot_config/mcuboot_logging.h index c6a1cf78a..e80b0a76f 100644 --- a/boot/mbed/include/mcuboot_config/mcuboot_logging.h +++ b/boot/mbed/include/mcuboot_config/mcuboot_logging.h @@ -36,6 +36,8 @@ #define MCUBOOT_LOG_LEVEL MCUBOOT_LOG_LEVEL_OFF #endif +// Set Mbed log level appropriately if not already set +#ifndef MBED_TRACE_MAX_LEVEL #if MCUBOOT_LOG_LEVEL == MCUBOOT_LOG_LEVEL_ERROR #define MBED_TRACE_MAX_LEVEL TRACE_LEVEL_ERROR #elif MCUBOOT_LOG_LEVEL == MCUBOOT_LOG_LEVEL_WARNING @@ -45,6 +47,7 @@ #elif MCUBOOT_LOG_LEVEL == MCUBOOT_LOG_LEVEL_DEBUG #define MBED_TRACE_MAX_LEVEL TRACE_LEVEL_DEBUG #endif +#endif #define TRACE_GROUP "MCUb" #include "mbed-trace/mbed_trace.h" diff --git a/boot/mbed/mbed_lib.json b/boot/mbed/mbed_lib.json index f5b7b6743..f7c7ff14f 100644 --- a/boot/mbed/mbed_lib.json +++ b/boot/mbed/mbed_lib.json @@ -88,7 +88,7 @@ "value": true }, "max-img-sectors": { - "help": "Maximum number of flash sectors per image slot. Target-dependent, please set on a per-target basis.", + "help": "Maximum number of flash sectors per image slot. This should be set to account for the sector sizes of both the main and secondary block devices. Target-dependent, please set on a per-target basis.", "macro_name": "MCUBOOT_MAX_IMG_SECTORS", "required": true }, @@ -119,7 +119,7 @@ "value": null }, "encrypt-rsa": { - "help": "Encrypt images using RSA (NOT TESTED)", + "help": "Encrypt update images using RSA", "macro_name": "MCUBOOT_ENCRYPT_RSA", "accepted_values": [true, null], "value": null @@ -189,6 +189,11 @@ "xip-secondary-slot-address": { "help": "Specify start address for secondary slot address in XIP-accessible memory. This is required if direct-xip is enabled.", "value": null + }, + "flash-block-size": { + "help": "Size in bytes of a programmable block of the flash memory.", + "macro_name": "MCUBOOT_BOOT_MAX_ALIGN", + "value": 8 } } } diff --git a/boot/mbed/mcuboot_imgtool.cmake b/boot/mbed/mcuboot_imgtool.cmake new file mode 100644 index 000000000..9760196fe --- /dev/null +++ b/boot/mbed/mcuboot_imgtool.cmake @@ -0,0 +1,219 @@ +# Copyright (c) 2024 Jamie Smith +# SPDX-License-Identifier: Apache-2.0 + +check_python_package(imgtool.main MCUBOOT_IMGTOOL_FOUND) + +get_filename_component(IMGTOOL_SCRIPTS_DIR ${CMAKE_CURRENT_LIST_DIR}/../../scripts REALPATH) + +# Find or install imgtool + +if(NOT MCUBOOT_IMGTOOL_FOUND) + # If we are using the Mbed venv, we can install asn1tools automatically + if(MBED_CREATE_PYTHON_VENV) + message(STATUS "mcuboot: Installing imgtool into Mbed's Python virtualenv") + execute_process( + COMMAND ${Python3_EXECUTABLE} -m pip install ${IMGTOOL_SCRIPTS_DIR} + COMMAND_ERROR_IS_FATAL ANY + ) + else() + message(FATAL_ERROR "The mcuboot imgtool python package needs to be installed (from mcuboot/scripts/) into Mbed's python interpreter (${Python3_EXECUTABLE})") + endif() +endif() + +# Signing key +set(MCUBOOT_SIGNING_KEY "" CACHE STRING "Path to key file (.pem) used to sign firmware updates for your device. The public key will be stored in the bootloader. This file must be kept safe!") + +# Make sure the signing key path is absolute for EXISTS, relative to the top level build dir +get_filename_component(MCUBOOT_SIGNING_KEY_ABSPATH "${MCUBOOT_SIGNING_KEY}" ABSOLUTE BASE_DIR ${CMAKE_SOURCE_DIR}) +set(MCUBOOT_SIGNING_KEY_ABSPATH ${MCUBOOT_SIGNING_KEY_ABSPATH} CACHE INTERNAL "Absolute version of MCUBOOT_SIGNING_KEY" FORCE) + +if("${MCUBOOT_SIGNING_KEY}" STREQUAL "" OR NOT EXISTS "${MCUBOOT_SIGNING_KEY_ABSPATH}") + message(FATAL_ERROR "Must specify path to valid image signing key via MCUBOOT_SIGNING_KEY CMake option in order to build this project.") +endif() + +# Encryption key +if("MCUBOOT_ENCRYPT_RSA=1" IN_LIST MBED_CONFIG_DEFINITIONS) + set(MCUBOOT_ENCRYPTION_KEY "" CACHE STRING "Path to key file (.pem) used to encrypt firmware updates for your device. The private key will be stored in the bootloader. This file must be kept safe!") + + # Make sure the signing key path is absolute for EXISTS, relative to the top level build dir + get_filename_component(MCUBOOT_ENCRYPTION_KEY_ABSPATH "${MCUBOOT_ENCRYPTION_KEY}" ABSOLUTE BASE_DIR ${CMAKE_SOURCE_DIR}) + set(MCUBOOT_ENCRYPTION_KEY_ABSPATH ${MCUBOOT_ENCRYPTION_KEY_ABSPATH} CACHE INTERNAL "Absolute version of MCUBOOT_ENCRYPTION_KEY" FORCE) + + if("${MCUBOOT_ENCRYPTION_KEY}" STREQUAL "" OR NOT EXISTS "${MCUBOOT_ENCRYPTION_KEY_ABSPATH}") + message(FATAL_ERROR "Since mcuboot.encrypt-rsa is enabled, you must specify the path to a valid image encryption key via the MCUBOOT_ENCRYPTION_KEY CMake option in order to build this project.") + endif() +endif() + +# Imgtool usage functions + +# +# Generate a signed image hex file for the given executable target. +# +function(_mcuboot_generate_image TARGET IMAGE_TYPE IMAGE_BASE_PATH) + if("${MBED_OUTPUT_EXT}" STREQUAL "bin") + message(FATAL_ERROR "Hex file output must be enabled to use mcuboot. Set MBED_OUTPUT_EXT to empty string after including app.cmake in your top level CMakeLists.txt!") + endif() + + if("${PROJECT_VERSION}" STREQUAL "") + message(FATAL_ERROR "You must set the project version to sign images by passing a version number into your app's project() command!") + endif() + + # mbed_generate_bin_hex() puts the hex file at the following path + set(TARGET_HEX_FILE ${CMAKE_CURRENT_BINARY_DIR}/$.hex) + + # Grab header size + if(NOT "${MBED_CONFIG_DEFINITIONS}" MATCHES "MCUBOOT_HEADER_SIZE=(0x[0-9A-Fa-f]+)") + message(FATAL_ERROR "Couldn't find MCUBOOT_HEADER_SIZE in Mbed configuration!") + endif() + set(HEADER_SIZE_HEX ${CMAKE_MATCH_1}) + + # Grab slot size + if(NOT "${MBED_CONFIG_DEFINITIONS}" MATCHES "MCUBOOT_SLOT_SIZE=(0x[0-9A-Fa-f]+)") + message(FATAL_ERROR "Couldn't find MCUBOOT_SLOT_SIZE in Mbed configuration!") + endif() + set(SLOT_SIZE_HEX ${CMAKE_MATCH_1}) + + get_property(objcopy GLOBAL PROPERTY ELF2BIN) + + if(${IMAGE_TYPE} STREQUAL "update" AND "MCUBOOT_ENCRYPT_RSA=1" IN_LIST MBED_CONFIG_DEFINITIONS) + set(IMGTOOL_EXTRA_ARGS --encrypt ${MCUBOOT_ENCRYPTION_KEY_ABSPATH}) + elseif(${IMAGE_TYPE} STREQUAL "initial" AND "MCUBOOT_ENCRYPT_RSA=1" IN_LIST MBED_CONFIG_DEFINITIONS) + # If encryption is enabled, generate unencrypted initial image which supports encryption. + # See https://github.com/mbed-ce/mbed-os/issues/401#issuecomment-2567099213 + set(IMGTOOL_EXTRA_ARGS --clear) + else() + set(IMGTOOL_EXTRA_ARGS "") + endif() + + add_custom_command( + TARGET ${TARGET} + POST_BUILD + DEPENDS ${MCUBOOT_SIGNING_KEY_ABSPATH} + COMMAND + ${Python3_EXECUTABLE} -m imgtool.main + sign + --key ${MCUBOOT_SIGNING_KEY_ABSPATH} # this specifies the file containing the keys used to sign/verify the application + --align 4 # this lets mcuboot know the intrinsic alignment of the flash (32-bits = 4 byte alignment) + --version ${PROJECT_VERSION} # this sets the version number of the application + --header-size ${HEADER_SIZE_HEX} # this must be the same as the value specified in mcuboot.header-size configuration + --pad-header # this tells imgtool to insert the entire header, including any necessary padding bytes. + --slot-size ${SLOT_SIZE_HEX} # this specifies the maximum size of the application ("slot size"). It must be the same as the configured mcuboot.slot-size! + ${IMGTOOL_EXTRA_ARGS} + ${TARGET_HEX_FILE} ${IMAGE_BASE_PATH}.hex + + COMMAND + ${CMAKE_COMMAND} -E echo "-- built: ${IMAGE_BASE_PATH}.hex" + + # Also generate bin file + COMMAND + ${objcopy} -I ihex -O binary ${IMAGE_BASE_PATH}.hex ${IMAGE_BASE_PATH}.bin + + COMMAND + ${CMAKE_COMMAND} -E echo "-- built: ${IMAGE_BASE_PATH}.bin" + + COMMENT "Generating mcuboot ${IMAGE_TYPE} image for ${TARGET}..." + WORKING_DIRECTORY ${CMAKE_BINARY_DIR} + VERBATIM + ) +endfunction(_mcuboot_generate_image) + +# +# Generate an initial image hex file for the given executable target. +# This initial image is what should be flashed to a blank device (along with the bootloader). +# A flash target (ninja flash-${TARGET}-initial-image) will also be created. +# +# NOTE: This function must be called *after* mbed_set_post_build() for the target! +# +# If you wish to specify the base name of the initial image, pass that as the second argument to +# this function. Otherwise, it will default to $-initial-image +# +function(mcuboot_generate_initial_image TARGET) # optional 2nd arg: initial image base filename + # Figure out file path + if("${ARGN}" STREQUAL "") + set(INITIAL_IMAGE_BASE_PATH ${CMAKE_CURRENT_BINARY_DIR}/$-initial-image) + else() + set(INITIAL_IMAGE_BASE_PATH ${CMAKE_CURRENT_BINARY_DIR}/${ARGN}) + endif() + + _mcuboot_generate_image(${TARGET} initial ${INITIAL_IMAGE_BASE_PATH}) + + # Create a flash target. + # We need to be slightly creative here -- Mbed thinks that the application start address + # is +
, but we actually want to upload to . + # So we need to temporarily override MBED_UPLOAD_BASE_ADDR with an offset value + if(NOT "${MBED_CONFIG_DEFINITIONS}" MATCHES "MCUBOOT_HEADER_SIZE=(0x[0-9A-Fa-f]+)") + message(FATAL_ERROR "Couldn't find MCUBOOT_HEADER_SIZE in Mbed configuration!") + endif() + set(HEADER_SIZE_HEX ${CMAKE_MATCH_1}) + math(EXPR MBED_UPLOAD_BASE_ADDR "${MBED_UPLOAD_BASE_ADDR} - ${HEADER_SIZE_HEX}" OUTPUT_FORMAT HEXADECIMAL) + + gen_upload_target(${TARGET}-initial-image ${INITIAL_IMAGE_BASE_PATH}.bin) + if(TARGET flash-${TARGET}-initial-image) + add_dependencies(flash-${TARGET}-initial-image ${TARGET}) + endif() +endfunction(mcuboot_generate_initial_image) + +# +# Generate an update image hex file for the given executable target. +# This image is what should be flashed to the secondary block device and passed to +# mcuboot as an update file. +# +# NOTE: This function must be called *after* mbed_set_post_build() for the target! +# +# NOTE 2: The hex file produced by this function will still "declare" its address as the primary slot +# address. This can cause issues if you pass it to a tool that uses this offset to decide where to load it. +# If this is a problem, we recommend the "arm-none-eabi-objcopy --change-addresses" command to change this address. +# +# If you wish to specify the base name of the update image, pass that as the second argument to +# this function. Otherwise, it will default to $-update-image +# +function(mcuboot_generate_update_image TARGET) # optional 2nd arg: update image base filename + # Figure out file path + if("${ARGN}" STREQUAL "") + set(UPDATE_IMAGE_BASE_PATH ${CMAKE_CURRENT_BINARY_DIR}/$-update-image) + else() + set(UPDATE_IMAGE_BASE_PATH${CMAKE_CURRENT_BINARY_DIR}/${ARGN}) + endif() + + _mcuboot_generate_image(${TARGET} update ${UPDATE_IMAGE_BASE_PATH}) +endfunction(mcuboot_generate_update_image) + +# +# Generate a C source file with signing keys in it at the given location. +# The file should be added as a source file to a library built in the same directory. +# +function(mcuboot_generate_signing_keys_file SIGNING_KEYS_C_PATH) + add_custom_command( + OUTPUT ${SIGNING_KEYS_C_PATH} + COMMAND + ${Python3_EXECUTABLE} -m imgtool.main + getpub + --key ${MCUBOOT_SIGNING_KEY_ABSPATH} + --output ${SIGNING_KEYS_C_PATH} + + DEPENDS ${MCUBOOT_SIGNING_KEY_ABSPATH} + COMMENT "Converting signing key to C source..." + WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} + VERBATIM + ) +endfunction(mcuboot_generate_signing_keys_file) + +# +# Generate a C source file with the encryption private key in it at the given location. +# The file should be added as a source file to a library built in the same directory. +# +function(mcuboot_generate_encryption_key_file ENC_KEY_C_PATH) + add_custom_command( + OUTPUT ${ENC_KEY_C_PATH} + COMMAND + ${Python3_EXECUTABLE} -m imgtool.main + getpriv + --key ${MCUBOOT_SIGNING_KEY_ABSPATH} + > ${ENC_KEY_C_PATH} + + DEPENDS ${MCUBOOT_SIGNING_KEY_ABSPATH} + COMMENT "Converting encryption key to C source..." + WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} + VERBATIM + ) +endfunction(mcuboot_generate_encryption_key_file) \ No newline at end of file diff --git a/boot/mbed/mcuboot_main.cpp b/boot/mbed/mcuboot_main.cpp index bf95e3abf..3c31bdf49 100644 --- a/boot/mbed/mcuboot_main.cpp +++ b/boot/mbed/mcuboot_main.cpp @@ -19,6 +19,7 @@ #if MCUBOOT_BOOTLOADER_BUILD #include +#include #include "bootutil/bootutil.h" #include "bootutil/image.h" #include "hal/serial_api.h" @@ -83,7 +84,7 @@ int main() // Workaround: The extra \n ensures the last trace gets flushed // before mbed_start_application() destroys the stack and jumps // to the application - tr_info("Booting firmware image at 0x%x\n", address); + tr_info("Booting firmware image at 0x%" PRIx32 "\n", address); // Run the application in the primary slot // Add header size offset to calculate the actual start address of application diff --git a/boot/mbed/src/flash_map_backend.cpp b/boot/mbed/src/flash_map_backend.cpp index 955ac42b6..d673e5038 100644 --- a/boot/mbed/src/flash_map_backend.cpp +++ b/boot/mbed/src/flash_map_backend.cpp @@ -18,6 +18,7 @@ #include #include +#include #include "flash_map_backend/flash_map_backend.h" #include "flash_map_backend/secondary_bd.h" #include "sysflash/sysflash.h" @@ -142,7 +143,7 @@ int flash_area_read(const struct flash_area* fap, uint32_t off, void* dst, uint3 return -1; } if (MCUBOOT_READ_GRANULARITY < read_size) { - MCUBOOT_LOG_ERR("Please increase MCUBOOT_READ_GRANULARITY (currently %u) to be at least %u", + MCUBOOT_LOG_ERR("Please increase MCUBOOT_READ_GRANULARITY (currently %u) to be at least %" PRIu32, MCUBOOT_READ_GRANULARITY, read_size); return -1; } @@ -214,11 +215,14 @@ int flash_area_get_sectors(int fa_id, uint32_t* count, struct flash_sector* sect /* Loop through sectors and collect information on them */ bd_addr_t offset = 0; *count = 0; - while (*count < MCUBOOT_MAX_IMG_SECTORS && bd->is_valid_read(offset, bd->get_read_size())) { + while (bd->is_valid_read(offset, bd->get_read_size())) { - sectors[*count].fs_off = offset; bd_size_t erase_size = bd->get_erase_size(offset); - sectors[*count].fs_size = erase_size; + + if (*count < MCUBOOT_MAX_IMG_SECTORS) { + sectors[*count].fs_off = offset; + sectors[*count].fs_size = erase_size; + } offset += erase_size; *count += 1; From 4bda587549c0fccd5cd9b59d76c8edf061ee84c3 Mon Sep 17 00:00:00 2001 From: Jamie McCrae Date: Thu, 9 Jan 2025 11:09:49 +0000 Subject: [PATCH 06/15] boot: bootutil: Add TLV for size of compressed but decrypted image This TLV is needed in order to know what the data length provided to the decompression system is to remove the padding that is a resultant of the encryption block size Signed-off-by: Jamie McCrae --- boot/bootutil/include/bootutil/image.h | 1 + 1 file changed, 1 insertion(+) diff --git a/boot/bootutil/include/bootutil/image.h b/boot/bootutil/include/bootutil/image.h index 243910815..501ee33ee 100644 --- a/boot/bootutil/include/bootutil/image.h +++ b/boot/bootutil/include/bootutil/image.h @@ -126,6 +126,7 @@ struct flash_area; * the format and size of the raw slot (compressed) * signature */ +#define IMAGE_TLV_COMP_DEC_SIZE 0x73 /* Compressed decrypted image size */ /* * vendor reserved TLVs at xxA0-xxFF, * where xx denotes the upper byte From 517fc979386713afb2ef8fbd8e5430720af15791 Mon Sep 17 00:00:00 2001 From: Almir Okato Date: Thu, 19 Dec 2024 18:10:37 -0300 Subject: [PATCH 07/15] espressif: fix missing macro for esp32s3 XMC flash support Add CONFIG_BOOTLOADER_FLASH_XMC_SUPPORT macro to esp32s3 sdkconfig.h Signed-off-by: Almir Okato --- boot/espressif/hal/include/esp32s3/sdkconfig.h | 1 + 1 file changed, 1 insertion(+) diff --git a/boot/espressif/hal/include/esp32s3/sdkconfig.h b/boot/espressif/hal/include/esp32s3/sdkconfig.h index 25581c80d..9d5762358 100644 --- a/boot/espressif/hal/include/esp32s3/sdkconfig.h +++ b/boot/espressif/hal/include/esp32s3/sdkconfig.h @@ -25,3 +25,4 @@ #define CONFIG_EFUSE_VIRTUAL_OFFSET 0x250000 #define CONFIG_EFUSE_VIRTUAL_SIZE 0x2000 #define CONFIG_EFUSE_MAX_BLK_LEN 256 +#define CONFIG_BOOTLOADER_FLASH_XMC_SUPPORT 1 From 9286264563ab5509d2ae74fab8fa4b201c7982ff Mon Sep 17 00:00:00 2001 From: Almir Okato Date: Thu, 19 Dec 2024 18:16:10 -0300 Subject: [PATCH 08/15] espressif: update readme-espressif.md documentation Update SoC x RTOS status for ESP32-C2, ESP32-C6 and ESP32-H2 Also add missing cd command to the guide Signed-off-by: Almir Okato --- docs/readme-espressif.md | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/docs/readme-espressif.md b/docs/readme-espressif.md index 21004df98..9629b66a6 100644 --- a/docs/readme-espressif.md +++ b/docs/readme-espressif.md @@ -14,10 +14,10 @@ Documentation about the MCUboot bootloader design, operation and features can be The current port is available for use in the following SoCs within the OSes: -| | ESP32 | ESP32-S2 | ESP32-C3 | ESP32-S3 | ESP32-C2 | ESP32-C6 | ESP32-H2 | -| :----: | :-----: | :-----: | :-----: | :-----: | :---------: | :-----: | :-----: | -| Zephyr | Supported | Supported | Supported | Supported | In progress | In progress | In progress | -| NuttX | Supported | Supported | Supported | Supported | In progress | In progress | In progress | +| | ESP32 | ESP32-S2 | ESP32-C3 | ESP32-S3 | ESP32-C2 | ESP32-C6 | ESP32-H2 | +| :----: | :-------: | :-------: | :-------: | :-------: | :---------: | :-------: | :---------: | +| Zephyr | Supported | Supported | Supported | Supported | Supported | Supported | In progress | +| NuttX | Supported | Supported | Supported | Supported | In progress | Supported | Supported | Notice that any customization in the memory layout from the OS application must be done aware of the bootloader own memory layout to avoid overlapping. More information on the section @@ -94,6 +94,10 @@ Additional configuration related to MCUboot features and slot partitioning may b 1. Compile and generate the BIN: + ```bash + cd /boot/espressif + ``` + ```bash cmake -DCMAKE_TOOLCHAIN_FILE=tools/toolchain-.cmake -DMCUBOOT_TARGET= -DESP_HAL_PATH= -DMCUBOOT_FLASH_PORT= -B build -GNinja ``` From 59e9f03bb3a78c78bdf100d66e9d088a344e7c33 Mon Sep 17 00:00:00 2001 From: Almir Okato Date: Thu, 19 Dec 2024 18:33:43 -0300 Subject: [PATCH 09/15] espressif: add checking for supported IDF version Verify if IDF-based HAL version is supported Signed-off-by: Almir Okato --- boot/espressif/CMakeLists.txt | 21 +++++++++++++++++++ boot/espressif/tools/utils.cmake | 13 ++++++++++++ ci/espressif_install.sh | 2 +- .../espressif-idf-version-checking.md | 2 ++ 4 files changed, 37 insertions(+), 1 deletion(-) create mode 100644 docs/release-notes.d/espressif-idf-version-checking.md diff --git a/boot/espressif/CMakeLists.txt b/boot/espressif/CMakeLists.txt index d1e18d2da..05358839c 100644 --- a/boot/espressif/CMakeLists.txt +++ b/boot/espressif/CMakeLists.txt @@ -14,6 +14,8 @@ endif() add_definitions(-DMCUBOOT_TARGET=${MCUBOOT_TARGET}) add_definitions(-D__ESPRESSIF__=1) +set(EXPECTED_IDF_HAL_VERSION "5.1.4") + if ("${MCUBOOT_TARGET}" STREQUAL "esp32" OR "${MCUBOOT_TARGET}" STREQUAL "esp32s2" OR "${MCUBOOT_TARGET}" STREQUAL "esp32s3") @@ -92,6 +94,25 @@ if (NOT DEFINED ESP_HAL_PATH) endif() endif() endif() +message(STATUS "Defined ESP_HAL_PATH: ${ESP_HAL_PATH}") + +# Verify from which IDF version the HAL is based on +set(IDF_VER_HEADER_FILE "${ESP_HAL_PATH}/components/esp_common/include/esp_idf_version.h") + +get_version_from_header("ESP_IDF_VERSION_MAJOR" ${IDF_VER_HEADER_FILE} IDF_VERSION_MAJOR) +get_version_from_header("ESP_IDF_VERSION_MINOR" ${IDF_VER_HEADER_FILE} IDF_VERSION_MINOR) +get_version_from_header("ESP_IDF_VERSION_PATCH" ${IDF_VER_HEADER_FILE} IDF_VERSION_PATCH) + +set(IDF_VERSION "${IDF_VERSION_MAJOR}.${IDF_VERSION_MINOR}.${IDF_VERSION_PATCH}") + +if (NOT IDF_VERSION VERSION_EQUAL ${EXPECTED_IDF_HAL_VERSION}) + message(FATAL_ERROR + "Unsupported HAL version ${IDF_VERSION}, expected ${EXPECTED_IDF_HAL_VERSION}. \ + Verify if the RTOS repository, where you are trying to build from, is up to date, \ + or check the installation pointed on ESP_HAL_PATH.") +else () + message(STATUS "HAL based on ESP-IDF version: ${IDF_VERSION}") +endif() execute_process( COMMAND git describe --tags diff --git a/boot/espressif/tools/utils.cmake b/boot/espressif/tools/utils.cmake index 238b30eb2..965571fda 100644 --- a/boot/espressif/tools/utils.cmake +++ b/boot/espressif/tools/utils.cmake @@ -29,3 +29,16 @@ function(parse_and_set_config_file CONFIG_FILE) endif() endforeach() endfunction() + +# Auxiliar function to get IDF version from esp_idf_version.h file +function(get_version_from_header VAR_NAME HEADER_FILE VERSION_OUT) + # Read the header file and extract the value of the specified macro + file(READ "${HEADER_FILE}" CONTENTS) + string(REGEX MATCH "#define ${VAR_NAME}[ ]+([0-9]+)" MATCH "${CONTENTS}") + if(MATCH) + string(REGEX REPLACE "#define ${VAR_NAME}[ ]+([0-9]+)" "\\1" VERSION "${MATCH}") + set(${VERSION_OUT} "${VERSION}" PARENT_SCOPE) + else() + message(FATAL_ERROR "Could not find ${VAR_NAME} in ${HEADER_FILE}") + endif() +endfunction() diff --git a/ci/espressif_install.sh b/ci/espressif_install.sh index c2ec2c4ed..4ac52c9ab 100755 --- a/ci/espressif_install.sh +++ b/ci/espressif_install.sh @@ -10,7 +10,7 @@ install_imgtool() { install_idf() { pushd $HOME - git clone --depth=1 https://github.com/espressif/esp-idf.git --branch release/v5.1 + git clone --depth=1 https://github.com/espressif/esp-idf.git --branch v5.1.4 [[ $? -ne 0 ]] && exit 1 $HOME/esp-idf/install.sh diff --git a/docs/release-notes.d/espressif-idf-version-checking.md b/docs/release-notes.d/espressif-idf-version-checking.md new file mode 100644 index 000000000..8944a6959 --- /dev/null +++ b/docs/release-notes.d/espressif-idf-version-checking.md @@ -0,0 +1,2 @@ +- Added verification for supported IDF-based HAL version. +- Fixed missing macro for XMC flash devices on ESP32-S3 From 256a02c3a5dd244f765c697a125b34ed1a52e576 Mon Sep 17 00:00:00 2001 From: Michael Konieczny Date: Sat, 11 Jan 2025 15:54:45 +0100 Subject: [PATCH 10/15] added missing MCUBOOT_VERSION_TWEAK in Zephyr port Signed-off-by: Michael Konieczny --- boot/zephyr/include/mcuboot_config/mcuboot_config.h | 1 + 1 file changed, 1 insertion(+) diff --git a/boot/zephyr/include/mcuboot_config/mcuboot_config.h b/boot/zephyr/include/mcuboot_config/mcuboot_config.h index 573155b39..60fb8e600 100644 --- a/boot/zephyr/include/mcuboot_config/mcuboot_config.h +++ b/boot/zephyr/include/mcuboot_config/mcuboot_config.h @@ -323,6 +323,7 @@ #define MCUBOOT_VERSION_MAJOR APP_VERSION_MAJOR #define MCUBOOT_VERSION_MINOR APP_VERSION_MINOR #define MCUBOOT_VERSION_PATCHLEVEL APP_PATCHLEVEL +#define MCUBOOT_VERSION_TWEAK APP_TWEAK #endif /* Support 32-byte aligned flash sizes */ From 1da18e9060d7af0df9b1e85e07c75ef717ad4723 Mon Sep 17 00:00:00 2001 From: Mateusz Michalek Date: Thu, 2 Jan 2025 14:48:28 +0100 Subject: [PATCH 11/15] scripts: imgtool: fix compression with encryption adds TLV which stores compressed image size in case encryption is on. This is to avoid wrong streaam size due to encryption padding. Signed-off-by: Mateusz Michalek --- scripts/imgtool/image.py | 11 ++++++++--- scripts/imgtool/main.py | 17 ++++++++++++----- 2 files changed, 20 insertions(+), 8 deletions(-) diff --git a/scripts/imgtool/image.py b/scripts/imgtool/image.py index 88ef7b90c..3e2c11073 100644 --- a/scripts/imgtool/image.py +++ b/scripts/imgtool/image.py @@ -94,6 +94,7 @@ 'DECOMP_SIZE': 0x70, 'DECOMP_SHA': 0x71, 'DECOMP_SIGNATURE': 0x72, + 'COMP_DEC_SIZE' : 0x73, } TLV_SIZE = 4 @@ -460,7 +461,7 @@ def create(self, key, public_key_format, enckey, dependencies=None, sw_type=None, custom_tlvs=None, compression_tlvs=None, compression_type=None, encrypt_keylen=128, clear=False, fixed_sig=None, pub_key=None, vector_to_sign=None, - user_sha='auto', is_pure=False): + user_sha='auto', is_pure=False, keep_comp_size=False, dont_encrypt=False): self.enckey = enckey # key decides on sha, then pub_key; of both are none default is used @@ -522,6 +523,9 @@ def create(self, key, public_key_format, enckey, dependencies=None, dependencies_num = len(dependencies[DEP_IMAGES_KEY]) protected_tlv_size += (dependencies_num * 16) + if keep_comp_size: + compression_tlvs["COMP_DEC_SIZE"] = struct.pack( + self.get_struct_endian() + 'L', self.image_size) if compression_tlvs is not None: for value in compression_tlvs.values(): protected_tlv_size += TLV_SIZE + len(value) @@ -537,7 +541,7 @@ def create(self, key, public_key_format, enckey, dependencies=None, # # This adds the padding if image is not aligned to the 16 Bytes # in encrypted mode - if self.enckey is not None: + if self.enckey is not None and dont_encrypt is False: pad_len = len(self.payload) % 16 if pad_len > 0: pad = bytes(16 - pad_len) @@ -594,6 +598,7 @@ def create(self, key, public_key_format, enckey, dependencies=None, prot_tlv.add(tag, value) protected_tlv_off = len(self.payload) + self.payload += prot_tlv.get() tlv = TLV(self.endian) @@ -657,7 +662,7 @@ def create(self, key, public_key_format, enckey, dependencies=None, if protected_tlv_off is not None: self.payload = self.payload[:protected_tlv_off] - if enckey is not None: + if enckey is not None and dont_encrypt is False: if encrypt_keylen == 256: plainkey = os.urandom(32) else: diff --git a/scripts/imgtool/main.py b/scripts/imgtool/main.py index 434530c7a..28caa8947 100755 --- a/scripts/imgtool/main.py +++ b/scripts/imgtool/main.py @@ -521,12 +521,11 @@ def sign(key, public_key_format, align, version, pad_sig, header_size, 'Pure signatures, currently, enforces preferred hash algorithm, ' 'and forbids sha selection by user.') - img.create(key, public_key_format, enckey, dependencies, boot_record, + if compression in ["lzma2", "lzma2armthumb"]: + img.create(key, public_key_format, enckey, dependencies, boot_record, custom_tlvs, compression_tlvs, None, int(encrypt_keylen), clear, baked_signature, pub_key, vector_to_sign, user_sha=user_sha, - is_pure=is_pure) - - if compression in ["lzma2", "lzma2armthumb"]: + is_pure=is_pure, keep_comp_size=False, dont_encrypt=True) compressed_img = image.Image(version=decode_version(version), header_size=header_size, pad_header=pad_header, pad=pad, confirm=confirm, align=int(align), @@ -562,12 +561,20 @@ def sign(key, public_key_format, align, version, pad_sig, header_size, lc = comp_default_lc, lp = comp_default_lp) compressed_img.load_compressed(compressed_data, compression_header) compressed_img.base_addr = img.base_addr + keep_comp_size = False; + if enckey: + keep_comp_size = True compressed_img.create(key, public_key_format, enckey, dependencies, boot_record, custom_tlvs, compression_tlvs, compression, int(encrypt_keylen), clear, baked_signature, pub_key, vector_to_sign, user_sha=user_sha, - is_pure=is_pure) + is_pure=is_pure, keep_comp_size=keep_comp_size) img = compressed_img + else: + img.create(key, public_key_format, enckey, dependencies, boot_record, + custom_tlvs, compression_tlvs, None, int(encrypt_keylen), clear, + baked_signature, pub_key, vector_to_sign, user_sha=user_sha, + is_pure=is_pure) img.save(outfile, hex_addr) if sig_out is not None: new_signature = img.get_signature() From b18b91c2b1fed39887e534631dea1a2a95f5b1d2 Mon Sep 17 00:00:00 2001 From: Jamie McCrae Date: Wed, 15 Jan 2025 13:35:35 +0000 Subject: [PATCH 12/15] boot: boot_serial: Fix uninitialised variables for upload Fixes some issues whereby some variables were not initialised, and undefined values were wrongly used instead Signed-off-by: Jamie McCrae --- boot/boot_serial/src/boot_serial.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/boot/boot_serial/src/boot_serial.c b/boot/boot_serial/src/boot_serial.c index 137cb5633..8b256c623 100644 --- a/boot/boot_serial/src/boot_serial.c +++ b/boot/boot_serial/src/boot_serial.c @@ -452,8 +452,8 @@ bs_set(char *buf, int len) uint8_t image_index = 0; size_t decoded = 0; uint8_t hash[IMAGE_HASH_SIZE]; - bool confirm; - struct zcbor_string img_hash; + bool confirm = false; + struct zcbor_string img_hash = { 0 }; bool ok; int rc; @@ -798,7 +798,7 @@ bs_upload(char *buf, int len) size_t img_size_tmp = SIZE_MAX; /* Temp variable for image size */ const struct flash_area *fap = NULL; int rc; - struct zcbor_string img_chunk_data; + struct zcbor_string img_chunk_data = { 0 }; size_t decoded = 0; bool ok; #ifdef MCUBOOT_ERASE_PROGRESSIVELY @@ -1021,7 +1021,7 @@ bs_upload(char *buf, int len) } } } else { - out_invalid_data: +out_invalid_data: rc = MGMT_ERR_EINVAL; } From 0cd1d0a46b8efc97a195b0a787aac067eaffd8cc Mon Sep 17 00:00:00 2001 From: Jamie McCrae Date: Wed, 15 Jan 2025 13:37:44 +0000 Subject: [PATCH 13/15] docs: release-notes: Add note on serial recovery fix Adds a note about a fix for unitialised variables Signed-off-by: Jamie McCrae --- docs/release-notes.d/serial-recovery-var.md | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 docs/release-notes.d/serial-recovery-var.md diff --git a/docs/release-notes.d/serial-recovery-var.md b/docs/release-notes.d/serial-recovery-var.md new file mode 100644 index 000000000..e86477ca8 --- /dev/null +++ b/docs/release-notes.d/serial-recovery-var.md @@ -0,0 +1,3 @@ +- Fixed issue with serial recovery variables not being + correctly initialised to default values which could cause + some commands to do unexpected operations From cd22b693da426826e0255f8ee5b18d7360d9bc8f Mon Sep 17 00:00:00 2001 From: Sylvio Alves Date: Mon, 13 Jan 2025 11:04:04 -0300 Subject: [PATCH 14/15] espressif: extend loader data Add additional regions in loader to include RTC, LP, IROM and DROM information. Signed-off-by: Sylvio Alves --- .../espressif/hal/include/esp_mcuboot_image.h | 29 ++++++--- boot/espressif/port/esp32s2/ld/bootloader.ld | 2 +- boot/espressif/port/esp_loader.c | 65 +++++++++++++++++++ .../espressif-idf-version-checking.md | 1 + 4 files changed, 88 insertions(+), 9 deletions(-) diff --git a/boot/espressif/hal/include/esp_mcuboot_image.h b/boot/espressif/hal/include/esp_mcuboot_image.h index baccf08fb..95b8a9c78 100644 --- a/boot/espressif/hal/include/esp_mcuboot_image.h +++ b/boot/espressif/hal/include/esp_mcuboot_image.h @@ -15,12 +15,25 @@ * for MCUboot-Espressif port booting. */ typedef struct esp_image_load_header { - uint32_t header_magic; /* Magic for load header */ - uint32_t entry_addr; /* Application entry address */ - uint32_t iram_dest_addr; /* Destination address(VMA) for IRAM region */ - uint32_t iram_flash_offset; /* Flash offset(LMA) for start of IRAM region */ - uint32_t iram_size; /* Size of IRAM region */ - uint32_t dram_dest_addr; /* Destination address(VMA) for DRAM region */ - uint32_t dram_flash_offset; /* Flash offset(LMA) for start of DRAM region */ - uint32_t dram_size; /* Size of DRAM region */ + uint32_t header_magic; /* Magic for load header */ + uint32_t entry_addr; /* Application entry address */ + uint32_t iram_dest_addr; /* Destination address(VMA) for IRAM region */ + uint32_t iram_flash_offset; /* Flash offset(LMA) for start of IRAM region */ + uint32_t iram_size; /* Size of IRAM region */ + uint32_t dram_dest_addr; /* Destination address(VMA) for DRAM region */ + uint32_t dram_flash_offset; /* Flash offset(LMA) for start of DRAM region */ + uint32_t dram_size; /* Size of DRAM region */ + uint32_t lp_rtc_iram_dest_addr; /* Destination address (VMA) for LP_IRAM region */ + uint32_t lp_rtc_iram_flash_offset; /* Flash offset (LMA) for LP_IRAM region */ + uint32_t lp_rtc_iram_size; /* Size of LP_IRAM region */ + uint32_t lp_rtc_dram_dest_addr; /* Destination address (VMA) for LP_DRAM region */ + uint32_t lp_rtc_dram_flash_offset; /* Flash offset (LMA) for LP_DRAM region */ + uint32_t lp_rtc_dram_size; /* Size of LP_DRAM region */ + uint32_t irom_map_addr; /* Mapped address (VMA) for IROM region */ + uint32_t irom_flash_offset; /* Flash offset (LMA) for IROM region */ + uint32_t irom_size; /* Size of IROM region */ + uint32_t drom_map_addr; /* Mapped address (VMA) for DROM region */ + uint32_t drom_flash_offset; /* Flash offset (LMA) for DROM region */ + uint32_t drom_size; /* Size of DROM region */ + uint32_t _reserved[4]; /* Up to 24 words reserved for the header */ } esp_image_load_header_t; diff --git a/boot/espressif/port/esp32s2/ld/bootloader.ld b/boot/espressif/port/esp32s2/ld/bootloader.ld index cf159c312..b615b73c5 100644 --- a/boot/espressif/port/esp32s2/ld/bootloader.ld +++ b/boot/espressif/port/esp32s2/ld/bootloader.ld @@ -14,7 +14,7 @@ MEMORY { iram_seg (RWX) : org = 0x40047000, len = 0x9000 iram_loader_seg (RWX) : org = 0x40050000, len = 0x6000 - dram_seg (RW) : org = 0x3FFE6000, len = 0x9000 + dram_seg (RW) : org = 0x3FFE6000, len = 0x9A00 } /* Default entry point: */ diff --git a/boot/espressif/port/esp_loader.c b/boot/espressif/port/esp_loader.c index 907466521..8180bc516 100644 --- a/boot/espressif/port/esp_loader.c +++ b/boot/espressif/port/esp_loader.c @@ -23,6 +23,24 @@ #include "app_cpu_start.h" #endif +#include "esp_rom_sys.h" +#include "esp_cpu.h" + +#if CONFIG_IDF_TARGET_ESP32 +#define LP_RTC_PREFIX "RTC" +#elif CONFIG_IDF_TARGET_ESP32S2 +#define LP_RTC_PREFIX "RTC" +#elif CONFIG_IDF_TARGET_ESP32S3 +#define LP_RTC_PREFIX "RTC" +#elif CONFIG_IDF_TARGET_ESP32C2 +#elif CONFIG_IDF_TARGET_ESP32C3 +#define LP_RTC_PREFIX "RTC" +#elif CONFIG_IDF_TARGET_ESP32C6 +#define LP_RTC_PREFIX "LP" +#elif CONFIG_IDF_TARGET_ESP32H2 +#define LP_RTC_PREFIX "LP" +#endif + static int load_segment(const struct flash_area *fap, uint32_t data_addr, uint32_t data_len, uint32_t load_addr) { const uint32_t *data = (const uint32_t *)bootloader_mmap((fap->fa_off + data_addr), data_len); @@ -69,6 +87,26 @@ void esp_app_image_load(int image_index, int slot, unsigned int hdr_offset, unsi FIH_PANIC; } +#if SOC_RTC_FAST_MEM_SUPPORTED + if (load_header.lp_rtc_iram_size > 0) { + if (!esp_ptr_in_rtc_iram_fast((void *)load_header.lp_rtc_iram_dest_addr) || + !esp_ptr_in_rtc_iram_fast((void *)(load_header.lp_rtc_iram_dest_addr + load_header.lp_rtc_iram_size))) { + BOOT_LOG_ERR("%s_IRAM region in load header is not valid. Aborting", LP_RTC_PREFIX); + FIH_PANIC; + } + } +#endif + +#if SOC_RTC_SLOW_MEM_SUPPORTED + if (load_header.lp_rtc_dram_size > 0) { + if (!esp_ptr_in_rtc_slow((void *)load_header.lp_rtc_dram_dest_addr) || + !esp_ptr_in_rtc_slow((void *)(load_header.lp_rtc_dram_dest_addr + load_header.lp_rtc_dram_size))) { + BOOT_LOG_ERR("%s_RAM region in load header is not valid. Aborting %p", LP_RTC_PREFIX, load_header.lp_rtc_dram_dest_addr); + FIH_PANIC; + } + } +#endif + if (!esp_ptr_in_iram((void *)load_header.entry_addr)) { BOOT_LOG_ERR("Application entry point (0x%x) is not in IRAM. Aborting", load_header.entry_addr); FIH_PANIC; @@ -80,6 +118,33 @@ void esp_app_image_load(int image_index, int slot, unsigned int hdr_offset, unsi BOOT_LOG_INF("IRAM segment: start=0x%x, size=0x%x, vaddr=0x%x", fap->fa_off + load_header.iram_flash_offset, load_header.iram_size, load_header.iram_dest_addr); load_segment(fap, load_header.iram_flash_offset, load_header.iram_size, load_header.iram_dest_addr); +#if SOC_RTC_FAST_MEM_SUPPORTED || SOC_RTC_SLOW_MEM_SUPPORTED + if (load_header.lp_rtc_dram_size > 0) { + soc_reset_reason_t reset_reason = esp_rom_get_reset_reason(0); + + /* Unless waking from deep sleep (implying RTC memory is intact), load its segments */ + if (reset_reason != RESET_REASON_CORE_DEEP_SLEEP) { + BOOT_LOG_INF("%s_RAM segment: paddr=%08xh, vaddr=%08xh, size=%05xh (%6d) load", LP_RTC_PREFIX, + (fap->fa_off + load_header.lp_rtc_dram_flash_offset), load_header.lp_rtc_dram_dest_addr, + load_header.lp_rtc_dram_size, load_header.lp_rtc_dram_size); + load_segment(fap, load_header.lp_rtc_dram_flash_offset, + load_header.lp_rtc_dram_size, load_header.lp_rtc_dram_dest_addr); + } else { + BOOT_LOG_INF("%s_RAM segment: paddr=%08xh, vaddr=%08xh, size=%05xh (%6d) noload", LP_RTC_PREFIX, + load_header.lp_rtc_dram_flash_offset, load_header.lp_rtc_dram_dest_addr, + load_header.lp_rtc_dram_size, load_header.lp_rtc_dram_size); + } + } + + if (load_header.lp_rtc_iram_size > 0) { + BOOT_LOG_INF("%s_IRAM segment: paddr=%08xh, vaddr=%08xh, size=%05xh (%6d) load", LP_RTC_PREFIX, + (fap->fa_off + load_header.lp_rtc_iram_flash_offset), load_header.lp_rtc_iram_dest_addr, + load_header.lp_rtc_iram_size, load_header.lp_rtc_iram_size); + load_segment(fap, load_header.lp_rtc_iram_flash_offset, + load_header.lp_rtc_iram_size, load_header.lp_rtc_iram_dest_addr); + } +#endif + BOOT_LOG_INF("start=0x%x", load_header.entry_addr); uart_tx_wait_idle(0); diff --git a/docs/release-notes.d/espressif-idf-version-checking.md b/docs/release-notes.d/espressif-idf-version-checking.md index 8944a6959..ff12912c7 100644 --- a/docs/release-notes.d/espressif-idf-version-checking.md +++ b/docs/release-notes.d/espressif-idf-version-checking.md @@ -1,2 +1,3 @@ - Added verification for supported IDF-based HAL version. - Fixed missing macro for XMC flash devices on ESP32-S3 +- Extended image loader header to include RTC/LP RAM, DROM and IROM segments. From 06747985eee7c27d891f2529c58e18f4a84ea6a3 Mon Sep 17 00:00:00 2001 From: Dominik Ermel Date: Fri, 3 Jan 2025 16:08:43 +0000 Subject: [PATCH 15/15] zephyr: Remove scratch from flash_area_id_from_multi_image_slot The mapping does not seem to be needed as scratch is opened directly, and there is only one for all images anyway. Simulator seems to error out when asked to identify scratch with this function. Signed-off-by: Dominik Ermel --- boot/zephyr/flash_map_extended.c | 3 --- 1 file changed, 3 deletions(-) diff --git a/boot/zephyr/flash_map_extended.c b/boot/zephyr/flash_map_extended.c index 4631da75b..bf0d8f191 100644 --- a/boot/zephyr/flash_map_extended.c +++ b/boot/zephyr/flash_map_extended.c @@ -62,9 +62,6 @@ int flash_area_id_from_multi_image_slot(int image_index, int slot) case 0: return FLASH_AREA_IMAGE_PRIMARY(image_index); #if !defined(CONFIG_SINGLE_APPLICATION_SLOT) case 1: return FLASH_AREA_IMAGE_SECONDARY(image_index); -#endif -#if defined(CONFIG_BOOT_SWAP_USING_SCRATCH) - case 2: return FLASH_AREA_IMAGE_SCRATCH; #endif }