From ba56472ac54b08aefb50ff45bb1377105ece1099 Mon Sep 17 00:00:00 2001 From: Dominik Ermel Date: Thu, 29 May 2025 13:43:14 +0000 Subject: [PATCH 001/420] [nrf fromlist] bootutil: Move all encryption TLV helper identifiers into one place Make enc_key_public.h single point of definitions for key sizes, TLV indexes and so on. Upstream PR #: 2327 Signed-off-by: Dominik Ermel (cherry picked from commit 2d9395822dcd0ed6fff7a85fc32da489eb49f491) --- .../include/bootutil/bootutil_macros.h | 19 +++++ boot/bootutil/include/bootutil/crypto/rsa.h | 4 +- boot/bootutil/include/bootutil/enc_key.h | 2 - .../include/bootutil/enc_key_public.h | 77 +++++++++++++++---- boot/bootutil/src/encrypted.c | 32 ++------ boot/bootutil/src/encrypted_psa.c | 10 --- 6 files changed, 86 insertions(+), 58 deletions(-) create mode 100644 boot/bootutil/include/bootutil/bootutil_macros.h diff --git a/boot/bootutil/include/bootutil/bootutil_macros.h b/boot/bootutil/include/bootutil/bootutil_macros.h new file mode 100644 index 000000000..e8d27b792 --- /dev/null +++ b/boot/bootutil/include/bootutil/bootutil_macros.h @@ -0,0 +1,19 @@ +/* + * SPDX-License-Identifier: Apache-2.0 + * + * Copyright (c) 2025 Nordic Semiconductor ASA + * + */ + +#ifndef H_BOOTUTIL_MACROS +#define H_BOOTUTIL_MACROS + +#ifndef ALIGN_UP +#define ALIGN_UP(num, align) (((num) + ((align) - 1)) & ~((align) - 1)) +#endif + +#ifndef ALIGN_DOWN +#define ALIGN_DOWN(num, align) ((num) & ~((align) - 1)) +#endif + +#endif diff --git a/boot/bootutil/include/bootutil/crypto/rsa.h b/boot/bootutil/include/bootutil/crypto/rsa.h index 581e4ec9b..87ab1de56 100644 --- a/boot/bootutil/include/bootutil/crypto/rsa.h +++ b/boot/bootutil/include/bootutil/crypto/rsa.h @@ -100,12 +100,12 @@ static int bootutil_rsa_oaep_decrypt( return -1; } size_t input_size = PSA_BITS_TO_BYTES(psa_get_key_bits(&key_attr)); - if (input_size != TLV_ENC_RSA_SZ) { + if (input_size != BOOT_ENC_TLV_SIZE) { return -1; } status = psa_asymmetric_decrypt(ctx->key_id, PSA_ALG_RSA_OAEP(PSA_ALG_SHA_256), - input, TLV_ENC_RSA_SZ, NULL, 0, + input, BOOT_ENC_TLV_SIZE, NULL, 0, output, output_max_len, olen); return (int)status; } diff --git a/boot/bootutil/include/bootutil/enc_key.h b/boot/bootutil/include/bootutil/enc_key.h index 9240d699d..85cb7e1b9 100644 --- a/boot/bootutil/include/bootutil/enc_key.h +++ b/boot/bootutil/include/bootutil/enc_key.h @@ -39,8 +39,6 @@ extern "C" { #endif -#define BOOT_ENC_TLV_ALIGN_SIZE ALIGN_UP(BOOT_ENC_TLV_SIZE, BOOT_MAX_ALIGN) - struct enc_key_data { uint8_t valid; bootutil_aes_ctr_context aes_ctr; diff --git a/boot/bootutil/include/bootutil/enc_key_public.h b/boot/bootutil/include/bootutil/enc_key_public.h index 6874cfbc8..55b06b025 100644 --- a/boot/bootutil/include/bootutil/enc_key_public.h +++ b/boot/bootutil/include/bootutil/enc_key_public.h @@ -28,37 +28,80 @@ #ifndef BOOTUTIL_ENC_KEY_PUBLIC_H #define BOOTUTIL_ENC_KEY_PUBLIC_H #include +#include + #ifdef __cplusplus extern "C" { #endif -#ifndef ALIGN_UP -#define ALIGN_UP(num, align) (((num) + ((align) - 1)) & ~((align) - 1)) -#endif +/* The unit provides following system wide definitions: + * BOOT_ENC_TLV_SIZE -- is the complete size of TLV with encryption data. + * BOOT_ENC_TLV -- is the encryption TLV type, should be given value + * of one of IMAGE_TVL_ENC_ identifiers. + * BOOT_ENC_KEY_SIZE -- is the encryption key size; this includes portion + * of TLV data stream taken by key. + * + * For ECIES based key exchange there is additionally provided: + * EC_PUBK_LEN -- is the length, in bytes, of a public key; depends + * selected key exchange. + * EC_PRIVK_LEN -- is the length, in bytes, of a private key; depends + * on selected key exchange. + * EC_SHARED_LEN -- is the length, in bytes, of a shared key resulting + * from processing of private and public key; depends + * on selected key exchange parameters. + * + * ECIES TLV processing uses following TLVs, from this header: + * EC_TAG_INDEX -- is the HMAC tag of encryption key index within TLV data + * stream. + * EC_TAG_LEN -- is the HMAC tag length. + * EC_PUBK_INDEX -- is the index of shared public key within TLV data stream; + * EC_PUBK_LEN represents length in bytes. + * EC_CIPHERKEY_INDEX -- is the encryption key index within TLV data stream. + * EC_CIPHERKEY_LEN -- is the length of an encryption key; depends on selected + * encryption. + * + * Note that in case of ECIES, the BOOT_ENC_TLV_SIZE will be defined as + * a sum of EC_*_LEN TLV components, defined for selected key exchange. + */ #ifdef MCUBOOT_AES_256 -#define BOOT_ENC_KEY_SIZE 32 +# define BOOT_ENC_KEY_SIZE 32 #else -#define BOOT_ENC_KEY_SIZE 16 +# define BOOT_ENC_KEY_SIZE 16 #endif -#define BOOT_ENC_KEY_ALIGN_SIZE ALIGN_UP(BOOT_ENC_KEY_SIZE, BOOT_MAX_ALIGN) - -#define TLV_ENC_RSA_SZ 256 -#define TLV_ENC_KW_SZ (BOOT_ENC_KEY_SIZE + 8) -#define TLV_ENC_EC256_SZ (65 + 32 + BOOT_ENC_KEY_SIZE) -#define TLV_ENC_X25519_SZ (32 + 32 + BOOT_ENC_KEY_SIZE) - #if defined(MCUBOOT_ENCRYPT_RSA) -#define BOOT_ENC_TLV_SIZE TLV_ENC_RSA_SZ +# define BOOT_ENC_TLV_SIZE (256) +# define BOOT_ENC_TLV IMAGE_TLV_ENC_RSA2048 #elif defined(MCUBOOT_ENCRYPT_EC256) -#define BOOT_ENC_TLV_SIZE TLV_ENC_EC256_SZ +# define EC_PUBK_LEN (65) +# define EC_PRIVK_LEN (32) +# define EC_SHARED_LEN (32) +# define BOOT_ENC_TLV IMAGE_TLV_ENC_EC256 #elif defined(MCUBOOT_ENCRYPT_X25519) -#define BOOT_ENC_TLV_SIZE TLV_ENC_X25519_SZ -#else -#define BOOT_ENC_TLV_SIZE TLV_ENC_KW_SZ +# define EC_PUBK_LEN (32) +# define EC_PRIVK_LEN (32) +# define EC_SHARED_LEN (32) +# define BOOT_ENC_TLV IMAGE_TLV_ENC_X25519 +#elif defined(MCUBOOT_ENCRYPT_KW) +# define BOOT_ENC_TLV_SIZE (BOOT_ENC_KEY_SIZE + 8) +# define BOOT_ENC_TLV IMAGE_TLV_ENC_KW #endif +/* Common ECIES definitions */ +#if defined(EC_PUBK_LEN) +# define EC_PUBK_INDEX (0) +# define EC_TAG_LEN (32) +# define EC_TAG_INDEX (EC_PUBK_INDEX + EC_PUBK_LEN) +# define EC_CIPHERKEY_INDEX (EC_TAG_INDEX + EC_TAG_LEN) +# define EC_CIPHERKEY_LEN BOOT_ENC_KEY_SIZE +# define EC_SHARED_KEY_LEN (32) +# define BOOT_ENC_TLV_SIZE (EC_PUBK_LEN + EC_TAG_LEN + EC_CIPHERKEY_LEN) +#endif + +#define BOOT_ENC_KEY_ALIGN_SIZE ALIGN_UP(BOOT_ENC_KEY_SIZE, BOOT_MAX_ALIGN) +#define BOOT_ENC_TLV_ALIGN_SIZE ALIGN_UP(BOOT_ENC_TLV_SIZE, BOOT_MAX_ALIGN) + #ifdef __cplusplus } #endif diff --git a/boot/bootutil/src/encrypted.c b/boot/bootutil/src/encrypted.c index bbe40751f..f64493656 100644 --- a/boot/bootutil/src/encrypted.c +++ b/boot/bootutil/src/encrypted.c @@ -46,28 +46,6 @@ #include "bootutil_priv.h" -#define EXPECTED_ENC_LEN BOOT_ENC_TLV_SIZE - -#if defined(MCUBOOT_ENCRYPT_RSA) -# define EXPECTED_ENC_TLV IMAGE_TLV_ENC_RSA2048 -#elif defined(MCUBOOT_ENCRYPT_KW) -# define EXPECTED_ENC_TLV IMAGE_TLV_ENC_KW -#elif defined(MCUBOOT_ENCRYPT_EC256) -# define EXPECTED_ENC_TLV IMAGE_TLV_ENC_EC256 -# define EC_PUBK_INDEX (0) -# define EC_TAG_INDEX (65) -# define EC_CIPHERKEY_INDEX (65 + 32) -_Static_assert(EC_CIPHERKEY_INDEX + BOOT_ENC_KEY_SIZE == EXPECTED_ENC_LEN, - "Please fix ECIES-P256 component indexes"); -#elif defined(MCUBOOT_ENCRYPT_X25519) -# define EXPECTED_ENC_TLV IMAGE_TLV_ENC_X25519 -# define EC_PUBK_INDEX (0) -# define EC_TAG_INDEX (32) -# define EC_CIPHERKEY_INDEX (32 + 32) -_Static_assert(EC_CIPHERKEY_INDEX + BOOT_ENC_KEY_SIZE == EXPECTED_ENC_LEN, - "Please fix ECIES-X25519 component indexes"); -#endif - /* NOUP Fixme: */ #if !defined(CONFIG_BOOT_ED25519_PSA) #if defined(MCUBOOT_ENCRYPT_EC256) || defined(MCUBOOT_ENCRYPT_X25519) @@ -104,7 +82,7 @@ key_unwrap(const uint8_t *wrapped, uint8_t *enckey, struct bootutil_key *bootuti if (rc != 0) { goto done; } - rc = bootutil_aes_kw_unwrap(&aes_kw, wrapped, TLV_ENC_KW_SZ, enckey, BOOT_ENC_KEY_SIZE); + rc = bootutil_aes_kw_unwrap(&aes_kw, wrapped, BOOT_ENC_TLV_SIZE, enckey, BOOT_ENC_KEY_SIZE); if (rc != 0) { goto done; } @@ -621,7 +599,7 @@ boot_enc_load(struct boot_loader_state *state, int slot, #if MCUBOOT_SWAP_SAVE_ENCTLV uint8_t *buf; #else - uint8_t buf[EXPECTED_ENC_LEN]; + uint8_t buf[BOOT_ENC_TLV_SIZE]; #endif int rc; @@ -641,7 +619,7 @@ boot_enc_load(struct boot_loader_state *state, int slot, #endif #endif - rc = bootutil_tlv_iter_begin(&it, hdr, fap, EXPECTED_ENC_TLV, false); + rc = bootutil_tlv_iter_begin(&it, hdr, fap, BOOT_ENC_TLV, false); if (rc) { return -1; } @@ -651,7 +629,7 @@ boot_enc_load(struct boot_loader_state *state, int slot, return rc; } - if (len != EXPECTED_ENC_LEN) { + if (len != BOOT_ENC_TLV_SIZE) { return -1; } @@ -660,7 +638,7 @@ boot_enc_load(struct boot_loader_state *state, int slot, memset(buf, 0xff, BOOT_ENC_TLV_ALIGN_SIZE); #endif - rc = flash_area_read(fap, off, buf, EXPECTED_ENC_LEN); + rc = flash_area_read(fap, off, buf, BOOT_ENC_TLV_SIZE); if (rc) { return -1; } diff --git a/boot/bootutil/src/encrypted_psa.c b/boot/bootutil/src/encrypted_psa.c index 313372fb1..d604df201 100644 --- a/boot/bootutil/src/encrypted_psa.c +++ b/boot/bootutil/src/encrypted_psa.c @@ -27,16 +27,6 @@ BOOT_LOG_MODULE_DECLARE(mcuboot_psa_enc); -#define EXPECTED_ENC_LEN BOOT_ENC_TLV_SIZE -#define EC_PUBK_INDEX (0) -#define EC_PUBK_LEN (32) -#define EC_TAG_INDEX (EC_PUBK_INDEX + EC_PUBK_LEN) -#define EC_TAG_LEN (32) -#define EC_CIPHERKEY_INDEX (EC_TAG_INDEX + EC_TAG_LEN) -#define EC_CIPHERKEY_LEN BOOT_ENC_KEY_SIZE -_Static_assert(EC_CIPHERKEY_INDEX + BOOT_ENC_KEY_SIZE == EXPECTED_ENC_LEN, - "Please fix ECIES-X25519 component indexes"); - #define X25519_OID "\x6e" static const uint8_t ec_pubkey_oid[] = MBEDTLS_OID_ISO_IDENTIFIED_ORG \ MBEDTLS_OID_ORG_GOV X25519_OID; From 4fb63a68022b62451bdcca2b2c25a3968eaaedbc Mon Sep 17 00:00:00 2001 From: Dominik Ermel Date: Thu, 29 May 2025 16:14:33 +0000 Subject: [PATCH 002/420] [nrf fromlist] bootutil: Remove redundant ALIGN definitions Use bootutil_macros.h instead. Upstream PR #: 2327 Signed-off-by: Dominik Ermel (cherry picked from commit c1bb3a34cf3d0d6ed612b15716946dfdd59132d7) --- boot/bootutil/include/bootutil/bootutil_public.h | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-) diff --git a/boot/bootutil/include/bootutil/bootutil_public.h b/boot/bootutil/include/bootutil/bootutil_public.h index e2795ab3e..933553f9f 100644 --- a/boot/bootutil/include/bootutil/bootutil_public.h +++ b/boot/bootutil/include/bootutil/bootutil_public.h @@ -43,20 +43,13 @@ #include #include #include +#include #include #ifdef __cplusplus extern "C" { #endif -#ifndef ALIGN_UP -#define ALIGN_UP(num, align) (((num) + ((align) - 1)) & ~((align) - 1)) -#endif - -#ifndef ALIGN_DOWN -#define ALIGN_DOWN(num, align) ((num) & ~((align) - 1)) -#endif - /** Attempt to boot the contents of the primary slot. */ #define BOOT_SWAP_TYPE_NONE 1 From 6e4285ae3e5c759082c8c7e0c067efb012a4b9bc Mon Sep 17 00:00:00 2001 From: Dominik Ermel Date: Fri, 30 May 2025 17:01:49 +0000 Subject: [PATCH 003/420] [nrf fromlist] bootutil: Replace local identifiers with common definitions Cleanup. Upstream PR #: 2327 Signed-off-by: Dominik Ermel (cherry picked from commit f4a50814f17d26da4208b62d2f14ec09c5b67d64) --- boot/bootutil/src/encrypted.c | 21 +++++++++------------ boot/bootutil/src/encrypted_psa.c | 8 +++----- 2 files changed, 12 insertions(+), 17 deletions(-) diff --git a/boot/bootutil/src/encrypted.c b/boot/bootutil/src/encrypted.c index f64493656..e0078a7be 100644 --- a/boot/bootutil/src/encrypted.c +++ b/boot/bootutil/src/encrypted.c @@ -97,9 +97,6 @@ key_unwrap(const uint8_t *wrapped, uint8_t *enckey, struct bootutil_key *bootuti static const uint8_t ec_pubkey_oid[] = MBEDTLS_OID_EC_ALG_UNRESTRICTED; static const uint8_t ec_secp256r1_oid[] = MBEDTLS_OID_EC_GRP_SECP256R1; -#define SHARED_KEY_LEN NUM_ECC_BYTES -#define PRIV_KEY_LEN NUM_ECC_BYTES - /* * Parses the output of `imgtool keygen`, which produces a PKCS#8 elliptic * curve keypair. See RFC5208 and RFC5915. @@ -179,9 +176,6 @@ parse_ec256_enckey(uint8_t **p, uint8_t *end, uint8_t *private_key) static const uint8_t ec_pubkey_oid[] = MBEDTLS_OID_ISO_IDENTIFIED_ORG \ MBEDTLS_OID_ORG_GOV X25519_OID; -#define SHARED_KEY_LEN 32 -#define PRIV_KEY_LEN 32 - static int parse_x25519_enckey(uint8_t **p, uint8_t *end, uint8_t *private_key) { @@ -221,11 +215,11 @@ parse_x25519_enckey(uint8_t **p, uint8_t *end, uint8_t *private_key) return -7; } - if (len != PRIV_KEY_LEN) { + if (len != EC_PRIVK_LEN) { return -8; } - memcpy(private_key, *p, PRIV_KEY_LEN); + memcpy(private_key, *p, EC_PRIVK_LEN); return 0; } #endif /* defined(MCUBOOT_ENCRYPT_X25519) */ @@ -399,11 +393,11 @@ boot_decrypt_key(const uint8_t *buf, uint8_t *enckey) bootutil_hmac_sha256_context hmac; bootutil_aes_ctr_context aes_ctr; uint8_t tag[BOOTUTIL_CRYPTO_SHA256_DIGEST_SIZE]; - uint8_t shared[SHARED_KEY_LEN]; + uint8_t shared[EC_SHARED_LEN]; uint8_t derived_key[BOOT_ENC_KEY_SIZE + BOOTUTIL_CRYPTO_SHA256_DIGEST_SIZE]; uint8_t *cp; uint8_t *cpend; - uint8_t private_key[PRIV_KEY_LEN]; + uint8_t private_key[EC_PRIVK_LEN]; uint8_t counter[BOOT_ENC_BLOCK_SIZE]; uint16_t len; #endif @@ -509,7 +503,7 @@ boot_decrypt_key(const uint8_t *buf, uint8_t *enckey) */ len = BOOT_ENC_KEY_SIZE + BOOTUTIL_CRYPTO_SHA256_DIGEST_SIZE; - rc = hkdf(shared, SHARED_KEY_LEN, (uint8_t *)"MCUBoot_ECIES_v1", 16, + rc = hkdf(shared, EC_SHARED_LEN, (uint8_t *)"MCUBoot_ECIES_v1", 16, derived_key, &len); if (rc != 0 || len != (BOOT_ENC_KEY_SIZE + BOOTUTIL_CRYPTO_SHA256_DIGEST_SIZE)) { return -1; @@ -521,6 +515,9 @@ boot_decrypt_key(const uint8_t *buf, uint8_t *enckey) bootutil_hmac_sha256_init(&hmac); + /* First BOOT_ENC_KEY_SIZE are used for decryption, remaining 32 bytes are used + * for MAC tag key + */ rc = bootutil_hmac_sha256_set_key(&hmac, &derived_key[BOOT_ENC_KEY_SIZE], 32); if (rc != 0) { (void)bootutil_hmac_sha256_drop(&hmac); @@ -540,7 +537,7 @@ boot_decrypt_key(const uint8_t *buf, uint8_t *enckey) return -1; } - if (bootutil_constant_time_compare(tag, &buf[EC_TAG_INDEX], 32) != 0) { + if (bootutil_constant_time_compare(tag, &buf[EC_TAG_INDEX], EC_TAG_LEN) != 0) { (void)bootutil_hmac_sha256_drop(&hmac); return -1; } diff --git a/boot/bootutil/src/encrypted_psa.c b/boot/bootutil/src/encrypted_psa.c index d604df201..04b5fbee4 100644 --- a/boot/bootutil/src/encrypted_psa.c +++ b/boot/bootutil/src/encrypted_psa.c @@ -31,8 +31,6 @@ BOOT_LOG_MODULE_DECLARE(mcuboot_psa_enc); static const uint8_t ec_pubkey_oid[] = MBEDTLS_OID_ISO_IDENTIFIED_ORG \ MBEDTLS_OID_ORG_GOV X25519_OID; -#define PRIV_KEY_LEN 32 - /* Partitioning of HKDF derived material, from the exchange derived key */ /* AES key encryption key */ #define HKDF_AES_KEY_INDEX 0 @@ -83,11 +81,11 @@ parse_x25519_enckey(uint8_t **p, uint8_t *end, uint8_t *private_key) return -7; } - if (len != PRIV_KEY_LEN) { + if (len != EC_PRIVK_LEN) { return -8; } - memcpy(private_key, *p, PRIV_KEY_LEN); + memcpy(private_key, *p, EC_PRIVK_LEN); return 0; } @@ -117,7 +115,7 @@ boot_decrypt_key(const uint8_t *buf, uint8_t *enckey) uint8_t derived_key[HKDF_SIZE]; uint8_t *cp; uint8_t *cpend; - uint8_t private_key[PRIV_KEY_LEN]; + uint8_t private_key[EC_PRIVK_LEN]; size_t len; psa_status_t psa_ret = PSA_ERROR_BAD_STATE; psa_status_t psa_cleanup_ret = PSA_ERROR_BAD_STATE; From 884efcadeffbf61483f9ee1c9171b0e1806ba704 Mon Sep 17 00:00:00 2001 From: Dominik Ermel Date: Wed, 11 Jun 2025 14:14:43 +0000 Subject: [PATCH 004/420] [nrf fromlist] bootutil: Fix boot_scramble_region escaping flash area Incorrect range check fix. Upstream PR #: 2337 Signed-off-by: Dominik Ermel (cherry picked from commit fa17bc97c594bc4c2178d53a83f48fbcc244ed47) --- boot/bootutil/src/loader.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/boot/bootutil/src/loader.c b/boot/bootutil/src/loader.c index ffd2456a7..44275fcb9 100644 --- a/boot/bootutil/src/loader.c +++ b/boot/bootutil/src/loader.c @@ -1274,7 +1274,7 @@ boot_scramble_region(const struct flash_area *fa, uint32_t off, uint32_t size, b end_offset = ALIGN_DOWN((off + size), write_block); } - while (true) { + while (off != end_offset) { /* Write over the area to scramble data that is there */ rc = flash_area_write(fa, off, buf, write_block); if (rc != 0) { @@ -1291,12 +1291,12 @@ boot_scramble_region(const struct flash_area *fa, uint32_t off, uint32_t size, b off -= write_block; } else { - if (end_offset < off) { + off += write_block; + + if (end_offset <= off) { /* Reached the end offset in range and already scrambled it */ break; } - - off += write_block; } } } From 46980ce0bf11ad8966783c2bfe53a6223c332066 Mon Sep 17 00:00:00 2001 From: Michal Kozikowski Date: Mon, 9 Jun 2025 17:14:47 +0200 Subject: [PATCH 005/420] [nrf fromtree] scripts: imgtool: Compression of no header-padded images This fixes issues when trying to compress images with no header padding requested. Upstream PR #: 2334 Signed-off-by: Michal Kozikowski (cherry picked from commit 9e0bebc8c3cf984e4d12182a9390275521fe54d6) --- scripts/imgtool/image.py | 24 +++++++++++++++--------- scripts/imgtool/main.py | 8 +++++--- 2 files changed, 20 insertions(+), 12 deletions(-) diff --git a/scripts/imgtool/image.py b/scripts/imgtool/image.py index 566a47e00..c7fb9e553 100644 --- a/scripts/imgtool/image.py +++ b/scripts/imgtool/image.py @@ -348,7 +348,6 @@ def load(self, path): self.payload = copy.copy(self.infile_data) except FileNotFoundError: raise click.UsageError("Input file not found") - self.image_size = len(self.payload) # Add the image header if needed. if self.pad_header and self.header_size > 0: @@ -358,6 +357,8 @@ def load(self, path): self.payload = bytes([self.erased_val] * self.header_size) + \ self.payload + self.image_size = len(self.payload) - self.header_size + self.check_header() def load_compressed(self, data, compression_header): @@ -366,14 +367,19 @@ def load_compressed(self, data, compression_header): self.image_size = len(self.payload) # Add the image header if needed. - if self.pad_header and self.header_size > 0: - if self.base_addr: - # Adjust base_addr for new header - self.base_addr -= self.header_size - self.payload = bytes([self.erased_val] * self.header_size) + \ - self.payload - - self.check_header() + if self.header_size > 0: + if self.pad_header: + if self.base_addr: + # Adjust base_addr for new header + self.base_addr -= self.header_size + self.payload = bytes([self.erased_val] * self.header_size) + \ + self.payload + else: + # Fill header padding with zeros to align with what is expected + # for uncompressed images when no pad_header is requested + # (see self.check_header()) + self.payload = bytes([0] * self.header_size) + \ + self.payload def save(self, path, hex_addr=None): """Save an image from a given file""" diff --git a/scripts/imgtool/main.py b/scripts/imgtool/main.py index 1cdb792a5..78f2e77ec 100755 --- a/scripts/imgtool/main.py +++ b/scripts/imgtool/main.py @@ -542,9 +542,11 @@ def sign(key, public_key_format, align, version, pad_sig, header_size, ] if compression == "lzma2armthumb": compression_filters.insert(0, {"id":lzma.FILTER_ARMTHUMB}) - compressed_data = lzma.compress(img.get_infile_data(),filters=compression_filters, - format=lzma.FORMAT_RAW) - uncompressed_size = len(img.get_infile_data()) + + infile_offset = 0 if pad_header else header_size + compressed_data = lzma.compress(img.get_infile_data()[infile_offset:], + filters=compression_filters, format=lzma.FORMAT_RAW) + uncompressed_size = len(img.get_infile_data()[infile_offset:]) compressed_size = len(compressed_data) print(f"compressed image size: {compressed_size} bytes") print(f"original image size: {uncompressed_size} bytes") From 6a4025b10a7901c20d08814dd6ed228a0ee01a2f Mon Sep 17 00:00:00 2001 From: Tomasz Chyrowicz Date: Mon, 16 Jun 2025 16:26:16 +0200 Subject: [PATCH 006/420] [nrf fromlist] zephyr: Fix pinreset trigger The hfwinfo returns bitmask, not single values. Upstream PR #: 2342 Signed-off-by: Tomasz Chyrowicz (cherry picked from commit 18e3bc8b261b018983e2300ec4e68e027c863a14) --- boot/zephyr/io.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/boot/zephyr/io.c b/boot/zephyr/io.c index 309f1ab94..f2342c1ad 100644 --- a/boot/zephyr/io.c +++ b/boot/zephyr/io.c @@ -181,7 +181,7 @@ bool io_detect_pin_reset(void) rc = hwinfo_get_reset_cause(&reset_cause); - if (rc == 0 && reset_cause == RESET_PIN) { + if (rc == 0 && (reset_cause & RESET_PIN)) { (void)hwinfo_clear_reset_cause(); return true; } From 57ceb536003462cbed6dde26221667d64fbbbc0e Mon Sep 17 00:00:00 2001 From: Michal Kozikowski Date: Mon, 16 Jun 2025 11:41:28 +0200 Subject: [PATCH 007/420] [nrf fromtree] bootutil: loader: overwrite-only mode fix for trailer erase This fixes issues when trying to erase secondary slot trailer for platforms with MCUBOOT_SUPPORT_DEV_WITHOUT_ERASE set from flash driver. Calling explicitly to 'scramble' region ensures we delete the trailer. Upstream PR #: 2341 Signed-off-by: Michal Kozikowski (cherry picked from commit bb644c7c41b84aebe0e6456099598cef776e7142) --- boot/bootutil/src/loader.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/boot/bootutil/src/loader.c b/boot/bootutil/src/loader.c index 44275fcb9..62f980b69 100644 --- a/boot/bootutil/src/loader.c +++ b/boot/bootutil/src/loader.c @@ -1687,19 +1687,19 @@ boot_copy_image(struct boot_loader_state *state, struct boot_status *bs) * trailer that was left might trigger a new upgrade. */ BOOT_LOG_DBG("erasing secondary header"); - rc = boot_erase_region(fap_secondary_slot, - boot_img_sector_off(state, BOOT_SECONDARY_SLOT, 0), - boot_img_sector_size(state, BOOT_SECONDARY_SLOT, 0), false); + rc = boot_scramble_region(fap_secondary_slot, + boot_img_sector_off(state, BOOT_SECONDARY_SLOT, 0), + boot_img_sector_size(state, BOOT_SECONDARY_SLOT, 0), false); assert(rc == 0); #endif last_sector = boot_img_num_sectors(state, BOOT_SECONDARY_SLOT) - 1; BOOT_LOG_DBG("erasing secondary trailer"); - rc = boot_erase_region(fap_secondary_slot, - boot_img_sector_off(state, BOOT_SECONDARY_SLOT, - last_sector), - boot_img_sector_size(state, BOOT_SECONDARY_SLOT, - last_sector), false); + rc = boot_scramble_region(fap_secondary_slot, + boot_img_sector_off(state, BOOT_SECONDARY_SLOT, + last_sector), + boot_img_sector_size(state, BOOT_SECONDARY_SLOT, + last_sector), false); assert(rc == 0); /* TODO: Perhaps verify the primary slot's signature again? */ From 657e048b0f4b043893a48704bab23afe5f4b2221 Mon Sep 17 00:00:00 2001 From: Sayooj K Karun Date: Wed, 23 Apr 2025 18:13:11 +0530 Subject: [PATCH 008/420] [nrf fromtree] boot: zephyr: Refactor DFU entry logic Consolidates USB DFU entry logic by unifying GPIO and timeout-based DFU triggers under a common flag. This avoids code duplication and improves maintainability. Also improves log clarity for different DFU exit conditions. Signed-off-by: Sayooj K Karun (cherry picked from commit 402d3f7ff11973577f1bc966151fccf53192f32b) Signed-off-by: Dominik Ermel --- boot/zephyr/main.c | 38 ++++++++++++++++++++++---------------- 1 file changed, 22 insertions(+), 16 deletions(-) diff --git a/boot/zephyr/main.c b/boot/zephyr/main.c index 4ecf191e7..ddea864de 100644 --- a/boot/zephyr/main.c +++ b/boot/zephyr/main.c @@ -2,6 +2,7 @@ * Copyright (c) 2012-2014 Wind River Systems, Inc. * Copyright (c) 2020 Arm Limited * Copyright (c) 2021-2023 Nordic Semiconductor ASA + * Copyright (c) 2025 Aerlync Labs Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -434,6 +435,9 @@ int main(void) { struct boot_rsp rsp; int rc; +#if defined(CONFIG_BOOT_USB_DFU_GPIO) || defined(CONFIG_BOOT_USB_DFU_WAIT) + bool usb_dfu_requested = false; +#endif FIH_DECLARE(fih_rc, FIH_FAILURE); MCUBOOT_WATCHDOG_SETUP(); @@ -473,35 +477,37 @@ int main(void) #if defined(CONFIG_BOOT_USB_DFU_GPIO) if (io_detect_pin()) { + usb_dfu_requested = true; + #ifdef CONFIG_MCUBOOT_INDICATION_LED io_led_set(1); #endif mcuboot_status_change(MCUBOOT_STATUS_USB_DFU_ENTERED); + } +#elif defined(CONFIG_BOOT_USB_DFU_WAIT) + usb_dfu_requested = true; +#endif +#if defined(CONFIG_BOOT_USB_DFU_GPIO) || defined(CONFIG_BOOT_USB_DFU_WAIT) + if (usb_dfu_requested) { rc = usb_enable(NULL); if (rc) { - BOOT_LOG_ERR("Cannot enable USB"); + BOOT_LOG_ERR("Cannot enable USB: %d", rc); } else { BOOT_LOG_INF("Waiting for USB DFU"); - wait_for_usb_dfu(K_FOREVER); + +#if defined(CONFIG_BOOT_USB_DFU_WAIT) + mcuboot_status_change(MCUBOOT_STATUS_USB_DFU_WAITING); + wait_for_usb_dfu(K_MSEC(CONFIG_BOOT_USB_DFU_WAIT_DELAY_MS)); BOOT_LOG_INF("USB DFU wait time elapsed"); + mcuboot_status_change(MCUBOOT_STATUS_USB_DFU_TIMED_OUT); +#else + wait_for_usb_dfu(K_FOREVER); + BOOT_LOG_INF("USB DFU wait terminated"); +#endif } } -#elif defined(CONFIG_BOOT_USB_DFU_WAIT) - rc = usb_enable(NULL); - if (rc) { - BOOT_LOG_ERR("Cannot enable USB"); - } else { - BOOT_LOG_INF("Waiting for USB DFU"); - - mcuboot_status_change(MCUBOOT_STATUS_USB_DFU_WAITING); - - wait_for_usb_dfu(K_MSEC(CONFIG_BOOT_USB_DFU_WAIT_DELAY_MS)); - BOOT_LOG_INF("USB DFU wait time elapsed"); - - mcuboot_status_change(MCUBOOT_STATUS_USB_DFU_TIMED_OUT); - } #endif #ifdef CONFIG_BOOT_SERIAL_WAIT_FOR_DFU From b7f129b42e6ee98b18c1fbe2ac0ea59109663e57 Mon Sep 17 00:00:00 2001 From: Dominik Ermel Date: Thu, 15 May 2025 15:43:57 +0000 Subject: [PATCH 009/420] [nrf fromtree] bootutil: Improve logging coverage Add additional log lines to allow easier tracking potential failures in image validation. Signed-off-by: Dominik Ermel (cherry picked from commit 11f9c6f2fa5cba2ca42e6371c42786bd43a4837e) --- boot/bootutil/src/bootutil_misc.c | 17 ++++++++++++++++ boot/bootutil/src/bootutil_public.c | 22 +++++++++++++++++---- boot/bootutil/src/ed25519_psa.c | 2 ++ boot/bootutil/src/encrypted.c | 8 ++++++++ boot/bootutil/src/encrypted_psa.c | 4 +++- boot/bootutil/src/image_ecdsa.c | 7 +++++++ boot/bootutil/src/image_ed25519.c | 17 +++++++++++++++- boot/bootutil/src/image_rsa.c | 5 +++++ boot/bootutil/src/image_validate.c | 23 +++++++++++++++++++++- boot/bootutil/src/loader.c | 30 +++++++++++++++++++++++++++++ boot/bootutil/src/swap_misc.c | 2 +- boot/bootutil/src/tlv.c | 14 ++++++++++++++ 12 files changed, 143 insertions(+), 8 deletions(-) diff --git a/boot/bootutil/src/bootutil_misc.c b/boot/bootutil/src/bootutil_misc.c index 0091165d5..56e791043 100644 --- a/boot/bootutil/src/bootutil_misc.c +++ b/boot/bootutil/src/bootutil_misc.c @@ -155,6 +155,9 @@ int boot_trailer_scramble_offset(const struct flash_area *fa, size_t alignment, { int ret = 0; + BOOT_LOG_DBG("boot_trailer_scramble_offset: flash_area %p, alignment %u", + fa, (unsigned int)alignment); + /* Not allowed to enforce alignment smaller than device allows */ if (alignment < flash_area_align(fa)) { alignment = flash_area_align(fa); @@ -176,6 +179,9 @@ int boot_trailer_scramble_offset(const struct flash_area *fa, size_t alignment, *off = flash_area_get_size(fa) - ALIGN_DOWN(boot_trailer_sz(alignment), alignment); } + BOOT_LOG_DBG("boot_trailer_scramble_offset: final alignment %u, offset %u", + (unsigned int)alignment, (unsigned int)*off); + return ret; } @@ -187,6 +193,8 @@ int boot_header_scramble_off_sz(const struct flash_area *fa, int slot, size_t *o size_t loff = 0; struct flash_sector sector; + BOOT_LOG_DBG("boot_header_scramble_off_sz: slot %d", slot); + (void)slot; #if defined(MCUBOOT_SWAP_USING_OFFSET) /* In case of swap offset, header of secondary slot image is positioned @@ -215,6 +223,8 @@ int boot_header_scramble_off_sz(const struct flash_area *fa, int slot, size_t *o } *off = loff; + BOOT_LOG_DBG("boot_header_scramble_off_sz: size %u", (unsigned int)*size); + return ret; } @@ -601,6 +611,9 @@ boot_erase_region(const struct flash_area *fa, uint32_t off, uint32_t size, bool { int rc = 0; + BOOT_LOG_DBG("boot_erase_region: flash_area %p, offset %d, size %d, backwards == %d", + fa, off, size, (int)backwards); + if (off >= flash_area_get_size(fa) || (flash_area_get_size(fa) - off) < size) { rc = -1; goto end; @@ -608,6 +621,8 @@ boot_erase_region(const struct flash_area *fa, uint32_t off, uint32_t size, bool uint32_t end_offset = 0; struct flash_sector sector; + BOOT_LOG_DBG("boot_erase_region: device with erase"); + if (backwards) { /* Get the lowest page offset first */ rc = flash_area_get_sector(fa, off, §or); @@ -681,6 +696,8 @@ boot_erase_region(const struct flash_area *fa, uint32_t off, uint32_t size, bool off += 1; } } + } else { + BOOT_LOG_DBG("boot_erase_region: device without erase"); } end: diff --git a/boot/bootutil/src/bootutil_public.c b/boot/bootutil/src/bootutil_public.c index 102118864..8860fca41 100644 --- a/boot/bootutil/src/bootutil_public.c +++ b/boot/bootutil/src/bootutil_public.c @@ -324,7 +324,7 @@ boot_write_magic(const struct flash_area *fap) memset(&magic[0], erased_val, sizeof(magic)); memcpy(&magic[BOOT_MAGIC_ALIGN_SIZE - BOOT_MAGIC_SZ], BOOT_IMG_MAGIC, BOOT_MAGIC_SZ); - BOOT_LOG_DBG("writing magic; fa_id=%d off=0x%lx (0x%lx)", + BOOT_LOG_DBG("boot_write_magic: fa_id=%d off=0x%lx (0x%lx)", flash_area_get_id(fap), (unsigned long)off, (unsigned long)(flash_area_get_off(fap) + off)); rc = flash_area_write(fap, pad_off, &magic[0], BOOT_MAGIC_ALIGN_SIZE); @@ -350,9 +350,14 @@ boot_write_trailer(const struct flash_area *fap, uint32_t off, uint32_t align; int rc; + BOOT_LOG_DBG("boot_write_trailer: for %p at %d, size = %d", + fap, off, inlen); + align = flash_area_align(fap); align = ALIGN_UP(inlen, align); if (align > BOOT_MAX_ALIGN) { + /* This should never happen */ + assert(0); return -1; } erased_val = flash_area_erased_val(fap); @@ -596,6 +601,9 @@ boot_set_next(const struct flash_area *fa, bool active, bool confirm) struct boot_swap_state slot_state; int rc; + BOOT_LOG_DBG("boot_set_next: fa %p active == %d, confirm == %d", + fa, (int)active, (int)confirm); + if (active) { /* The only way to set active slot for next boot is to confirm it, * as DirectXIP will conclude that, since slot has not been confirmed @@ -606,6 +614,7 @@ boot_set_next(const struct flash_area *fa, bool active, bool confirm) rc = boot_read_swap_state(fa, &slot_state); if (rc != 0) { + BOOT_LOG_DBG("boot_set_next: error %d reading state", rc); return rc; } @@ -733,6 +742,8 @@ boot_set_confirmed_multi(int image_index) rc = flash_area_open(FLASH_AREA_IMAGE_PRIMARY(image_index), &fap); if (rc != 0) { + BOOT_LOG_DBG("boot_set_confirmed_multi: error %d opening image %d", + rc, image_index); return BOOT_EFLASH; } @@ -760,13 +771,14 @@ int boot_image_load_header(const struct flash_area *fa_p, struct image_header *hdr) { - uint32_t size; + uint32_t size = 0; int rc = flash_area_read(fa_p, 0, hdr, sizeof *hdr); + BOOT_LOG_DBG("boot_image_load_header: from %p, result %d", fa_p, rc); + if (rc != 0) { - rc = BOOT_EFLASH; BOOT_LOG_ERR("Failed reading image header"); - return BOOT_EFLASH; + return BOOT_EFLASH; } if (hdr->ih_magic != IMAGE_MAGIC) { @@ -783,6 +795,8 @@ boot_image_load_header(const struct flash_area *fa_p, if (!boot_u32_safe_add(&size, hdr->ih_img_size, hdr->ih_hdr_size) || size >= flash_area_get_size(fa_p)) { + BOOT_LOG_ERR("Image size bigger than designated area: %lu > %lu", + (unsigned long)size, (unsigned long)flash_area_get_size(fa_p)); return BOOT_EBADIMAGE; } diff --git a/boot/bootutil/src/ed25519_psa.c b/boot/bootutil/src/ed25519_psa.c index 12ba20ac1..5b8a4ed7c 100644 --- a/boot/bootutil/src/ed25519_psa.c +++ b/boot/bootutil/src/ed25519_psa.c @@ -29,6 +29,8 @@ int ED25519_verify(const uint8_t *message, size_t message_len, psa_key_id_t kid; int ret = 0; /* Fail by default */ + BOOT_LOG_DBG("ED25519_verify: PSA implementation"); + /* Initialize PSA Crypto */ status = psa_crypto_init(); if (status != PSA_SUCCESS) { diff --git a/boot/bootutil/src/encrypted.c b/boot/bootutil/src/encrypted.c index e0078a7be..cf6f380e2 100644 --- a/boot/bootutil/src/encrypted.c +++ b/boot/bootutil/src/encrypted.c @@ -43,6 +43,9 @@ #include "bootutil/enc_key.h" #include "bootutil/sign_key.h" #include "bootutil/crypto/common.h" +#include "bootutil/bootutil_log.h" + +BOOT_LOG_MODULE_DECLARE(mcuboot); #include "bootutil_priv.h" @@ -383,6 +386,8 @@ boot_decrypt_key(const uint8_t *buf, uint8_t *enckey) uint8_t *cpend; size_t olen; #endif + + BOOT_LOG_DBG("boot_decrypt_key"); #if defined(MCUBOOT_ENCRYPT_EC256) bootutil_ecdh_p256_context ecdh_p256; #endif @@ -600,8 +605,11 @@ boot_enc_load(struct boot_loader_state *state, int slot, #endif int rc; + BOOT_LOG_DBG("boot_enc_load: slot %d", slot); + /* Already loaded... */ if (enc_state[slot].valid) { + BOOT_LOG_DBG("boot_enc_load: already loaded"); return 1; } diff --git a/boot/bootutil/src/encrypted_psa.c b/boot/bootutil/src/encrypted_psa.c index 04b5fbee4..6f60a1955 100644 --- a/boot/bootutil/src/encrypted_psa.c +++ b/boot/bootutil/src/encrypted_psa.c @@ -134,9 +134,11 @@ boot_decrypt_key(const uint8_t *buf, uint8_t *enckey) uint8_t iv_and_key[PSA_CIPHER_IV_LENGTH(PSA_KEY_TYPE_AES, PSA_ALG_CTR) + BOOT_ENC_KEY_SIZE]; + BOOT_LOG_DBG("boot_decrypt_key: PSA ED25519"); + psa_ret = psa_crypto_init(); if (psa_ret != PSA_SUCCESS) { - BOOT_LOG_ERR("AES crypto init failed %d", psa_ret); + BOOT_LOG_ERR("PSA crypto init failed %d", psa_ret); return -1; } diff --git a/boot/bootutil/src/image_ecdsa.c b/boot/bootutil/src/image_ecdsa.c index 4604913b4..30c7d0d0f 100644 --- a/boot/bootutil/src/image_ecdsa.c +++ b/boot/bootutil/src/image_ecdsa.c @@ -28,6 +28,9 @@ #include #include "mcuboot_config/mcuboot_config.h" +#include "bootutil/bootutil_log.h" + +BOOT_LOG_MODULE_DECLARE(mcuboot); #if defined(MCUBOOT_SIGN_EC256) || defined(MCUBOOT_SIGN_EC384) @@ -46,6 +49,8 @@ bootutil_verify_sig(uint8_t *hash, uint32_t hlen, uint8_t *sig, size_t slen, uint8_t *pubkey; uint8_t *end; + BOOT_LOG_DBG("bootutil_verify_sig: ECDSA builtin key %d", key_id); + pubkey = (uint8_t *)bootutil_keys[key_id].key; end = pubkey + *bootutil_keys[key_id].len; bootutil_ecdsa_init(&ctx); @@ -75,6 +80,8 @@ bootutil_verify_sig(uint8_t *hash, uint32_t hlen, uint8_t *sig, size_t slen, bootutil_ecdsa_context ctx; FIH_DECLARE(fih_rc, FIH_FAILURE); + BOOT_LOG_DBG("bootutil_verify_sig: ECDSA embedded key %hhd", key_id); + /* Use builtin key for image verification, no key parsing is required. */ ctx.key_id = key_id; bootutil_ecdsa_init(&ctx); diff --git a/boot/bootutil/src/image_ed25519.c b/boot/bootutil/src/image_ed25519.c index ffb8cec3b..4d83bb3d7 100644 --- a/boot/bootutil/src/image_ed25519.c +++ b/boot/bootutil/src/image_ed25519.c @@ -21,8 +21,11 @@ #include "bootutil/crypto/common.h" #endif -#include "bootutil_priv.h" +#include "bootutil/bootutil_log.h" #include "bootutil/crypto/sha.h" +#include "bootutil_priv.h" + +BOOT_LOG_MODULE_DECLARE(mcuboot); #define EDDSA_SIGNATURE_LENGTH 64 #define NUM_ED25519_BYTES 32 @@ -90,7 +93,11 @@ bootutil_verify(uint8_t *buf, uint32_t blen, uint8_t *pubkey; uint8_t *end; + BOOT_LOG_DBG("bootutil_verify: ED25519 key_id %d", (int)key_id); + if (slen != EDDSA_SIGNATURE_LENGTH) { + BOOT_LOG_DBG("bootutil_verify: expected slen %d, got %u", + EDDSA_SIGNATURE_LENGTH, (unsigned int)slen); FIH_SET(fih_rc, FIH_FAILURE); goto out; } @@ -101,6 +108,7 @@ bootutil_verify(uint8_t *buf, uint32_t blen, #if !defined(MCUBOOT_KEY_IMPORT_BYPASS_ASN) rc = bootutil_import_key(&pubkey, end); if (rc) { + BOOT_LOG_DBG("bootutil_verify: import key failed %d", rc); FIH_SET(fih_rc, FIH_FAILURE); goto out; } @@ -110,6 +118,7 @@ bootutil_verify(uint8_t *buf, uint32_t blen, * There is no check whether this is the correct key, * here, by the algorithm selected. */ + BOOT_LOG_DBG("bootutil_verify: bypass ASN1"); if (*bootutil_keys[key_id].len < NUM_ED25519_BYTES) { FIH_SET(fih_rc, FIH_FAILURE); goto out; @@ -144,7 +153,11 @@ bootutil_verify_sig(uint8_t *hash, uint32_t hlen, { FIH_DECLARE(fih_rc, FIH_FAILURE); + BOOT_LOG_DBG("bootutil_verify_sig: ED25519 key_id %d", (int)key_id); + if (hlen != IMAGE_HASH_SIZE) { + BOOT_LOG_DBG("bootutil_verify_sig: expected hlen %d, got %d", + IMAGE_HASH_SIZE, hlen); FIH_SET(fih_rc, FIH_FAILURE); goto out; } @@ -167,6 +180,8 @@ bootutil_verify_img(uint8_t *img, uint32_t size, { FIH_DECLARE(fih_rc, FIH_FAILURE); + BOOT_LOG_DBG("bootutil_verify_img: ED25519 key_id %d", (int)key_id); + FIH_CALL(bootutil_verify, fih_rc, img, size, sig, slen, key_id); diff --git a/boot/bootutil/src/image_rsa.c b/boot/bootutil/src/image_rsa.c index 778a92b46..5479b75eb 100644 --- a/boot/bootutil/src/image_rsa.c +++ b/boot/bootutil/src/image_rsa.c @@ -28,6 +28,9 @@ #include #include "mcuboot_config/mcuboot_config.h" +#include "bootutil/bootutil_log.h" + +BOOT_LOG_MODULE_DECLARE(mcuboot); #ifdef MCUBOOT_SIGN_RSA #include "bootutil_priv.h" @@ -267,6 +270,8 @@ bootutil_verify_sig(uint8_t *hash, uint32_t hlen, uint8_t *sig, size_t slen, uint8_t *cp; uint8_t *end; + BOOT_LOG_DBG("bootutil_verify_sig: RSA key_id %d", key_id); + bootutil_rsa_init(&ctx); cp = (uint8_t *)bootutil_keys[key_id].key; diff --git a/boot/bootutil/src/image_validate.c b/boot/bootutil/src/image_validate.c index 521251a40..eec678724 100644 --- a/boot/bootutil/src/image_validate.c +++ b/boot/bootutil/src/image_validate.c @@ -41,6 +41,9 @@ #include "bootutil/fault_injection_hardening.h" #include "mcuboot_config/mcuboot_config.h" +#include "bootutil/bootutil_log.h" + +BOOT_LOG_MODULE_DECLARE(mcuboot); #ifdef MCUBOOT_ENC_IMAGES #include "bootutil/enc_key.h" @@ -107,6 +110,7 @@ bootutil_img_hash(struct boot_loader_state *state, (void)tmp_buf_sz; #endif #endif + BOOT_LOG_DBG("bootutil_img_hash"); #ifdef MCUBOOT_ENC_IMAGES if (state == NULL) { @@ -120,6 +124,7 @@ bootutil_img_hash(struct boot_loader_state *state, /* Encrypted images only exist in the secondary slot */ if (MUST_DECRYPT(fap, image_index, hdr) && !boot_enc_valid(enc_state, 1)) { + BOOT_LOG_DBG("bootutil_img_hash: error encrypted image found in primary slot"); return -1; } #endif @@ -187,6 +192,8 @@ bootutil_img_hash(struct boot_loader_state *state, #endif if (rc) { bootutil_sha_drop(&sha_ctx); + BOOT_LOG_DBG("bootutil_img_validate Error %d reading data chunk %p %u %u", + rc, fap, off, blk_sz); return rc; } #ifdef MCUBOOT_ENC_IMAGES @@ -280,6 +287,8 @@ bootutil_find_key(uint8_t *keyhash, uint8_t keyhash_len) const struct bootutil_key *key; uint8_t hash[IMAGE_HASH_SIZE]; + BOOT_LOG_DBG("bootutil_find_key"); + if (keyhash_len > IMAGE_HASH_SIZE) { return -1; } @@ -308,6 +317,8 @@ bootutil_find_key(uint8_t image_index, uint8_t *key, uint16_t key_len) int rc; FIH_DECLARE(fih_rc, FIH_FAILURE); + BOOT_LOG_DBG("bootutil_find_key: image_index %d", image_index); + bootutil_sha_init(&sha_ctx); bootutil_sha_update(&sha_ctx, key, key_len); bootutil_sha_finish(&sha_ctx, hash); @@ -518,6 +529,8 @@ bootutil_img_validate(struct boot_loader_state *state, FIH_DECLARE(security_counter_valid, FIH_FAILURE); #endif + BOOT_LOG_DBG("bootutil_img_validate: flash area %p", fap); + #if defined(EXPECTED_HASH_TLV) && !defined(MCUBOOT_SIGN_PURE) #if defined(MCUBOOT_SWAP_USING_OFFSET) && defined(MCUBOOT_SERIAL_RECOVERY) rc = bootutil_img_hash(state, hdr, fap, tmp_buf, tmp_buf_sz, hash, seed, seed_len, @@ -538,7 +551,8 @@ bootutil_img_validate(struct boot_loader_state *state, /* If Pure type signature is expected then it has to be there */ rc = bootutil_check_for_pure(hdr, fap); if (rc != 0) { - goto out; + BOOT_LOG_DBG("bootutil_img_validate: pure expected"); + goto out; } #endif @@ -552,6 +566,7 @@ bootutil_img_validate(struct boot_loader_state *state, rc = bootutil_tlv_iter_begin(&it, hdr, fap, IMAGE_TLV_ANY, false); if (rc) { + BOOT_LOG_DBG("bootutil_img_validate: TLV iteration failed %d", rc); goto out; } @@ -560,9 +575,11 @@ bootutil_img_validate(struct boot_loader_state *state, #else img_sz = it.tlv_end; #endif + BOOT_LOG_DBG("bootutil_img_validate: TLV off %u, end %u", it.tlv_off, it.tlv_end); if (img_sz > bootutil_max_image_size(state, fap)) { rc = -1; + BOOT_LOG_DBG("bootutil_img_validate: TLV beyond image size"); goto out; } @@ -593,6 +610,7 @@ bootutil_img_validate(struct boot_loader_state *state, } } if (!found) { + BOOT_LOG_DBG("bootutil_img_validate: TLV %d not permitted", type); FIH_SET(fih_rc, FIH_FAILURE); goto out; } @@ -602,6 +620,7 @@ bootutil_img_validate(struct boot_loader_state *state, #if defined(EXPECTED_HASH_TLV) && !defined(MCUBOOT_SIGN_PURE) case EXPECTED_HASH_TLV: { + BOOT_LOG_DBG("bootutil_img_validate: EXPECTED_HASH_TLV == %d", EXPECTED_HASH_TLV); /* Verify the image hash. This must always be present. */ if (len != sizeof(hash)) { rc = -1; @@ -625,6 +644,7 @@ bootutil_img_validate(struct boot_loader_state *state, #ifdef EXPECTED_KEY_TLV case EXPECTED_KEY_TLV: { + BOOT_LOG_DBG("bootutil_img_validate: EXPECTED_KEY_TLV == %d", EXPECTED_KEY_TLV); /* * Determine which key we should be checking. */ @@ -655,6 +675,7 @@ bootutil_img_validate(struct boot_loader_state *state, #ifdef EXPECTED_SIG_TLV case EXPECTED_SIG_TLV: { + BOOT_LOG_DBG("bootutil_img_validate: EXPECTED_SIG_TLV == %d", EXPECTED_SIG_TLV); /* Ignore this signature if it is out of bounds. */ if (key_id < 0 || key_id >= bootutil_key_cnt) { key_id = -1; diff --git a/boot/bootutil/src/loader.c b/boot/bootutil/src/loader.c index 62f980b69..6654245ad 100644 --- a/boot/bootutil/src/loader.c +++ b/boot/bootutil/src/loader.c @@ -283,6 +283,19 @@ static int boot_version_cmp(const struct image_version *ver1, const struct image_version *ver2) { +#if !defined(MCUBOOT_VERSION_CMP_USE_BUILD_NUMBER) + BOOT_LOG_DBG("boot_version_cmp: ver1 %u.%u.%u vs ver2 %u.%u.%u", + (unsigned)ver1->iv_major, (unsigned)ver1->iv_minor, + (unsigned)ver1->iv_revision, (unsigned)ver2->iv_major, + (unsigned)ver2->iv_minor, (unsigned)ver2->iv_revision); +#else + BOOT_LOG_DBG("boot_version_cmp: ver1 %u.%u.%u.%u vs ver2 %u.%u.%u.%u", + (unsigned)ver1->iv_major, (unsigned)ver1->iv_minor, + (unsigned)ver1->iv_revision, (unsigned)ver1->iv_build_num, + (unsigned)ver2->iv_major, (unsigned)ver2->iv_minor, + (unsigned)ver2->iv_revision, (unsigned)ver2->iv_build_num); +#endif + if (ver1->iv_major > ver2->iv_major) { return 1; } @@ -554,6 +567,7 @@ boot_verify_slot_dependencies(struct boot_loader_state *state, uint32_t slot) fap = BOOT_IMG_AREA(state, slot); assert(fap != NULL); + BOOT_LOG_DBG("boot_verify_slot_dependencies"); #if defined(MCUBOOT_SWAP_USING_OFFSET) it.start_off = boot_get_state_secondary_offset(state, fap); #endif @@ -581,6 +595,8 @@ boot_verify_slot_dependencies(struct boot_loader_state *state, uint32_t slot) rc = LOAD_IMAGE_DATA(boot_img_hdr(state, slot), fap, off, &dep, len); if (rc != 0) { + BOOT_LOG_DBG("boot_verify_slot_dependencies: error %d reading dependency %p %d %d", + rc, fap, off, len); rc = BOOT_EFLASH; goto done; } @@ -593,6 +609,7 @@ boot_verify_slot_dependencies(struct boot_loader_state *state, uint32_t slot) /* Verify dependency and modify the swap type if not satisfied. */ rc = boot_verify_slot_dependency(state, &dep); if (rc != 0) { + BOOT_LOG_DBG("boot_verify_slot_dependencies: not satisfied"); /* Dependency not satisfied */ goto done; } @@ -1005,6 +1022,9 @@ boot_validate_slot(struct boot_loader_state *state, int slot, struct image_header *hdr; FIH_DECLARE(fih_rc, FIH_FAILURE); + BOOT_LOG_DBG("boot_validate_slot: slot %d, expected_swap_type %d", + slot, expected_swap_type); + #if !defined(MCUBOOT_SWAP_USING_OFFSET) (void)expected_swap_type; #endif @@ -1250,6 +1270,8 @@ boot_scramble_region(const struct flash_area *fa, uint32_t off, uint32_t size, b { int rc = 0; + BOOT_LOG_DBG("boot_scramble_region: %p %d %d %d", fa, off, size, (int)backwards); + if (size == 0) { goto done; } @@ -1264,6 +1286,7 @@ boot_scramble_region(const struct flash_area *fa, uint32_t off, uint32_t size, b const size_t write_block = flash_area_align(fa); uint32_t end_offset; + BOOT_LOG_DBG("boot_scramble_region: device without erase, overwriting"); memset(buf, flash_area_erased_val(fa), sizeof(buf)); if (backwards) { @@ -1273,11 +1296,14 @@ boot_scramble_region(const struct flash_area *fa, uint32_t off, uint32_t size, b } else { end_offset = ALIGN_DOWN((off + size), write_block); } + BOOT_LOG_DBG("boot_scramble_region: start offset %u, end offset %u", off, end_offset); while (off != end_offset) { /* Write over the area to scramble data that is there */ rc = flash_area_write(fa, off, buf, write_block); if (rc != 0) { + BOOT_LOG_DBG("boot_scramble_region: error %d for %p %d %u", + rc, fa, off, (unsigned int)write_block); break; } @@ -2348,6 +2374,8 @@ context_boot_go(struct boot_loader_state *state, struct boot_rsp *rsp) bool has_upgrade; volatile int fih_cnt; + BOOT_LOG_DBG("context_boot_go"); + #if defined(__BOOTSIM__) /* The array of slot sectors are defined here (as opposed to file scope) so * that they don't get allocated for non-boot-loader apps. This is @@ -3216,6 +3244,8 @@ static void boot_fetch_slot_state_sizes(void) assert(rc == 0); if (rc != 0) { + BOOT_LOG_DBG("boot_fetch_slot_state_sizes: error %d for %d", + rc, fa_id); goto finish; } } diff --git a/boot/bootutil/src/swap_misc.c b/boot/bootutil/src/swap_misc.c index ac9412b0f..a4c39c20a 100644 --- a/boot/bootutil/src/swap_misc.c +++ b/boot/bootutil/src/swap_misc.c @@ -80,7 +80,7 @@ swap_scramble_trailer_sectors(const struct boot_loader_state *state, size_t off; int rc; - BOOT_LOG_DBG("Scrambling trailer; fa_id=%d", flash_area_get_id(fap)); + BOOT_LOG_DBG("swap_scramble_trailer_sectors: fa_id=%d", flash_area_get_id(fap)); /* Delete starting from last sector and moving to beginning */ rc = boot_trailer_scramble_offset(fap, BOOT_WRITE_SZ(state), &off); diff --git a/boot/bootutil/src/tlv.c b/boot/bootutil/src/tlv.c index 629bc235d..a69b3d8bd 100644 --- a/boot/bootutil/src/tlv.c +++ b/boot/bootutil/src/tlv.c @@ -21,9 +21,12 @@ #include #include "bootutil/bootutil.h" +#include "bootutil/bootutil_log.h" #include "bootutil/image.h" #include "bootutil_priv.h" +BOOT_LOG_MODULE_DECLARE(mcuboot); + /* * Initialize a TLV iterator. * @@ -43,6 +46,8 @@ bootutil_tlv_iter_begin(struct image_tlv_iter *it, const struct image_header *hd uint32_t off_; struct image_tlv_info info; + BOOT_LOG_DBG("bootutil_tlv_iter_begin: type %d, prot == %d", type, (int)prot); + if (it == NULL || hdr == NULL || fap == NULL) { return -1; } @@ -108,6 +113,9 @@ bootutil_tlv_iter_next(struct image_tlv_iter *it, uint32_t *off, uint16_t *len, return -1; } + BOOT_LOG_DBG("bootutil_tlv_iter_next: searching for %d (%d is any) starting at %d ending at %d", + it->type, IMAGE_TLV_ANY, it->tlv_off, it->tlv_end); + while (it->tlv_off < it->tlv_end) { if (it->hdr->ih_protect_tlv_size > 0 && it->tlv_off == it->prot_end) { it->tlv_off += sizeof(struct image_tlv_info); @@ -115,11 +123,14 @@ bootutil_tlv_iter_next(struct image_tlv_iter *it, uint32_t *off, uint16_t *len, rc = LOAD_IMAGE_DATA(it->hdr, it->fap, it->tlv_off, &tlv, sizeof tlv); if (rc) { + BOOT_LOG_DBG("bootutil_tlv_iter_next: load failed with %d for %p %d", + rc, it->fap, it->tlv_off); return -1; } /* No more TLVs in the protected area */ if (it->prot && it->tlv_off >= it->prot_end) { + BOOT_LOG_DBG("bootutil_tlv_iter_next: protected TLV %d not found", it->type); return 1; } @@ -130,12 +141,15 @@ bootutil_tlv_iter_next(struct image_tlv_iter *it, uint32_t *off, uint16_t *len, *off = it->tlv_off + sizeof(tlv); *len = tlv.it_len; it->tlv_off += sizeof(tlv) + tlv.it_len; + BOOT_LOG_DBG("bootutil_tlv_iter_next: TLV %d found at %d (size %d)", + *type, *off, *len); return 0; } it->tlv_off += sizeof(tlv) + tlv.it_len; } + BOOT_LOG_DBG("bootutil_tlv_iter_next: TLV %d not found", it->type); return 1; } From eaa6a90bce63822bfb2e3691681e39abe739dcd8 Mon Sep 17 00:00:00 2001 From: Dominik Ermel Date: Thu, 15 May 2025 15:45:44 +0000 Subject: [PATCH 010/420] [nrf fromtree] zephyr: Improve logging Improve logging to make it easier to track image validation failures in development. Signed-off-by: Dominik Ermel (cherry picked from commit c5011f2b75ebdf3327a6530b38ab9f9f3ff7a0f7) --- boot/zephyr/firmware_loader.c | 8 ++++++++ boot/zephyr/main.c | 8 ++++++++ boot/zephyr/single_loader.c | 6 ++++++ 3 files changed, 22 insertions(+) diff --git a/boot/zephyr/firmware_loader.c b/boot/zephyr/firmware_loader.c index d0f70af4a..1df848634 100644 --- a/boot/zephyr/firmware_loader.c +++ b/boot/zephyr/firmware_loader.c @@ -40,6 +40,8 @@ boot_image_validate(const struct flash_area *fa_p, static uint8_t tmpbuf[BOOT_TMPBUF_SZ]; FIH_DECLARE(fih_rc, FIH_FAILURE); + BOOT_LOG_DBG("boot_image_validate: encrypted == %d", (int)IS_ENCRYPTED(hdr)); + /* NOTE: The first argument to boot_image_validate, for enc_state pointer, * is allowed to be NULL only because the single image loader compiles * with BOOT_IMAGE_NUMBER == 1, which excludes the code that uses @@ -71,6 +73,8 @@ boot_image_validate_once(const struct flash_area *fa_p, int rc; FIH_DECLARE(fih_rc, FIH_FAILURE); + BOOT_LOG_DBG("boot_image_validate_once: flash area %p", fap_p); + memset(&state, 0, sizeof(struct boot_swap_state)); rc = boot_read_swap_state(fa_p, &state); if (rc != 0) @@ -108,6 +112,8 @@ static fih_ret validate_image_slot(int slot, struct boot_rsp *rsp) int rc = -1; FIH_DECLARE(fih_rc, FIH_FAILURE); + BOOT_LOG_DBG("validate_image_slot: slot %d", slot); + rc = flash_area_open(slot, &_fa_p); assert(rc == 0); @@ -156,6 +162,8 @@ boot_go(struct boot_rsp *rsp) bool boot_firmware_loader = false; FIH_DECLARE(fih_rc, FIH_FAILURE); + BOOT_LOG_DBG("boot_go: firmware loader"); + #ifdef CONFIG_BOOT_FIRMWARE_LOADER_ENTRANCE_GPIO if (io_detect_pin() && !io_boot_skip_serial_recovery()) { diff --git a/boot/zephyr/main.c b/boot/zephyr/main.c index ddea864de..2e57bd999 100644 --- a/boot/zephyr/main.c +++ b/boot/zephyr/main.c @@ -463,6 +463,7 @@ int main(void) mcuboot_status_change(MCUBOOT_STATUS_STARTUP); #ifdef CONFIG_BOOT_SERIAL_ENTRANCE_GPIO + BOOT_LOG_DBG("Checking GPIO for serial recovery"); if (io_detect_pin() && !io_boot_skip_serial_recovery()) { boot_serial_enter(); @@ -470,13 +471,17 @@ int main(void) #endif #ifdef CONFIG_BOOT_SERIAL_PIN_RESET + BOOT_LOG_DBG("Checking RESET pin for serial recovery"); if (io_detect_pin_reset()) { boot_serial_enter(); } #endif #if defined(CONFIG_BOOT_USB_DFU_GPIO) + BOOT_LOG_DBG("Checking GPIO for USB DFU request"); if (io_detect_pin()) { + BOOT_LOG_DBG("Entering USB DFU"); + usb_dfu_requested = true; #ifdef CONFIG_MCUBOOT_INDICATION_LED @@ -498,6 +503,7 @@ int main(void) BOOT_LOG_INF("Waiting for USB DFU"); #if defined(CONFIG_BOOT_USB_DFU_WAIT) + BOOT_LOG_DBG("Waiting for USB DFU for %dms", CONFIG_BOOT_USB_DFU_WAIT_DELAY_MS); mcuboot_status_change(MCUBOOT_STATUS_USB_DFU_WAITING); wait_for_usb_dfu(K_MSEC(CONFIG_BOOT_USB_DFU_WAIT_DELAY_MS)); BOOT_LOG_INF("USB DFU wait time elapsed"); @@ -529,12 +535,14 @@ int main(void) if (FIH_EQ(fih_rc, FIH_BOOT_HOOK_REGULAR)) { FIH_CALL(boot_go, fih_rc, &rsp); } + BOOT_LOG_DBG("Left boot_go with success == %d", FIH_EQ(fih_rc, FIH_SUCCESS) ? 1 : 0); #ifdef CONFIG_BOOT_SERIAL_BOOT_MODE if (io_detect_boot_mode()) { /* Boot mode to stay in bootloader, clear status and enter serial * recovery mode */ + BOOT_LOG_DBG("Staying in serial recovery"); boot_serial_enter(); } #endif diff --git a/boot/zephyr/single_loader.c b/boot/zephyr/single_loader.c index 28e9cdf15..31c4a8bf7 100644 --- a/boot/zephyr/single_loader.c +++ b/boot/zephyr/single_loader.c @@ -44,6 +44,8 @@ boot_image_validate(const struct flash_area *fa_p, static uint8_t tmpbuf[BOOT_TMPBUF_SZ]; FIH_DECLARE(fih_rc, FIH_FAILURE); + BOOT_LOG_DBG("boot_image_validate: encrypted == %d", (int)IS_ENCRYPTED(hdr)); + /* NOTE: The first argument to boot_image_validate, for enc_state pointer, * is allowed to be NULL only because the single image loader compiles * with BOOT_IMAGE_NUMBER == 1, which excludes the code that uses @@ -75,6 +77,8 @@ boot_image_validate_once(const struct flash_area *fa_p, int rc; FIH_DECLARE(fih_rc, FIH_FAILURE); + BOOT_LOG_DBG("boot_image_validate_once: flash area %p", fap_p); + memset(&state, 0, sizeof(struct boot_swap_state)); rc = boot_read_swap_state(fa_p, &state); if (rc != 0) @@ -112,6 +116,8 @@ boot_go(struct boot_rsp *rsp) int rc = -1; FIH_DECLARE(fih_rc, FIH_FAILURE); + BOOT_LOG_DBG("boot_go: Single loader"); + rc = flash_area_open(FLASH_AREA_IMAGE_PRIMARY(0), &_fa_p); assert(rc == 0); From 0529cbe7a955f006b5f5f2b7e22788cdde541483 Mon Sep 17 00:00:00 2001 From: Dominik Ermel Date: Wed, 28 May 2025 17:01:17 +0000 Subject: [PATCH 011/420] [nrf fromtree] bootutil: Small cleanup in image.h Fixed comments indentation. Signed-off-by: Dominik Ermel (cherry picked from commit e56cecc45b70e596052bf3bb0440601e366199f5) --- boot/bootutil/include/bootutil/image.h | 105 ++++++++++++------------- 1 file changed, 52 insertions(+), 53 deletions(-) diff --git a/boot/bootutil/include/bootutil/image.h b/boot/bootutil/include/bootutil/image.h index 15de3e01a..f49eab347 100644 --- a/boot/bootutil/include/bootutil/image.h +++ b/boot/bootutil/include/bootutil/image.h @@ -46,8 +46,6 @@ extern "C" { #define STRUCT_PACKED struct __attribute__((__packed__)) #endif -struct flash_area; - #define IMAGE_MAGIC 0x96f3b83d #define IMAGE_MAGIC_V1 0x96f3b83c #define IMAGE_MAGIC_NONE 0xffffffff @@ -98,50 +96,50 @@ struct flash_area; * 1st on identifies the public key which should be used to verify it. * 2nd one is the actual signature. */ -#define IMAGE_TLV_KEYHASH 0x01 /* hash of the public key */ -#define IMAGE_TLV_PUBKEY 0x02 /* public key */ -#define IMAGE_TLV_SHA256 0x10 /* SHA256 of image hdr and body */ -#define IMAGE_TLV_SHA384 0x11 /* SHA384 of image hdr and body */ -#define IMAGE_TLV_SHA512 0x12 /* SHA512 of image hdr and body */ -#define IMAGE_TLV_RSA2048_PSS 0x20 /* RSA2048 of hash output */ -#define IMAGE_TLV_ECDSA224 0x21 /* ECDSA of hash output - Not supported anymore */ -#define IMAGE_TLV_ECDSA_SIG 0x22 /* ECDSA of hash output */ -#define IMAGE_TLV_RSA3072_PSS 0x23 /* RSA3072 of hash output */ -#define IMAGE_TLV_ED25519 0x24 /* ed25519 of hash output */ -#define IMAGE_TLV_SIG_PURE 0x25 /* Indicator that attached signature has been prepared - * over image rather than its digest. - */ -#define IMAGE_TLV_ENC_RSA2048 0x30 /* Key encrypted with RSA-OAEP-2048 */ -#define IMAGE_TLV_ENC_KW 0x31 /* Key encrypted with AES-KW 128 or 256*/ -#define IMAGE_TLV_ENC_EC256 0x32 /* Key encrypted with ECIES-EC256 */ -#define IMAGE_TLV_ENC_X25519 0x33 /* Key encrypted with ECIES-X25519 */ -#define IMAGE_TLV_DEPENDENCY 0x40 /* Image depends on other image */ -#define IMAGE_TLV_SEC_CNT 0x50 /* security counter */ -#define IMAGE_TLV_BOOT_RECORD 0x60 /* measured boot record */ +#define IMAGE_TLV_KEYHASH 0x01 /* hash of the public key */ +#define IMAGE_TLV_PUBKEY 0x02 /* public key */ +#define IMAGE_TLV_SHA256 0x10 /* SHA256 of image hdr and body */ +#define IMAGE_TLV_SHA384 0x11 /* SHA384 of image hdr and body */ +#define IMAGE_TLV_SHA512 0x12 /* SHA512 of image hdr and body */ +#define IMAGE_TLV_RSA2048_PSS 0x20 /* RSA2048 of hash output */ +#define IMAGE_TLV_ECDSA224 0x21 /* ECDSA of hash output - Not supported anymore */ +#define IMAGE_TLV_ECDSA_SIG 0x22 /* ECDSA of hash output */ +#define IMAGE_TLV_RSA3072_PSS 0x23 /* RSA3072 of hash output */ +#define IMAGE_TLV_ED25519 0x24 /* ed25519 of hash output */ +#define IMAGE_TLV_SIG_PURE 0x25 /* Indicator that attached signature has been prepared + * over image rather than its digest. + */ +#define IMAGE_TLV_ENC_RSA2048 0x30 /* Key encrypted with RSA-OAEP-2048 */ +#define IMAGE_TLV_ENC_KW 0x31 /* Key encrypted with AES-KW 128 or 256*/ +#define IMAGE_TLV_ENC_EC256 0x32 /* Key encrypted with ECIES-EC256 */ +#define IMAGE_TLV_ENC_X25519 0x33 /* Key encrypted with ECIES-X25519 */ +#define IMAGE_TLV_DEPENDENCY 0x40 /* Image depends on other image */ +#define IMAGE_TLV_SEC_CNT 0x50 /* security counter */ +#define IMAGE_TLV_BOOT_RECORD 0x60 /* measured boot record */ /* The following flags relate to compressed images and are for the decompressed image data */ -#define IMAGE_TLV_DECOMP_SIZE 0x70 /* Decompressed image size excluding header/TLVs */ -#define IMAGE_TLV_DECOMP_SHA 0x71 /* - * Decompressed image shaX hash, this field must match - * the format and size of the raw slot (compressed) - * shaX hash - */ -#define IMAGE_TLV_DECOMP_SIGNATURE 0x72 /* - * Decompressed image signature, this field must match - * 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 - * range. Examples: - * 0x00a0 - 0x00ff - * 0x01a0 - 0x01ff - * 0x02a0 - 0x02ff - * ... - * 0xffa0 - 0xfffe - */ -#define IMAGE_TLV_ANY 0xffff /* Used to iterate over all TLV */ +#define IMAGE_TLV_DECOMP_SIZE 0x70 /* Decompressed image size excluding header/TLVs */ +#define IMAGE_TLV_DECOMP_SHA 0x71 /* + * Decompressed image shaX hash, this field must match + * the format and size of the raw slot (compressed) + * shaX hash + */ +#define IMAGE_TLV_DECOMP_SIGNATURE 0x72 /* + * Decompressed image signature, this field must match + * 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 + * range. Examples: + * 0x00a0 - 0x00ff + * 0x01a0 - 0x01ff + * 0x02a0 - 0x02ff + * ... + * 0xffa0 - 0xfffe + */ +#define IMAGE_TLV_ANY 0xffff /* Used to iterate over all TLV */ STRUCT_PACKED image_version { uint8_t iv_major; @@ -164,10 +162,10 @@ struct image_dependency { STRUCT_PACKED image_header { uint32_t ih_magic; uint32_t ih_load_addr; - uint16_t ih_hdr_size; /* Size of image header (bytes). */ - uint16_t ih_protect_tlv_size; /* Size of protected TLV area (bytes). */ - uint32_t ih_img_size; /* Does not include header. */ - uint32_t ih_flags; /* IMAGE_F_[...]. */ + uint16_t ih_hdr_size; /* Size of image header (bytes). */ + uint16_t ih_protect_tlv_size; /* Size of protected TLV area (bytes). */ + uint32_t ih_img_size; /* Does not include header. */ + uint32_t ih_flags; /* IMAGE_F_[...]. */ struct image_version ih_ver; uint32_t _pad1; }; @@ -175,13 +173,13 @@ STRUCT_PACKED image_header { /** Image TLV header. All fields in little endian. */ STRUCT_PACKED image_tlv_info { uint16_t it_magic; - uint16_t it_tlv_tot; /* size of TLV area (including tlv_info header) */ + uint16_t it_tlv_tot; /* size of TLV area (including tlv_info header) */ }; /** Image trailer TLV format. All fields in little endian. */ STRUCT_PACKED image_tlv { - uint16_t it_type; /* IMAGE_TLV_[...]. */ - uint16_t it_len; /* Data length (not including TLV header). */ + uint16_t it_type; /* IMAGE_TLV_[...]. */ + uint16_t it_len; /* Data length (not including TLV header). */ }; #define ENCRYPTIONFLAGS (IMAGE_F_ENCRYPTED_AES128 | IMAGE_F_ENCRYPTED_AES256) @@ -199,8 +197,9 @@ STRUCT_PACKED image_tlv { _Static_assert(sizeof(struct image_header) == IMAGE_HEADER_SIZE, "struct image_header not required size"); -struct enc_key_data; struct boot_loader_state; +struct flash_area; + fih_ret bootutil_img_validate(struct boot_loader_state *state, struct image_header *hdr, const struct flash_area *fap, From 860d366a4b150918b7abf27df20d5246eb4cb235 Mon Sep 17 00:00:00 2001 From: Dominik Ermel Date: Wed, 7 May 2025 16:01:02 +0000 Subject: [PATCH 012/420] [nrf fromtree] doc: Add information on supporting SHA512 with ECIES-X25519 Information on TLV and format. Signed-off-by: Dominik Ermel (cherry picked from commit e542295f266a63657f18a2e6a77723941cc8d0b3) --- docs/encrypted_images.md | 21 +++++++++++++++------ 1 file changed, 15 insertions(+), 6 deletions(-) diff --git a/docs/encrypted_images.md b/docs/encrypted_images.md index ebc4f46ed..5f775ef18 100644 --- a/docs/encrypted_images.md +++ b/docs/encrypted_images.md @@ -92,24 +92,33 @@ libraries. The whole key encryption can be summarized as: keypair. Those keys will be our ephemeral keys. * Generate a new secret (DH) using the ephemeral private key and the public key that corresponds to the private key embedded in the HW. -* Derive the new keys from the secret using HKDF (built on HMAC-SHA256). We - are not using a `salt` and using an `info` of `MCUBoot_ECIES_v1`, generating - 48 bytes of key material. +* Derive the new keys from the secret using HKDF. We are not using a `salt` + and using an `info` of `MCUBoot_ECIES_v1`, generating 48 bytes of key material. * A new random encryption key is generated (for AES). This is the AES key used to encrypt the images. * The key is encrypted with AES-128-CTR or AES-256-CTR and a `nonce` of 0 using the first 16 bytes of key material generated previously by the HKDF. -* The encrypted key now goes through a HMAC-SHA256 using the remaining 32 +* The encrypted key now goes through a HMAC using the remaining 32 bytes of key material from the HKDF. +There are different TLVs for ECIES-P256, ECIES-X25519 with SHA256 HKDF/HMAC +and ECIES-X25519 with SHA512 HKDF/HMAC. The final TLV is built from the 65 bytes for ECIES-P256 or 32 bytes for ECIES-X25519, which correspond to the ephemeral public key, followed by the -32 bytes of MAC tag and the 16 or 32 bytes of the encrypted key, resulting in -a TLV of 113 or 129 bytes for ECIES-P256 and 80 or 96 bytes for ECIES-X25519. +MAC tag and the 16 or 32 bytes of the encrypted key, resulting in final TLV +length: + * ECIES-P256 has TLV length 113 to 129 bytes, depending on AES key length. + * ECIES-X25519 on SHA256 TLV length is 80 or 96 bytes, depending on AES key + length. + * ECIES-X25519 on SHA512 TLV length is 112 or 128, depending on AES key + length. The implemenation of ECIES-P256 is named ENC_EC256 in the source code and artifacts while ECIES-X25519 is named ENC_X25519. +Note that MCUboot is built to support only one ECIES and HMAC SHA at once, +and truncated HMAC is not supported at this time + ## [Upgrade process](#upgrade-process) When starting a new upgrade process, `MCUboot` checks that the image in the From 736d33ee0e557481df17bec4ecfe9990f562340c Mon Sep 17 00:00:00 2001 From: Dominik Ermel Date: Thu, 8 May 2025 19:38:29 +0000 Subject: [PATCH 013/420] [nrf fromtree] bootutil: Add support for HAMC-SHA512 with ECIES-X25519 Add support for HKDF/HMAC based on SHA512 for ECIES-X25519 key exchange. The commit adds MCUBOOT_HMAC_SHA512 that enables new TLV IMAGE_TLV_ENC_X25519_SHA512. Encryption code has been altered to support the MCUBOOT_HMAC_SHA512. Signed-off-by: Dominik Ermel (cherry picked from commit 1d83177ca286122395b105bfddbaa854aae20748) --- boot/bootutil/include/bootutil/enc_key_public.h | 17 +++++++++++++++-- boot/bootutil/include/bootutil/image.h | 3 +++ boot/bootutil/src/encrypted_psa.c | 12 +++++++++--- boot/bootutil/src/image_validate.c | 4 ++++ 4 files changed, 31 insertions(+), 5 deletions(-) diff --git a/boot/bootutil/include/bootutil/enc_key_public.h b/boot/bootutil/include/bootutil/enc_key_public.h index 55b06b025..4582dfcf7 100644 --- a/boot/bootutil/include/bootutil/enc_key_public.h +++ b/boot/bootutil/include/bootutil/enc_key_public.h @@ -70,10 +70,19 @@ extern "C" { # define BOOT_ENC_KEY_SIZE 16 #endif +#ifdef MCUBOOT_HMAC_SHA512 +# define BOOT_HMAC_SIZE 64 +#else +# define BOOT_HMAC_SIZE 32 +#endif + #if defined(MCUBOOT_ENCRYPT_RSA) # define BOOT_ENC_TLV_SIZE (256) # define BOOT_ENC_TLV IMAGE_TLV_ENC_RSA2048 #elif defined(MCUBOOT_ENCRYPT_EC256) +# if defined(MCUBOOT_HMAC_SHA512) +# error "ECIES-P256 does not support HMAC-SHA512" +# endif # define EC_PUBK_LEN (65) # define EC_PRIVK_LEN (32) # define EC_SHARED_LEN (32) @@ -82,7 +91,11 @@ extern "C" { # define EC_PUBK_LEN (32) # define EC_PRIVK_LEN (32) # define EC_SHARED_LEN (32) -# define BOOT_ENC_TLV IMAGE_TLV_ENC_X25519 +# if !defined(MCUBOOT_HMAC_SHA512) +# define BOOT_ENC_TLV IMAGE_TLV_ENC_X25519 +# else +# define BOOT_ENC_TLV IMAGE_TLV_ENC_X25519_SHA512 +# endif #elif defined(MCUBOOT_ENCRYPT_KW) # define BOOT_ENC_TLV_SIZE (BOOT_ENC_KEY_SIZE + 8) # define BOOT_ENC_TLV IMAGE_TLV_ENC_KW @@ -91,7 +104,7 @@ extern "C" { /* Common ECIES definitions */ #if defined(EC_PUBK_LEN) # define EC_PUBK_INDEX (0) -# define EC_TAG_LEN (32) +# define EC_TAG_LEN (BOOT_HMAC_SIZE) # define EC_TAG_INDEX (EC_PUBK_INDEX + EC_PUBK_LEN) # define EC_CIPHERKEY_INDEX (EC_TAG_INDEX + EC_TAG_LEN) # define EC_CIPHERKEY_LEN BOOT_ENC_KEY_SIZE diff --git a/boot/bootutil/include/bootutil/image.h b/boot/bootutil/include/bootutil/image.h index f49eab347..11c54b633 100644 --- a/boot/bootutil/include/bootutil/image.h +++ b/boot/bootutil/include/bootutil/image.h @@ -113,6 +113,9 @@ extern "C" { #define IMAGE_TLV_ENC_KW 0x31 /* Key encrypted with AES-KW 128 or 256*/ #define IMAGE_TLV_ENC_EC256 0x32 /* Key encrypted with ECIES-EC256 */ #define IMAGE_TLV_ENC_X25519 0x33 /* Key encrypted with ECIES-X25519 */ +#define IMAGE_TLV_ENC_X25519_SHA512 0x34 /* Key exchange using ECIES-X25519 and SHA512 for MAC + * tag and HKDF in key derivation process + */ #define IMAGE_TLV_DEPENDENCY 0x40 /* Image depends on other image */ #define IMAGE_TLV_SEC_CNT 0x50 /* security counter */ #define IMAGE_TLV_BOOT_RECORD 0x60 /* measured boot record */ diff --git a/boot/bootutil/src/encrypted_psa.c b/boot/bootutil/src/encrypted_psa.c index 6f60a1955..0cfdc9768 100644 --- a/boot/bootutil/src/encrypted_psa.c +++ b/boot/bootutil/src/encrypted_psa.c @@ -27,6 +27,12 @@ BOOT_LOG_MODULE_DECLARE(mcuboot_psa_enc); +#if defined(MCUBOOT_HMAC_SHA512) +#define PSA_HMAC_HKDF_SHA PSA_ALG_SHA_512 +#else +#define PSA_HMAC_HKDF_SHA PSA_ALG_SHA_256 +#endif + #define X25519_OID "\x6e" static const uint8_t ec_pubkey_oid[] = MBEDTLS_OID_ISO_IDENTIFIED_ORG \ MBEDTLS_OID_ORG_GOV X25519_OID; @@ -162,7 +168,7 @@ boot_decrypt_key(const uint8_t *buf, uint8_t *enckey) return -1; } - key_do_alg = PSA_ALG_KEY_AGREEMENT(PSA_ALG_ECDH, PSA_ALG_HKDF(PSA_ALG_SHA_256)); + key_do_alg = PSA_ALG_KEY_AGREEMENT(PSA_ALG_ECDH, PSA_ALG_HKDF(PSA_HMAC_HKDF_SHA)); psa_ret = psa_key_derivation_setup(&key_do, key_do_alg); if (psa_ret != PSA_SUCCESS) { @@ -225,7 +231,7 @@ boot_decrypt_key(const uint8_t *buf, uint8_t *enckey) */ psa_set_key_type(&kattr, PSA_KEY_TYPE_HMAC); psa_set_key_usage_flags(&kattr, PSA_KEY_USAGE_VERIFY_MESSAGE); - psa_set_key_algorithm(&kattr, PSA_ALG_HMAC(PSA_ALG_SHA_256)); + psa_set_key_algorithm(&kattr, PSA_ALG_HMAC(PSA_HMAC_HKDF_SHA)); /* Import the MAC tag key part of derived key */ psa_ret = psa_import_key(&kattr, @@ -239,7 +245,7 @@ boot_decrypt_key(const uint8_t *buf, uint8_t *enckey) } /* Verify the MAC tag of the random encryption key */ - psa_ret = psa_mac_verify(kid, PSA_ALG_HMAC(PSA_ALG_SHA_256), + psa_ret = psa_mac_verify(kid, PSA_ALG_HMAC(PSA_HMAC_HKDF_SHA), &buf[EC_CIPHERKEY_INDEX], EC_CIPHERKEY_LEN, &buf[EC_TAG_INDEX], EC_TAG_LEN); diff --git a/boot/bootutil/src/image_validate.c b/boot/bootutil/src/image_validate.c index eec678724..f6d4ba224 100644 --- a/boot/bootutil/src/image_validate.c +++ b/boot/bootutil/src/image_validate.c @@ -474,7 +474,11 @@ static const uint16_t allowed_unprot_tlvs[] = { IMAGE_TLV_ENC_RSA2048, IMAGE_TLV_ENC_KW, IMAGE_TLV_ENC_EC256, +#if !defined(MCUBOOT_HMAC_SHA512) IMAGE_TLV_ENC_X25519, +#else + IMAGE_TLV_ENC_X25519_SHA512, +#endif /* Mark end with ANY. */ IMAGE_TLV_ANY, }; From 1a457e304f3c879db9a5a170992a3af376b1d430 Mon Sep 17 00:00:00 2001 From: Dominik Ermel Date: Thu, 8 May 2025 19:45:39 +0000 Subject: [PATCH 014/420] [nrf fromtree] zephyr: Support for HKDF/HMAC with SHA512 The commit adds CONFIG_BOOT_HMAC_SHA512 that enables MCUboot configuration option MCUBOOT_HMAC_SHA512, that is used for switching HKDF/HMAC in ECIES key exchange to SHA512, from default SHA256. This option, currently, is only available for ECIES-X25519 with PSA as crypto backend. Signed-off-by: Dominik Ermel (cherry picked from commit 377191693ca934a1791fe76011dc589454138ca7) --- boot/zephyr/Kconfig | 9 +++++++++ boot/zephyr/include/mcuboot_config/mcuboot_config.h | 7 +++++++ 2 files changed, 16 insertions(+) diff --git a/boot/zephyr/Kconfig b/boot/zephyr/Kconfig index acc0314a6..dc445b4ed 100644 --- a/boot/zephyr/Kconfig +++ b/boot/zephyr/Kconfig @@ -601,6 +601,15 @@ config BOOT_ENCRYPT_X25519 help Hidden option selecting x25519 encryption. +config BOOT_HMAC_SHA512 + bool "Use SHA512 for HMAC/HKDF" + depends on BOOT_ENCRYPT_X25519 + depends on BOOT_USE_PSA_CRYPTO + help + By default SHA256 is used for HKDF/HMAC in key exchange expansion + and verification. This options switches to SHA512. The option is + mainly useful to reduce numer of compiled in SHA algorithms. + config BOOT_ENCRYPTION_KEY_FILE string "Encryption key file" depends on BOOT_ENCRYPT_IMAGE diff --git a/boot/zephyr/include/mcuboot_config/mcuboot_config.h b/boot/zephyr/include/mcuboot_config/mcuboot_config.h index fd003565a..820ffd752 100644 --- a/boot/zephyr/include/mcuboot_config/mcuboot_config.h +++ b/boot/zephyr/include/mcuboot_config/mcuboot_config.h @@ -153,6 +153,13 @@ #define MCUBOOT_ENCRYPT_X25519 #endif +/* Support for HMAC/HKDF using SHA512; this is used in key exchange where + * HKDF is used for key expansion and HMAC is used for key verification. + */ +#ifdef CONFIG_BOOT_HMAC_SHA512 +#define MCUBOOT_HMAC_SHA512 +#endif + #ifdef CONFIG_BOOT_DECOMPRESSION #define MCUBOOT_DECOMPRESS_IMAGES #endif From c4c82e20aed038dc62fef8d2499afa162d3d8e9d Mon Sep 17 00:00:00 2001 From: Dominik Ermel Date: Fri, 9 May 2025 15:28:47 +0000 Subject: [PATCH 015/420] [nrf fromtree] imgtool: Add support for HMAC/HKDF-SHA512 with ECIES-X25519 Commit adds imgtool command line option --hmac-sha allowing to select between SHA256 and SHA512 for HMAC/HKDF. Signed-off-by: Dominik Ermel (cherry picked from commit a36f951307dbb170d5e6a1f23603dc8edd6af80d) --- scripts/imgtool/image.py | 37 +++++++++++++++++++++++++++---------- scripts/imgtool/main.py | 11 +++++++---- 2 files changed, 34 insertions(+), 14 deletions(-) diff --git a/scripts/imgtool/image.py b/scripts/imgtool/image.py index c7fb9e553..03e2cbb62 100644 --- a/scripts/imgtool/image.py +++ b/scripts/imgtool/image.py @@ -88,6 +88,7 @@ 'ENCKW': 0x31, 'ENCEC256': 0x32, 'ENCX25519': 0x33, + 'ENCX25519_SHA512': 0x34, 'DEPENDENCY': 0x40, 'SEC_CNT': 0x50, 'BOOT_RECORD': 0x60, @@ -435,7 +436,7 @@ def check_trailer(self): len(self.payload), tsize, self.slot_size) raise click.UsageError(msg) - def ecies_hkdf(self, enckey, plainkey): + def ecies_hkdf(self, enckey, plainkey, hmac_sha_alg): if isinstance(enckey, ecdsa.ECDSA256P1Public): newpk = ec.generate_private_key(ec.SECP256R1(), default_backend()) shared = newpk.exchange(ec.ECDH(), enckey._get_public()) @@ -443,13 +444,13 @@ def ecies_hkdf(self, enckey, plainkey): newpk = X25519PrivateKey.generate() shared = newpk.exchange(enckey._get_public()) derived_key = HKDF( - algorithm=hashes.SHA256(), length=48, salt=None, + algorithm=hmac_sha_alg, length=48, salt=None, info=b'MCUBoot_ECIES_v1', backend=default_backend()).derive(shared) encryptor = Cipher(algorithms.AES(derived_key[:16]), modes.CTR(bytes([0] * 16)), backend=default_backend()).encryptor() cipherkey = encryptor.update(plainkey) + encryptor.finalize() - mac = hmac.HMAC(derived_key[16:], hashes.SHA256(), + mac = hmac.HMAC(derived_key[16:], hmac_sha_alg, backend=default_backend()) mac.update(cipherkey) ciphermac = mac.finalize() @@ -467,7 +468,8 @@ 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, keep_comp_size=False, dont_encrypt=False): + user_sha='auto', hmac_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 @@ -674,6 +676,17 @@ def create(self, key, public_key_format, enckey, dependencies=None, else: plainkey = os.urandom(16) + if not isinstance(enckey, rsa.RSAPublic): + if hmac_sha == 'auto' or hmac_sha == '256': + hmac_sha = '256' + hmac_sha_alg = hashes.SHA256() + elif hmac_sha == '512': + if not isinstance(enckey, x25519.X25519Public): + raise click.UsageError("Currently only ECIES-X25519 supports HMAC-SHA512") + hmac_sha_alg = hashes.SHA512() + else: + raise click.UsageError("Unsupported HMAC-SHA") + if isinstance(enckey, rsa.RSAPublic): cipherkey = enckey._get_public().encrypt( plainkey, padding.OAEP( @@ -682,15 +695,19 @@ def create(self, key, public_key_format, enckey, dependencies=None, label=None)) self.enctlv_len = len(cipherkey) tlv.add('ENCRSA2048', cipherkey) - elif isinstance(enckey, (ecdsa.ECDSA256P1Public, - x25519.X25519Public)): - cipherkey, mac, pubk = self.ecies_hkdf(enckey, plainkey) + elif isinstance(enckey, ecdsa.ECDSA256P1Public): + cipherkey, mac, pubk = self.ecies_hkdf(enckey, plainkey, hmac_sha_alg) enctlv = pubk + mac + cipherkey self.enctlv_len = len(enctlv) - if isinstance(enckey, ecdsa.ECDSA256P1Public): - tlv.add('ENCEC256', enctlv) - else: + tlv.add('ENCEC256', enctlv) + elif isinstance(enckey, x25519.X25519Public): + cipherkey, mac, pubk = self.ecies_hkdf(enckey, plainkey, hmac_sha_alg) + enctlv = pubk + mac + cipherkey + self.enctlv_len = len(enctlv) + if (hmac_sha == '256'): tlv.add('ENCX25519', enctlv) + else: + tlv.add('ENCX25519_SHA512', enctlv) if not clear: nonce = bytes([0] * 16) diff --git a/scripts/imgtool/main.py b/scripts/imgtool/main.py index 78f2e77ec..5ff1f8f9f 100755 --- a/scripts/imgtool/main.py +++ b/scripts/imgtool/main.py @@ -84,6 +84,7 @@ def gen_x25519(keyfile, passwd): } valid_formats = ['openssl', 'pkcs8'] valid_sha = [ 'auto', '256', '384', '512' ] +valid_hmac_sha = [ 'auto', '256', '512' ] def load_signature(sigfile): @@ -437,6 +438,8 @@ def convert(self, value, param, ctx): @click.option('--sha', 'user_sha', type=click.Choice(valid_sha), default='auto', help='selected sha algorithm to use; defaults to "auto" which is 256 if ' 'no cryptographic signature is used, or default for signature type') +@click.option('--hmac-sha', 'hmac_sha', type=click.Choice(valid_hmac_sha), default='auto', + help='sha algorithm used in HKDF/HMAC in ECIES key exchange TLV') @click.option('--vector-to-sign', type=click.Choice(['payload', 'digest']), help='send to OUTFILE the payload or payload''s digest instead ' 'of complied image. These data can be used for external image ' @@ -449,7 +452,7 @@ 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, is_pure, + clear, fix_sig, fix_sig_pubkey, sig_out, user_sha, hmac_sha, is_pure, vector_to_sign, non_bootable): if confirm: @@ -526,7 +529,7 @@ def sign(key, public_key_format, align, version, pad_sig, header_size, 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, keep_comp_size=False, dont_encrypt=True) + hmac_sha=hmac_sha, 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), @@ -570,14 +573,14 @@ 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, hmac_sha=hmac_sha, 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) + hmac_sha=hmac_sha, is_pure=is_pure) img.save(outfile, hex_addr) if sig_out is not None: new_signature = img.get_signature() From 80f8e8c926b6e4c7e8a3fca4e97867575ed39300 Mon Sep 17 00:00:00 2001 From: Tomasz Chyrowicz Date: Tue, 1 Jul 2025 16:43:52 +0200 Subject: [PATCH 016/420] [nrf fromtree] bootutil: Use flash base address for direct hash Fetch the flash base address if direct hash calculation is performed. Signed-off-by: Tomasz Chyrowicz (cherry picked from commit 6a178d29f98ff5288c9534474ae72fe1ab499e1f) --- boot/bootutil/src/image_validate.c | 11 ++++++++++- docs/release-notes.d/fix-direct-hash-base-address.md | 2 ++ 2 files changed, 12 insertions(+), 1 deletion(-) create mode 100644 docs/release-notes.d/fix-direct-hash-base-address.md diff --git a/boot/bootutil/src/image_validate.c b/boot/bootutil/src/image_validate.c index f6d4ba224..17193a63d 100644 --- a/boot/bootutil/src/image_validate.c +++ b/boot/bootutil/src/image_validate.c @@ -87,6 +87,10 @@ bootutil_img_hash(struct boot_loader_state *state, uint32_t off; uint32_t blk_sz; #endif +#ifdef MCUBOOT_HASH_STORAGE_DIRECTLY + uintptr_t base = 0; + int fa_ret; +#endif #if defined(MCUBOOT_ENC_IMAGES) struct enc_key_data *enc_state; int image_index; @@ -160,7 +164,12 @@ bootutil_img_hash(struct boot_loader_state *state, /* No chunk loading, storage is mapped to address space and can * be directly given to hashing function. */ - bootutil_sha_update(&sha_ctx, (void *)flash_area_get_off(fap), size); + fa_ret = flash_device_base(flash_area_get_device_id(fap), &base); + if (fa_ret != 0) { + base = 0; + } + + bootutil_sha_update(&sha_ctx, (void *)(base + flash_area_get_off(fap)), size); #else /* MCUBOOT_HASH_STORAGE_DIRECTLY */ #ifdef MCUBOOT_RAM_LOAD bootutil_sha_update(&sha_ctx, diff --git a/docs/release-notes.d/fix-direct-hash-base-address.md b/docs/release-notes.d/fix-direct-hash-base-address.md new file mode 100644 index 000000000..041a45134 --- /dev/null +++ b/docs/release-notes.d/fix-direct-hash-base-address.md @@ -0,0 +1,2 @@ + - Fixed issue in image_validate when `MCUBOOT_HASH_STORAGE_DIRECTLY` is enabled + for platforms with NVM memory that does not start at 0x00. From 22199979e37e55cbf37053fa099baf29550967e1 Mon Sep 17 00:00:00 2001 From: Jamie McCrae Date: Tue, 8 Jul 2025 08:52:19 +0100 Subject: [PATCH 017/420] [nrf fromlist] boot: zephyr: boards: Remove outdated nrf54l15pdk board config This board has not been supported in a long time, remove it Upstream PR #: 2380 Signed-off-by: Jamie McCrae (cherry picked from commit 78ad12e17024b8c56ee6c828d3a9851a191a729e) --- boot/zephyr/boards/nrf54l15pdk_nrf54l15_cpuapp.conf | 10 ---------- 1 file changed, 10 deletions(-) delete mode 100644 boot/zephyr/boards/nrf54l15pdk_nrf54l15_cpuapp.conf diff --git a/boot/zephyr/boards/nrf54l15pdk_nrf54l15_cpuapp.conf b/boot/zephyr/boards/nrf54l15pdk_nrf54l15_cpuapp.conf deleted file mode 100644 index 43d8cebe3..000000000 --- a/boot/zephyr/boards/nrf54l15pdk_nrf54l15_cpuapp.conf +++ /dev/null @@ -1,10 +0,0 @@ -# Copyright (c) 2024 Nordic Semiconductor ASA -# -# SPDX-License-Identifier: Apache-2.0 -# -CONFIG_BOOT_MAX_IMG_SECTORS=256 - -# Ensure that the SPI NOR driver is disabled by default -CONFIG_SPI_NOR=n - -CONFIG_BOOT_WATCHDOG_FEED=n From 422c6370ef884e9953b41662f6e51147ff14bea0 Mon Sep 17 00:00:00 2001 From: Tomasz Chyrowicz Date: Fri, 23 May 2025 13:26:51 +0200 Subject: [PATCH 018/420] [nrf fromlist] bootutil: Unify app_max_size() implementations Remove redundant application size calculations in favor of a swap-specific function, implemented inside swap_.c. In this way, slot sizes use the same restrictions as image validation. Upstream PR #: 2318 Signed-off-by: Tomasz Chyrowicz (cherry picked from commit cf1f76cfb843f790e89fe33204fe52d48f4950b9) --- .../include/bootutil/bootutil_public.h | 6 + boot/bootutil/src/bootutil_misc.c | 102 +----------- boot/bootutil/src/bootutil_priv.h | 18 +-- boot/bootutil/src/swap_move.c | 55 +++---- boot/bootutil/src/swap_offset.c | 64 +++----- boot/bootutil/src/swap_scratch.c | 146 +++++++++++++++++- 6 files changed, 202 insertions(+), 189 deletions(-) diff --git a/boot/bootutil/include/bootutil/bootutil_public.h b/boot/bootutil/include/bootutil/bootutil_public.h index 933553f9f..421d854b1 100644 --- a/boot/bootutil/include/bootutil/bootutil_public.h +++ b/boot/bootutil/include/bootutil/bootutil_public.h @@ -295,6 +295,12 @@ boot_set_next(const struct flash_area *fa, bool active, bool confirm); /** * Attempts to load image header from flash; verifies flash header fields. * + * The selected update method (i.e. swap move) may impose additional restrictions + * on the image size (i.e. due to the presence of the image trailer). + * Such restrictions are not verified by this function. + * These checks are implemented as part of the boot_image_validate(..) that uses + * sizes from the bootutil_max_image_size(..). + * * @param[in] fa_p flash area pointer * @param[out] hdr buffer for image header * diff --git a/boot/bootutil/src/bootutil_misc.c b/boot/bootutil/src/bootutil_misc.c index 56e791043..17ed4c616 100644 --- a/boot/bootutil/src/bootutil_misc.c +++ b/boot/bootutil/src/bootutil_misc.c @@ -42,6 +42,10 @@ #ifdef MCUBOOT_ENC_IMAGES #include "bootutil/enc_key.h" #endif +#if defined(MCUBOOT_SWAP_USING_MOVE) || defined(MCUBOOT_SWAP_USING_OFFSET) || \ + defined(MCUBOOT_SWAP_USING_SCRATCH) +#include "swap_priv.h" +#endif BOOT_LOG_MODULE_DECLARE(mcuboot); @@ -235,8 +239,7 @@ int boot_header_scramble_off_sz(const struct flash_area *fa, int slot, size_t *o * status during the swap of the last sector from primary/secondary (which * is the first swap operation) and thus only requires space for one swap. */ -static uint32_t -boot_scratch_trailer_sz(uint32_t min_write_sz) +uint32_t boot_scratch_trailer_sz(uint32_t min_write_sz) { return boot_status_entry_sz(min_write_sz) + boot_trailer_info_sz(); } @@ -422,44 +425,6 @@ boot_write_enc_key(const struct flash_area *fap, uint8_t slot, } #endif -#ifdef MCUBOOT_SWAP_USING_SCRATCH -size_t -boot_get_first_trailer_sector(struct boot_loader_state *state, size_t slot, size_t trailer_sz) -{ - size_t first_trailer_sector = boot_img_num_sectors(state, slot) - 1; - size_t sector_sz = boot_img_sector_size(state, slot, first_trailer_sector); - size_t trailer_sector_sz = sector_sz; - - while (trailer_sector_sz < trailer_sz) { - /* Consider that the image trailer may span across sectors of different sizes */ - --first_trailer_sector; - sector_sz = boot_img_sector_size(state, slot, first_trailer_sector); - - trailer_sector_sz += sector_sz; - } - - return first_trailer_sector; -} - -/** - * Returns the offset to the end of the first sector of a given slot that holds image trailer data. - * - * @param state Current bootloader's state. - * @param slot The index of the slot to consider. - * @param trailer_sz The size of the trailer, in bytes. - * - * @return The offset to the end of the first sector of the slot that holds image trailer data. - */ -static uint32_t -get_first_trailer_sector_end_off(struct boot_loader_state *state, size_t slot, size_t trailer_sz) -{ - size_t first_trailer_sector = boot_get_first_trailer_sector(state, slot, trailer_sz); - - return boot_img_sector_off(state, slot, first_trailer_sector) + - boot_img_sector_size(state, slot, first_trailer_sector); -} -#endif /* MCUBOOT_SWAP_USING_SCRATCH */ - uint32_t bootutil_max_image_size(struct boot_loader_state *state, const struct flash_area *fap) { #if defined(MCUBOOT_SINGLE_APPLICATION_SLOT) || \ @@ -467,61 +432,10 @@ uint32_t bootutil_max_image_size(struct boot_loader_state *state, const struct f defined(MCUBOOT_SINGLE_APPLICATION_SLOT_RAM_LOAD) (void) state; return boot_status_off(fap); -#elif defined(MCUBOOT_SWAP_USING_SCRATCH) - size_t slot_trailer_sz = boot_trailer_sz(BOOT_WRITE_SZ(state)); - size_t slot_trailer_off = flash_area_get_size(fap) - slot_trailer_sz; - - /* If the trailer doesn't fit in the last sector of the primary or secondary slot, some padding - * might have to be inserted between the end of the firmware image and the beginning of the - * trailer to ensure there is enough space for the trailer in the scratch area when the last - * sector of the secondary will be copied to the scratch area. - * - * The value of the padding depends on the amount of trailer data that is contained in the first - * trailer containing part of the trailer in the primary and secondary slot. - */ - size_t trailer_sector_primary_end_off = - get_first_trailer_sector_end_off(state, BOOT_PRIMARY_SLOT, slot_trailer_sz); - size_t trailer_sector_secondary_end_off = - get_first_trailer_sector_end_off(state, BOOT_SECONDARY_SLOT, slot_trailer_sz); - - size_t trailer_sz_in_first_sector; - - if (trailer_sector_primary_end_off > trailer_sector_secondary_end_off) { - trailer_sz_in_first_sector = trailer_sector_primary_end_off - slot_trailer_off; - } else { - trailer_sz_in_first_sector = trailer_sector_secondary_end_off - slot_trailer_off; - } - - size_t trailer_padding = 0; - size_t scratch_trailer_sz = boot_scratch_trailer_sz(BOOT_WRITE_SZ(state)); - - if (scratch_trailer_sz > trailer_sz_in_first_sector) { - trailer_padding = scratch_trailer_sz - trailer_sz_in_first_sector; - } - - return slot_trailer_off - trailer_padding; -#elif defined(MCUBOOT_SWAP_USING_MOVE) || defined(MCUBOOT_SWAP_USING_OFFSET) +#elif defined(MCUBOOT_SWAP_USING_MOVE) || defined(MCUBOOT_SWAP_USING_OFFSET) \ + || defined(MCUBOOT_SWAP_USING_SCRATCH) (void) fap; - - /* The slot whose size is used to compute the maximum image size must be the one containing the - * padding required for the swap. */ -#ifdef MCUBOOT_SWAP_USING_MOVE - size_t slot = BOOT_PRIMARY_SLOT; -#else - size_t slot = BOOT_SECONDARY_SLOT; -#endif - - const struct flash_area *fap_padded_slot = BOOT_IMG_AREA(state, slot); - assert(fap_padded_slot != NULL); - - size_t trailer_sz = boot_trailer_sz(BOOT_WRITE_SZ(state)); - size_t sector_sz = boot_img_sector_size(state, slot, 0); - size_t padding_sz = sector_sz; - - /* The trailer size needs to be sector-aligned */ - trailer_sz = ALIGN_UP(trailer_sz, sector_sz); - - return flash_area_get_size(fap_padded_slot) - trailer_sz - padding_sz; + return app_max_size(state); #elif defined(MCUBOOT_OVERWRITE_ONLY) (void) state; return boot_swap_info_off(fap); diff --git a/boot/bootutil/src/bootutil_priv.h b/boot/bootutil/src/bootutil_priv.h index 72e94aee9..5d5a58a04 100644 --- a/boot/bootutil/src/bootutil_priv.h +++ b/boot/bootutil/src/bootutil_priv.h @@ -363,18 +363,14 @@ int boot_read_enc_key(const struct flash_area *fap, uint8_t slot, struct boot_status *bs); #endif -#ifdef MCUBOOT_SWAP_USING_SCRATCH -/** - * Finds the first sector of a given slot that holds image trailer data. - * - * @param state Current bootloader's state. - * @param slot The index of the slot to consider. - * @param trailer_sz The size of the trailer, in bytes. - * - * @return The index of the first sector of the slot that holds image trailer data. +#if MCUBOOT_SWAP_USING_SCRATCH +/* + * Similar to `boot_trailer_sz` but this function returns the space used to + * store status in the scratch partition. The scratch partition only stores + * status during the swap of the last sector from primary/secondary (which + * is the first swap operation) and thus only requires space for one swap. */ -size_t -boot_get_first_trailer_sector(struct boot_loader_state *state, size_t slot, size_t trailer_sz); +uint32_t boot_scratch_trailer_sz(uint32_t min_write_sz); #endif /** diff --git a/boot/bootutil/src/swap_move.c b/boot/bootutil/src/swap_move.c index 9349cde37..8b7bcab13 100644 --- a/boot/bootutil/src/swap_move.c +++ b/boot/bootutil/src/swap_move.c @@ -227,29 +227,6 @@ boot_status_internal_off(const struct boot_status *bs, int elem_sz) return off; } -static int app_max_sectors(struct boot_loader_state *state) -{ - uint32_t sz = 0; - uint32_t sector_sz; - uint32_t trailer_sz; - uint32_t first_trailer_idx; - - sector_sz = boot_img_sector_size(state, BOOT_PRIMARY_SLOT, 0); - trailer_sz = boot_trailer_sz(BOOT_WRITE_SZ(state)); - /* subtract 1 for swap and at least 1 for trailer */ - first_trailer_idx = boot_img_num_sectors(state, BOOT_PRIMARY_SLOT) - 2; - - while (1) { - sz += sector_sz; - if (sz >= trailer_sz) { - break; - } - first_trailer_idx--; - } - - return first_trailer_idx; -} - int boot_slots_compatible(struct boot_loader_state *state) { @@ -258,19 +235,16 @@ boot_slots_compatible(struct boot_loader_state *state) size_t sector_sz_pri = 0; size_t sector_sz_sec = 0; size_t i; - size_t num_usable_sectors_pri; num_sectors_pri = boot_img_num_sectors(state, BOOT_PRIMARY_SLOT); num_sectors_sec = boot_img_num_sectors(state, BOOT_SECONDARY_SLOT); - num_usable_sectors_pri = app_max_sectors(state); if ((num_sectors_pri != num_sectors_sec) && - (num_sectors_pri != (num_sectors_sec + 1)) && - (num_usable_sectors_pri != (num_sectors_sec + 1))) { + (num_sectors_pri != (num_sectors_sec + 1))) { BOOT_LOG_WRN("Cannot upgrade: not a compatible amount of sectors"); BOOT_LOG_DBG("slot0 sectors: %d, slot1 sectors: %d, usable slot0 sectors: %d", (int)num_sectors_pri, (int)num_sectors_sec, - (int)(num_usable_sectors_pri - 1)); + (int)(num_sectors_pri - 1)); return 0; } else if (num_sectors_pri > BOOT_MAX_IMG_SECTORS) { BOOT_LOG_WRN("Cannot upgrade: more sectors than allowed"); @@ -280,7 +254,7 @@ boot_slots_compatible(struct boot_loader_state *state) /* Optimal says primary has one more than secondary. Always. Both have trailers. */ if (num_sectors_pri != (num_sectors_sec + 1)) { BOOT_LOG_DBG("Non-optimal sector distribution, slot0 has %d usable sectors (%d assigned) " - "but slot1 has %d assigned", (int)num_usable_sectors_pri, + "but slot1 has %d assigned", (int)(num_sectors_pri - 1), (int)num_sectors_pri, (int)num_sectors_sec); } @@ -340,7 +314,6 @@ swap_status_source(struct boot_loader_state *state) struct boot_swap_state state_primary_slot; struct boot_swap_state state_secondary_slot; int rc; - uint8_t source; uint8_t image_index; #if (BOOT_IMAGE_NUMBER == 1) @@ -365,10 +338,8 @@ swap_status_source(struct boot_loader_state *state) state_primary_slot.copy_done == BOOT_FLAG_UNSET && state_secondary_slot.magic != BOOT_MAGIC_GOOD) { - source = BOOT_STATUS_SOURCE_PRIMARY_SLOT; - BOOT_LOG_INF("Boot source: primary slot"); - return source; + return BOOT_STATUS_SOURCE_PRIMARY_SLOT; } BOOT_LOG_INF("Boot source: none"); @@ -590,11 +561,23 @@ swap_run(struct boot_loader_state *state, struct boot_status *bs, int app_max_size(struct boot_loader_state *state) { - uint32_t sector_sz_primary; + uint32_t available_pri_sz; + uint32_t available_sec_sz; + + size_t trailer_sz = boot_trailer_sz(BOOT_WRITE_SZ(state)); + size_t sector_sz = boot_img_sector_size(state, BOOT_PRIMARY_SLOT, 0); + size_t padding_sz = sector_sz; - sector_sz_primary = boot_img_sector_size(state, BOOT_PRIMARY_SLOT, 0); + /* The trailer size needs to be sector-aligned */ + trailer_sz = ALIGN_UP(trailer_sz, sector_sz); + + /* The slot whose size is used to compute the maximum image size must be the one containing the + * padding required for the swap. + */ + available_pri_sz = boot_img_num_sectors(state, BOOT_PRIMARY_SLOT) * sector_sz - trailer_sz - padding_sz; + available_sec_sz = boot_img_num_sectors(state, BOOT_SECONDARY_SLOT) * sector_sz - trailer_sz; - return app_max_sectors(state) * sector_sz_primary; + return (available_pri_sz < available_sec_sz ? available_pri_sz : available_sec_sz); } #endif diff --git a/boot/bootutil/src/swap_offset.c b/boot/bootutil/src/swap_offset.c index 8bc6e760a..d8bfac318 100644 --- a/boot/bootutil/src/swap_offset.c +++ b/boot/bootutil/src/swap_offset.c @@ -302,33 +302,6 @@ uint32_t boot_status_internal_off(const struct boot_status *bs, int elem_sz) return off; } -static int app_max_sectors(struct boot_loader_state *state) -{ - uint32_t sz = 0; - uint32_t sector_sz; - uint32_t trailer_sz; - uint32_t available_sectors_pri; - uint32_t available_sectors_sec; - uint32_t trailer_sectors = 0; - - sector_sz = boot_img_sector_size(state, BOOT_PRIMARY_SLOT, 0); - trailer_sz = boot_trailer_sz(BOOT_WRITE_SZ(state)); - - while (1) { - sz += sector_sz; - ++trailer_sectors; - - if (sz >= trailer_sz) { - break; - } - } - - available_sectors_pri = boot_img_num_sectors(state, BOOT_PRIMARY_SLOT) - trailer_sectors; - available_sectors_sec = boot_img_num_sectors(state, BOOT_SECONDARY_SLOT) - 1; - - return (available_sectors_pri < available_sectors_sec ? available_sectors_pri : available_sectors_sec); -} - int boot_slots_compatible(struct boot_loader_state *state) { size_t num_sectors_pri; @@ -336,32 +309,30 @@ int boot_slots_compatible(struct boot_loader_state *state) size_t sector_sz_pri = 0; size_t sector_sz_sec = 0; size_t i; - size_t num_usable_sectors; num_sectors_pri = boot_img_num_sectors(state, BOOT_PRIMARY_SLOT); num_sectors_sec = boot_img_num_sectors(state, BOOT_SECONDARY_SLOT); - num_usable_sectors = app_max_sectors(state); if (num_sectors_pri != num_sectors_sec && - (num_sectors_pri + 1) != num_sectors_sec && - num_usable_sectors != (num_sectors_sec - 1)) { + (num_sectors_pri + 1) != num_sectors_sec) { BOOT_LOG_WRN("Cannot upgrade: not a compatible amount of sectors"); BOOT_LOG_DBG("slot0 sectors: %d, slot1 sectors: %d, usable sectors: %d", (int)num_sectors_pri, (int)num_sectors_sec, - (int)(num_usable_sectors)); + (int)(num_sectors_sec - 1)); return 0; } else if (num_sectors_pri > BOOT_MAX_IMG_SECTORS) { BOOT_LOG_WRN("Cannot upgrade: more sectors than allowed"); return 0; } - if ((num_usable_sectors + 1) != num_sectors_sec) { + /* Optimal says secondary has one more than primary. Always. Both have trailers. */ + if ((num_sectors_pri + 1) != num_sectors_sec) { BOOT_LOG_DBG("Non-optimal sector distribution, slot0 has %d usable sectors " - "but slot1 has %d usable sectors", (int)(num_usable_sectors), + "but slot1 has %d usable sectors", (int)(num_sectors_pri), ((int)num_sectors_sec - 1)); } - for (i = 0; i < num_usable_sectors; i++) { + for (i = 0; i < (num_sectors_sec - 1); i++) { sector_sz_pri = boot_img_sector_size(state, BOOT_PRIMARY_SLOT, i); sector_sz_sec = boot_img_sector_size(state, BOOT_SECONDARY_SLOT, i); @@ -417,7 +388,6 @@ int swap_status_source(struct boot_loader_state *state) struct boot_swap_state state_primary_slot; struct boot_swap_state state_secondary_slot; int rc; - uint8_t source; uint8_t image_index; #if (BOOT_IMAGE_NUMBER == 1) @@ -439,10 +409,8 @@ int swap_status_source(struct boot_loader_state *state) state_primary_slot.copy_done == BOOT_FLAG_UNSET && state_secondary_slot.magic != BOOT_MAGIC_GOOD) { - source = BOOT_STATUS_SOURCE_PRIMARY_SLOT; - BOOT_LOG_INF("Boot source: primary slot"); - return source; + return BOOT_STATUS_SOURCE_PRIMARY_SLOT; } BOOT_LOG_INF("Boot source: none"); @@ -729,11 +697,23 @@ void swap_run(struct boot_loader_state *state, struct boot_status *bs, int app_max_size(struct boot_loader_state *state) { - uint32_t sector_sz_primary; + uint32_t available_pri_sz; + uint32_t available_sec_sz; + + size_t trailer_sz = boot_trailer_sz(BOOT_WRITE_SZ(state)); + size_t sector_sz = boot_img_sector_size(state, BOOT_PRIMARY_SLOT, 0); + size_t padding_sz = sector_sz; + + /* The trailer size needs to be sector-aligned */ + trailer_sz = ALIGN_UP(trailer_sz, sector_sz); - sector_sz_primary = boot_img_sector_size(state, BOOT_PRIMARY_SLOT, 0); + /* The slot whose size is used to compute the maximum image size must be the one containing the + * padding required for the swap. + */ + available_pri_sz = boot_img_num_sectors(state, BOOT_PRIMARY_SLOT) * sector_sz - trailer_sz; + available_sec_sz = boot_img_num_sectors(state, BOOT_SECONDARY_SLOT) * sector_sz - trailer_sz - padding_sz; - return app_max_sectors(state) * sector_sz_primary; + return (available_pri_sz < available_sec_sz ? available_pri_sz : available_sec_sz); } /* Compute the total size of the given image. Includes the size of the TLVs. */ diff --git a/boot/bootutil/src/swap_scratch.c b/boot/bootutil/src/swap_scratch.c index f9dbb7103..e1d49de49 100644 --- a/boot/bootutil/src/swap_scratch.c +++ b/boot/bootutil/src/swap_scratch.c @@ -47,6 +47,136 @@ int boot_status_fails = 0; #define BOOT_STATUS_ASSERT(x) ASSERT(x) #endif +#if MCUBOOT_SWAP_USING_SCRATCH +/** + * Finds the first sector of a given slot that holds image trailer data. + * + * @param state Current bootloader's state. + * @param slot The index of the slot to consider. + * @param trailer_sz The size of the trailer, in bytes. + * + * @return The index of the first sector of the slot that holds image trailer data. + */ +static size_t +boot_get_first_trailer_sector(struct boot_loader_state *state, size_t slot, size_t trailer_sz) +{ + size_t first_trailer_sector = boot_img_num_sectors(state, slot) - 1; + size_t sector_sz = boot_img_sector_size(state, slot, first_trailer_sector); + size_t trailer_sector_sz = sector_sz; + + while (trailer_sector_sz < trailer_sz) { + /* Consider that the image trailer may span across sectors of different sizes */ + --first_trailer_sector; + sector_sz = boot_img_sector_size(state, slot, first_trailer_sector); + + trailer_sector_sz += sector_sz; + } + + return first_trailer_sector; +} + +/** + * Returns the offset to the end of the first sector of a given slot that holds image trailer data. + * + * @param state Current bootloader's state. + * @param slot The index of the slot to consider. + * @param trailer_sz The size of the trailer, in bytes. + * + * @return The offset to the end of the first sector of the slot that holds image trailer data. + */ +static uint32_t +get_first_trailer_sector_end_off(struct boot_loader_state *state, size_t slot, size_t trailer_sz) +{ + size_t first_trailer_sector = boot_get_first_trailer_sector(state, slot, trailer_sz); + + return boot_img_sector_off(state, slot, first_trailer_sector) + + boot_img_sector_size(state, slot, first_trailer_sector); +} + +/** + * Returns the size of the part of the slot that can be used for storing image data. + * + * @param state Current bootloader's state. + * @param slot_size The size of the slot partition. + * + * @return The offset to the end of the first sector of the slot that holds image trailer data. + */ +static size_t app_max_size_adjust_to_trailer(struct boot_loader_state *state, size_t slot_size) +{ + size_t slot_trailer_sz = boot_trailer_sz(BOOT_WRITE_SZ(state)); + size_t slot_trailer_off = slot_size - slot_trailer_sz; + size_t trailer_sz_in_first_sector; + size_t trailer_sector_end_off; + + + size_t trailer_sector_primary_end_off = + get_first_trailer_sector_end_off(state, BOOT_PRIMARY_SLOT, slot_trailer_sz); + size_t trailer_sector_secondary_end_off = + get_first_trailer_sector_end_off(state, BOOT_SECONDARY_SLOT, slot_trailer_sz); + + /* If slots have sectors of different sizes, we need to find the "common" sector + * boundary (slot compatibility checks ensure that the larger sector contains a multiple + * of the smaller sector size). This will be the larger of the + * trailer_sector_primary_end_off/trailer_sector_secondary_end_off. + * + * <-------copy size-------> <--------copy size------> <----copy size---> + * v v v v + * +------------+------------+-------------------------+------------------+ + * | sector | sector | sector | sector | + * +------------+------------+------------+------------+------------------+ + * | sector | sector | sector | sector | + * +-------------------------+------------+------------+------------------+ + * + * The swap logic always uses the common boundary when performing the copy. + * Hence, the first trailer sector used for calculation is the larger + * sector from the two slots. + * + * <-----------copy size---------------> + * | sector | sector | + * +-----------------------------------+ + * | sector | + * +-----------------------------------+ + * |Image->| |<-trailer------------| + * +-----------------------------------+ + * | |<-scratch trailer>| + * +-----------------------------------+ + */ + if (trailer_sector_primary_end_off > trailer_sector_secondary_end_off) { + trailer_sector_end_off = trailer_sector_primary_end_off; + } else { + trailer_sector_end_off = trailer_sector_secondary_end_off; + } + + trailer_sz_in_first_sector = trailer_sector_end_off - slot_trailer_off; + + size_t trailer_padding = 0; + size_t scratch_trailer_sz = boot_scratch_trailer_sz(BOOT_WRITE_SZ(state)); + + /* Some padding might have to be inserted between the end of the firmware image and the + * beginning of the trailer to ensure there is enough space for the trailer in the scratch area + * when the last sector of the secondary will be copied to the scratch area. + * + * +-----------------------------------+-----------------------------------+ + * | sector | sector | + * +-----------------------------------+-----------------------------------+ + * |Image->| |<--trailer---|-----------trailer (cont.)-------->| + * +-----------------------------------+-----------------------------------+ + * | |<----scratch trailer---->| + * +-----------------------------------+ + * <-padding-> + * <--------scratch area size--------> + * + * The value of the padding depends on the amount of trailer data that is contained in the first + * sector containing part of the trailer in the primary and secondary slot. + */ + if (scratch_trailer_sz > trailer_sz_in_first_sector) { + trailer_padding = scratch_trailer_sz - trailer_sz_in_first_sector; + } + + return slot_trailer_off - trailer_padding; +} +#endif /* MCUBOOT_SWAP_USING_SCRATCH */ + #if !defined(MCUBOOT_DIRECT_XIP) && !defined(MCUBOOT_RAM_LOAD) /** * Reads the status of a partially-completed swap, if any. This is necessary @@ -821,8 +951,8 @@ int app_max_size(struct boot_loader_state *state) size_t num_sectors_primary; size_t num_sectors_secondary; size_t sz0, sz1; - size_t primary_slot_sz, secondary_slot_sz; #ifndef MCUBOOT_OVERWRITE_ONLY + size_t slot_sz; size_t scratch_sz; #endif size_t i, j; @@ -842,8 +972,11 @@ int app_max_size(struct boot_loader_state *state) * number of a slot's sectors are able to fit into another, which only * excludes cases where sector sizes are not a multiple of each other. */ - i = sz0 = primary_slot_sz = 0; - j = sz1 = secondary_slot_sz = 0; +#ifndef MCUBOOT_OVERWRITE_ONLY + slot_sz = 0; +#endif + i = sz0 = 0; + j = sz1 = 0; smaller = 0; while (i < num_sectors_primary || j < num_sectors_secondary) { if (sz0 == sz1) { @@ -876,8 +1009,7 @@ int app_max_size(struct boot_loader_state *state) } #ifndef MCUBOOT_OVERWRITE_ONLY if (sz0 == sz1) { - primary_slot_sz += sz0; - secondary_slot_sz += sz1; + slot_sz += sz0; /* Scratch has to fit each swap operation to the size of the larger * sector among the primary slot and the secondary slot. */ @@ -892,8 +1024,10 @@ int app_max_size(struct boot_loader_state *state) #ifdef MCUBOOT_OVERWRITE_ONLY return (sz1 < sz0 ? sz1 : sz0); +#elif MCUBOOT_SWAP_USING_SCRATCH + return app_max_size_adjust_to_trailer(state, slot_sz); #else - return (secondary_slot_sz < primary_slot_sz ? secondary_slot_sz : primary_slot_sz); + return slot_sz; #endif } #else From b0ad970425de01e09370badbc2ab449aa6292649 Mon Sep 17 00:00:00 2001 From: Michal Kozikowski Date: Fri, 4 Jul 2025 11:59:41 +0200 Subject: [PATCH 019/420] [nrf fromlist] zephyr: boards: nrf - remove redundant multithreading configuration Remove configs that enable multithreading just because of SPI/QSPI use. Currently, nrf drivers do not depend on multithreading, so it is not needed and this change can save memory usage. Upstream PR #: 2375 Signed-off-by: Michal Kozikowski (cherry picked from commit dd6b3ac0cab12eebf6420367184ae498faf5e458) --- boot/zephyr/boards/nrf52840dk_qspi_secondary_boot.conf | 1 - boot/zephyr/boards/nrf54h20dk_nrf54h20_cpuapp_iron.conf | 2 -- 2 files changed, 3 deletions(-) diff --git a/boot/zephyr/boards/nrf52840dk_qspi_secondary_boot.conf b/boot/zephyr/boards/nrf52840dk_qspi_secondary_boot.conf index 9f984be4f..5f3b7808b 100644 --- a/boot/zephyr/boards/nrf52840dk_qspi_secondary_boot.conf +++ b/boot/zephyr/boards/nrf52840dk_qspi_secondary_boot.conf @@ -1,2 +1 @@ -CONFIG_MULTITHREADING=y CONFIG_BOOT_MAX_IMG_SECTORS=256 diff --git a/boot/zephyr/boards/nrf54h20dk_nrf54h20_cpuapp_iron.conf b/boot/zephyr/boards/nrf54h20dk_nrf54h20_cpuapp_iron.conf index 50d349255..12c96ff0f 100644 --- a/boot/zephyr/boards/nrf54h20dk_nrf54h20_cpuapp_iron.conf +++ b/boot/zephyr/boards/nrf54h20dk_nrf54h20_cpuapp_iron.conf @@ -7,5 +7,3 @@ CONFIG_SPI_NOR=n CONFIG_BOOT_WATCHDOG_FEED=n - -CONFIG_MULTITHREADING=y From cf5187c5df8e1270f66ae48978eeea5be7a4d4ed Mon Sep 17 00:00:00 2001 From: Mateusz Michalek Date: Wed, 2 Jul 2025 11:12:29 +0200 Subject: [PATCH 020/420] [nrf fromtree] boot: zephyr: RAM cleanup debug loop Option to put execution in infinite loop. Meant to be used for debug. Signed-off-by: Mateusz Michalek (cherry picked from commit 5eaf190a8a9d8fc032b989bf96fc56b3b756dd55) --- boot/zephyr/Kconfig | 7 +++++++ boot/zephyr/main.c | 3 +++ 2 files changed, 10 insertions(+) diff --git a/boot/zephyr/Kconfig b/boot/zephyr/Kconfig index dc445b4ed..4b58f3fab 100644 --- a/boot/zephyr/Kconfig +++ b/boot/zephyr/Kconfig @@ -364,6 +364,13 @@ config MCUBOOT_CLEANUP_RAM help Sets contents of memory to 0 before jumping to application. +config MCUBOOT_INFINITE_LOOP_AFTER_RAM_CLEANUP + bool "Infinite loop after RAM cleanup" + depends on MCUBOOT_CLEANUP_RAM + help + Verification option that keeps execution in infinite loop after + RAM cleanup has been performed. + config MBEDTLS_CFG_FILE # It might be awkward to define an Mbed TLS header file when TinyCrypt # is used, but the fact is that Mbed TLS' ASN1 parse module is used diff --git a/boot/zephyr/main.c b/boot/zephyr/main.c index 2e57bd999..0cb793b2d 100644 --- a/boot/zephyr/main.c +++ b/boot/zephyr/main.c @@ -249,6 +249,9 @@ static void do_boot(struct boot_rsp *rsp) " b clear\n" "out:\n" " dsb\n" +#if CONFIG_MCUBOOT_INFINITE_LOOP_AFTER_RAM_CLEANUP + " b out\n" +#endif /*CONFIG_MCUBOOT_INFINITE_LOOP_AFTER_RAM_CLEANUP */ /* jump to reset vector of an app */ " bx r0\n" : From edbba12dec2fae0c51c03304c798d4ec0ad35d3a Mon Sep 17 00:00:00 2001 From: Dominik Ermel Date: Wed, 16 Jul 2025 16:01:36 +0000 Subject: [PATCH 021/420] [nrf fromlist] zephyr: Improve SHA support selectors Commit introduces BOOT_SOMETHING_USES_SHA<256,384,512> Kconfig options that can be used to control what algorithms should be compiled in with crypto backends. Upstream PR #: 2390 Signed-off-by: Dominik Ermel (cherry picked from commit 62ee266633a78c40eb8c9ca9dac60588fc1d23c5) --- boot/zephyr/Kconfig | 64 ++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 58 insertions(+), 6 deletions(-) diff --git a/boot/zephyr/Kconfig b/boot/zephyr/Kconfig index 4b58f3fab..ef9eb2433 100644 --- a/boot/zephyr/Kconfig +++ b/boot/zephyr/Kconfig @@ -70,15 +70,20 @@ if BOOT_USE_PSA_CRYPTO config BOOT_PSA_IMG_HASH_ALG_SHA256_DEPENDENCIES bool - default y if BOOT_IMG_HASH_ALG_SHA256 + default y if BOOT_SOMETHING_USES_SHA256 select PSA_WANT_ALG_SHA_256 help Dependencies for hashing with SHA256 -config BOOT_ED25519_PSA_DEPENDENCIES +config BOOT_PSA_IMG_HASH_ALG_SHA512_DEPENDENCIES bool - select PSA_WANT_ALG_SHA_256 + default y if BOOT_SOMETHING_USES_SHA512 select PSA_WANT_ALG_SHA_512 + help + Dependencies for hashing with SHA512 + +config BOOT_ED25519_PSA_DEPENDENCIES + bool select PSA_WANT_ALG_PURE_EDDSA # Seems that upstream mbedTLS does not have TE #select PSA_WANT_ECC_TWISTED_EDWARDS_255 @@ -129,6 +134,30 @@ config SINGLE_APPLICATION_SLOT uploading a new application overwrites the one that previously occupied the area. +config BOOT_SOMETHING_USES_SHA256 + bool + help + Hidden option that should be selected when something requires + SHA256 implementation in any form. It should be used by crypto + backends to enable support for SHA256 in code and/or hardware + drivers. + +config BOOT_SOMETHING_USES_SHA384 + bool + help + Hidden option that should be selected when something requires + SHA384 implementation in any form. It should be used by crypto + backends to enable support for SHA384 in code and/or hardware + drivers. + +config BOOT_SOMETHING_USES_SHA512 + bool + help + Hidden option that should be selected when something requires + SHA512 implementation in any form. It should be used by crypto + backends to enable support for SHA512 in code and/or hardware + drivers. + config BOOT_IMG_HASH_ALG_SHA256_ALLOW bool help @@ -173,18 +202,21 @@ choice BOOT_IMG_HASH_ALG config BOOT_IMG_HASH_ALG_SHA256 bool "SHA256" depends on BOOT_IMG_HASH_ALG_SHA256_ALLOW + select BOOT_SOMETHING_USES_SHA256 help SHA256 algorithm config BOOT_IMG_HASH_ALG_SHA384 bool "SHA384" depends on BOOT_IMG_HASH_ALG_SHA384_ALLOW + select BOOT_SOMETHING_USES_SHA384 help SHA384 algorithm config BOOT_IMG_HASH_ALG_SHA512 bool "SHA512" depends on BOOT_IMG_HASH_ALG_SHA512_ALLOW + select BOOT_SOMETHING_USES_SHA512 help SHA512 algorithm @@ -608,14 +640,34 @@ config BOOT_ENCRYPT_X25519 help Hidden option selecting x25519 encryption. +if BOOT_ENCRYPT_X25519 && BOOT_USE_PSA_CRYPTO + +choice BOOT_HMAC_SHA + prompt "SHA used for HMAC and HKDF in encryption key exchange" + default BOOT_HMAC_SHA256 + help + HMAC/HKDF sha algorithm may be selected to synchronize sha + usage with other places in code and reduce compiled in + implementations. + +config BOOT_HMAC_SHA256 + bool "Use SHA256 for HMAC/HKDF" + select BOOT_SOMETHING_USES_SHA256 + help + This is default for ED25519. + config BOOT_HMAC_SHA512 bool "Use SHA512 for HMAC/HKDF" depends on BOOT_ENCRYPT_X25519 depends on BOOT_USE_PSA_CRYPTO + select BOOT_SOMETHING_USES_SHA512 help - By default SHA256 is used for HKDF/HMAC in key exchange expansion - and verification. This options switches to SHA512. The option is - mainly useful to reduce numer of compiled in SHA algorithms. + With ED25519, this option is worth selecting when SHA512 is used + for hashing of an image to reduce number of compiled sha algorithms. + +endchoice # BOOT_HMAC_SHA + +endif # BOOT_ENCRYPT_X25519 && BOOT_USE_PSA_CRYPTO config BOOT_ENCRYPTION_KEY_FILE string "Encryption key file" From d8bd9285ea84ab0d71b95c8f02d76844f69a83a6 Mon Sep 17 00:00:00 2001 From: Tomasz Chyrowicz Date: Mon, 16 Jun 2025 17:23:23 +0200 Subject: [PATCH 022/420] [nrf fromtree] loader: Allow to specify slot number in version Allow to depend on a specific slot while specifying the version number. This functionality is useful when the Direct XIP mode is used and the booting process of other images is done by the next stage, not the MCUboot itself. Signed-off-by: Tomasz Chyrowicz (cherry picked from commit dce784a2f2a045c3643b9baf02e9f4fc40530b7b) --- boot/bootutil/include/bootutil/image.h | 8 + boot/bootutil/src/loader.c | 167 +++++++++++++++++- boot/zephyr/Kconfig | 9 + .../include/mcuboot_config/mcuboot_config.h | 4 + docs/design.md | 17 ++ docs/imgtool.md | 13 +- scripts/imgtool/image.py | 3 +- scripts/imgtool/main.py | 32 +++- 8 files changed, 247 insertions(+), 6 deletions(-) diff --git a/boot/bootutil/include/bootutil/image.h b/boot/bootutil/include/bootutil/image.h index 11c54b633..52fa6d1bb 100644 --- a/boot/bootutil/include/bootutil/image.h +++ b/boot/bootutil/include/bootutil/image.h @@ -144,6 +144,10 @@ extern "C" { */ #define IMAGE_TLV_ANY 0xffff /* Used to iterate over all TLV */ +#define VERSION_DEP_SLOT_ACTIVE 0x00 /* Check dependency against active slot. */ +#define VERSION_DEP_SLOT_PRIMARY 0x01 /* Check dependency against primary slot. */ +#define VERSION_DEP_SLOT_SECONDARY 0x02 /* Check dependency against secondary slot. */ + STRUCT_PACKED image_version { uint8_t iv_major; uint8_t iv_minor; @@ -153,7 +157,11 @@ STRUCT_PACKED image_version { struct image_dependency { uint8_t image_id; /* Image index (from 0) */ +#ifdef MCUBOOT_VERSION_CMP_USE_SLOT_NUMBER + uint8_t slot; /* Image slot */ +#else uint8_t _pad1; +#endif /* MCUBOOT_VERSION_CMP_USE_SLOT_NUMBER */ uint16_t _pad2; struct image_version image_min_version; /* Indicates at minimum which * version of firmware must be diff --git a/boot/bootutil/src/loader.c b/boot/bootutil/src/loader.c index 6654245ad..8c73f7652 100644 --- a/boot/bootutil/src/loader.c +++ b/boot/bootutil/src/loader.c @@ -424,6 +424,24 @@ boot_verify_slot_dependency(struct boot_loader_state *state, uint8_t swap_type = state->swap_type[dep->image_id]; dep_slot = BOOT_IS_UPGRADE(swap_type) ? BOOT_SECONDARY_SLOT : BOOT_PRIMARY_SLOT; +#elif defined(MCUBOOT_VERSION_CMP_USE_SLOT_NUMBER) + switch(dep->slot) { + case VERSION_DEP_SLOT_ACTIVE: + dep_slot = state->slot_usage[dep->image_id].active_slot; + break; + case VERSION_DEP_SLOT_PRIMARY: + dep_slot = BOOT_PRIMARY_SLOT; + break; + case VERSION_DEP_SLOT_SECONDARY: + dep_slot = BOOT_SECONDARY_SLOT; + break; + default: + return -1; + } + + if (!state->slot_usage[dep->image_id].slot_available[dep_slot]) { + return -1; + } #else dep_slot = state->slot_usage[dep->image_id].active_slot; #endif @@ -461,7 +479,27 @@ boot_verify_slot_dependency(struct boot_loader_state *state, } #endif - return rc; +#ifdef MCUBOOT_VERSION_CMP_USE_SLOT_NUMBER + if (rc == 0) { + switch(dep->slot) { + case VERSION_DEP_SLOT_PRIMARY: + state->slot_usage[dep->image_id].slot_available[BOOT_PRIMARY_SLOT] = true; + state->slot_usage[dep->image_id].slot_available[BOOT_SECONDARY_SLOT] = false; + state->slot_usage[dep->image_id].active_slot = BOOT_PRIMARY_SLOT; + break; + case VERSION_DEP_SLOT_SECONDARY: + state->slot_usage[dep->image_id].slot_available[BOOT_PRIMARY_SLOT] = false; + state->slot_usage[dep->image_id].slot_available[BOOT_SECONDARY_SLOT] = true; + state->slot_usage[dep->image_id].active_slot = BOOT_SECONDARY_SLOT; + break; + case VERSION_DEP_SLOT_ACTIVE: + default: + break; + } + } +#endif /* MCUBOOT_VERSION_CMP_USE_SLOT_NUMBER */ + +return rc; } #if !defined(MCUBOOT_DIRECT_XIP) && !defined(MCUBOOT_RAM_LOAD) @@ -606,6 +644,19 @@ boot_verify_slot_dependencies(struct boot_loader_state *state, uint32_t slot) goto done; } +#ifdef MCUBOOT_VERSION_CMP_USE_SLOT_NUMBER + /* Validate against possible dependency slot values. */ + switch(dep->slot) { + case VERSION_DEP_SLOT_ACTIVE: + case VERSION_DEP_SLOT_PRIMARY: + case VERSION_DEP_SLOT_SECONDARY: + break; + default: + rc = BOOT_EBADARGS; + goto done; + } +#endif /* MCUBOOT_VERSION_CMP_USE_SLOT_NUMBER */ + /* Verify dependency and modify the swap type if not satisfied. */ rc = boot_verify_slot_dependency(state, &dep); if (rc != 0) { @@ -2932,6 +2983,119 @@ boot_select_or_erase(struct boot_loader_state *state) } #endif /* MCUBOOT_DIRECT_XIP && MCUBOOT_DIRECT_XIP_REVERT */ +#ifdef MCUBOOT_VERSION_CMP_USE_SLOT_NUMBER +/** + * Tries to load a slot for all the images with validation. + * + * @param state Boot loader status information. + * + * @return 0 on success; nonzero on failure. + */ +fih_ret +boot_load_and_validate_images(struct boot_loader_state *state) +{ + uint32_t active_slot; + int rc; + fih_ret fih_rc; + uint32_t slot; + + /* Go over all the images and all slots and validate them */ + IMAGES_ITER(BOOT_CURR_IMG(state)) { + for (slot = 0; slot < BOOT_NUM_SLOTS; slot++) { +#if BOOT_IMAGE_NUMBER > 1 + if (state->img_mask[BOOT_CURR_IMG(state)]) { + continue; + } +#endif + + /* Save the number of the active slot. */ + state->slot_usage[BOOT_CURR_IMG(state)].active_slot = slot; + +#ifdef MCUBOOT_DIRECT_XIP + rc = boot_rom_address_check(state); + if (rc != 0) { + /* The image is placed in an unsuitable slot. */ + state->slot_usage[BOOT_CURR_IMG(state)].slot_available[slot] = false; + state->slot_usage[BOOT_CURR_IMG(state)].active_slot = NO_ACTIVE_SLOT; + continue; + } + +#ifdef MCUBOOT_DIRECT_XIP_REVERT + rc = boot_select_or_erase(state); + if (rc != 0) { + /* The selected image slot has been erased. */ + state->slot_usage[BOOT_CURR_IMG(state)].slot_available[slot] = false; + state->slot_usage[BOOT_CURR_IMG(state)].active_slot = NO_ACTIVE_SLOT; + continue; + } +#endif /* MCUBOOT_DIRECT_XIP_REVERT */ +#endif /* MCUBOOT_DIRECT_XIP */ + +#ifdef MCUBOOT_RAM_LOAD + /* Image is first loaded to RAM and authenticated there in order to + * prevent TOCTOU attack during image copy. This could be applied + * when loading images from external (untrusted) flash to internal + * (trusted) RAM and image is authenticated before copying. + */ + rc = boot_load_image_to_sram(state); + if (rc != 0 ) { + /* Image cannot be ramloaded. */ + boot_remove_image_from_flash(state, slot); + state->slot_usage[BOOT_CURR_IMG(state)].slot_available[slot] = false; + state->slot_usage[BOOT_CURR_IMG(state)].active_slot = NO_ACTIVE_SLOT; + continue; + } +#endif /* MCUBOOT_RAM_LOAD */ + + FIH_CALL(boot_validate_slot, fih_rc, state, slot, NULL, 0); + if (FIH_NOT_EQ(fih_rc, FIH_SUCCESS)) { + /* Image is invalid. */ +#ifdef MCUBOOT_RAM_LOAD + boot_remove_image_from_sram(state); +#endif /* MCUBOOT_RAM_LOAD */ + state->slot_usage[BOOT_CURR_IMG(state)].slot_available[slot] = false; + state->slot_usage[BOOT_CURR_IMG(state)].active_slot = NO_ACTIVE_SLOT; + continue; + } + + /* Valid image loaded from a slot, go to the next slot. */ + state->slot_usage[BOOT_CURR_IMG(state)].active_slot = NO_ACTIVE_SLOT; + } + } + + /* Go over all the images and all slots and validate them */ + IMAGES_ITER(BOOT_CURR_IMG(state)) { + /* All slots tried until a valid image found. Breaking from this loop + * means that a valid image found or already loaded. If no slot is + * found the function returns with error code. */ + while (true) { + /* Go over all the slots and try to load one */ + active_slot = state->slot_usage[BOOT_CURR_IMG(state)].active_slot; + if (active_slot != NO_ACTIVE_SLOT){ + /* A slot is already active, go to next image. */ + break; + } + + active_slot = find_slot_with_highest_version(state); + if (active_slot == NO_ACTIVE_SLOT) { + BOOT_LOG_INF("No slot to load for image %d", + BOOT_CURR_IMG(state)); + FIH_RET(FIH_FAILURE); + } + + /* Save the number of the active slot. */ + state->slot_usage[BOOT_CURR_IMG(state)].active_slot = active_slot; + + /* Valid image loaded from a slot, go to the next image. */ + break; + } + } + + FIH_RET(FIH_SUCCESS); +} + +#else /* MCUBOOT_VERSION_CMP_USE_SLOT_NUMBER */ + /** * Tries to load a slot for all the images with validation. * @@ -3029,6 +3193,7 @@ boot_load_and_validate_images(struct boot_loader_state *state) FIH_RET(FIH_SUCCESS); } +#endif /* MCUBOOT_VERSION_CMP_USE_SLOT_NUMBER */ /** * Updates the security counter for the current image. diff --git a/boot/zephyr/Kconfig b/boot/zephyr/Kconfig index ef9eb2433..fcd9f5d35 100644 --- a/boot/zephyr/Kconfig +++ b/boot/zephyr/Kconfig @@ -949,6 +949,15 @@ config BOOT_VERSION_CMP_USE_BUILD_NUMBER minor and revision. Enable this option to take into account the build number as well. +config BOOT_VERSION_CMP_USE_SLOT_NUMBER + bool "Use slot number while comparing image version" + depends on (UPDATEABLE_IMAGE_NUMBER > 1) || BOOT_DIRECT_XIP || \ + BOOT_RAM_LOAD || MCUBOOT_DOWNGRADE_PREVENTION + help + By default, the image slot comparison relies only on active slot. + Enable this option to take into account the specified slot number + instead. + choice BOOT_DOWNGRADE_PREVENTION_CHOICE prompt "Downgrade prevention" optional diff --git a/boot/zephyr/include/mcuboot_config/mcuboot_config.h b/boot/zephyr/include/mcuboot_config/mcuboot_config.h index 820ffd752..f0dc214b6 100644 --- a/boot/zephyr/include/mcuboot_config/mcuboot_config.h +++ b/boot/zephyr/include/mcuboot_config/mcuboot_config.h @@ -120,6 +120,10 @@ #define MCUBOOT_VERSION_CMP_USE_BUILD_NUMBER #endif +#ifdef CONFIG_BOOT_VERSION_CMP_USE_SLOT_NUMBER +#define MCUBOOT_VERSION_CMP_USE_SLOT_NUMBER +#endif + #ifdef CONFIG_BOOT_SWAP_SAVE_ENCTLV #define MCUBOOT_SWAP_SAVE_ENCTLV 1 #endif diff --git a/docs/design.md b/docs/design.md index 66fcd45f9..c080b2b82 100755 --- a/docs/design.md +++ b/docs/design.md @@ -890,6 +890,23 @@ process is presented below. + Boot into image in the primary slot of the 0th image position\ (other image in the boot chain is started by another image). +By enabling the `MCUBOOT_VERSION_CMP_USE_SLOT_NUMBER` configuration option, +the dependency check may be extended to match for a specified slot of a specific +image. This functionality is useful in a multi-core system when Direct XIP mode +is used. +In this case, the main image can be started from one of the two (primary or +secondary) slots. +If there is a fixed connection between the slots of two different images, +e.g. if the main image always chainloads a companion image from the same slot, +the check must take this into account and only consider a matching slot when +resolving dependencies. + +There are three values that can be passed when specifying dependencies: + +1. ``active``: the dependency should be checked against either primary or secondary slot. +2. ``primary``: the dependency should be checked only against primary slot. +3. ``secondary``: the dependency should be checked only against secondary slot. + ### [Multiple image boot for RAM loading and direct-xip](#multiple-image-boot-for-ram-loading-and-direct-xip) The operation of the bootloader is different when the ram-load or the diff --git a/docs/imgtool.md b/docs/imgtool.md index 958e1af15..c68652dca 100644 --- a/docs/imgtool.md +++ b/docs/imgtool.md @@ -91,7 +91,8 @@ primary slot and adds a header and trailer that the bootloader is expecting: the `auto` keyword to automatically generate it from the image version. -d, --dependencies TEXT Add dependence on another image, format: - "(,), ... " + "(,[,] + ), ... " --pad-sig Add 0-2 bytes of padding to ECDSA signature (for mcuboot <1.5) -H, --header-size INTEGER [required] @@ -182,6 +183,16 @@ which the current image depends on. The `image_version` is the minimum version of that image to satisfy compliance. For example `-d "(1, 1.2.3+0)"` means this image depends on Image 1 which version has to be at least 1.2.3+0. +In addition, a dependency can specify the slot as follows: +`-d "(image_id, slot, image_version)"`. The `image_id` is the number of the +image on which the current image depends. +The slot specifies which slots of the image are to be taken into account +(`active`: primary or secondary, `primary`: only primary `secondary`: only +secondary slot). The `image_version` is the minimum version of that image to +fulfill the requirements. +For example `-d "(1, primary, 1.2.3+0)"` means that this image depends on the +primary slot of the Image 1, whose version must be at least 1.2.3+0. + The `--public-key-format` argument can be used to distinguish where the public key is stored for image authentication. The `hash` option is used by default, in which case only the hash of the public key is added to the TLV area (the full diff --git a/scripts/imgtool/image.py b/scripts/imgtool/image.py index 03e2cbb62..4e2830370 100644 --- a/scripts/imgtool/image.py +++ b/scripts/imgtool/image.py @@ -589,8 +589,9 @@ def create(self, key, public_key_format, enckey, dependencies=None, if dependencies is not None: for i in range(dependencies_num): payload = struct.pack( - e + 'B3x' + 'BBHI', + e + 'BB2x' + 'BBHI', int(dependencies[DEP_IMAGES_KEY][i]), + dependencies[DEP_VERSIONS_KEY][i].slot, dependencies[DEP_VERSIONS_KEY][i].major, dependencies[DEP_VERSIONS_KEY][i].minor, dependencies[DEP_VERSIONS_KEY][i].revision, diff --git a/scripts/imgtool/main.py b/scripts/imgtool/main.py index 5ff1f8f9f..7f9a53657 100755 --- a/scripts/imgtool/main.py +++ b/scripts/imgtool/main.py @@ -27,6 +27,7 @@ import lzma import hashlib import base64 +from collections import namedtuple from imgtool import image, imgtool_version from imgtool.version import decode_version from imgtool.dumpinfo import dump_imginfo @@ -45,6 +46,14 @@ sys.exit("Python %s.%s or newer is required by imgtool." % MIN_PYTHON_VERSION) +SlottedSemiSemVersion = namedtuple('SemiSemVersion', ['major', 'minor', 'revision', + 'build', 'slot']) + +DEPENDENCY_SLOT_VALUES = { + 'active': 0x00, + 'primary': 0x01, + 'secondary': 0x02 +} def gen_rsa2048(keyfile, passwd): keys.RSA.generate().export_private(path=keyfile, passwd=passwd) @@ -301,16 +310,33 @@ def get_dependencies(ctx, param, value): if len(images) == 0: raise click.BadParameter( "Image dependency format is invalid: {}".format(value)) - raw_versions = re.findall(r",\s*([0-9.+]+)\)", value) + raw_versions = re.findall(r",\s*((active|primary|secondary)\s*,)?\s*([0-9.+]+)\)", value) if len(images) != len(raw_versions): raise click.BadParameter( '''There's a mismatch between the number of dependency images and versions in: {}'''.format(value)) for raw_version in raw_versions: try: - versions.append(decode_version(raw_version)) + decoded_version = decode_version(raw_version[2]) + if len(raw_version[1]) > 0: + slotted_version = SlottedSemiSemVersion( + decoded_version.major, + decoded_version.minor, + decoded_version.revision, + decoded_version.build, + DEPENDENCY_SLOT_VALUES[raw_version[1]] + ) + else: + slotted_version = SlottedSemiSemVersion( + decoded_version.major, + decoded_version.minor, + decoded_version.revision, + decoded_version.build, + 0 + ) except ValueError as e: raise click.BadParameter("{}".format(e)) + versions.append(slotted_version) dependencies = dict() dependencies[image.DEP_IMAGES_KEY] = images dependencies[image.DEP_VERSIONS_KEY] = versions @@ -405,7 +431,7 @@ def convert(self, value, param, ctx): '(for mcuboot <1.5)') @click.option('-d', '--dependencies', callback=get_dependencies, required=False, help='''Add dependence on another image, format: - "(,), ... "''') + "(,[,]), ... "''') @click.option('-s', '--security-counter', callback=validate_security_counter, help='Specify the value of security counter. Use the `auto` ' 'keyword to automatically generate it from the image version.') From 7ad728fef39f60eee0c09e6a2300a17b1ccee212 Mon Sep 17 00:00:00 2001 From: Artur Hadasz Date: Mon, 21 Jul 2025 15:59:10 +0200 Subject: [PATCH 023/420] [nrf fromtree] zephyr: Enable building ECDSA PSA variant Adds Kconfig option CONFIG_BOOT_ECDSA_PSA that allows to switch ECDSA to PSA backend. Signed-off-by: Artur Hadasz (cherry picked from commit 5ee96f5bc0dc506e56ef348960fae0b8f14b038e) --- boot/zephyr/CMakeLists.txt | 5 ++++- boot/zephyr/Kconfig | 18 ++++++++++++++++++ 2 files changed, 22 insertions(+), 1 deletion(-) diff --git a/boot/zephyr/CMakeLists.txt b/boot/zephyr/CMakeLists.txt index 159962543..76ada498e 100644 --- a/boot/zephyr/CMakeLists.txt +++ b/boot/zephyr/CMakeLists.txt @@ -186,7 +186,10 @@ else() endif() if(CONFIG_BOOT_SIGNATURE_TYPE_ECDSA_P256 OR CONFIG_BOOT_ENCRYPT_EC256) - if(MBEDTLS_ASN1_DIR) + # When ECDSA PSA is used, do not pull in additional ASN.1 include + # directories or sources, as it would cause incorrect header files + # to be included. + if(MBEDTLS_ASN1_DIR AND NOT CONFIG_BOOT_ECDSA_PSA) zephyr_library_include_directories( ${MBEDTLS_ASN1_DIR}/include ) diff --git a/boot/zephyr/Kconfig b/boot/zephyr/Kconfig index fcd9f5d35..0e8265002 100644 --- a/boot/zephyr/Kconfig +++ b/boot/zephyr/Kconfig @@ -113,6 +113,14 @@ config BOOT_X25519_PSA_DEPENDENCIES endif # BOOT_ENCRYPT_IMAGE +config BOOT_ECDSA_PSA_DEPENDENCIES + bool + select PSA_WANT_ALG_ECDSA + select PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_IMPORT + select PSA_WANT_ECC_SECP_R1_256 + help + Dependencies for ECDSA signature + if MBEDTLS_ENABLE_HEAP config MBEDTLS_HEAP_SIZE @@ -282,6 +290,16 @@ config BOOT_ECDSA_CC310 select NRF_CC310_BL select NRFXLIB_CRYPTO select BOOT_USE_CC310 + +config BOOT_ECDSA_PSA + bool "Use psa cryptoo" + select BOOT_USE_PSA_CRYPTO + select PSA_CRYPTO_CLIENT + select PSA_CRYPTO_C + select BOOT_IMG_HASH_ALG_SHA256_ALLOW + select BOOT_IMG_HASH_ALG_SHA512_ALLOW + select BOOT_ECDSA_PSA_DEPENDENCIES + endchoice # Ecdsa implementation endif From 727cc28fcc10b78fc2f8b3fb5fd60ea71596160f Mon Sep 17 00:00:00 2001 From: Carles Cufi Date: Tue, 10 Oct 2023 15:51:54 +0200 Subject: [PATCH 024/420] [nrf noup] github: Add a commit tags check workflow Use the generic commit-tags action to provide sauce tag checks. Signed-off-by: Carles Cufi (cherry picked from commit 67c4da497005924017ad815d020555f591e2fc38) --- .github/workflows/commit-tags.yml | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) create mode 100644 .github/workflows/commit-tags.yml diff --git a/.github/workflows/commit-tags.yml b/.github/workflows/commit-tags.yml new file mode 100644 index 000000000..534ed5b58 --- /dev/null +++ b/.github/workflows/commit-tags.yml @@ -0,0 +1,28 @@ +name: Commit tags + +on: + pull_request: + types: [synchronize, opened, reopened, edited, labeled, unlabeled, + milestoned, demilestoned, assigned, unassigned, ready_for_review, + review_requested] + +jobs: + commit_tags: + runs-on: ubuntu-22.04 + name: Run commit tags checks on patch series (PR) + steps: + - name: Update PATH for west + run: | + echo "$HOME/.local/bin" >> $GITHUB_PATH + + - name: Checkout the code + uses: actions/checkout@v3 + with: + ref: ${{ github.event.pull_request.head.sha }} + fetch-depth: 0 + + - name: Run the commit tags + uses: nrfconnect/action-commit-tags@main + with: + target: . + upstream: mcu-tools/mcuboot/main From 7ac4eeb0b9ad01f90d002cf34d1e84a6b0e539ab Mon Sep 17 00:00:00 2001 From: Sigvart Hovland Date: Tue, 26 Mar 2019 15:42:38 +0100 Subject: [PATCH 025/420] [nrf noup] zephyr: Remove duplication from cmake MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Removes the `add_subdirectory` of nrfxlib it will still check that the nrfxlib is located outside the mcuboot directory. Signed-off-by: Sigvart Hovland Signed-off-by: Andrzej Puzdrowski Signed-off-by: Martí Bolívar Signed-off-by: Emil Obalski Signed-off-by: Andrzej Puzdrowski Signed-off-by: Håkon Øye Amundsen Signed-off-by: Ioannis Glaropoulos Signed-off-by: Torsten Rasmussen Signed-off-by: Jamie McCrae Signed-off-by: Dominik Ermel (cherry picked from commit 0566363271acec5347e523af62b3d7ddc5e501a2) --- boot/zephyr/CMakeLists.txt | 2 -- 1 file changed, 2 deletions(-) diff --git a/boot/zephyr/CMakeLists.txt b/boot/zephyr/CMakeLists.txt index 76ada498e..b0e43cd50 100644 --- a/boot/zephyr/CMakeLists.txt +++ b/boot/zephyr/CMakeLists.txt @@ -50,8 +50,6 @@ if(NOT EXISTS ${NRFXLIB_DIR}) To use the tinycrypt set `CONFIG_BOOT_ECDSA_TINYCRYPT` to y. ------------------------------------------------------------------------") endif() -# Don't include this if we are using west - add_subdirectory(${NRFXLIB_DIR} ${PROJECT_BINARY_DIR}/nrfxlib) endif() zephyr_library_include_directories( From 54f21298ed294b707b5c78f6da81b5e2d262e95b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mart=C3=AD=20Bol=C3=ADvar?= Date: Fri, 3 Sep 2021 14:38:54 -0700 Subject: [PATCH 026/420] [nrf noup] zephyr: add 'minimal' configuration files MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add prj_minimal.conf, a Kconfig fragment to be used for minimally sized image production. The minimal fragment has been simplified for only external crypto. Move partition sizing into Kconfig to be consistent with the method used by b0. Using this fragment with prj_minimal.conf makes MCUboot < 16kB for all nRF devices (9160 still needs 32kB partition). Ref: NCSDK-6704 Signed-off-by: Stephen Stauts Signed-off-by: Martí Bolívar Signed-off-by: Sebastian Bøe Signed-off-by: Torsten Rasmussen Signed-off-by: Jamie McCrae Signed-off-by: Dominik Ermel Signed-off-by: Andrzej Puzdrowski Signed-off-by: Artur Hadasz (cherry picked from commit 33d3e61f00efdcb606cac25f8b0566123ef3b26f) --- .../nrf5340dk_nrf5340_cpuapp_minimal.conf | 13 ++++++ boot/zephyr/prj_minimal.conf | 41 +++++++++++++++++++ 2 files changed, 54 insertions(+) create mode 100644 boot/zephyr/boards/nrf5340dk_nrf5340_cpuapp_minimal.conf create mode 100644 boot/zephyr/prj_minimal.conf diff --git a/boot/zephyr/boards/nrf5340dk_nrf5340_cpuapp_minimal.conf b/boot/zephyr/boards/nrf5340dk_nrf5340_cpuapp_minimal.conf new file mode 100644 index 000000000..dd5468106 --- /dev/null +++ b/boot/zephyr/boards/nrf5340dk_nrf5340_cpuapp_minimal.conf @@ -0,0 +1,13 @@ +# +# Copyright (c) 2021 Nordic Semiconductor ASA +# +# SPDX-License-Identifier: LicenseRef-Nordic-5-Clause +# + +# CC3xx is currently not used for nrf53 +CONFIG_HW_CC3XX=n +CONFIG_NRF_CC3XX_PLATFORM=n + +# Required for kernel operation +CONFIG_CLOCK_CONTROL=y +CONFIG_SYS_CLOCK_EXISTS=y diff --git a/boot/zephyr/prj_minimal.conf b/boot/zephyr/prj_minimal.conf new file mode 100644 index 000000000..91cf1bc96 --- /dev/null +++ b/boot/zephyr/prj_minimal.conf @@ -0,0 +1,41 @@ +# +# Copyright (c) 2021 Nordic Semiconductor ASA +# +# SPDX-License-Identifier: LicenseRef-Nordic-5-Clause +# + +CONFIG_MAIN_STACK_SIZE=10240 +CONFIG_MBEDTLS_CFG_FILE="mcuboot-mbedtls-cfg.h" + +CONFIG_FLASH=y +CONFIG_FPROTECT=y +CONFIG_PM=n + +CONFIG_BOOT_SWAP_SAVE_ENCTLV=n +CONFIG_BOOT_ENCRYPT_IMAGE=n + +CONFIG_BOOT_BOOTSTRAP=n +CONFIG_BOOT_UPGRADE_ONLY=n + +### Minimal Configurations ### +CONFIG_BOOT_USE_MIN_PARTITION_SIZE=y +CONFIG_ASSERT=n +CONFIG_BOOT_BANNER=n +CONFIG_NCS_BOOT_BANNER=n +CONFIG_CLOCK_CONTROL=n +CONFIG_CONSOLE=n +CONFIG_CONSOLE_HANDLER=n +CONFIG_GPIO=n +CONFIG_KERNEL_MEM_POOL=n +CONFIG_LOG=n +CONFIG_COMMON_LIBC_CALLOC=n +CONFIG_COMMON_LIBC_MALLOC=n +CONFIG_COMMON_LIBC_REALLOCARRAY=n +CONFIG_NCS_SAMPLES_DEFAULTS=n +CONFIG_NO_RUNTIME_CHECKS=y +CONFIG_NRF_RTC_TIMER=n +CONFIG_PRINTK=n +CONFIG_SERIAL=n +CONFIG_SIZE_OPTIMIZATIONS=y +CONFIG_SYS_CLOCK_EXISTS=n +CONFIG_UART_CONSOLE=n From 313de9ca5b4e9015642b100007f4314483121f68 Mon Sep 17 00:00:00 2001 From: Bernt Johan Damslora Date: Fri, 20 Sep 2019 18:25:41 +0200 Subject: [PATCH 027/420] [nrf noup] boards: add support for Thingy:91 Adds project configurations for the two systems on the Thingy:91 (PCA-20035) board. The bootloader that is factory-programmed on thing91 does not support ECDSA signature type. Hence this commit also sets the signature type to RSA for applications built for Thingy:91. Signed-off-by: Bernt Johan Damslora Signed-off-by: Sigvart Hovland Signed-off-by: Jon Helge Nistad Signed-off-by: Balaji Srinivasan Signed-off-by: Robert Lubos Signed-off-by: Torsten Rasmussen Signed-off-by: Jamie McCrae Signed-off-by: Marek Pieta Signed-off-by: Dominik Ermel (cherry picked from commit 0512d8dbeaf49330865c9095496814bf5b8fc4ad) --- boot/zephyr/boards/thingy91_nrf52840.conf | 34 +++++++++++++++++++++++ boot/zephyr/boards/thingy91_nrf9160.conf | 13 +++++++++ 2 files changed, 47 insertions(+) create mode 100644 boot/zephyr/boards/thingy91_nrf52840.conf create mode 100644 boot/zephyr/boards/thingy91_nrf9160.conf diff --git a/boot/zephyr/boards/thingy91_nrf52840.conf b/boot/zephyr/boards/thingy91_nrf52840.conf new file mode 100644 index 000000000..c0d183401 --- /dev/null +++ b/boot/zephyr/boards/thingy91_nrf52840.conf @@ -0,0 +1,34 @@ +# Disable Zephyr console +CONFIG_LOG=n +CONFIG_CONSOLE=n +CONFIG_CONSOLE_HANDLER=n +CONFIG_UART_CONSOLE=n + +# The build won't fit on the partition allocated for it without size +# optimizations. +CONFIG_SIZE_OPTIMIZATIONS=y +CONFIG_PM_PARTITION_SIZE_MCUBOOT=0x12000 + +# Serial +CONFIG_SERIAL=y +CONFIG_UART_NRFX=y +CONFIG_UART_INTERRUPT_DRIVEN=y +CONFIG_UART_LINE_CTRL=y + +# MCUboot serial recovery +CONFIG_GPIO=y +CONFIG_MCUBOOT_SERIAL=y +CONFIG_BOOT_SERIAL_CDC_ACM=y + +# Required by USB +CONFIG_MULTITHREADING=y + +# USB +CONFIG_USB_DEVICE_STACK=y +CONFIG_USB_DEVICE_PRODUCT="MCUBOOT" +CONFIG_USB_CDC_ACM=y +CONFIG_USB_COMPOSITE_DEVICE=y +CONFIG_USB_MASS_STORAGE=n +CONFIG_USB_DEVICE_MANUFACTURER="Nordic Semiconductor" +CONFIG_USB_DEVICE_VID=0x1915 +CONFIG_USB_DEVICE_PID=0x520F diff --git a/boot/zephyr/boards/thingy91_nrf9160.conf b/boot/zephyr/boards/thingy91_nrf9160.conf new file mode 100644 index 000000000..1bf2e424d --- /dev/null +++ b/boot/zephyr/boards/thingy91_nrf9160.conf @@ -0,0 +1,13 @@ +# Disable Zephyr console +CONFIG_CONSOLE=n +CONFIG_CONSOLE_HANDLER=n +CONFIG_UART_CONSOLE=n + +# Disable Flash protection +CONFIG_FPROTECT=n + +# MCUBoot settings +CONFIG_BOOT_MAX_IMG_SECTORS=256 + +# MCUboot serial recovery +CONFIG_MCUBOOT_SERIAL=y From abaff579f26f58d9c8969ee5863d5e44d56bcc7e Mon Sep 17 00:00:00 2001 From: Damian Krolik Date: Mon, 21 Mar 2022 13:44:27 +0100 Subject: [PATCH 028/420] [nrf noup] zephyr: Restore default RTC user channel count The default value of CONFIG_NRF_RTC_TIMER_USER_CHAN_COUNT for nRF52 SOCs has been changed from 0 to 3, but it makes MCUBoot get stuck on erasing flash pages when swapping two images. Restore the previous value until the RTC issue is resolved (see NCSDK-14427) Signed-off-by: Damian Krolik Signed-off-by: Torsten Rasmussen Signed-off-by: Jamie McCrae Signed-off-by: Dominik Ermel (cherry picked from commit 3957a30521a42f1794dca54f3e8f383f8d69ce8a) --- boot/zephyr/prj.conf | 1 + 1 file changed, 1 insertion(+) diff --git a/boot/zephyr/prj.conf b/boot/zephyr/prj.conf index 119e07579..51dc99b27 100644 --- a/boot/zephyr/prj.conf +++ b/boot/zephyr/prj.conf @@ -34,3 +34,4 @@ CONFIG_MCUBOOT_LOG_LEVEL_INF=y CONFIG_CBPRINTF_NANO=y ### Use the minimal C library to reduce flash usage CONFIG_MINIMAL_LIBC=y +CONFIG_NRF_RTC_TIMER_USER_CHAN_COUNT=0 From 19d7a4e5526a1b6d7d9282508d1089add9936df6 Mon Sep 17 00:00:00 2001 From: Maximilian Deubel Date: Fri, 8 Dec 2023 13:18:12 +0100 Subject: [PATCH 029/420] [nrf noup] boards: thingy91x: add board config This patch adds board configuration for the Thingy:91 X. Signed-off-by: Maximilian Deubel (cherry picked from commit 1b2d11cfa241f049dac60282de43c17abcf02398) --- .../boards/thingy91x_nrf5340_cpuapp.conf | 54 +++++++++++++++++++ boot/zephyr/boards/thingy91x_nrf9151.conf | 8 +++ 2 files changed, 62 insertions(+) create mode 100644 boot/zephyr/boards/thingy91x_nrf5340_cpuapp.conf create mode 100644 boot/zephyr/boards/thingy91x_nrf9151.conf diff --git a/boot/zephyr/boards/thingy91x_nrf5340_cpuapp.conf b/boot/zephyr/boards/thingy91x_nrf5340_cpuapp.conf new file mode 100644 index 000000000..72dfa7fca --- /dev/null +++ b/boot/zephyr/boards/thingy91x_nrf5340_cpuapp.conf @@ -0,0 +1,54 @@ +# MCUBoot settings +CONFIG_BOOT_MAX_IMG_SECTORS=110 + +# MCUboot serial recovery +CONFIG_MCUBOOT_SERIAL=y + +# Disable Zephyr console +CONFIG_LOG=n +CONFIG_CONSOLE=n +CONFIG_CONSOLE_HANDLER=n +CONFIG_UART_CONSOLE=n + +# Serial +CONFIG_SERIAL=y +CONFIG_UART_NRFX=y +CONFIG_UART_INTERRUPT_DRIVEN=y +CONFIG_UART_LINE_CTRL=y + +# MCUboot serial recovery +CONFIG_GPIO=y +CONFIG_MCUBOOT_SERIAL=y +CONFIG_BOOT_SERIAL_CDC_ACM=y + +# Required by USB +CONFIG_MULTITHREADING=y + +# USB +CONFIG_USB_DEVICE_STACK=y +CONFIG_USB_DEVICE_PRODUCT="MCUBOOT" +CONFIG_USB_CDC_ACM=y +CONFIG_USB_COMPOSITE_DEVICE=y +CONFIG_USB_MASS_STORAGE=n +CONFIG_USB_DEVICE_MANUFACTURER="Nordic Semiconductor" +CONFIG_USB_DEVICE_VID=0x1915 +CONFIG_USB_DEVICE_PID=0x520F + +CONFIG_BOOT_SERIAL_BOOT_MODE=y + +CONFIG_PM_PARTITION_SIZE_MCUBOOT=0x13E00 + +# The following configurations are required to support simultaneous multi image update +CONFIG_PCD_APP=y +CONFIG_UPDATEABLE_IMAGE_NUMBER=2 +CONFIG_BOOT_UPGRADE_ONLY=y +# The network core cannot access external flash directly. The flash simulator must be used to +# provide a memory region that is used to forward the new firmware to the network core. +CONFIG_FLASH_SIMULATOR=y +CONFIG_FLASH_SIMULATOR_DOUBLE_WRITES=y +CONFIG_FLASH_SIMULATOR_STATS=n + +CONFIG_BOOT_IMAGE_ACCESS_HOOKS=y +CONFIG_MCUBOOT_SERIAL_DIRECT_IMAGE_UPLOAD=y + +CONFIG_NRF53_RECOVERY_NETWORK_CORE=y diff --git a/boot/zephyr/boards/thingy91x_nrf9151.conf b/boot/zephyr/boards/thingy91x_nrf9151.conf new file mode 100644 index 000000000..33cd3301c --- /dev/null +++ b/boot/zephyr/boards/thingy91x_nrf9151.conf @@ -0,0 +1,8 @@ +# MCUBoot settings +CONFIG_BOOT_MAX_IMG_SECTORS=512 + +CONFIG_SPI=y +CONFIG_SPI_NOR=y +CONFIG_SPI_NOR_FLASH_LAYOUT_PAGE_SIZE=4096 +CONFIG_SPI_NOR_SFDP_DEVICETREE=y +CONFIG_MULTITHREADING=y From 89361bdec45690575952743ef65bc357977ddbb9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebastian=20B=C3=B8e?= Date: Wed, 12 Dec 2018 08:59:47 +0100 Subject: [PATCH 030/420] [nrf noup] treewide: add NCS partition manager support MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Partition Manager is an nRF Connect SDK component which uses yaml files to resolve flash partition placement with a holistic view of the device. This component's MCUboot portions began life as upstream mcuboot PR#430. This added support for being built as a sub image from the downstream Nordic patch set for a zephyr multi image build system (mcuboot 430 was combined with effor submitted to upstream zephyr as PR#13672, which was ultimately reworked after being rejected for mainline at the ELCE 2019 conference in Lyon). It has since evolved over time. This is the version that will go into NCS v1.3. It features: - page size aligned partitions for all partitions used by mcuboot. - image swaps without scratch partitions Add support for configurations where there exists two primary slots but only one secondary slot, which is shared. These two primary slots are the regular application and B1. B1 can be either S0 or S1 depending on the state of the device. Decide where an upgrade should be stored by looking at the vector table. Provide update candidates for both s0 and s1. These candidates must be signed with mcuboot after being signed by b0. Additional notes: - we make update.hex without trailer data This is needed for serial recovery to work using hex files. Prior to this the update.hex got TLV data at the end of the partition, which caused many blank pages to be included, which made it hard to use in a serial recovery scheme. Instead, make update.hex without TLV data at the end, and provide a new file test_update.hex which contains the TLV data, and can be directly flashed to test the upgrade procedure. - we use a function for signing the application as future-proofing for when other components must be signed as well - this includes an update to single image applications that enables support for partition manager; when single image DFU is used, a scratch partition is not needed. - In NCS, image 1 primary slot is the upgrade bank for mcuboot (IE S0 or S1 depending on the active slot). It is not required that this slot contains any valid data. - The nRF boards all have a single flash page size, and partition manager deals with the size of the update partitions and so on, so we must skip a boot_slots_compatible() check to avoid getting an error. - There is no need to verify the target when using partition manager. - We lock mcuboot using fprotect before jumping, to enable the secure boot property of the system. - Call fw_info_ext_api_provide() before booting if EXT_API_PROVIDE EXT_API is enabled. This is relevant only when the immutable bootloader has booted mcuboot. Signed-off-by: Håkon Øye Amundsen Signed-off-by: Øyvind Rønningstad Signed-off-by: Sebastian Bøe Signed-off-by: Sigvart Hovland Signed-off-by: Martí Bolívar Signed-off-by: Torsten Rasmussen Signed-off-by: Andrzej Głąbek Signed-off-by: Robert Lubos Signed-off-by: Andrzej Puzdrowski Signed-off-by: Emil Obalski Signed-off-by: Pawel Dunaj Signed-off-by: Ioannis Glaropoulos Signed-off-by: Johann Fischer Signed-off-by: Vidar Berg Signed-off-by: Draus, Sebastian Signed-off-by: Trond Einar Snekvik Signed-off-by: Jamie McCrae Signed-off-by: Joakim Andersson Signed-off-by: Georgios Vasilakis Signed-off-by: Dominik Ermel (cherry picked from commit 9554013f013d5bc067b41d9ad470bc09c346eb71) --- boot/bootutil/src/loader.c | 95 ++++++++++++++++++++++--- boot/bootutil/src/swap_move.c | 13 ++++ boot/bootutil/src/swap_scratch.c | 13 ++++ boot/zephyr/CMakeLists.txt | 7 ++ boot/zephyr/Kconfig | 2 + boot/zephyr/include/sysflash/sysflash.h | 48 +++++++++++++ boot/zephyr/include/target.h | 4 ++ boot/zephyr/main.c | 45 ++++++++++++ boot/zephyr/pm.yml | 77 ++++++++++++++++++++ boot/zephyr/prj.conf | 1 + ext/nrf/cc310_glue.h | 2 +- zephyr/module.yml | 3 +- 12 files changed, 299 insertions(+), 11 deletions(-) create mode 100644 boot/zephyr/pm.yml diff --git a/boot/bootutil/src/loader.c b/boot/bootutil/src/loader.c index 8c73f7652..d6092d86b 100644 --- a/boot/bootutil/src/loader.c +++ b/boot/bootutil/src/loader.c @@ -145,6 +145,15 @@ boot_read_image_headers(struct boot_loader_state *state, bool require_all, * * Failure to read any headers is a fatal error. */ +#ifdef PM_S1_ADDRESS + /* Patch needed for NCS. The primary slot of the second image + * (image 1) will not contain a valid image header until an upgrade + * of mcuboot has happened (filling S1 with the new version). + */ + if (BOOT_CURR_IMG(state) == 1 && i == 0) { + continue; + } +#endif /* PM_S1_ADDRESS */ if (i > 0 && !require_all) { return 0; } else { @@ -1204,7 +1213,24 @@ boot_validate_slot(struct boot_loader_state *state, int slot, goto out; } - if (reset_value < pri_fa->fa_off || reset_value> (pri_fa->fa_off + pri_fa->fa_size)) { + uint32_t min_addr, max_addr; + +#ifdef PM_CPUNET_APP_ADDRESS + /* The primary slot for the network core is emulated in RAM. + * Its flash_area hasn't got relevant boundaries. + * Therfore need to override its boundaries for the check. + */ + if (BOOT_CURR_IMG(state) == 1) { + min_addr = PM_CPUNET_APP_ADDRESS; + max_addr = PM_CPUNET_APP_ADDRESS + PM_CPUNET_APP_SIZE; + } else +#endif + { + min_addr = pri_fa->fa_off; + max_addr = pri_fa->fa_off + pri_fa->fa_size; + } + + if (reset_value < min_addr || reset_value> (max_addr)) { BOOT_LOG_ERR("Reset address of image in secondary slot is not in the primary slot"); BOOT_LOG_ERR("Erasing image from secondary slot"); @@ -1280,6 +1306,42 @@ boot_validated_swap_type(struct boot_loader_state *state, { int swap_type; FIH_DECLARE(fih_rc, FIH_FAILURE); +#ifdef PM_S1_ADDRESS + /* Patch needed for NCS. Since image 0 (the app) and image 1 (the other + * B1 slot S0 or S1) share the same secondary slot, we need to check + * whether the update candidate in the secondary slot is intended for + * image 0 or image 1 primary by looking at the address of the reset + * vector. Note that there are good reasons for not using img_num from + * the swap info. + */ + const struct flash_area *secondary_fa = + BOOT_IMG_AREA(state, BOOT_SECONDARY_SLOT); + struct image_header *hdr = + (struct image_header *)secondary_fa->fa_off; + + if (hdr->ih_magic == IMAGE_MAGIC) { + const struct flash_area *primary_fa; + uint32_t vtable_addr = (uint32_t)hdr + hdr->ih_hdr_size; + uint32_t *vtable = (uint32_t *)(vtable_addr); + uint32_t reset_addr = vtable[1]; + int rc = flash_area_open( + flash_area_id_from_multi_image_slot( + BOOT_CURR_IMG(state), + BOOT_PRIMARY_SLOT), + &primary_fa); + + if (rc != 0) { + return BOOT_SWAP_TYPE_FAIL; + } + /* Get start and end of primary slot for current image */ + if (reset_addr < primary_fa->fa_off || + reset_addr > (primary_fa->fa_off + primary_fa->fa_size)) { + /* The image in the secondary slot is not intended for this image + */ + return BOOT_SWAP_TYPE_NONE; + } + } +#endif swap_type = boot_swap_type_multi(BOOT_CURR_IMG(state)); if (BOOT_IS_UPGRADE(swap_type)) { @@ -2655,15 +2717,25 @@ context_boot_go(struct boot_loader_state *state, struct boot_rsp *rsp) } #ifdef MCUBOOT_VALIDATE_PRIMARY_SLOT - FIH_CALL(boot_validate_slot, fih_rc, state, BOOT_PRIMARY_SLOT, NULL, 0); - /* Check for all possible values is redundant in normal operation it - * is meant to prevent FI attack. +#ifdef PM_S1_ADDRESS + /* Patch needed for NCS. Image 1 primary is the currently + * executing MCUBoot image, and is therefore already validated by NSIB and + * does not need to also be validated by MCUBoot. */ - if (FIH_NOT_EQ(fih_rc, FIH_SUCCESS) || - FIH_EQ(fih_rc, FIH_FAILURE) || - FIH_EQ(fih_rc, FIH_NO_BOOTABLE_IMAGE)) { - FIH_SET(fih_rc, FIH_FAILURE); - goto out; + bool image_validated_by_nsib = BOOT_CURR_IMG(state) == 1; + if (!image_validated_by_nsib) +#endif + { + FIH_CALL(boot_validate_slot, fih_rc, state, BOOT_PRIMARY_SLOT, NULL, 0); + /* Check for all possible values is redundant in normal operation it + * is meant to prevent FI attack. + */ + if (FIH_NOT_EQ(fih_rc, FIH_SUCCESS) || + FIH_EQ(fih_rc, FIH_FAILURE) || + FIH_EQ(fih_rc, FIH_NO_BOOTABLE_IMAGE)) { + FIH_SET(fih_rc, FIH_FAILURE); + goto out; + } } #else /* Even if we're not re-validating the primary slot, we could be booting @@ -2680,11 +2752,16 @@ context_boot_go(struct boot_loader_state *state, struct boot_rsp *rsp) } #endif /* MCUBOOT_VALIDATE_PRIMARY_SLOT */ +#ifdef PM_S1_ADDRESS + if (!image_validated_by_nsib) +#endif + { rc = boot_update_hw_rollback_protection(state); if (rc != 0) { FIH_SET(fih_rc, FIH_FAILURE); goto out; } + } rc = boot_add_shared_data(state, BOOT_PRIMARY_SLOT); if (rc != 0) { diff --git a/boot/bootutil/src/swap_move.c b/boot/bootutil/src/swap_move.c index 8b7bcab13..ed0947076 100644 --- a/boot/bootutil/src/swap_move.c +++ b/boot/bootutil/src/swap_move.c @@ -230,6 +230,18 @@ boot_status_internal_off(const struct boot_status *bs, int elem_sz) int boot_slots_compatible(struct boot_loader_state *state) { +#ifdef PM_S1_ADDRESS + /* Patch needed for NCS. In this case, image 1 primary points to the other + * B1 slot (ie S0 or S1), and image 0 primary points to the app. + * With this configuration, image 0 and image 1 share the secondary slot. + * Hence, the primary slot of image 1 will be *smaller* than image 1's + * secondary slot. This is not allowed in upstream mcuboot, so we need + * this patch to allow it. Also, all of these checks are redundant when + * partition manager is in use, and since we have the same sector size + * in all of our flash. + */ + return 1; +#else size_t num_sectors_pri; size_t num_sectors_sec; size_t sector_sz_pri = 0; @@ -295,6 +307,7 @@ boot_slots_compatible(struct boot_loader_state *state) } return 1; +#endif /* PM_S1_ADDRESS */ } #define BOOT_LOG_SWAP_STATE(area, state) \ diff --git a/boot/bootutil/src/swap_scratch.c b/boot/bootutil/src/swap_scratch.c index e1d49de49..360dbe88c 100644 --- a/boot/bootutil/src/swap_scratch.c +++ b/boot/bootutil/src/swap_scratch.c @@ -271,6 +271,18 @@ boot_status_internal_off(const struct boot_status *bs, int elem_sz) int boot_slots_compatible(struct boot_loader_state *state) { +#ifdef PM_S1_ADDRESS + /* Patch needed for NCS. In this case, image 1 primary points to the other + * B1 slot (ie S0 or S1), and image 0 primary points to the app. + * With this configuration, image 0 and image 1 share the secondary slot. + * Hence, the primary slot of image 1 will be *smaller* than image 1's + * secondary slot. This is not allowed in upstream mcuboot, so we need + * this patch to allow it. Also, all of these checks are redundant when + * partition manager is in use, and since we have the same sector size + * in all of our flash. + */ + return 1; +#else size_t num_sectors_primary; size_t num_sectors_secondary; size_t sz0, sz1; @@ -368,6 +380,7 @@ boot_slots_compatible(struct boot_loader_state *state) #endif return 1; +#endif /* PM_S1_ADDRESS */ } #define BOOT_LOG_SWAP_STATE(area, state) \ diff --git a/boot/zephyr/CMakeLists.txt b/boot/zephyr/CMakeLists.txt index b0e43cd50..9424efcc3 100644 --- a/boot/zephyr/CMakeLists.txt +++ b/boot/zephyr/CMakeLists.txt @@ -355,6 +355,13 @@ if(NOT CONFIG_BOOT_SIGNATURE_KEY_FILE STREQUAL "") endif() message("MCUBoot bootloader key file: ${KEY_FILE}") + set_property( + GLOBAL + PROPERTY + KEY_FILE + ${KEY_FILE} + ) + set(mcuboot_default_signature_files ${MCUBOOT_DIR}/root-ec-p256-pkcs8.pem ${MCUBOOT_DIR}/root-ec-p384.pem diff --git a/boot/zephyr/Kconfig b/boot/zephyr/Kconfig index 0e8265002..c37911f8e 100644 --- a/boot/zephyr/Kconfig +++ b/boot/zephyr/Kconfig @@ -9,6 +9,8 @@ mainmenu "MCUboot configuration" comment "MCUboot-specific configuration options" +source "$(ZEPHYR_NRF_MODULE_DIR)/modules/mcuboot/boot/zephyr/Kconfig" + # Hidden option to mark a project as MCUboot config MCUBOOT default y diff --git a/boot/zephyr/include/sysflash/sysflash.h b/boot/zephyr/include/sysflash/sysflash.h index 16d222280..99cbf56b7 100644 --- a/boot/zephyr/include/sysflash/sysflash.h +++ b/boot/zephyr/include/sysflash/sysflash.h @@ -7,6 +7,52 @@ #ifndef __SYSFLASH_H__ #define __SYSFLASH_H__ +#if USE_PARTITION_MANAGER +#include +#include + +#ifndef CONFIG_SINGLE_APPLICATION_SLOT + +#if (MCUBOOT_IMAGE_NUMBER == 1) + +#define FLASH_AREA_IMAGE_PRIMARY(x) PM_MCUBOOT_PRIMARY_ID +#define FLASH_AREA_IMAGE_SECONDARY(x) PM_MCUBOOT_SECONDARY_ID + +#elif (MCUBOOT_IMAGE_NUMBER == 2) + +extern uint32_t _image_1_primary_slot_id[]; + +#define FLASH_AREA_IMAGE_PRIMARY(x) \ + ((x == 0) ? \ + PM_MCUBOOT_PRIMARY_ID : \ + (x == 1) ? \ + (uint32_t)_image_1_primary_slot_id : \ + 255 ) + +#define FLASH_AREA_IMAGE_SECONDARY(x) \ + ((x == 0) ? \ + PM_MCUBOOT_SECONDARY_ID: \ + (x == 1) ? \ + PM_MCUBOOT_SECONDARY_ID: \ + 255 ) +#endif +#define FLASH_AREA_IMAGE_SCRATCH PM_MCUBOOT_SCRATCH_ID + +#else /* CONFIG_SINGLE_APPLICATION_SLOT */ + +#define FLASH_AREA_IMAGE_PRIMARY(x) PM_MCUBOOT_PRIMARY_ID +#define FLASH_AREA_IMAGE_SECONDARY(x) PM_MCUBOOT_PRIMARY_ID +/* NOTE: Scratch parition is not used by single image DFU but some of + * functions in common files reference it, so the definitions has been + * provided to allow compilation of common units. + */ +#define FLASH_AREA_IMAGE_SCRATCH 0 + +#endif /* CONFIG_SINGLE_APPLICATION_SLOT */ + +#else + +#include #include #include #include @@ -65,4 +111,6 @@ static inline uint32_t __flash_area_ids_for_slot(int img, int slot) #endif /* CONFIG_SINGLE_APPLICATION_SLOT */ +#endif /* USE_PARTITION_MANAGER */ + #endif /* __SYSFLASH_H__ */ diff --git a/boot/zephyr/include/target.h b/boot/zephyr/include/target.h index ea160752e..856686785 100644 --- a/boot/zephyr/include/target.h +++ b/boot/zephyr/include/target.h @@ -8,6 +8,8 @@ #ifndef H_TARGETS_TARGET_ #define H_TARGETS_TARGET_ +#ifndef USE_PARTITION_MANAGER + #if defined(MCUBOOT_TARGET_CONFIG) /* * Target-specific definitions are permitted in legacy cases that @@ -47,4 +49,6 @@ #error "Target support is incomplete; cannot build mcuboot." #endif +#endif /* ifndef USE_PARTITION_MANAGER */ + #endif /* H_TARGETS_TARGET_ */ diff --git a/boot/zephyr/main.c b/boot/zephyr/main.c index 0cb793b2d..b61b535e0 100644 --- a/boot/zephyr/main.c +++ b/boot/zephyr/main.c @@ -71,6 +71,10 @@ #endif /* CONFIG_SOC_FAMILY_ESPRESSIF_ESP32 */ +#ifdef CONFIG_FW_INFO +#include +#endif + #ifdef CONFIG_MCUBOOT_SERIAL #include "boot_serial/boot_serial.h" #include "serial_adapter/serial_adapter.h" @@ -131,6 +135,11 @@ K_SEM_DEFINE(boot_log_sem, 1, 1); * !defined(ZEPHYR_LOG_MODE_MINIMAL) */ +#if USE_PARTITION_MANAGER && CONFIG_FPROTECT +#include +#include +#endif + BOOT_LOG_MODULE_REGISTER(mcuboot); void os_heap_init(void); @@ -182,6 +191,19 @@ static void do_boot(struct boot_rsp *rsp) /* Disable the USB to prevent it from firing interrupts */ usb_disable(); #endif + +#if defined(CONFIG_FW_INFO) && !defined(CONFIG_EXT_API_PROVIDE_EXT_API_UNUSED) + bool provided = fw_info_ext_api_provide(fw_info_find((uint32_t)vt), true); + +#ifdef PM_S0_ADDRESS + /* Only fail if the immutable bootloader is present. */ + if (!provided) { + BOOT_LOG_ERR("Failed to provide EXT_APIs\n"); + return; + } +#endif +#endif + #if CONFIG_MCUBOOT_CLEANUP_ARM_CORE cleanup_arm_nvic(); /* cleanup NVIC registers */ @@ -606,7 +628,30 @@ int main(void) mcuboot_status_change(MCUBOOT_STATUS_BOOTABLE_IMAGE_FOUND); +#if USE_PARTITION_MANAGER && CONFIG_FPROTECT + +#ifdef PM_S1_ADDRESS +/* MCUBoot is stored in either S0 or S1, protect both */ +#define PROTECT_SIZE (PM_MCUBOOT_PRIMARY_ADDRESS - PM_S0_ADDRESS) +#define PROTECT_ADDR PM_S0_ADDRESS +#else +/* There is only one instance of MCUBoot */ +#define PROTECT_SIZE (PM_MCUBOOT_PRIMARY_ADDRESS - PM_MCUBOOT_ADDRESS) +#define PROTECT_ADDR PM_MCUBOOT_ADDRESS +#endif + + rc = fprotect_area(PROTECT_ADDR, PROTECT_SIZE); + + if (rc != 0) { + BOOT_LOG_ERR("Protect mcuboot flash failed, cancel startup."); + while (1) + ; + } + +#endif /* USE_PARTITION_MANAGER && CONFIG_FPROTECT */ + ZEPHYR_BOOT_LOG_STOP(); + do_boot(&rsp); mcuboot_status_change(MCUBOOT_STATUS_BOOT_FAILED); diff --git a/boot/zephyr/pm.yml b/boot/zephyr/pm.yml new file mode 100644 index 000000000..5df9ae547 --- /dev/null +++ b/boot/zephyr/pm.yml @@ -0,0 +1,77 @@ +#include + +mcuboot: + size: CONFIG_PM_PARTITION_SIZE_MCUBOOT + placement: + before: [mcuboot_primary] +#if defined(CONFIG_HIDE_CHILD_PARENT_CONFIG) + align: {end: 0x1000} +#endif + +mcuboot_primary_app: + # All images to be placed in MCUboot's slot 0 should be placed in this + # partition + span: [app] + +mcuboot_primary: + span: [mcuboot_pad, mcuboot_primary_app] + +# Partition for secondary slot is not created if building in single application +# slot configuration. +#if !defined(CONFIG_SINGLE_APPLICATION_SLOT) && !defined(CONFIG_BOOT_DIRECT_XIP) +mcuboot_secondary: + share_size: [mcuboot_primary] +#if defined(CONFIG_PM_EXTERNAL_FLASH_MCUBOOT_SECONDARY) + region: external_flash + placement: + align: {start: 4} +#else + placement: + align: {start: CONFIG_FPROTECT_BLOCK_SIZE} + align_next: CONFIG_FPROTECT_BLOCK_SIZE # Ensure that the next partition does not interfere with this image + after: mcuboot_primary +#endif /* CONFIG_PM_EXTERNAL_FLASH_MCUBOOT_SECONDARY */ + +#endif /* !defined(CONFIG_SINGLE_APPLICATION_SLOT) && !defined(CONFIG_BOOT_DIRECT_XIP) */ + +#if CONFIG_BOOT_DIRECT_XIP + +# Direct XIP is enabled, reserve area for metadata (padding) and name the +# partition so that its clear that it is not the secondary slot, but the direct +# XIP alternative. + +mcuboot_secondary_pad: + share_size: mcuboot_pad + placement: + after: mcuboot_primary + align: {start: CONFIG_FPROTECT_BLOCK_SIZE} + +mcuboot_secondary_app: + share_size: mcuboot_primary_app + placement: + after: mcuboot_secondary_pad + +mcuboot_secondary: + span: [mcuboot_secondary_pad, mcuboot_secondary_app] + +#endif /* CONFIG_BOOT_DIRECT_XIP */ + +#if CONFIG_BOOT_SWAP_USING_SCRATCH +mcuboot_scratch: + size: CONFIG_PM_PARTITION_SIZE_MCUBOOT_SCRATCH + placement: + after: app + align: {start: CONFIG_FPROTECT_BLOCK_SIZE} +#endif /* CONFIG_BOOT_SWAP_USING_SCRATCH */ + +# Padding placed before image to boot. This reserves space for the MCUboot image header +# and it ensures that the boot image gets linked with the correct address offset in flash. +mcuboot_pad: + # MCUboot pad must be placed before the primary application partition. + # The primary application partition includes the secure firmware if present. + size: CONFIG_PM_PARTITION_SIZE_MCUBOOT_PAD + placement: + before: [mcuboot_primary_app] +#ifdef CONFIG_FPROTECT + align: {start: CONFIG_FPROTECT_BLOCK_SIZE} +#endif diff --git a/boot/zephyr/prj.conf b/boot/zephyr/prj.conf index 51dc99b27..6d538d1de 100644 --- a/boot/zephyr/prj.conf +++ b/boot/zephyr/prj.conf @@ -18,6 +18,7 @@ CONFIG_BOOT_BOOTSTRAP=n # CONFIG_TINYCRYPT_SHA256 is not set CONFIG_FLASH=y +CONFIG_FPROTECT=y ### Various Zephyr boards enable features that we don't want. # CONFIG_BT is not set diff --git a/ext/nrf/cc310_glue.h b/ext/nrf/cc310_glue.h index ed3ed5c00..22eb94911 100644 --- a/ext/nrf/cc310_glue.h +++ b/ext/nrf/cc310_glue.h @@ -22,7 +22,7 @@ #include #include #include -#include +#include #include /* diff --git a/zephyr/module.yml b/zephyr/module.yml index d2af55384..b73ae2a0d 100644 --- a/zephyr/module.yml +++ b/zephyr/module.yml @@ -1,7 +1,8 @@ samples: - boot/zephyr build: - cmake: ./boot/bootutil/zephyr + cmake-ext: True + kconfig-ext: True sysbuild-cmake: boot/zephyr/sysbuild package-managers: pip: From 2cdbcb02a960f625e7a067f37ab573a4ebaa03a7 Mon Sep 17 00:00:00 2001 From: Sigvart Hovland Date: Thu, 27 Aug 2020 14:29:31 +0200 Subject: [PATCH 031/420] [nrf noup] boot: nrf53-specific customizations MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Add network core bootloader implementation Enables network core updates of nrf53 using MCUBoot by identifying images through their start addresses. Also implements the control and transfer using the PCD module. - Add support for multi image DFU using partition manager. - Add check for netcore addr if NSIB is enabled so netcore updates works - boot: zephyr: move thingy53_nrf5340_cpuapp.conf downstream Moved the board configuration for Thingy:53 Application Core to the nRF Connect SDK MCUboot downstream repository. The configuration file contains references to the Kconfig modules that are only available in the nRF Connect SDK. The current configuration is set up to work in the nRF Connect SDK environment and cannot be used upstream. - pm: enable ram flash partition using common flag This patch makes mcuboot_primary_1 ram-flash partition selectable using CONFIG_NRF53_MCUBOOT_PRIMARY_1_RAM_FLASH property. This is needed since CONFIG_NRF53_MULTI_IMAGE_UPDATE become not only configuration which requires that partition. - MCUBoot configures USB CDC by its own. There is no need for BOARD_SERIAL_BACKEND_CDC_ACM option to configure anything which is later overwritten anyway. Jira: NCSDK-18596 Signed-off-by: Andrzej Puzdrowski Signed-off-by: Emil Obalski Signed-off-by: Håkon Øye Amundsen Signed-off-by: Ioannis Glaropoulos Signed-off-by: Jamie McCrae Signed-off-by: Johann Fischer Signed-off-by: Kamil Piszczek Signed-off-by: Ole Sæther Signed-off-by: Sigvart Hovland Signed-off-by: Simon Iversen Signed-off-by: Torsten Rasmussen Signed-off-by: Trond Einar Snekvik Signed-off-by: Mateusz Kapala Signed-off-by: Dominik Ermel Signed-off-by: Michal Kozikowski (cherry picked from commit 3db6eca8c7968a1eb1cb11fda08f763004f8226d) --- boot/bootutil/src/loader.c | 96 ++++++++++++++----- .../boards/thingy53_nrf5340_cpuapp.conf | 74 +++++++++++++- boot/zephyr/include/sysflash/sysflash.h | 23 +++++ boot/zephyr/main.c | 7 ++ boot/zephyr/pm.yml | 13 +++ 5 files changed, 185 insertions(+), 28 deletions(-) diff --git a/boot/bootutil/src/loader.c b/boot/bootutil/src/loader.c index d6092d86b..9a6f3015c 100644 --- a/boot/bootutil/src/loader.c +++ b/boot/bootutil/src/loader.c @@ -50,6 +50,10 @@ #include "bootutil/boot_hooks.h" #include "bootutil/mcuboot_status.h" +#if defined(CONFIG_SOC_NRF5340_CPUAPP) && defined(PM_CPUNET_B0N_ADDRESS) && defined(CONFIG_PCD_APP) +#include +#endif + #ifdef MCUBOOT_ENC_IMAGES #include "bootutil/enc_key.h" #endif @@ -1306,7 +1310,15 @@ boot_validated_swap_type(struct boot_loader_state *state, { int swap_type; FIH_DECLARE(fih_rc, FIH_FAILURE); -#ifdef PM_S1_ADDRESS + bool upgrade_valid = false; + +#if defined(PM_S1_ADDRESS) || defined(CONFIG_SOC_NRF5340_CPUAPP) + const struct flash_area *secondary_fa = + BOOT_IMG_AREA(state, BOOT_SECONDARY_SLOT); + struct image_header *hdr = (struct image_header *)secondary_fa->fa_off; + uint32_t vtable_addr = 0; + uint32_t *vtable = 0; + uint32_t reset_addr = 0; /* Patch needed for NCS. Since image 0 (the app) and image 1 (the other * B1 slot S0 or S1) share the same secondary slot, we need to check * whether the update candidate in the secondary slot is intended for @@ -1314,34 +1326,36 @@ boot_validated_swap_type(struct boot_loader_state *state, * vector. Note that there are good reasons for not using img_num from * the swap info. */ - const struct flash_area *secondary_fa = - BOOT_IMG_AREA(state, BOOT_SECONDARY_SLOT); - struct image_header *hdr = - (struct image_header *)secondary_fa->fa_off; if (hdr->ih_magic == IMAGE_MAGIC) { - const struct flash_area *primary_fa; - uint32_t vtable_addr = (uint32_t)hdr + hdr->ih_hdr_size; - uint32_t *vtable = (uint32_t *)(vtable_addr); - uint32_t reset_addr = vtable[1]; - int rc = flash_area_open( - flash_area_id_from_multi_image_slot( - BOOT_CURR_IMG(state), - BOOT_PRIMARY_SLOT), - &primary_fa); - - if (rc != 0) { - return BOOT_SWAP_TYPE_FAIL; - } - /* Get start and end of primary slot for current image */ - if (reset_addr < primary_fa->fa_off || - reset_addr > (primary_fa->fa_off + primary_fa->fa_size)) { - /* The image in the secondary slot is not intended for this image - */ - return BOOT_SWAP_TYPE_NONE; - } - } + vtable_addr = (uint32_t)hdr + hdr->ih_hdr_size; + vtable = (uint32_t *)(vtable_addr); + reset_addr = vtable[1]; +#ifdef PM_S1_ADDRESS +#ifdef PM_CPUNET_B0N_ADDRESS + if(reset_addr < PM_CPUNET_B0N_ADDRESS) #endif + { + const struct flash_area *primary_fa; + int rc = flash_area_open(flash_area_id_from_multi_image_slot( + BOOT_CURR_IMG(state), + BOOT_PRIMARY_SLOT), + &primary_fa); + + if (rc != 0) { + return BOOT_SWAP_TYPE_FAIL; + } + /* Get start and end of primary slot for current image */ + if (reset_addr < primary_fa->fa_off || + reset_addr > (primary_fa->fa_off + primary_fa->fa_size)) { + /* The image in the secondary slot is not intended for this image + */ + return BOOT_SWAP_TYPE_NONE; + } + } +#endif /* PM_S1_ADDRESS */ + } +#endif /* PM_S1_ADDRESS || CONFIG_SOC_NRF5340_CPUAPP */ swap_type = boot_swap_type_multi(BOOT_CURR_IMG(state)); if (BOOT_IS_UPGRADE(swap_type)) { @@ -1355,7 +1369,37 @@ boot_validated_swap_type(struct boot_loader_state *state, } else { swap_type = BOOT_SWAP_TYPE_FAIL; } + } else { + upgrade_valid = true; + } + +#if defined(CONFIG_SOC_NRF5340_CPUAPP) && defined(PM_CPUNET_B0N_ADDRESS) + /* If the update is valid, and it targets the network core: perform the + * update and indicate to the caller of this function that no update is + * available + */ + if (upgrade_valid && reset_addr > PM_CPUNET_B0N_ADDRESS) { + uint32_t fw_size = hdr->ih_img_size; + + BOOT_LOG_INF("Starting network core update"); + int rc = pcd_network_core_update(vtable, fw_size); + + if (rc != 0) { + swap_type = BOOT_SWAP_TYPE_FAIL; + } else { + BOOT_LOG_INF("Done updating network core"); +#if defined(MCUBOOT_SWAP_USING_SCRATCH) || defined(MCUBOOT_SWAP_USING_MOVE) + /* swap_erase_trailer_sectors is undefined if upgrade only + * method is used. There is no need to erase sectors, because + * the image cannot be reverted. + */ + rc = swap_erase_trailer_sectors(state, + secondary_fa); +#endif + swap_type = BOOT_SWAP_TYPE_NONE; + } } +#endif /* CONFIG_SOC_NRF5340_CPUAPP */ } return swap_type; diff --git a/boot/zephyr/boards/thingy53_nrf5340_cpuapp.conf b/boot/zephyr/boards/thingy53_nrf5340_cpuapp.conf index f2e42fd64..93be36738 100644 --- a/boot/zephyr/boards/thingy53_nrf5340_cpuapp.conf +++ b/boot/zephyr/boards/thingy53_nrf5340_cpuapp.conf @@ -1,3 +1,73 @@ -CONFIG_NORDIC_QSPI_NOR=n -CONFIG_SPI=n +CONFIG_SIZE_OPTIMIZATIONS=y + +CONFIG_SYSTEM_CLOCK_NO_WAIT=y +CONFIG_PM=n + +CONFIG_MAIN_STACK_SIZE=10240 +CONFIG_MBEDTLS_CFG_FILE="mcuboot-mbedtls-cfg.h" + +CONFIG_BOOT_MAX_IMG_SECTORS=2048 +CONFIG_BOOT_SIGNATURE_TYPE_RSA=y + +# Flash +CONFIG_FLASH=y +CONFIG_BOOT_ERASE_PROGRESSIVELY=y +CONFIG_SOC_FLASH_NRF_EMULATE_ONE_BYTE_WRITE_ACCESS=y +CONFIG_FPROTECT=y + +# Serial +CONFIG_SERIAL=y +CONFIG_UART_LINE_CTRL=y + +# MCUBoot serial +CONFIG_GPIO=y +CONFIG_MCUBOOT_SERIAL=y +CONFIG_MCUBOOT_SERIAL_DIRECT_IMAGE_UPLOAD=y +CONFIG_BOOT_SERIAL_CDC_ACM=y + +# Required by QSPI +CONFIG_NORDIC_QSPI_NOR=y +CONFIG_NORDIC_QSPI_NOR_FLASH_LAYOUT_PAGE_SIZE=4096 +CONFIG_NORDIC_QSPI_NOR_STACK_WRITE_BUFFER_SIZE=16 + +# Required by USB CONFIG_MULTITHREADING=y + +# USB +CONFIG_BOARD_SERIAL_BACKEND_CDC_ACM=n +CONFIG_USB_DEVICE_REMOTE_WAKEUP=n +CONFIG_USB_DEVICE_MANUFACTURER="Nordic Semiconductor ASA" +CONFIG_USB_DEVICE_PRODUCT="Bootloader Thingy:53" +CONFIG_USB_DEVICE_VID=0x1915 +CONFIG_USB_DEVICE_PID=0x5300 +CONFIG_USB_CDC_ACM=y + +# Decrease memory footprint +CONFIG_CBPRINTF_NANO=y +CONFIG_TIMESLICING=n +CONFIG_BOOT_BANNER=n +CONFIG_CONSOLE=n +CONFIG_CONSOLE_HANDLER=n +CONFIG_UART_CONSOLE=n +CONFIG_USE_SEGGER_RTT=n +CONFIG_LOG=n +CONFIG_ERRNO=n +CONFIG_PRINTK=n +CONFIG_RESET_ON_FATAL_ERROR=n +CONFIG_SPI=n +CONFIG_I2C=n +CONFIG_UART_NRFX=n + +# The following configurations are required to support simultaneous multi image update +CONFIG_PCD_APP=y +CONFIG_UPDATEABLE_IMAGE_NUMBER=2 +CONFIG_BOOT_UPGRADE_ONLY=y +# The network core cannot access external flash directly. The flash simulator must be used to +# provide a memory region that is used to forward the new firmware to the network core. +CONFIG_FLASH_SIMULATOR=y +CONFIG_FLASH_SIMULATOR_DOUBLE_WRITES=y +CONFIG_FLASH_SIMULATOR_STATS=n + +# Enable custom command to erase settings partition. +CONFIG_ENABLE_MGMT_PERUSER=y +CONFIG_BOOT_MGMT_CUSTOM_STORAGE_ERASE=y diff --git a/boot/zephyr/include/sysflash/sysflash.h b/boot/zephyr/include/sysflash/sysflash.h index 99cbf56b7..7112f9baa 100644 --- a/boot/zephyr/include/sysflash/sysflash.h +++ b/boot/zephyr/include/sysflash/sysflash.h @@ -20,6 +20,11 @@ #elif (MCUBOOT_IMAGE_NUMBER == 2) +/* If B0 is present then two bootloaders are present, and we must use + * a single secondary slot for both primary slots. + */ +#ifdef PM_B0_ADDRESS + extern uint32_t _image_1_primary_slot_id[]; #define FLASH_AREA_IMAGE_PRIMARY(x) \ @@ -35,6 +40,24 @@ extern uint32_t _image_1_primary_slot_id[]; (x == 1) ? \ PM_MCUBOOT_SECONDARY_ID: \ 255 ) +#else + +#define FLASH_AREA_IMAGE_PRIMARY(x) \ + ((x == 0) ? \ + PM_MCUBOOT_PRIMARY_ID : \ + (x == 1) ? \ + PM_MCUBOOT_PRIMARY_1_ID : \ + 255 ) + +#define FLASH_AREA_IMAGE_SECONDARY(x) \ + ((x == 0) ? \ + PM_MCUBOOT_SECONDARY_ID: \ + (x == 1) ? \ + PM_MCUBOOT_SECONDARY_1_ID: \ + 255 ) + +#endif /* PM_B0_ADDRESS */ + #endif #define FLASH_AREA_IMAGE_SCRATCH PM_MCUBOOT_SCRATCH_ID diff --git a/boot/zephyr/main.c b/boot/zephyr/main.c index b61b535e0..c243a1ac7 100644 --- a/boot/zephyr/main.c +++ b/boot/zephyr/main.c @@ -93,6 +93,10 @@ const struct boot_uart_funcs boot_funcs = { #include #endif +#if defined(CONFIG_SOC_NRF5340_CPUAPP) && defined(PM_CPUNET_B0N_ADDRESS) && defined(CONFIG_PCD_APP) +#include +#endif + /* CONFIG_LOG_MINIMAL is the legacy Kconfig property, * replaced by CONFIG_LOG_MODE_MINIMAL. */ @@ -648,6 +652,9 @@ int main(void) ; } +#if defined(CONFIG_SOC_NRF5340_CPUAPP) && defined(PM_CPUNET_B0N_ADDRESS) && defined(CONFIG_PCD_APP) + pcd_lock_ram(); +#endif #endif /* USE_PARTITION_MANAGER && CONFIG_FPROTECT */ ZEPHYR_BOOT_LOG_STOP(); diff --git a/boot/zephyr/pm.yml b/boot/zephyr/pm.yml index 5df9ae547..13ffc44aa 100644 --- a/boot/zephyr/pm.yml +++ b/boot/zephyr/pm.yml @@ -75,3 +75,16 @@ mcuboot_pad: #ifdef CONFIG_FPROTECT align: {start: CONFIG_FPROTECT_BLOCK_SIZE} #endif + +#if (CONFIG_NRF53_MCUBOOT_PRIMARY_1_RAM_FLASH) +mcuboot_primary_1: + region: ram_flash + size: CONFIG_NRF53_RAM_FLASH_SIZE +#endif /* CONFIG_NRF53_MULTI_IMAGE_UPDATE */ + +#if (CONFIG_NRF53_MULTI_IMAGE_UPDATE) +mcuboot_secondary_1: + region: external_flash + size: CONFIG_NRF53_RAM_FLASH_SIZE + +#endif /* CONFIG_NRF53_MULTI_IMAGE_UPDATE */ From 0f2061be7ecee80c2b2c6772efc719415e89b880 Mon Sep 17 00:00:00 2001 From: Andrzej Puzdrowski Date: Thu, 27 Feb 2020 12:48:56 +0100 Subject: [PATCH 032/420] [nrf noup] zephyr: clean peripherals state before boot MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Do some cleanup of nRF peripherals. This is necessary since Zephyr doesn't have any driver deinitialization functionality, and we'd like to leave peripherals in a more predictable state before booting the Zephyr image. This should be re-worked when the zephyr driver model allows us to deinitialize devices cleanly before jumping to the chain-loaded image. Signed-off-by: Andrzej Puzdrowski Signed-off-by: Robert Lubos Signed-off-by: Torsten Rasmussen Signed-off-by: Øyvind Rønningstad Signed-off-by: Martí Bolívar Signed-off-by: Håkon Øye Amundsen Signed-off-by: Ioannis Glaropoulos Signed-off-by: Johann Fischer Signed-off-by: Trond Einar Snekvik Signed-off-by: Torsten Rasmussen Signed-off-by: Jamie McCrae Signed-off-by: Dominik Ermel (cherry picked from commit c14ac2bfaa7324a93a0abdb01ea3b96a2589d29d) --- boot/zephyr/CMakeLists.txt | 6 +++ boot/zephyr/include/nrf_cleanup.h | 19 +++++++ boot/zephyr/main.c | 8 ++- boot/zephyr/nrf_cleanup.c | 83 +++++++++++++++++++++++++++++++ 4 files changed, 115 insertions(+), 1 deletion(-) create mode 100644 boot/zephyr/include/nrf_cleanup.h create mode 100644 boot/zephyr/nrf_cleanup.c diff --git a/boot/zephyr/CMakeLists.txt b/boot/zephyr/CMakeLists.txt index 9424efcc3..e19f10455 100644 --- a/boot/zephyr/CMakeLists.txt +++ b/boot/zephyr/CMakeLists.txt @@ -719,3 +719,9 @@ if(SYSBUILD) set(mcuboot_image_footer_size ${required_size} CACHE INTERNAL "Estimated MCUboot image trailer size" FORCE) set(mcuboot_image_upgrade_footer_size ${required_upgrade_size} CACHE INTERNAL "Estimated MCUboot update image trailer size" FORCE) endif() + +if(CONFIG_MCUBOOT_NRF_CLEANUP_PERIPHERAL) +zephyr_library_sources( + ${BOOT_DIR}/zephyr/nrf_cleanup.c +) +endif() diff --git a/boot/zephyr/include/nrf_cleanup.h b/boot/zephyr/include/nrf_cleanup.h new file mode 100644 index 000000000..6b04cedfe --- /dev/null +++ b/boot/zephyr/include/nrf_cleanup.h @@ -0,0 +1,19 @@ +/* + * Copyright (c) 2020 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: LicenseRef-Nordic-5-Clause + */ + +#ifndef H_NRF_CLEANUP_ +#define H_NRF_CLEANUP_ + +/** + * Perform cleanup on some peripheral resources used by MCUBoot prior chainload + * the application. + * + * This function disables all RTC instances and UARTE instances. + * It Disables their interrupts signals as well. + */ +void nrf_cleanup_peripheral(void); + +#endif diff --git a/boot/zephyr/main.c b/boot/zephyr/main.c index c243a1ac7..d3d88980a 100644 --- a/boot/zephyr/main.c +++ b/boot/zephyr/main.c @@ -144,6 +144,10 @@ K_SEM_DEFINE(boot_log_sem, 1, 1); #include #endif +#if CONFIG_MCUBOOT_NRF_CLEANUP_PERIPHERAL +#include +#endif + BOOT_LOG_MODULE_REGISTER(mcuboot); void os_heap_init(void); @@ -207,7 +211,9 @@ static void do_boot(struct boot_rsp *rsp) } #endif #endif - +#if CONFIG_MCUBOOT_NRF_CLEANUP_PERIPHERAL + nrf_cleanup_peripheral(); +#endif #if CONFIG_MCUBOOT_CLEANUP_ARM_CORE cleanup_arm_nvic(); /* cleanup NVIC registers */ diff --git a/boot/zephyr/nrf_cleanup.c b/boot/zephyr/nrf_cleanup.c new file mode 100644 index 000000000..5bab26b24 --- /dev/null +++ b/boot/zephyr/nrf_cleanup.c @@ -0,0 +1,83 @@ +/* + * Copyright (c) 2020 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: LicenseRef-Nordic-5-Clause + */ + +#include +#if defined(NRF_UARTE0) || defined(NRF_UARTE1) + #include +#endif +#if defined(NRF_RTC0) || defined(NRF_RTC1) || defined(NRF_RTC2) + #include +#endif +#if defined(NRF_PPI) + #include +#endif +#if defined(NRF_DPPIC) + #include +#endif + +#include + +#define NRF_UARTE_SUBSCRIBE_CONF_OFFS offsetof(NRF_UARTE_Type, SUBSCRIBE_STARTRX) +#define NRF_UARTE_SUBSCRIBE_CONF_SIZE (offsetof(NRF_UARTE_Type, EVENTS_CTS) -\ + NRF_UARTE_SUBSCRIBE_CONF_OFFS) + +#define NRF_UARTE_PUBLISH_CONF_OFFS offsetof(NRF_UARTE_Type, PUBLISH_CTS) +#define NRF_UARTE_PUBLISH_CONF_SIZE (offsetof(NRF_UARTE_Type, SHORTS) -\ + NRF_UARTE_PUBLISH_CONF_OFFS) + +#if defined(NRF_RTC0) || defined(NRF_RTC1) || defined(NRF_RTC2) +static inline void nrf_cleanup_rtc(NRF_RTC_Type * rtc_reg) +{ + nrf_rtc_task_trigger(rtc_reg, NRF_RTC_TASK_STOP); + nrf_rtc_event_disable(rtc_reg, 0xFFFFFFFF); + nrf_rtc_int_disable(rtc_reg, 0xFFFFFFFF); +} +#endif + +static void nrf_cleanup_clock(void) +{ + nrf_clock_int_disable(NRF_CLOCK, 0xFFFFFFFF); +} + +void nrf_cleanup_peripheral(void) +{ +#if defined(NRF_RTC0) + nrf_cleanup_rtc(NRF_RTC0); +#endif +#if defined(NRF_RTC1) + nrf_cleanup_rtc(NRF_RTC1); +#endif +#if defined(NRF_RTC2) + nrf_cleanup_rtc(NRF_RTC2); +#endif +#if defined(NRF_UARTE0) + nrf_uarte_disable(NRF_UARTE0); + nrf_uarte_int_disable(NRF_UARTE0, 0xFFFFFFFF); +#if defined(NRF_DPPIC) + /* Clear all SUBSCRIBE configurations. */ + memset((uint8_t *)NRF_UARTE0 + NRF_UARTE_SUBSCRIBE_CONF_OFFS, 0, NRF_UARTE_SUBSCRIBE_CONF_SIZE); + /* Clear all PUBLISH configurations. */ + memset((uint8_t *)NRF_UARTE0 + NRF_UARTE_PUBLISH_CONF_OFFS, 0, NRF_UARTE_PUBLISH_CONF_SIZE); +#endif +#endif +#if defined(NRF_UARTE1) + nrf_uarte_disable(NRF_UARTE1); + nrf_uarte_int_disable(NRF_UARTE1, 0xFFFFFFFF); +#if defined(NRF_DPPIC) + /* Clear all SUBSCRIBE configurations. */ + memset((uint8_t *)NRF_UARTE1 + NRF_UARTE_SUBSCRIBE_CONF_OFFS, 0, NRF_UARTE_SUBSCRIBE_CONF_SIZE); + /* Clear all PUBLISH configurations. */ + memset((uint8_t *)NRF_UARTE1 + NRF_UARTE_PUBLISH_CONF_OFFS, 0, NRF_UARTE_PUBLISH_CONF_SIZE); +#endif +#endif +#if defined(NRF_PPI) + nrf_ppi_channels_disable_all(NRF_PPI); +#endif +#if defined(NRF_DPPIC) + nrf_dppi_channels_disable_all(NRF_DPPIC); +#endif + nrf_cleanup_clock(); +} From c9f632d1ddd6774e750577a83b562f5b739249fc Mon Sep 17 00:00:00 2001 From: Sigvart Hovland Date: Fri, 6 Jan 2023 12:24:48 +0100 Subject: [PATCH 033/420] [nrf noup] zephyr: Clean up non-secure RAM if enabled MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit To ensure that MCUBoot does not leak keys or other material through memory to non-secure side we clear the memory before jumping to the next image. Signed-off-by: Sigvart Hovland Signed-off-by: Dominik Ermel Signed-off-by: Ole Sæther (cherry picked from commit 11ea3a21b446f4018ed09c883d56840e20816c80) --- boot/zephyr/CMakeLists.txt | 2 +- boot/zephyr/include/nrf_cleanup.h | 5 ++ boot/zephyr/main.c | 5 +- boot/zephyr/nrf_cleanup.c | 79 +++++++++++++++++++++++-------- 4 files changed, 69 insertions(+), 22 deletions(-) diff --git a/boot/zephyr/CMakeLists.txt b/boot/zephyr/CMakeLists.txt index e19f10455..424cf1315 100644 --- a/boot/zephyr/CMakeLists.txt +++ b/boot/zephyr/CMakeLists.txt @@ -720,7 +720,7 @@ if(SYSBUILD) set(mcuboot_image_upgrade_footer_size ${required_upgrade_size} CACHE INTERNAL "Estimated MCUboot update image trailer size" FORCE) endif() -if(CONFIG_MCUBOOT_NRF_CLEANUP_PERIPHERAL) +if(CONFIG_MCUBOOT_NRF_CLEANUP_PERIPHERAL OR CONFIG_MCUBOOT_CLEANUP_NONSECURE_RAM) zephyr_library_sources( ${BOOT_DIR}/zephyr/nrf_cleanup.c ) diff --git a/boot/zephyr/include/nrf_cleanup.h b/boot/zephyr/include/nrf_cleanup.h index 6b04cedfe..9e87e13f5 100644 --- a/boot/zephyr/include/nrf_cleanup.h +++ b/boot/zephyr/include/nrf_cleanup.h @@ -16,4 +16,9 @@ */ void nrf_cleanup_peripheral(void); +/** + * Perform cleanup of non-secure RAM that may have been used by MCUBoot. + */ +void nrf_cleanup_ns_ram(void); + #endif diff --git a/boot/zephyr/main.c b/boot/zephyr/main.c index d3d88980a..8f846ac05 100644 --- a/boot/zephyr/main.c +++ b/boot/zephyr/main.c @@ -144,7 +144,7 @@ K_SEM_DEFINE(boot_log_sem, 1, 1); #include #endif -#if CONFIG_MCUBOOT_NRF_CLEANUP_PERIPHERAL +#if CONFIG_MCUBOOT_NRF_CLEANUP_PERIPHERAL || CONFIG_MCUBOOT_NRF_CLEANUP_NONSECURE_RAM #include #endif @@ -214,6 +214,9 @@ static void do_boot(struct boot_rsp *rsp) #if CONFIG_MCUBOOT_NRF_CLEANUP_PERIPHERAL nrf_cleanup_peripheral(); #endif +#if CONFIG_MCUBOOT_NRF_CLEANUP_NONSECURE_RAM && defined(PM_SRAM_NONSECURE_NAME) + nrf_cleanup_ns_ram(); +#endif #if CONFIG_MCUBOOT_CLEANUP_ARM_CORE cleanup_arm_nvic(); /* cleanup NVIC registers */ diff --git a/boot/zephyr/nrf_cleanup.c b/boot/zephyr/nrf_cleanup.c index 5bab26b24..051705ec9 100644 --- a/boot/zephyr/nrf_cleanup.c +++ b/boot/zephyr/nrf_cleanup.c @@ -5,9 +5,8 @@ */ #include -#if defined(NRF_UARTE0) || defined(NRF_UARTE1) - #include -#endif +#include +#include #if defined(NRF_RTC0) || defined(NRF_RTC1) || defined(NRF_RTC2) #include #endif @@ -20,6 +19,15 @@ #include +#if USE_PARTITION_MANAGER +#include +#endif + +#if defined(NRF_UARTE0) || defined(NRF_UARTE1) || defined(NRF_UARTE20) || \ + defined(NRF_UARTE30) +#define NRF_UARTE_CLEANUP +#endif + #define NRF_UARTE_SUBSCRIBE_CONF_OFFS offsetof(NRF_UARTE_Type, SUBSCRIBE_STARTRX) #define NRF_UARTE_SUBSCRIBE_CONF_SIZE (offsetof(NRF_UARTE_Type, EVENTS_CTS) -\ NRF_UARTE_SUBSCRIBE_CONF_OFFS) @@ -37,6 +45,23 @@ static inline void nrf_cleanup_rtc(NRF_RTC_Type * rtc_reg) } #endif +#if defined(NRF_UARTE_CLEANUP) +static NRF_UARTE_Type *nrf_uarte_to_clean[] = { +#if defined(NRF_UARTE0) + NRF_UARTE0, +#endif +#if defined(NRF_UARTE1) + NRF_UARTE1, +#endif +#if defined(NRF_UARTE20) + NRF_UARTE20, +#endif +#if defined(NRF_UARTE30) + NRF_UARTE30, +#endif +}; +#endif + static void nrf_cleanup_clock(void) { nrf_clock_int_disable(NRF_CLOCK, 0xFFFFFFFF); @@ -53,26 +78,31 @@ void nrf_cleanup_peripheral(void) #if defined(NRF_RTC2) nrf_cleanup_rtc(NRF_RTC2); #endif -#if defined(NRF_UARTE0) - nrf_uarte_disable(NRF_UARTE0); - nrf_uarte_int_disable(NRF_UARTE0, 0xFFFFFFFF); -#if defined(NRF_DPPIC) - /* Clear all SUBSCRIBE configurations. */ - memset((uint8_t *)NRF_UARTE0 + NRF_UARTE_SUBSCRIBE_CONF_OFFS, 0, NRF_UARTE_SUBSCRIBE_CONF_SIZE); - /* Clear all PUBLISH configurations. */ - memset((uint8_t *)NRF_UARTE0 + NRF_UARTE_PUBLISH_CONF_OFFS, 0, NRF_UARTE_PUBLISH_CONF_SIZE); -#endif -#endif -#if defined(NRF_UARTE1) - nrf_uarte_disable(NRF_UARTE1); - nrf_uarte_int_disable(NRF_UARTE1, 0xFFFFFFFF); + +#if defined(NRF_UARTE_CLEANUP) + for (int i = 0; i < sizeof(nrf_uarte_to_clean) / sizeof(nrf_uarte_to_clean[0]); ++i) { + NRF_UARTE_Type *current = nrf_uarte_to_clean[i]; + + nrfy_uarte_int_disable(current, 0xFFFFFFFF); + nrfy_uarte_int_uninit(current); + nrfy_uarte_task_trigger(current, NRF_UARTE_TASK_STOPRX); + + nrfy_uarte_event_clear(current, NRF_UARTE_EVENT_RXSTARTED); + nrfy_uarte_event_clear(current, NRF_UARTE_EVENT_ENDRX); + nrfy_uarte_event_clear(current, NRF_UARTE_EVENT_RXTO); + nrfy_uarte_disable(current); + #if defined(NRF_DPPIC) - /* Clear all SUBSCRIBE configurations. */ - memset((uint8_t *)NRF_UARTE1 + NRF_UARTE_SUBSCRIBE_CONF_OFFS, 0, NRF_UARTE_SUBSCRIBE_CONF_SIZE); - /* Clear all PUBLISH configurations. */ - memset((uint8_t *)NRF_UARTE1 + NRF_UARTE_PUBLISH_CONF_OFFS, 0, NRF_UARTE_PUBLISH_CONF_SIZE); + /* Clear all SUBSCRIBE configurations. */ + memset((uint8_t *)current + NRF_UARTE_SUBSCRIBE_CONF_OFFS, 0, + NRF_UARTE_SUBSCRIBE_CONF_SIZE); + /* Clear all PUBLISH configurations. */ + memset((uint8_t *)current + NRF_UARTE_PUBLISH_CONF_OFFS, 0, + NRF_UARTE_PUBLISH_CONF_SIZE); #endif + } #endif + #if defined(NRF_PPI) nrf_ppi_channels_disable_all(NRF_PPI); #endif @@ -81,3 +111,12 @@ void nrf_cleanup_peripheral(void) #endif nrf_cleanup_clock(); } + +#if USE_PARTITION_MANAGER \ + && defined(CONFIG_ARM_TRUSTZONE_M) \ + && defined(PM_SRAM_NONSECURE_NAME) +void nrf_cleanup_ns_ram(void) +{ + memset((void *) PM_SRAM_NONSECURE_ADDRESS, 0, PM_SRAM_NONSECURE_SIZE); +} +#endif From c1cf5e424057fea8a317bccd88dff62888453ccf Mon Sep 17 00:00:00 2001 From: Christian Taedcke Date: Thu, 10 Feb 2022 15:37:49 +0100 Subject: [PATCH 034/420] [nrf noup] loader: Fix reading reset addr to support ext flash MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit When mcuboot_secondary is on external flash, the image header cannot dircetly be accessed via secondary_fa->fa_off. Instead the provided function boot_img_hdr() is used now. Additionally a similar issue is present when trying to read the address of the reset handler. For this flash_area_read() is used now. With this patch is possible to have the update partiton mcuboot_secondary on external flash and update a updatable bootloader (mcuboot) in s0 and/or s1. Signed-off-by: Christian Taedcke Signed-off-by: Ole Sæther Signed-off-by: Sigvart Hovland Signed-off-by: Dominik Ermel (cherry picked from commit 36440318f0e7d7285a8ed89fe445273f294d220f) --- boot/bootutil/src/loader.c | 25 +++++++++++++++---------- 1 file changed, 15 insertions(+), 10 deletions(-) diff --git a/boot/bootutil/src/loader.c b/boot/bootutil/src/loader.c index 9a6f3015c..3e77a0cfb 100644 --- a/boot/bootutil/src/loader.c +++ b/boot/bootutil/src/loader.c @@ -1315,10 +1315,9 @@ boot_validated_swap_type(struct boot_loader_state *state, #if defined(PM_S1_ADDRESS) || defined(CONFIG_SOC_NRF5340_CPUAPP) const struct flash_area *secondary_fa = BOOT_IMG_AREA(state, BOOT_SECONDARY_SLOT); - struct image_header *hdr = (struct image_header *)secondary_fa->fa_off; - uint32_t vtable_addr = 0; - uint32_t *vtable = 0; + struct image_header *hdr = boot_img_hdr(state, BOOT_SECONDARY_SLOT); uint32_t reset_addr = 0; + int rc = 0; /* Patch needed for NCS. Since image 0 (the app) and image 1 (the other * B1 slot S0 or S1) share the same secondary slot, we need to check * whether the update candidate in the secondary slot is intended for @@ -1328,16 +1327,19 @@ boot_validated_swap_type(struct boot_loader_state *state, */ if (hdr->ih_magic == IMAGE_MAGIC) { - vtable_addr = (uint32_t)hdr + hdr->ih_hdr_size; - vtable = (uint32_t *)(vtable_addr); - reset_addr = vtable[1]; + rc = flash_area_read(secondary_fa, hdr->ih_hdr_size + + sizeof(uint32_t), &reset_addr, + sizeof(reset_addr)); + if (rc != 0) { + return BOOT_SWAP_TYPE_FAIL; + } #ifdef PM_S1_ADDRESS #ifdef PM_CPUNET_B0N_ADDRESS if(reset_addr < PM_CPUNET_B0N_ADDRESS) #endif { const struct flash_area *primary_fa; - int rc = flash_area_open(flash_area_id_from_multi_image_slot( + rc = flash_area_open(flash_area_id_from_multi_image_slot( BOOT_CURR_IMG(state), BOOT_PRIMARY_SLOT), &primary_fa); @@ -1373,16 +1375,19 @@ boot_validated_swap_type(struct boot_loader_state *state, upgrade_valid = true; } -#if defined(CONFIG_SOC_NRF5340_CPUAPP) && defined(PM_CPUNET_B0N_ADDRESS) +#if defined(CONFIG_SOC_NRF5340_CPUAPP) && defined(PM_CPUNET_B0N_ADDRESS) \ + && !defined(CONFIG_NRF53_MULTI_IMAGE_UPDATE) /* If the update is valid, and it targets the network core: perform the * update and indicate to the caller of this function that no update is * available */ if (upgrade_valid && reset_addr > PM_CPUNET_B0N_ADDRESS) { + struct image_header *hdr = (struct image_header *)secondary_fa->fa_off; + uint32_t vtable_addr = (uint32_t)hdr + hdr->ih_hdr_size; + uint32_t *net_core_fw_addr = (uint32_t *)(vtable_addr); uint32_t fw_size = hdr->ih_img_size; - BOOT_LOG_INF("Starting network core update"); - int rc = pcd_network_core_update(vtable, fw_size); + rc = pcd_network_core_update(net_core_fw_addr, fw_size); if (rc != 0) { swap_type = BOOT_SWAP_TYPE_FAIL; From 1ec17e963cb21d6978792e2aaf504838f20b52d8 Mon Sep 17 00:00:00 2001 From: Dominik Ermel Date: Fri, 22 Sep 2023 21:31:08 +0000 Subject: [PATCH 035/420] [nrf noup] loader: Do not check reset vector for XIP image The XIP image, 2, does not have reset vector. Signed-off-by: Dominik Ermel (cherry picked from commit 1e991723c85e8ef8d6df432f196ec75c89caf78c) --- boot/bootutil/src/loader.c | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/boot/bootutil/src/loader.c b/boot/bootutil/src/loader.c index 3e77a0cfb..6f33cad72 100644 --- a/boot/bootutil/src/loader.c +++ b/boot/bootutil/src/loader.c @@ -1206,6 +1206,16 @@ boot_validate_slot(struct boot_loader_state *state, int slot, * overwriting an application written to the incorrect slot. * This feature is only supported by ARM platforms. */ +#if MCUBOOT_IMAGE_NUMBER >= 3 + /* Currently the MCUboot can be configured for up to 3 image, where image number 2 is + * designated for XIP, where it is the second part of image stored in slots of image + * 0. This part of image is not bootable, as the XIP setup is done by the app in + * image 0 slot, and it does not carry the reset vector. + */ + if (fap == state->imgs[2][BOOT_SECONDARY_SLOT].area) { + goto out; + } +#endif if (fap == BOOT_IMG_AREA(state, BOOT_SECONDARY_SLOT)) { const struct flash_area *pri_fa = BOOT_IMG_AREA(state, BOOT_PRIMARY_SLOT); struct image_header *secondary_hdr = boot_img_hdr(state, slot); From c8d8f5a48cf1f17bad6cbc41dfd83a5f584ab005 Mon Sep 17 00:00:00 2001 From: Jamie McCrae Date: Mon, 18 Sep 2023 13:47:00 +0100 Subject: [PATCH 036/420] [nrf noup] zephyr: Add RAM flash configuration to cache for sysbuild Puts the flash simulation configurtion into cache variables that can be used by other applications and CMake code to know specifics on the simulated flash details Signed-off-by: Jamie McCrae (cherry picked from commit e92f17c3ecc644b2fc813e7440186c95d34aa965) --- boot/zephyr/CMakeLists.txt | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/boot/zephyr/CMakeLists.txt b/boot/zephyr/CMakeLists.txt index 424cf1315..3a94315f8 100644 --- a/boot/zephyr/CMakeLists.txt +++ b/boot/zephyr/CMakeLists.txt @@ -725,3 +725,14 @@ zephyr_library_sources( ${BOOT_DIR}/zephyr/nrf_cleanup.c ) endif() + +if(SYSBUILD AND CONFIG_PCD_APP) + # Sysbuild requires details of the RAM flash device are stored to the cache of MCUboot so + # that they can be read when running partition manager + dt_nodelabel(ram_flash_dev NODELABEL flash_sim0) + dt_reg_addr(ram_flash_addr PATH ${ram_flash_dev}) + dt_reg_size(ram_flash_size PATH ${ram_flash_dev}) + + set(RAM_FLASH_ADDR "${ram_flash_addr}" CACHE STRING "" FORCE) + set(RAM_FLASH_SIZE "${ram_flash_size}" CACHE STRING "" FORCE) +endif() From d07555bf0439aeec7c15609c46a85a06fa9be807 Mon Sep 17 00:00:00 2001 From: Sigvart Hovland Date: Tue, 17 Oct 2023 11:28:09 +0200 Subject: [PATCH 037/420] [nrf noup] zephyr: Boot even if EXT_ABI is not provided This removes the `return;` to ensure that the application is booted even if EXT_ABI is not provided to the application because it does not include `FW_INFO`. Added a bit more description to the error messages when FW_INFO is not found and EXT_ABI is not able to be provided to the next image. Ref. NCSDK-24132 Signed-off-by: Sigvart Hovland (cherry picked from commit 2d5f4f9291d7e70beabd726ba63ab31afd916ce4) --- boot/zephyr/main.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/boot/zephyr/main.c b/boot/zephyr/main.c index 8f846ac05..72d0e72ff 100644 --- a/boot/zephyr/main.c +++ b/boot/zephyr/main.c @@ -201,13 +201,16 @@ static void do_boot(struct boot_rsp *rsp) #endif #if defined(CONFIG_FW_INFO) && !defined(CONFIG_EXT_API_PROVIDE_EXT_API_UNUSED) - bool provided = fw_info_ext_api_provide(fw_info_find((uint32_t)vt), true); + const struct fw_info *firmware_info = fw_info_find((uint32_t) vt); + bool provided = fw_info_ext_api_provide(firmware_info, true); #ifdef PM_S0_ADDRESS /* Only fail if the immutable bootloader is present. */ if (!provided) { - BOOT_LOG_ERR("Failed to provide EXT_APIs\n"); - return; + if (firmware_info == NULL) { + BOOT_LOG_WRN("Unable to find firmware info structure in %p", vt); + } + BOOT_LOG_ERR("Failed to provide EXT_APIs to %p", vt); } #endif #endif From 420ac794db054e9a3bae31c6627d5b08920de0ed Mon Sep 17 00:00:00 2001 From: Sigvart Hovland Date: Wed, 27 Sep 2023 15:18:04 +0200 Subject: [PATCH 038/420] =?UTF-8?q?[nrf=20noup]=C2=A0loader:=20Add=20firmw?= =?UTF-8?q?are=20version=20check=20downgrade=20prevention?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit For nRF53, the only existing version number metadata is stored in the `firmware_info` structure in the network core. This utilizes PCD to read out the version number and compares it against the version number found in the secondary slot for the network core. Ref. NCSDK-21379 Signed-off-by: Sigvart Hovland (cherry picked from commit 42e8551d6bdcb50388ab7aac51d44aa12cf8ef55) --- boot/bootutil/src/loader.c | 22 +++++++++++++++++++--- 1 file changed, 19 insertions(+), 3 deletions(-) diff --git a/boot/bootutil/src/loader.c b/boot/bootutil/src/loader.c index 6f33cad72..a14215c28 100644 --- a/boot/bootutil/src/loader.c +++ b/boot/bootutil/src/loader.c @@ -52,6 +52,10 @@ #if defined(CONFIG_SOC_NRF5340_CPUAPP) && defined(PM_CPUNET_B0N_ADDRESS) && defined(CONFIG_PCD_APP) #include +#ifdef CONFIG_PCD_READ_NETCORE_APP_VERSION +#include +int pcd_version_cmp_net(const struct flash_area *fap, struct image_header *hdr); +#endif #endif #ifdef MCUBOOT_ENC_IMAGES @@ -1159,9 +1163,21 @@ boot_validate_slot(struct boot_loader_state *state, int slot, int rc; /* Check if version of secondary slot is sufficient */ - rc = boot_version_cmp( - &boot_img_hdr(state, BOOT_SECONDARY_SLOT)->ih_ver, - &boot_img_hdr(state, BOOT_PRIMARY_SLOT)->ih_ver); + +#if defined(CONFIG_SOC_NRF5340_CPUAPP) && defined(CONFIG_NRF53_MULTI_IMAGE_UPDATE) \ + && defined(CONFIG_PCD_APP) && defined(CONFIG_PCD_READ_NETCORE_APP_VERSION) + if (BOOT_CURR_IMG(state) == 1) { + rc = pcd_version_cmp_net(fap, boot_img_hdr(state, BOOT_SECONDARY_SLOT)); + } else { + rc = boot_version_cmp( + &boot_img_hdr(state, BOOT_SECONDARY_SLOT)->ih_ver, + &boot_img_hdr(state, BOOT_PRIMARY_SLOT)->ih_ver); + } +#else + rc = boot_version_cmp( + &boot_img_hdr(state, BOOT_SECONDARY_SLOT)->ih_ver, + &boot_img_hdr(state, BOOT_PRIMARY_SLOT)->ih_ver); +#endif if (rc < 0 && boot_check_header_erased(state, BOOT_PRIMARY_SLOT)) { BOOT_LOG_ERR("insufficient version in secondary slot"); boot_scramble_slot(fap, slot); From 937e0f6d566c43d7b2445bd74b586ef28fb64aff Mon Sep 17 00:00:00 2001 From: Nikodem Kastelik Date: Mon, 9 Oct 2023 09:55:57 +0200 Subject: [PATCH 039/420] [nrf noup] boards: thingy53: disable GPIO ISR support Change disables GPIO interrupt support in Zephyr GPIO driver, which is not obligatory for MCUboot. This is needed to reduce memory footprint. Signed-off-by: Nikodem Kastelik (cherry picked from commit 87d7d74c0ce9e97fad3e58ade37730e1a1c40348) --- boot/zephyr/boards/thingy53_nrf5340_cpuapp.conf | 1 + 1 file changed, 1 insertion(+) diff --git a/boot/zephyr/boards/thingy53_nrf5340_cpuapp.conf b/boot/zephyr/boards/thingy53_nrf5340_cpuapp.conf index 93be36738..d68509786 100644 --- a/boot/zephyr/boards/thingy53_nrf5340_cpuapp.conf +++ b/boot/zephyr/boards/thingy53_nrf5340_cpuapp.conf @@ -21,6 +21,7 @@ CONFIG_UART_LINE_CTRL=y # MCUBoot serial CONFIG_GPIO=y +CONFIG_GPIO_NRFX_INTERRUPT=n CONFIG_MCUBOOT_SERIAL=y CONFIG_MCUBOOT_SERIAL_DIRECT_IMAGE_UPLOAD=y CONFIG_BOOT_SERIAL_CDC_ACM=y From 470e7cb53980087f835c81eedd2b4c11180fde41 Mon Sep 17 00:00:00 2001 From: Sigvart Hovland Date: Tue, 30 Mar 2021 22:45:17 +0200 Subject: [PATCH 040/420] [nrf noup] loader: work-around for multi-image builds Seems multi-image dependencies are not supported for multi-image in NCS yet. This is a workaround which reverts some lines to restore previous MCUboot behavior, so that Immutable bootloader + MCUBoot type builds will work. Ref. NCSDK-8681 Signed-off-by: Sigvart Hovland (cherry picked from commit 663f42e61280b07dbb9083cb3c6713e15737c502) --- boot/bootutil/src/loader.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/boot/bootutil/src/loader.c b/boot/bootutil/src/loader.c index a14215c28..a596f8f56 100644 --- a/boot/bootutil/src/loader.c +++ b/boot/bootutil/src/loader.c @@ -547,7 +547,7 @@ boot_verify_dependencies(struct boot_loader_state *state) if (rc == 0) { /* All dependencies've been satisfied, continue with next image. */ BOOT_CURR_IMG(state)++; - } else { + } else if (rc == BOOT_EBADIMAGE) { /* Cannot upgrade due to non-met dependencies, so disable all * image upgrades. */ @@ -556,7 +556,10 @@ boot_verify_dependencies(struct boot_loader_state *state) BOOT_SWAP_TYPE(state) = BOOT_SWAP_TYPE_NONE; } break; - } + } else { + /* Other error happened, images are inconsistent */ + return rc; + } } return rc; } From 1ca64e93ce9f7484e9033989ff7dbfcacab0864b Mon Sep 17 00:00:00 2001 From: Jamie McCrae Date: Thu, 31 Aug 2023 08:58:31 +0100 Subject: [PATCH 041/420] [nrf noup] loader: Fix missing PCD define check Fixes a missing PCD define check, an image might have the network core partition layout set but if PCD support is not enabled then it should not assume that PCD support is part of mcuboot. Signed-off-by: Jamie McCrae (cherry picked from commit cd1fe3442bdf141bfe9e8925553aed562173ebb6) --- boot/bootutil/src/loader.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/boot/bootutil/src/loader.c b/boot/bootutil/src/loader.c index a596f8f56..301e528c4 100644 --- a/boot/bootutil/src/loader.c +++ b/boot/bootutil/src/loader.c @@ -1405,7 +1405,7 @@ boot_validated_swap_type(struct boot_loader_state *state, } #if defined(CONFIG_SOC_NRF5340_CPUAPP) && defined(PM_CPUNET_B0N_ADDRESS) \ - && !defined(CONFIG_NRF53_MULTI_IMAGE_UPDATE) + && !defined(CONFIG_NRF53_MULTI_IMAGE_UPDATE) && defined(CONFIG_PCD_APP) /* If the update is valid, and it targets the network core: perform the * update and indicate to the caller of this function that no update is * available @@ -1433,7 +1433,8 @@ boot_validated_swap_type(struct boot_loader_state *state, swap_type = BOOT_SWAP_TYPE_NONE; } } -#endif /* CONFIG_SOC_NRF5340_CPUAPP */ +#endif /* CONFIG_SOC_NRF5340_CPUAPP && PM_CPUNET_B0N_ADDRESS && + !CONFIG_NRF53_MULTI_IMAGE_UPDATE && CONFIG_PCD_APP */ } return swap_type; From 75073fd88eca232c350c9a0af3c859815cb1ca4e Mon Sep 17 00:00:00 2001 From: Sigvart Hovland Date: Wed, 31 May 2023 14:41:13 +0200 Subject: [PATCH 042/420] [nrf noup] boot: Add support for NSIB and multi-image This adds support for using both NSIB and the multi-image configuration in MCUboot. Before this was not possible due to upgradable bootloader support through NSIB was using the `UPDATEABLE_IMAGE_NUMBER` configuration to update the updateable bootloader. In this commit we change from using `FLASH_AREA_IMAGE_PRIMARY` to get the flash area ID to using the bootloader state where we set the flash area ID of the free updatable bootloader slot if the image is intended for this slot. Ref. NCSDK-19223 Ref. NCSDK-23305 Signed-off-by: Sigvart Hovland (cherry picked from commit a39070a2e56d9bbdf0772f298253a7b1592c1158) --- boot/bootutil/src/loader.c | 42 +++++++++++++++++++------ boot/zephyr/include/sysflash/sysflash.h | 19 +++++++++-- 2 files changed, 50 insertions(+), 11 deletions(-) diff --git a/boot/bootutil/src/loader.c b/boot/bootutil/src/loader.c index 301e528c4..d30470e48 100644 --- a/boot/bootutil/src/loader.c +++ b/boot/bootutil/src/loader.c @@ -1256,6 +1256,11 @@ boot_validate_slot(struct boot_loader_state *state, int slot, if (BOOT_CURR_IMG(state) == 1) { min_addr = PM_CPUNET_APP_ADDRESS; max_addr = PM_CPUNET_APP_ADDRESS + PM_CPUNET_APP_SIZE; +#ifdef PM_S1_ADDRESS + } else if (BOOT_CURR_IMG(state) == 0) { + min_addr = PM_S0_ADDRESS; + max_addr = pri_fa->fa_off + pri_fa->fa_size; +#endif } else #endif { @@ -1369,18 +1374,37 @@ boot_validated_swap_type(struct boot_loader_state *state, { const struct flash_area *primary_fa; rc = flash_area_open(flash_area_id_from_multi_image_slot( - BOOT_CURR_IMG(state), - BOOT_PRIMARY_SLOT), - &primary_fa); - + BOOT_CURR_IMG(state), BOOT_PRIMARY_SLOT), + &primary_fa); if (rc != 0) { return BOOT_SWAP_TYPE_FAIL; } - /* Get start and end of primary slot for current image */ - if (reset_addr < primary_fa->fa_off || - reset_addr > (primary_fa->fa_off + primary_fa->fa_size)) { - /* The image in the secondary slot is not intended for this image - */ + + /* Check start and end of primary slot for current image */ + if (reset_addr < primary_fa->fa_off) { +#if defined(CONFIG_SOC_NRF5340_CPUAPP) && defined(CONFIG_NRF53_MULTI_IMAGE_UPDATE) + const struct flash_area *nsib_fa; + + /* NSIB upgrade slot */ + rc = flash_area_open((uint32_t)_image_1_primary_slot_id, + &nsib_fa); + + if (rc != 0) { + return BOOT_SWAP_TYPE_FAIL; + } + + /* Image is placed before Primary and within the NSIB slot */ + if (reset_addr > nsib_fa->fa_off + && reset_addr < (nsib_fa->fa_off + nsib_fa->fa_size)) { + /* Set primary to be NSIB upgrade slot */ + BOOT_IMG_AREA(state, 0) = nsib_fa; + } +#else + return BOOT_SWAP_TYPE_NONE; +#endif + + } else if (reset_addr > (primary_fa->fa_off + primary_fa->fa_size)) { + /* The image in the secondary slot is not intended for any */ return BOOT_SWAP_TYPE_NONE; } } diff --git a/boot/zephyr/include/sysflash/sysflash.h b/boot/zephyr/include/sysflash/sysflash.h index 7112f9baa..f1ef4100e 100644 --- a/boot/zephyr/include/sysflash/sysflash.h +++ b/boot/zephyr/include/sysflash/sysflash.h @@ -23,9 +23,24 @@ /* If B0 is present then two bootloaders are present, and we must use * a single secondary slot for both primary slots. */ -#ifdef PM_B0_ADDRESS - +#if defined(PM_B0_ADDRESS) extern uint32_t _image_1_primary_slot_id[]; +#endif +#if defined(PM_B0_ADDRESS) && defined(CONFIG_NRF53_MULTI_IMAGE_UPDATE) +#define FLASH_AREA_IMAGE_PRIMARY(x) \ + ((x == 0) ? \ + PM_MCUBOOT_PRIMARY_ID : \ + (x == 1) ? \ + PM_MCUBOOT_PRIMARY_1_ID : \ + 255 ) + +#define FLASH_AREA_IMAGE_SECONDARY(x) \ + ((x == 0) ? \ + PM_MCUBOOT_SECONDARY_ID: \ + (x == 1) ? \ + PM_MCUBOOT_SECONDARY_1_ID: \ + 255 ) +#elif defined(PM_B0_ADDRESS) #define FLASH_AREA_IMAGE_PRIMARY(x) \ ((x == 0) ? \ From bc86df639008e27e8296b9253079944c689eacad Mon Sep 17 00:00:00 2001 From: Dominik Ermel Date: Thu, 10 Aug 2023 17:32:48 +0000 Subject: [PATCH 043/420] [nrf noup] sysflash: Move partition manager definitions to pm_sysflash.h Making sysflash.h and pm_sysflash.h more readable. Signed-off-by: Dominik Ermel (cherry picked from commit 8d4a62b09bd2bf155a3ea3ae993743694d5838da) --- boot/zephyr/include/sysflash/pm_sysflash.h | 92 ++++++++++++++++++++++ boot/zephyr/include/sysflash/sysflash.h | 90 ++------------------- 2 files changed, 97 insertions(+), 85 deletions(-) create mode 100644 boot/zephyr/include/sysflash/pm_sysflash.h diff --git a/boot/zephyr/include/sysflash/pm_sysflash.h b/boot/zephyr/include/sysflash/pm_sysflash.h new file mode 100644 index 000000000..377291e8b --- /dev/null +++ b/boot/zephyr/include/sysflash/pm_sysflash.h @@ -0,0 +1,92 @@ +/* + * Copyright (c) 2023 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: LicenseRef-Nordic-5-Clause + */ + +#ifndef __PM_SYSFLASH_H__ +#define __PM_SYSFLASH_H__ +/* Blocking the __SYSFLASH_H__ */ +#define __SYSFLASH_H__ + +#include +#include + +#ifndef CONFIG_SINGLE_APPLICATION_SLOT + +#if (MCUBOOT_IMAGE_NUMBER == 1) + +#define FLASH_AREA_IMAGE_PRIMARY(x) PM_MCUBOOT_PRIMARY_ID +#define FLASH_AREA_IMAGE_SECONDARY(x) PM_MCUBOOT_SECONDARY_ID + +#elif (MCUBOOT_IMAGE_NUMBER == 2) + +/* If B0 is present then two bootloaders are present, and we must use + * a single secondary slot for both primary slots. + */ +#if defined(PM_B0_ADDRESS) +extern uint32_t _image_1_primary_slot_id[]; +#endif +#if defined(PM_B0_ADDRESS) && defined(CONFIG_NRF53_MULTI_IMAGE_UPDATE) +#define FLASH_AREA_IMAGE_PRIMARY(x) \ + ((x == 0) ? \ + PM_MCUBOOT_PRIMARY_ID : \ + (x == 1) ? \ + PM_MCUBOOT_PRIMARY_1_ID : \ + 255 ) + +#define FLASH_AREA_IMAGE_SECONDARY(x) \ + ((x == 0) ? \ + PM_MCUBOOT_SECONDARY_ID: \ + (x == 1) ? \ + PM_MCUBOOT_SECONDARY_1_ID: \ + 255 ) +#elif defined(PM_B0_ADDRESS) + +#define FLASH_AREA_IMAGE_PRIMARY(x) \ + ((x == 0) ? \ + PM_MCUBOOT_PRIMARY_ID : \ + (x == 1) ? \ + (uint32_t)_image_1_primary_slot_id : \ + 255 ) + +#define FLASH_AREA_IMAGE_SECONDARY(x) \ + ((x == 0) ? \ + PM_MCUBOOT_SECONDARY_ID: \ + (x == 1) ? \ + PM_MCUBOOT_SECONDARY_ID: \ + 255 ) +#else + +#define FLASH_AREA_IMAGE_PRIMARY(x) \ + ((x == 0) ? \ + PM_MCUBOOT_PRIMARY_ID : \ + (x == 1) ? \ + PM_MCUBOOT_PRIMARY_1_ID : \ + 255 ) + +#define FLASH_AREA_IMAGE_SECONDARY(x) \ + ((x == 0) ? \ + PM_MCUBOOT_SECONDARY_ID: \ + (x == 1) ? \ + PM_MCUBOOT_SECONDARY_1_ID: \ + 255 ) + +#endif /* PM_B0_ADDRESS */ + +#endif +#define FLASH_AREA_IMAGE_SCRATCH PM_MCUBOOT_SCRATCH_ID + +#else /* CONFIG_SINGLE_APPLICATION_SLOT */ + +#define FLASH_AREA_IMAGE_PRIMARY(x) PM_MCUBOOT_PRIMARY_ID +#define FLASH_AREA_IMAGE_SECONDARY(x) PM_MCUBOOT_PRIMARY_ID +/* NOTE: Scratch parition is not used by single image DFU but some of + * functions in common files reference it, so the definitions has been + * provided to allow compilation of common units. + */ +#define FLASH_AREA_IMAGE_SCRATCH 0 + +#endif /* CONFIG_SINGLE_APPLICATION_SLOT */ + +#endif /* __PM_SYSFLASH_H__ */ diff --git a/boot/zephyr/include/sysflash/sysflash.h b/boot/zephyr/include/sysflash/sysflash.h index f1ef4100e..3c3638d7f 100644 --- a/boot/zephyr/include/sysflash/sysflash.h +++ b/boot/zephyr/include/sysflash/sysflash.h @@ -4,93 +4,15 @@ * SPDX-License-Identifier: Apache-2.0 */ -#ifndef __SYSFLASH_H__ -#define __SYSFLASH_H__ - #if USE_PARTITION_MANAGER -#include -#include - -#ifndef CONFIG_SINGLE_APPLICATION_SLOT - -#if (MCUBOOT_IMAGE_NUMBER == 1) - -#define FLASH_AREA_IMAGE_PRIMARY(x) PM_MCUBOOT_PRIMARY_ID -#define FLASH_AREA_IMAGE_SECONDARY(x) PM_MCUBOOT_SECONDARY_ID - -#elif (MCUBOOT_IMAGE_NUMBER == 2) - -/* If B0 is present then two bootloaders are present, and we must use - * a single secondary slot for both primary slots. - */ -#if defined(PM_B0_ADDRESS) -extern uint32_t _image_1_primary_slot_id[]; -#endif -#if defined(PM_B0_ADDRESS) && defined(CONFIG_NRF53_MULTI_IMAGE_UPDATE) -#define FLASH_AREA_IMAGE_PRIMARY(x) \ - ((x == 0) ? \ - PM_MCUBOOT_PRIMARY_ID : \ - (x == 1) ? \ - PM_MCUBOOT_PRIMARY_1_ID : \ - 255 ) - -#define FLASH_AREA_IMAGE_SECONDARY(x) \ - ((x == 0) ? \ - PM_MCUBOOT_SECONDARY_ID: \ - (x == 1) ? \ - PM_MCUBOOT_SECONDARY_1_ID: \ - 255 ) -#elif defined(PM_B0_ADDRESS) - -#define FLASH_AREA_IMAGE_PRIMARY(x) \ - ((x == 0) ? \ - PM_MCUBOOT_PRIMARY_ID : \ - (x == 1) ? \ - (uint32_t)_image_1_primary_slot_id : \ - 255 ) - -#define FLASH_AREA_IMAGE_SECONDARY(x) \ - ((x == 0) ? \ - PM_MCUBOOT_SECONDARY_ID: \ - (x == 1) ? \ - PM_MCUBOOT_SECONDARY_ID: \ - 255 ) -#else - -#define FLASH_AREA_IMAGE_PRIMARY(x) \ - ((x == 0) ? \ - PM_MCUBOOT_PRIMARY_ID : \ - (x == 1) ? \ - PM_MCUBOOT_PRIMARY_1_ID : \ - 255 ) - -#define FLASH_AREA_IMAGE_SECONDARY(x) \ - ((x == 0) ? \ - PM_MCUBOOT_SECONDARY_ID: \ - (x == 1) ? \ - PM_MCUBOOT_SECONDARY_1_ID: \ - 255 ) - -#endif /* PM_B0_ADDRESS */ - +/* Blocking the rest of the file */ +#define __SYSFLASH_H__ +#include #endif -#define FLASH_AREA_IMAGE_SCRATCH PM_MCUBOOT_SCRATCH_ID - -#else /* CONFIG_SINGLE_APPLICATION_SLOT */ - -#define FLASH_AREA_IMAGE_PRIMARY(x) PM_MCUBOOT_PRIMARY_ID -#define FLASH_AREA_IMAGE_SECONDARY(x) PM_MCUBOOT_PRIMARY_ID -/* NOTE: Scratch parition is not used by single image DFU but some of - * functions in common files reference it, so the definitions has been - * provided to allow compilation of common units. - */ -#define FLASH_AREA_IMAGE_SCRATCH 0 -#endif /* CONFIG_SINGLE_APPLICATION_SLOT */ - -#else +#ifndef __SYSFLASH_H__ +#define __SYSFLASH_H__ -#include #include #include #include @@ -149,6 +71,4 @@ static inline uint32_t __flash_area_ids_for_slot(int img, int slot) #endif /* CONFIG_SINGLE_APPLICATION_SLOT */ -#endif /* USE_PARTITION_MANAGER */ - #endif /* __SYSFLASH_H__ */ From 3b3298de5dae0055bf95c2bf62a7f45a8c36b950 Mon Sep 17 00:00:00 2001 From: Dominik Ermel Date: Fri, 11 Aug 2023 12:29:13 +0000 Subject: [PATCH 044/420] [nrf noup] sysflash: Add support for three images The commit modifies pm_sysflash.h to add support for three application images. Ref. NCSDK-19223 Signed-off-by: Dominik Ermel Signed-off-by: Sigvart Hovland (cherry picked from commit b1ef2487ce616483c914b168595d2188eb2a2bd0) --- boot/zephyr/include/sysflash/pm_sysflash.h | 82 ++++++++++++---------- 1 file changed, 45 insertions(+), 37 deletions(-) diff --git a/boot/zephyr/include/sysflash/pm_sysflash.h b/boot/zephyr/include/sysflash/pm_sysflash.h index 377291e8b..db60ddd03 100644 --- a/boot/zephyr/include/sysflash/pm_sysflash.h +++ b/boot/zephyr/include/sysflash/pm_sysflash.h @@ -11,37 +11,19 @@ #include #include +#include #ifndef CONFIG_SINGLE_APPLICATION_SLOT -#if (MCUBOOT_IMAGE_NUMBER == 1) - -#define FLASH_AREA_IMAGE_PRIMARY(x) PM_MCUBOOT_PRIMARY_ID -#define FLASH_AREA_IMAGE_SECONDARY(x) PM_MCUBOOT_SECONDARY_ID - -#elif (MCUBOOT_IMAGE_NUMBER == 2) - +#if (MCUBOOT_IMAGE_NUMBER == 2) && defined(PM_B0_ADDRESS) /* If B0 is present then two bootloaders are present, and we must use * a single secondary slot for both primary slots. */ -#if defined(PM_B0_ADDRESS) extern uint32_t _image_1_primary_slot_id[]; -#endif -#if defined(PM_B0_ADDRESS) && defined(CONFIG_NRF53_MULTI_IMAGE_UPDATE) -#define FLASH_AREA_IMAGE_PRIMARY(x) \ - ((x == 0) ? \ - PM_MCUBOOT_PRIMARY_ID : \ - (x == 1) ? \ - PM_MCUBOOT_PRIMARY_1_ID : \ - 255 ) +#endif /* (MCUBOOT_IMAGE_NUMBER == 2 && defined(PM_B0_ADDRESS) */ -#define FLASH_AREA_IMAGE_SECONDARY(x) \ - ((x == 0) ? \ - PM_MCUBOOT_SECONDARY_ID: \ - (x == 1) ? \ - PM_MCUBOOT_SECONDARY_1_ID: \ - 255 ) -#elif defined(PM_B0_ADDRESS) +#if (MCUBOOT_IMAGE_NUMBER == 2) && defined(PM_B0_ADDRESS) && \ + !defined(CONFIG_NRF53_MULTI_IMAGE_UPDATE) #define FLASH_AREA_IMAGE_PRIMARY(x) \ ((x == 0) ? \ @@ -56,26 +38,52 @@ extern uint32_t _image_1_primary_slot_id[]; (x == 1) ? \ PM_MCUBOOT_SECONDARY_ID: \ 255 ) + +#else /* MCUBOOT_IMAGE_NUMBER == 2) && defined(PM_B0_ADDRESS) && \ + * !defined(CONFIG_NRF53_MULTI_IMAGE_UPDATE) + */ + +/* Each pair of slots is separated by , and there is no terminating character */ +#define FLASH_AREA_IMAGE_0_SLOTS PM_MCUBOOT_PRIMARY_ID, PM_MCUBOOT_SECONDARY_ID +#define FLASH_AREA_IMAGE_1_SLOTS PM_MCUBOOT_PRIMARY_1_ID, PM_MCUBOOT_SECONDARY_1_ID +#define FLASH_AREA_IMAGE_2_SLOTS PM_MCUBOOT_PRIMARY_2_ID, PM_MCUBOOT_SECONDARY_2_ID + +#if (MCUBOOT_IMAGE_NUMBER == 1) +#define ALL_AVAILABLE_SLOTS FLASH_AREA_IMAGE_0_SLOTS +#elif (MCUBOOT_IMAGE_NUMBER == 2) +#define ALL_AVAILABLE_SLOTS FLASH_AREA_IMAGE_0_SLOTS, \ + FLASH_AREA_IMAGE_1_SLOTS +#elif (MCUBOOT_IMAGE_NUMBER == 3) +#define ALL_AVAILABLE_SLOTS FLASH_AREA_IMAGE_0_SLOTS, \ + FLASH_AREA_IMAGE_1_SLOTS, \ + FLASH_AREA_IMAGE_2_SLOTS #else +#error Unsupported number of images +#endif -#define FLASH_AREA_IMAGE_PRIMARY(x) \ - ((x == 0) ? \ - PM_MCUBOOT_PRIMARY_ID : \ - (x == 1) ? \ - PM_MCUBOOT_PRIMARY_1_ID : \ - 255 ) +static inline uint32_t __flash_area_ids_for_slot(int img, int slot) +{ + static const int all_slots[] = { + ALL_AVAILABLE_SLOTS + }; + return all_slots[img * 2 + slot]; +}; -#define FLASH_AREA_IMAGE_SECONDARY(x) \ - ((x == 0) ? \ - PM_MCUBOOT_SECONDARY_ID: \ - (x == 1) ? \ - PM_MCUBOOT_SECONDARY_1_ID: \ - 255 ) +#undef FLASH_AREA_IMAGE_0_SLOTS +#undef FLASH_AREA_IMAGE_1_SLOTS +#undef FLASH_AREA_IMAGE_2_SLOTS +#undef ALL_AVAILABLE_SLOTS -#endif /* PM_B0_ADDRESS */ +#define FLASH_AREA_IMAGE_PRIMARY(x) __flash_area_ids_for_slot(x, 0) +#define FLASH_AREA_IMAGE_SECONDARY(x) __flash_area_ids_for_slot(x, 1) +#if !defined(CONFIG_BOOT_SWAP_USING_MOVE) +#define FLASH_AREA_IMAGE_SCRATCH PM_MCUBOOT_SCRATCH_ID #endif -#define FLASH_AREA_IMAGE_SCRATCH PM_MCUBOOT_SCRATCH_ID + +#endif /* MCUBOOT_IMAGE_NUMBER == 2) && defined(PM_B0_ADDRESS) && \ + * !defined(CONFIG_NRF53_MULTI_IMAGE_UPDATE) + */ #else /* CONFIG_SINGLE_APPLICATION_SLOT */ From bd97f58190446c2a6e6a6e1a273b38a0ae848273 Mon Sep 17 00:00:00 2001 From: Andrzej Puzdrowski Date: Thu, 15 Feb 2024 16:47:25 +0100 Subject: [PATCH 045/420] [nrf noup] loader: introduced cleanup of unusable secondary slot Added procedure which clean-up content of all the secondary slot which contains valid header but couldn't be assigned to any of supported primary images. This behavior is needed when configuration allows to use one secondary slot for collecting image for multiple primary slots. Signed-off-by: Andrzej Puzdrowski (cherry picked from commit 6dca0d27546f4b1e808f82646b77522c57fd6d6f) --- boot/bootutil/src/loader.c | 90 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 90 insertions(+) diff --git a/boot/bootutil/src/loader.c b/boot/bootutil/src/loader.c index d30470e48..ab26dcdbf 100644 --- a/boot/bootutil/src/loader.c +++ b/boot/bootutil/src/loader.c @@ -1329,6 +1329,87 @@ boot_update_security_counter(struct boot_loader_state *state, int slot, int hdr_ } #endif /* MCUBOOT_HW_ROLLBACK_PROT */ +#if defined(CONFIG_MCUBOOT_CLEANUP_UNUSABLE_SECONDARY) &&\ +(defined(PM_S1_ADDRESS) || defined(CONFIG_SOC_NRF5340_CPUAPP)) + +#define SEC_SLOT_VIRGIN 0 +#define SEC_SLOT_TOUCHED 1 +#define SEC_SLOT_ASSIGNED 2 + +#if (MCUBOOT_IMAGE_NUMBER == 2) && defined(PM_B0_ADDRESS) && \ + !defined(CONFIG_NRF53_MULTI_IMAGE_UPDATE) +/* This configuration is peculiar - the one physical secondary slot is + * mocking two logical secondary + */ +#define SEC_SLOT_PHYSICAL_CNT 1 +#else +#define SEC_SLOT_PHYSICAL_CNT MCUBOOT_IMAGE_NUMBER +#endif + +static uint8_t sec_slot_assignmnet[SEC_SLOT_PHYSICAL_CNT] = {0}; + +static inline void sec_slot_touch(struct boot_loader_state *state) +{ + uint8_t idx = (SEC_SLOT_PHYSICAL_CNT == 1) ? 0 : BOOT_CURR_IMG(state); + + if (SEC_SLOT_VIRGIN == sec_slot_assignmnet[idx]) { + sec_slot_assignmnet[idx] = SEC_SLOT_TOUCHED; + } +} + +static inline void sec_slot_mark_assigned(struct boot_loader_state *state) +{ + uint8_t idx = (SEC_SLOT_PHYSICAL_CNT == 1) ? 0 : BOOT_CURR_IMG(state); + + sec_slot_assignmnet[idx] = SEC_SLOT_ASSIGNED; +} + +/** + * Cleanu up all secondary slot which couldn't be assigned to any primary slot. + * + * This function erases content of each secondary slot which contains valid + * header but couldn't be assigned to any of supported primary images. + * + * This function is supposed to be called after boot_validated_swap_type() + * iterates over all the images in context_boot_go(). + */ +static void sec_slot_cleanup_if_unusable(void) +{ + uint8_t idx; + + for (idx = 0; idx < SEC_SLOT_PHYSICAL_CNT; idx++) { + if (SEC_SLOT_TOUCHED == sec_slot_assignmnet[idx]) { + const struct flash_area *secondary_fa; + int rc; + + rc = flash_area_open(flash_area_id_from_multi_image_slot(idx, BOOT_SECONDARY_SLOT), + &secondary_fa); + if (!rc) { + rc = flash_area_erase(secondary_fa, 0, secondary_fa->fa_size); + if (!rc) { + BOOT_LOG_ERR("Cleaned-up secondary slot of %d. image.", idx); + } + } + + if (rc) { + BOOT_LOG_ERR("Can not cleanup secondary slot of %d. image.", idx); + } + } + } +} +#else +static inline void sec_slot_touch(struct boot_loader_state *state) +{ +} +static inline void sec_slot_mark_assigned(struct boot_loader_state *state) +{ +} +static inline void sec_slot_cleanup_if_unusable(void) +{ +} +#endif /* defined(CONFIG_MCUBOOT_CLEANUP_UNUSABLE_SECONDARY) &&\ + defined(PM_S1_ADDRESS) || defined(CONFIG_SOC_NRF5340_CPUAPP) */ + #if !defined(MCUBOOT_DIRECT_XIP) && !defined(MCUBOOT_RAM_LOAD) /** * Determines which swap operation to perform, if any. If it is determined @@ -1367,6 +1448,9 @@ boot_validated_swap_type(struct boot_loader_state *state, if (rc != 0) { return BOOT_SWAP_TYPE_FAIL; } + + sec_slot_touch(state); + #ifdef PM_S1_ADDRESS #ifdef PM_CPUNET_B0N_ADDRESS if(reset_addr < PM_CPUNET_B0N_ADDRESS) @@ -1401,6 +1485,7 @@ boot_validated_swap_type(struct boot_loader_state *state, } #else return BOOT_SWAP_TYPE_NONE; + #endif } else if (reset_addr > (primary_fa->fa_off + primary_fa->fa_size)) { @@ -1409,7 +1494,9 @@ boot_validated_swap_type(struct boot_loader_state *state, } } #endif /* PM_S1_ADDRESS */ + sec_slot_mark_assigned(state); } + #endif /* PM_S1_ADDRESS || CONFIG_SOC_NRF5340_CPUAPP */ swap_type = boot_swap_type_multi(BOOT_CURR_IMG(state)); @@ -2682,6 +2769,9 @@ context_boot_go(struct boot_loader_state *state, struct boot_rsp *rsp) } } + /* cleanup secondary slots which were recognized unusable*/ + sec_slot_cleanup_if_unusable(); + #if (BOOT_IMAGE_NUMBER > 1) if (has_upgrade) { /* Iterate over all the images and verify whether the image dependencies From 271e50509bfb6d9625f25b4b6f8ccd991799e93e Mon Sep 17 00:00:00 2001 From: Grzegorz Chwierut Date: Fri, 17 May 2024 18:25:07 +0200 Subject: [PATCH 046/420] [nrf noup] loader: remove cleanup for direct xip mode Move ifdefs just to not add code for cleanup unusable slot when direct xip mode is enabled to avoid warnings. Signed-off-by: Grzegorz Chwierut (cherry picked from commit b525a7791c837e04ebdf3dda67d3741a45a8c550) --- boot/bootutil/src/loader.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/boot/bootutil/src/loader.c b/boot/bootutil/src/loader.c index ab26dcdbf..7c379a7b2 100644 --- a/boot/bootutil/src/loader.c +++ b/boot/bootutil/src/loader.c @@ -1329,6 +1329,8 @@ boot_update_security_counter(struct boot_loader_state *state, int slot, int hdr_ } #endif /* MCUBOOT_HW_ROLLBACK_PROT */ +#if !defined(MCUBOOT_DIRECT_XIP) && !defined(MCUBOOT_RAM_LOAD) + #if defined(CONFIG_MCUBOOT_CLEANUP_UNUSABLE_SECONDARY) &&\ (defined(PM_S1_ADDRESS) || defined(CONFIG_SOC_NRF5340_CPUAPP)) @@ -1410,7 +1412,6 @@ static inline void sec_slot_cleanup_if_unusable(void) #endif /* defined(CONFIG_MCUBOOT_CLEANUP_UNUSABLE_SECONDARY) &&\ defined(PM_S1_ADDRESS) || defined(CONFIG_SOC_NRF5340_CPUAPP) */ -#if !defined(MCUBOOT_DIRECT_XIP) && !defined(MCUBOOT_RAM_LOAD) /** * Determines which swap operation to perform, if any. If it is determined * that a swap operation is required, the image in the secondary slot is checked From f5f382f4fe888e560e0db125fded0ef49ba6e7a7 Mon Sep 17 00:00:00 2001 From: Maximilian Deubel Date: Tue, 12 Mar 2024 12:30:52 +0100 Subject: [PATCH 047/420] [nrf noup] boards: thingy91x: enable serial recovery This patch disbales MCUBoot logging and enables serial recovery for the Thingy:91. Signed-off-by: Maximilian Deubel Signed-off-by: Bernt Johan Damslora (cherry picked from commit 654a1e3143542234c9931cd52b692cab632b1cc1) --- boot/zephyr/boards/thingy91x_nrf5340_cpuapp.conf | 10 ++++++++-- boot/zephyr/boards/thingy91x_nrf9151.conf | 9 +++++++++ 2 files changed, 17 insertions(+), 2 deletions(-) diff --git a/boot/zephyr/boards/thingy91x_nrf5340_cpuapp.conf b/boot/zephyr/boards/thingy91x_nrf5340_cpuapp.conf index 72dfa7fca..37c7e95b1 100644 --- a/boot/zephyr/boards/thingy91x_nrf5340_cpuapp.conf +++ b/boot/zephyr/boards/thingy91x_nrf5340_cpuapp.conf @@ -32,7 +32,7 @@ CONFIG_USB_COMPOSITE_DEVICE=y CONFIG_USB_MASS_STORAGE=n CONFIG_USB_DEVICE_MANUFACTURER="Nordic Semiconductor" CONFIG_USB_DEVICE_VID=0x1915 -CONFIG_USB_DEVICE_PID=0x520F +CONFIG_USB_DEVICE_PID=0x910A CONFIG_BOOT_SERIAL_BOOT_MODE=y @@ -49,6 +49,12 @@ CONFIG_FLASH_SIMULATOR_DOUBLE_WRITES=y CONFIG_FLASH_SIMULATOR_STATS=n CONFIG_BOOT_IMAGE_ACCESS_HOOKS=y -CONFIG_MCUBOOT_SERIAL_DIRECT_IMAGE_UPLOAD=y +# Makes it possible to update the network core using the flash simulator CONFIG_NRF53_RECOVERY_NETWORK_CORE=y + +CONFIG_MCUBOOT_SERIAL_DIRECT_IMAGE_UPLOAD=y +CONFIG_BOOT_SERIAL_IMG_GRP_IMAGE_STATE=y + +# Skip checks on the secondary image to make it possible to update MCUBoot on S1/S0 +CONFIG_MCUBOOT_VERIFY_IMG_ADDRESS=n diff --git a/boot/zephyr/boards/thingy91x_nrf9151.conf b/boot/zephyr/boards/thingy91x_nrf9151.conf index 33cd3301c..2efe1e170 100644 --- a/boot/zephyr/boards/thingy91x_nrf9151.conf +++ b/boot/zephyr/boards/thingy91x_nrf9151.conf @@ -6,3 +6,12 @@ CONFIG_SPI_NOR=y CONFIG_SPI_NOR_FLASH_LAYOUT_PAGE_SIZE=4096 CONFIG_SPI_NOR_SFDP_DEVICETREE=y CONFIG_MULTITHREADING=y + +# Disable Zephyr console and use UART for MCUboot serial recovery instead +CONFIG_CONSOLE=n +CONFIG_CONSOLE_HANDLER=n +CONFIG_UART_CONSOLE=n +CONFIG_MCUBOOT_SERIAL=y + +CONFIG_MCUBOOT_SERIAL_DIRECT_IMAGE_UPLOAD=y +CONFIG_BOOT_SERIAL_IMG_GRP_IMAGE_STATE=y From b8f6a06206675d1c51009215aeb9c7b1b348d45f Mon Sep 17 00:00:00 2001 From: Robert Lubos Date: Fri, 17 May 2024 14:14:54 +0200 Subject: [PATCH 048/420] [nrf noup] boot: zephyr: Disable boot banner if NCS_BOOT_BANNER is used Mcuboot's boot banner should not be used if NCS boot banner is enabled. Signed-off-by: Robert Lubos (cherry picked from commit 86ab04b79ab4494186d2c0b2577d7fd67459f0ce) --- boot/zephyr/Kconfig | 1 + 1 file changed, 1 insertion(+) diff --git a/boot/zephyr/Kconfig b/boot/zephyr/Kconfig index c37911f8e..c42928d1f 100644 --- a/boot/zephyr/Kconfig +++ b/boot/zephyr/Kconfig @@ -1078,6 +1078,7 @@ config BOOT_DISABLE_CACHES config MCUBOOT_BOOT_BANNER bool "Use MCUboot boot banner" depends on BOOT_BANNER + depends on !NCS_BOOT_BANNER depends on "$(APP_VERSION_EXTENDED_STRING)" != "" default y help From 8949a6a34d4522447069a6630866f136132e3ac3 Mon Sep 17 00:00:00 2001 From: Andrzej Puzdrowski Date: Mon, 27 May 2024 13:59:49 +0200 Subject: [PATCH 049/420] [nrf noup] boot/zephyr: fix fw_info search By the upstream patch the vt get now the pointer to the copy of the arm_vector instead of original. This patch fixes address of the firmware which is to be taken by the fw_info_find. Signed-off-by: Andrzej Puzdrowski (cherry picked from commit d4e6c3e1b5c9f6a1efcff7a26be1fa7ddeb8fc1b) --- boot/zephyr/main.c | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/boot/zephyr/main.c b/boot/zephyr/main.c index 72d0e72ff..64e11c3c6 100644 --- a/boot/zephyr/main.c +++ b/boot/zephyr/main.c @@ -201,7 +201,14 @@ static void do_boot(struct boot_rsp *rsp) #endif #if defined(CONFIG_FW_INFO) && !defined(CONFIG_EXT_API_PROVIDE_EXT_API_UNUSED) - const struct fw_info *firmware_info = fw_info_find((uint32_t) vt); + uintptr_t fw_start_addr; + + rc = flash_device_base(rsp->br_flash_dev_id, &fw_start_addr); + assert(rc == 0); + + fw_start_addr += rsp->br_image_off + rsp->br_hdr->ih_hdr_size; + + const struct fw_info *firmware_info = fw_info_find(fw_start_addr); bool provided = fw_info_ext_api_provide(firmware_info, true); #ifdef PM_S0_ADDRESS From c41b4a88811a7feeefea7146d44da3ecf9bafc24 Mon Sep 17 00:00:00 2001 From: Jamie McCrae Date: Tue, 11 Jun 2024 12:32:51 +0100 Subject: [PATCH 050/420] [nrf noup] boot: zephyr: Add NCS boot banner Adds a boot banner which shows as MCUboot Signed-off-by: Jamie McCrae (cherry picked from commit 4b3d6ab014bca42f57b25bfc1843a473f11cb898) --- boot/zephyr/prj.conf | 3 +++ 1 file changed, 3 insertions(+) diff --git a/boot/zephyr/prj.conf b/boot/zephyr/prj.conf index 6d538d1de..9ff1ba274 100644 --- a/boot/zephyr/prj.conf +++ b/boot/zephyr/prj.conf @@ -36,3 +36,6 @@ CONFIG_CBPRINTF_NANO=y ### Use the minimal C library to reduce flash usage CONFIG_MINIMAL_LIBC=y CONFIG_NRF_RTC_TIMER_USER_CHAN_COUNT=0 + +# NCS boot banner +CONFIG_NCS_APPLICATION_BOOT_BANNER_STRING="MCUboot" From bf143850d06f24d83c51bc904034e3ccdf22290c Mon Sep 17 00:00:00 2001 From: Andrzej Puzdrowski Date: Thu, 13 Jun 2024 16:34:55 +0200 Subject: [PATCH 051/420] [nrf noup] boot/../loader: skip downgrade prevention for s1/s0 This patch introduces skip on checking downgrade for s1/s0 upgrade image (chain-loaded by NSIB). which is used for upgrade MCUboot instance itself. Reason is that sdk-mcuboot has not access to semantic version of its own image. I also shouldn't touch HW counter used for hardware downgrade prevention for the application image (which was the case). HW counters for s0/s1 image are owned by NSIB because its role is to prevnt dongrades of s0/s1 MCUboot. Signed-off-by: Andrzej Puzdrowski (cherry picked from commit 101d9c06702a400e5f6522fd49d828476d38d590) --- boot/bootutil/include/bootutil/security_cnt.h | 9 ++ boot/bootutil/src/image_validate.c | 20 +++++ boot/bootutil/src/loader.c | 83 +++++++++++++++++++ 3 files changed, 112 insertions(+) diff --git a/boot/bootutil/include/bootutil/security_cnt.h b/boot/bootutil/include/bootutil/security_cnt.h index e1562d2e9..7e1389618 100644 --- a/boot/bootutil/include/bootutil/security_cnt.h +++ b/boot/bootutil/include/bootutil/security_cnt.h @@ -39,6 +39,15 @@ extern "C" { */ fih_ret boot_nv_security_counter_init(void); +/** + * Checks if the specified image should have a security counter present on it or not + * + * @param image_index Index of the image to check (from 0). + * + * @return FIH_SUCCESS if security counter should be present; FIH_FAILURE if otherwise + */ +fih_ret boot_nv_image_should_have_security_counter(uint32_t image_index); + /** * Reads the stored value of a given image's security counter. * diff --git a/boot/bootutil/src/image_validate.c b/boot/bootutil/src/image_validate.c index 17193a63d..ade67cc4b 100644 --- a/boot/bootutil/src/image_validate.c +++ b/boot/bootutil/src/image_validate.c @@ -540,6 +540,15 @@ bootutil_img_validate(struct boot_loader_state *state, fih_int security_cnt = fih_int_encode(INT_MAX); uint32_t img_security_cnt = 0; FIH_DECLARE(security_counter_valid, FIH_FAILURE); + FIH_DECLARE(security_counter_should_be_present, FIH_FAILURE); + + FIH_CALL(boot_nv_image_should_have_security_counter, security_counter_should_be_present, + image_index); + if (FIH_NOT_EQ(security_counter_should_be_present, FIH_SUCCESS) && + FIH_NOT_EQ(security_counter_should_be_present, FIH_FAILURE)) { + rc = -1; + goto out; + } #endif BOOT_LOG_DBG("bootutil_img_validate: flash area %p", fap); @@ -736,6 +745,10 @@ bootutil_img_validate(struct boot_loader_state *state, goto out; } + if (FIH_EQ(security_counter_should_be_present, FIH_FAILURE)) { + goto skip_security_counter_read; + } + FIH_CALL(boot_nv_security_counter_get, fih_rc, image_index, &security_cnt); if (FIH_NOT_EQ(fih_rc, FIH_SUCCESS)) { @@ -755,6 +768,7 @@ bootutil_img_validate(struct boot_loader_state *state, /* The image's security counter has been successfully verified. */ security_counter_valid = fih_rc; +skip_security_counter_read: break; } #endif /* MCUBOOT_HW_ROLLBACK_PROT */ @@ -774,10 +788,16 @@ bootutil_img_validate(struct boot_loader_state *state, FIH_SET(fih_rc, valid_signature); #endif #ifdef MCUBOOT_HW_ROLLBACK_PROT + if (FIH_EQ(security_counter_should_be_present, FIH_FAILURE)) { + goto skip_security_counter_check; + } + if (FIH_NOT_EQ(security_counter_valid, FIH_SUCCESS)) { rc = -1; goto out; } + +skip_security_counter_check: #endif out: diff --git a/boot/bootutil/src/loader.c b/boot/bootutil/src/loader.c index 7c379a7b2..355ebf46c 100644 --- a/boot/bootutil/src/loader.c +++ b/boot/bootutil/src/loader.c @@ -71,6 +71,9 @@ int pcd_version_cmp_net(const struct flash_area *fap, struct image_header *hdr); BOOT_LOG_MODULE_DECLARE(mcuboot); static struct boot_loader_state boot_data; +#ifdef PM_S1_ADDRESS +static bool owner_nsib[BOOT_IMAGE_NUMBER] = {false}; +#endif #if defined(MCUBOOT_SERIAL_IMG_GRP_SLOT_INFO) || defined(MCUBOOT_DATA_SHARING) static struct image_max_size image_max_sizes[BOOT_IMAGE_NUMBER] = {0}; @@ -1290,6 +1293,38 @@ boot_validate_slot(struct boot_loader_state *state, int slot, } #ifdef MCUBOOT_HW_ROLLBACK_PROT +/** + * Checks if the specified image should have a security counter present on it or not + * + * @param image_index Index of the image to check. + * + * @return true if security counter should be present; false if otherwise + */ +fih_ret boot_nv_image_should_have_security_counter(uint32_t image_index) +{ +#if defined(PM_S1_ADDRESS) + if (owner_nsib[image_index]) { + /* + * Downgrade prevention on S0/S1 image is managed by NSIB, which is a software (not + * hardware) check + */ + return FIH_FAILURE; + } +#endif + +#if defined(CONFIG_SOC_NRF5340_CPUAPP) && CONFIG_MCUBOOT_NETWORK_CORE_IMAGE_NUMBER != -1 + if (image_index == CONFIG_MCUBOOT_NETWORK_CORE_IMAGE_NUMBER) { + /* + * Downgrade prevention on network core image is managed by NSIB which is a software (not + * hardware) check + */ + return FIH_FAILURE; + } +#endif + + return FIH_SUCCESS; +} + /** * Updates the stored security counter value with the image's security counter * value which resides in the given slot, only if it's greater than the stored @@ -1311,6 +1346,26 @@ boot_update_security_counter(struct boot_loader_state *state, int slot, int hdr_ uint32_t img_security_cnt; int rc; +#if defined(PM_S1_ADDRESS) + if (owner_nsib[BOOT_CURR_IMG(state)]) { + /* + * Downgrade prevention on S0/S1 image is managed by NSIB which is a software (not + * hardware) check + */ + return 0; + } +#endif + +#if defined(CONFIG_SOC_NRF5340_CPUAPP) && CONFIG_MCUBOOT_NETWORK_CORE_IMAGE_NUMBER != -1 + if (BOOT_CURR_IMG(state) == CONFIG_MCUBOOT_NETWORK_CORE_IMAGE_NUMBER) { + /* + * Downgrade prevention on network core image is managed by NSIB which is a software (not + * hardware) check + */ + return 0; + } +#endif + fap = BOOT_IMG_AREA(state, slot); assert(fap != NULL); @@ -1427,6 +1482,9 @@ boot_validated_swap_type(struct boot_loader_state *state, int swap_type; FIH_DECLARE(fih_rc, FIH_FAILURE); bool upgrade_valid = false; +#if defined(PM_S1_ADDRESS) + owner_nsib[BOOT_CURR_IMG(state)] = false; +#endif #if defined(PM_S1_ADDRESS) || defined(CONFIG_SOC_NRF5340_CPUAPP) const struct flash_area *secondary_fa = @@ -1483,6 +1541,7 @@ boot_validated_swap_type(struct boot_loader_state *state, && reset_addr < (nsib_fa->fa_off + nsib_fa->fa_size)) { /* Set primary to be NSIB upgrade slot */ BOOT_IMG_AREA(state, 0) = nsib_fa; + owner_nsib[BOOT_CURR_IMG(state)] = true; } #else return BOOT_SWAP_TYPE_NONE; @@ -1493,6 +1552,10 @@ boot_validated_swap_type(struct boot_loader_state *state, /* The image in the secondary slot is not intended for any */ return BOOT_SWAP_TYPE_NONE; } + + if ((primary_fa->fa_off == PM_S0_ADDRESS) || (primary_fa->fa_off == PM_S1_ADDRESS)) { + owner_nsib[BOOT_CURR_IMG(state)] = true; + } } #endif /* PM_S1_ADDRESS */ sec_slot_mark_assigned(state); @@ -2631,6 +2694,26 @@ check_downgrade_prevention(struct boot_loader_state *state) uint32_t security_counter[2]; int rc; +#if defined(PM_S1_ADDRESS) + if (owner_nsib[BOOT_CURR_IMG(state)]) { + /* + * Downgrade prevention on S0/S1 image is managed by NSIB which is a software (not + * hardware) check + */ + return 0; + } +#endif + +#if defined(CONFIG_SOC_NRF5340_CPUAPP) && CONFIG_MCUBOOT_NETWORK_CORE_IMAGE_NUMBER != -1 + if (BOOT_CURR_IMG(state) == CONFIG_MCUBOOT_NETWORK_CORE_IMAGE_NUMBER) { + /* + * Downgrade prevention on network core image is managed by NSIB which is a software (not + * hardware) check + */ + return 0; + } +#endif + if (MCUBOOT_DOWNGRADE_PREVENTION_SECURITY_COUNTER) { /* If there was security no counter in slot 0, allow swap */ rc = bootutil_get_img_security_cnt(state, BOOT_PRIMARY_SLOT, From 674adc7d3f6508c9bfeb5f8af93ac489f93d25ce Mon Sep 17 00:00:00 2001 From: Andrzej Puzdrowski Date: Tue, 18 Jun 2024 17:35:41 +0200 Subject: [PATCH 052/420] [nrf noup] boot/../loader: reboot after updating s0/s1 As this is MCUboot updating itself, it should reboot the device so NSIB will chainload the update MCUboot Signed-off-by: Andrzej Puzdrowski (cherry picked from commit 6bb40d3a656aab1d61f222ad751aed49ff7fc5c3) --- boot/bootutil/src/loader.c | 10 ++++++++++ boot/zephyr/Kconfig | 1 + 2 files changed, 11 insertions(+) diff --git a/boot/bootutil/src/loader.c b/boot/bootutil/src/loader.c index 355ebf46c..f390d5aee 100644 --- a/boot/bootutil/src/loader.c +++ b/boot/bootutil/src/loader.c @@ -50,6 +50,10 @@ #include "bootutil/boot_hooks.h" #include "bootutil/mcuboot_status.h" +#ifdef __ZEPHYR__ +#include +#endif + #if defined(CONFIG_SOC_NRF5340_CPUAPP) && defined(PM_CPUNET_B0N_ADDRESS) && defined(CONFIG_PCD_APP) #include #ifdef CONFIG_PCD_READ_NETCORE_APP_VERSION @@ -2926,6 +2930,12 @@ context_boot_go(struct boot_loader_state *state, struct boot_rsp *rsp) rc = boot_perform_update(state, &bs); } assert(rc == 0); +#if defined(PM_S1_ADDRESS) && defined(CONFIG_REBOOT) + if (owner_nsib[BOOT_CURR_IMG(state)]) { + sys_reboot(SYS_REBOOT_COLD); + + } +#endif break; case BOOT_SWAP_TYPE_FAIL: diff --git a/boot/zephyr/Kconfig b/boot/zephyr/Kconfig index c42928d1f..89cda41bd 100644 --- a/boot/zephyr/Kconfig +++ b/boot/zephyr/Kconfig @@ -18,6 +18,7 @@ config MCUBOOT select MPU_ALLOW_FLASH_WRITE if ARM_MPU select USE_DT_CODE_PARTITION if HAS_FLASH_LOAD_OFFSET select MCUBOOT_BOOTUTIL_LIB + select REBOOT if SECURE_BOOT config BOOT_USE_MBEDTLS bool From 1f364bf2105226a6a12eb51ef25bce2a7fe1219b Mon Sep 17 00:00:00 2001 From: Jamie McCrae Date: Thu, 29 Aug 2024 12:41:37 +0100 Subject: [PATCH 053/420] [nrf noup] bootutil: loader: Fix netcore address checking Fixes an issues with wrongly checking the network core reset address Signed-off-by: Jamie McCrae (cherry picked from commit 71686796e8560f5a62db3cd1e8a03e4ca952beeb) --- boot/bootutil/src/loader.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/boot/bootutil/src/loader.c b/boot/bootutil/src/loader.c index f390d5aee..dabb562c9 100644 --- a/boot/bootutil/src/loader.c +++ b/boot/bootutil/src/loader.c @@ -1516,7 +1516,7 @@ boot_validated_swap_type(struct boot_loader_state *state, #ifdef PM_S1_ADDRESS #ifdef PM_CPUNET_B0N_ADDRESS - if(reset_addr < PM_CPUNET_B0N_ADDRESS) + if(!(reset_addr >= PM_CPUNET_APP_ADDRESS && reset_addr < PM_CPUNET_APP_END_ADDRESS)) #endif { const struct flash_area *primary_fa; @@ -1589,7 +1589,8 @@ boot_validated_swap_type(struct boot_loader_state *state, * update and indicate to the caller of this function that no update is * available */ - if (upgrade_valid && reset_addr > PM_CPUNET_B0N_ADDRESS) { + if (upgrade_valid && reset_addr >= PM_CPUNET_APP_ADDRESS && + reset_addr < PM_CPUNET_APP_END_ADDRESS) { struct image_header *hdr = (struct image_header *)secondary_fa->fa_off; uint32_t vtable_addr = (uint32_t)hdr + hdr->ih_hdr_size; uint32_t *net_core_fw_addr = (uint32_t *)(vtable_addr); From 62ddef300f7567b43014e8d8e71ca94e6bd4ef5c Mon Sep 17 00:00:00 2001 From: Andrzej Puzdrowski Date: Wed, 18 Sep 2024 12:28:37 +0200 Subject: [PATCH 054/420] [nrf noup] boards: nrf54l15dk: Disable FPROTECT FPROTECT is not suppored for nrf54l15dk. Signed-off-by: Andrzej Puzdrowski (cherry picked from commit 1c8ff2a3089233f4d8b17251f145e9844309ac6b) --- boot/zephyr/boards/nrf54l15dk_nrf54l15_cpuapp.conf | 3 +++ 1 file changed, 3 insertions(+) diff --git a/boot/zephyr/boards/nrf54l15dk_nrf54l15_cpuapp.conf b/boot/zephyr/boards/nrf54l15dk_nrf54l15_cpuapp.conf index c8fcd32c3..1dbd7c1ab 100644 --- a/boot/zephyr/boards/nrf54l15dk_nrf54l15_cpuapp.conf +++ b/boot/zephyr/boards/nrf54l15dk_nrf54l15_cpuapp.conf @@ -7,6 +7,9 @@ CONFIG_BOOT_MAX_IMG_SECTORS=256 # Ensure that the SPI NOR driver is disabled by default CONFIG_SPI_NOR=n +# TODO: below are not yet supported and need fixing +CONFIG_FPROTECT=n + CONFIG_BOOT_WATCHDOG_FEED=n # Ensure the fastest RRAM write operations From 2c64b71cf0f060786b0e821a6b94128d9f8e35e1 Mon Sep 17 00:00:00 2001 From: Sigvart Hovland Date: Thu, 14 Feb 2019 13:20:34 +0100 Subject: [PATCH 055/420] [nrf noup] boot: Add shared crypto for ECDSA and SHA MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Add functions for ecdsa_verify_secp256r1 and sha256 to use the shared crypto API * Add Kconfig and CMake variables for selecting shared crypto when using ecdsa * Add custom section to project for placing the API section in the correct location in flash * Add kconfig fragment for using external crypto Signed-off-by: Sigvart Hovland Signed-off-by: Martí Bolívar Signed-off-by: Emil Obalski Signed-off-by: Andrzej Puzdrowski Signed-off-by: Håkon Øye Amundsen Signed-off-by: Ioannis Glaropoulos Signed-off-by: Trond Einar Snekvik Signed-off-by: Georgios Vasilakis Signed-off-by: Johann Fischer Signed-off-by: Torsten Rasmussen Signed-off-by: Jamie McCrae Signed-off-by: Dominik Ermel Signed-off-by: Artur Hadasz (cherry picked from commit d3412b038b6a6195b0d1f5f6e5bdbd94a29f825a) --- boot/bootutil/include/bootutil/crypto/ecdsa.h | 66 +++++++++++++++++-- boot/bootutil/include/bootutil/crypto/sha.h | 32 +++++++++ boot/zephyr/CMakeLists.txt | 2 + boot/zephyr/external_crypto.conf | 20 ++++++ .../include/mcuboot_config/mcuboot_config.h | 2 + 5 files changed, 116 insertions(+), 6 deletions(-) create mode 100644 boot/zephyr/external_crypto.conf diff --git a/boot/bootutil/include/bootutil/crypto/ecdsa.h b/boot/bootutil/include/bootutil/crypto/ecdsa.h index 3b0541072..a5d0f8b1b 100644 --- a/boot/bootutil/include/bootutil/crypto/ecdsa.h +++ b/boot/bootutil/include/bootutil/crypto/ecdsa.h @@ -34,6 +34,7 @@ #if (defined(MCUBOOT_USE_TINYCRYPT) + \ defined(MCUBOOT_USE_CC310) + \ + defined(MCUBOOT_USE_NRF_EXTERNAL_CRYPTO) + \ defined(MCUBOOT_USE_PSA_OR_MBED_TLS)) != 1 #error "One crypto backend must be defined: either CC310/TINYCRYPT/MBED_TLS/PSA_CRYPTO" #endif @@ -70,12 +71,18 @@ #include "bootutil/sign_key.h" #include "common.h" +#if defined(MCUBOOT_USE_NRF_EXTERNAL_CRYPTO) + #include + #define NUM_ECC_BYTES (256 / 8) +#endif /* MCUBOOT_USE_NRF_EXTERNAL_CRYPTO */ + #ifdef __cplusplus extern "C" { #endif #if (defined(MCUBOOT_USE_TINYCRYPT) || defined(MCUBOOT_USE_MBED_TLS) || \ - defined(MCUBOOT_USE_CC310)) && !defined(MCUBOOT_USE_PSA_CRYPTO) + defined(MCUBOOT_USE_CC310) || defined(MCUBOOT_USE_NRF_EXTERNAL_CRYPTO)) \ + && !defined(MCUBOOT_USE_PSA_CRYPTO) /* * Declaring these like this adds NULL termination. */ @@ -127,8 +134,7 @@ static int bootutil_import_key(uint8_t **cp, uint8_t *end) } #endif /* (MCUBOOT_USE_TINYCRYPT || MCUBOOT_USE_MBED_TLS || MCUBOOT_USE_CC310) && !MCUBOOT_USE_PSA_CRYPTO */ -#if defined(MCUBOOT_USE_TINYCRYPT) -#ifndef MCUBOOT_ECDSA_NEED_ASN1_SIG +#ifndef MCUBOOT_USE_PSA_CRYPTO /* * cp points to ASN1 string containing an integer. * Verify the tag, and that the length is 32 bytes. Helper function. @@ -178,8 +184,9 @@ static int bootutil_decode_sig(uint8_t signature[NUM_ECC_BYTES * 2], uint8_t *cp } return 0; } -#endif /* not MCUBOOT_ECDSA_NEED_ASN1_SIG */ +#endif /* !MCUBOOT_USE_PSA_CRYPTO */ +#if defined(MCUBOOT_USE_TINYCRYPT) typedef uintptr_t bootutil_ecdsa_context; static inline void bootutil_ecdsa_init(bootutil_ecdsa_context *ctx) { @@ -248,8 +255,12 @@ static inline int bootutil_ecdsa_verify(bootutil_ecdsa_context *ctx, { (void)ctx; (void)pk_len; - (void)sig_len; (void)hash_len; + uint8_t dsig[2 * NUM_ECC_BYTES]; + + if (bootutil_decode_sig(dsig, sig, sig + sig_len)) { + return -1; + } /* Only support uncompressed keys. */ if (pk[0] != 0x04) { @@ -257,7 +268,7 @@ static inline int bootutil_ecdsa_verify(bootutil_ecdsa_context *ctx, } pk++; - return cc310_ecdsa_verify_secp256r1(hash, pk, sig, BOOTUTIL_CRYPTO_ECDSA_P256_HASH_SIZE); + return cc310_ecdsa_verify_secp256r1(hash, pk, dsig, BOOTUTIL_CRYPTO_ECDSA_P256_HASH_SIZE); } static inline int bootutil_ecdsa_parse_public_key(bootutil_ecdsa_context *ctx, @@ -613,6 +624,49 @@ static inline int bootutil_ecdsa_parse_public_key(bootutil_ecdsa_context *ctx, #endif /* MCUBOOT_USE_MBED_TLS */ +#if defined(MCUBOOT_USE_NRF_EXTERNAL_CRYPTO) +typedef uintptr_t bootutil_ecdsa_context; +static inline void bootutil_ecdsa_init(bootutil_ecdsa_context *ctx) +{ + (void)ctx; +} + +static inline void bootutil_ecdsa_drop(bootutil_ecdsa_context *ctx) +{ + (void)ctx; +} + +static inline int bootutil_ecdsa_verify(bootutil_ecdsa_context *ctx, + uint8_t *pk, size_t pk_len, + uint8_t *hash, size_t hash_len, + uint8_t *sig, size_t sig_len) +{ + (void)ctx; + (void)pk_len; + (void)hash_len; + uint8_t dsig[2 * NUM_ECC_BYTES]; + + if (bootutil_decode_sig(dsig, sig, sig + sig_len)) { + return -1; + } + + /* Only support uncompressed keys. */ + if (pk[0] != 0x04) { + return -1; + } + pk++; + + return bl_secp256r1_validate(hash, BOOTUTIL_CRYPTO_ECDSA_P256_HASH_SIZE, pk, dsig); +} + +static inline int bootutil_ecdsa_parse_public_key(bootutil_ecdsa_context *ctx, + uint8_t **cp,uint8_t *end) +{ + (void)ctx; + return bootutil_import_key(cp, end); +} +#endif /* MCUBOOT_USE_NRF_EXTERNAL_CRYPTO */ + #ifdef __cplusplus } #endif diff --git a/boot/bootutil/include/bootutil/crypto/sha.h b/boot/bootutil/include/bootutil/crypto/sha.h index 6a009ff95..b83a3ec40 100644 --- a/boot/bootutil/include/bootutil/crypto/sha.h +++ b/boot/bootutil/include/bootutil/crypto/sha.h @@ -30,6 +30,7 @@ #if (defined(MCUBOOT_USE_PSA_OR_MBED_TLS) + \ defined(MCUBOOT_USE_TINYCRYPT) + \ + defined(MCUBOOT_USE_NRF_EXTERNAL_CRYPTO) + \ defined(MCUBOOT_USE_CC310)) != 1 #error "One crypto backend must be defined: either CC310/MBED_TLS/TINYCRYPT/PSA_CRYPTO" #endif @@ -270,6 +271,37 @@ static inline int bootutil_sha_finish(bootutil_sha_context *ctx, } #endif /* MCUBOOT_USE_CC310 */ +#if defined(MCUBOOT_USE_NRF_EXTERNAL_CRYPTO) + +#include + +typedef bl_sha256_ctx_t bootutil_sha_context; + +static inline void bootutil_sha_init(bootutil_sha_context *ctx) +{ + bl_sha256_init(ctx); +} + +static inline void bootutil_sha_drop(bootutil_sha_context *ctx) +{ + (void)ctx; +} + +static inline int bootutil_sha_update(bootutil_sha_context *ctx, + const void *data, + uint32_t data_len) +{ + return bl_sha256_update(ctx, data, data_len); +} + +static inline int bootutil_sha_finish(bootutil_sha_context *ctx, + uint8_t *output) +{ + bl_sha256_finalize(ctx, output); + return 0; +} +#endif /* MCUBOOT_USE_NRF_EXTERNAL_CRYPTO */ + #ifdef __cplusplus } #endif diff --git a/boot/zephyr/CMakeLists.txt b/boot/zephyr/CMakeLists.txt index 3a94315f8..1db4ed270 100644 --- a/boot/zephyr/CMakeLists.txt +++ b/boot/zephyr/CMakeLists.txt @@ -215,6 +215,8 @@ if(CONFIG_BOOT_SIGNATURE_TYPE_ECDSA_P256 OR CONFIG_BOOT_ENCRYPT_EC256) zephyr_library_sources(${NRF_DIR}/cc310_glue.c) zephyr_library_include_directories(${NRF_DIR}) zephyr_link_libraries(nrfxlib_crypto) + elseif(CONFIG_BOOT_USE_NRF_EXTERNAL_CRYPTO) + zephyr_include_directories(${BL_CRYPTO_DIR}/../include) endif() if(CONFIG_MBEDTLS_CFG_FILE) diff --git a/boot/zephyr/external_crypto.conf b/boot/zephyr/external_crypto.conf new file mode 100644 index 000000000..8181ad51c --- /dev/null +++ b/boot/zephyr/external_crypto.conf @@ -0,0 +1,20 @@ +# +# Copyright (c) 2021 Nordic Semiconductor ASA +# +# SPDX-License-Identifier: LicenseRef-Nordic-5-Clause +# + +# These configurations should be used when using nrf/samples/bootloader +# as the immutable bootloader (B0), and MCUBoot as the second stage updateable +# bootloader. + +# Set ECDSA as signing mechanism +CONFIG_BOOT_SIGNATURE_TYPE_ECDSA_P256=y + +# Use crypto backend from B0 +CONFIG_BOOT_NRF_EXTERNAL_CRYPTO=y +CONFIG_SECURE_BOOT_CRYPTO=y +CONFIG_SB_CRYPTO_CLIENT_ECDSA_SECP256R1=y +CONFIG_SB_CRYPTO_CLIENT_SHA256=y +CONFIG_BL_SHA256_EXT_API_REQUIRED=y +CONFIG_BL_SECP256R1_EXT_API_REQUIRED=y diff --git a/boot/zephyr/include/mcuboot_config/mcuboot_config.h b/boot/zephyr/include/mcuboot_config/mcuboot_config.h index f0dc214b6..ae9571100 100644 --- a/boot/zephyr/include/mcuboot_config/mcuboot_config.h +++ b/boot/zephyr/include/mcuboot_config/mcuboot_config.h @@ -49,6 +49,8 @@ #endif #elif defined(CONFIG_BOOT_USE_PSA_CRYPTO) #define MCUBOOT_USE_PSA_CRYPTO +#elif defined(CONFIG_BOOT_USE_NRF_EXTERNAL_CRYPTO) +#define MCUBOOT_USE_NRF_EXTERNAL_CRYPTO #endif #ifdef CONFIG_BOOT_IMG_HASH_ALG_SHA512 From 599a1b9b55e61e17e1f9f95e1d8b136d0d5a3751 Mon Sep 17 00:00:00 2001 From: Markus Lassila Date: Fri, 30 Aug 2024 13:10:05 +0300 Subject: [PATCH 056/420] [nrf noup] boot: zephyr: Do not lock PCD region with TF-M Previously PCD memory was locked as read-only, non-secure in MCUboot. Given that TF-M also needs write to PCD to communicate with b0n, the memory is left unlocked and locked to read-only, non-secure in TF-M. Signed-off-by: Markus Lassila (cherry picked from commit d43ef93d466921cb225b2b15f7cb8e2a63f40770) --- boot/zephyr/main.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/boot/zephyr/main.c b/boot/zephyr/main.c index 64e11c3c6..c51616dda 100644 --- a/boot/zephyr/main.c +++ b/boot/zephyr/main.c @@ -672,7 +672,11 @@ int main(void) } #if defined(CONFIG_SOC_NRF5340_CPUAPP) && defined(PM_CPUNET_B0N_ADDRESS) && defined(CONFIG_PCD_APP) - pcd_lock_ram(); +#if defined(PM_TFM_SECURE_ADDRESS) + pcd_lock_ram(false); +#else + pcd_lock_ram(true); +#endif #endif #endif /* USE_PARTITION_MANAGER && CONFIG_FPROTECT */ From 352b2a4a9cdd531cb3a1401f100e7d82e7434958 Mon Sep 17 00:00:00 2001 From: Jamie McCrae Date: Tue, 10 Sep 2024 13:41:30 +0100 Subject: [PATCH 057/420] [nrf noup] treewide: Add support for sysbuild assigned images Adds support for image IDs that are assigned by sysbuild, which allows for dynamically supporting different configurations without needing dummy images to support different modes. Also fixes multiple deficiencies with the previous code where things were not properly accounted for e.g. using the swap algorithm including all swap status parts when updating s0/s1 MCUboot image which could overwrite and corrupt the image data in the other slot Adds support for getting the maximum allowable image size for NSIB Signed-off-by: Jamie McCrae Signed-off-by: Dominik Ermel (cherry picked from commit 99601b60adeb6707952665e3a708ae461ff48194) --- boot/bootutil/src/bootutil_misc.c | 12 ++ boot/bootutil/src/loader.c | 181 +++++++++++++-------- boot/bootutil/src/swap_nsib.c | 70 ++++++++ boot/bootutil/src/swap_priv.h | 8 + boot/zephyr/CMakeLists.txt | 6 + boot/zephyr/include/sysflash/pm_sysflash.h | 69 ++++---- 6 files changed, 241 insertions(+), 105 deletions(-) create mode 100644 boot/bootutil/src/swap_nsib.c diff --git a/boot/bootutil/src/bootutil_misc.c b/boot/bootutil/src/bootutil_misc.c index 17ed4c616..a88ad0dad 100644 --- a/boot/bootutil/src/bootutil_misc.c +++ b/boot/bootutil/src/bootutil_misc.c @@ -427,6 +427,18 @@ boot_write_enc_key(const struct flash_area *fap, uint8_t slot, uint32_t bootutil_max_image_size(struct boot_loader_state *state, const struct flash_area *fap) { +#if defined(CONFIG_MCUBOOT_MCUBOOT_IMAGE_NUMBER) && CONFIG_MCUBOOT_MCUBOOT_IMAGE_NUMBER != -1 + if (BOOT_CURR_IMG(state) == CONFIG_MCUBOOT_MCUBOOT_IMAGE_NUMBER) { + /* NSIB is a direct upgrade without any status or trailer, get the full size of the + * primary slot. + */ + const struct flash_area *fap_nsib = BOOT_IMG_AREA(state, 0); + assert(fap_nsib != NULL); + + return flash_area_get_size(fap_nsib); + } +#endif /* CONFIG_MCUBOOT_MCUBOOT_IMAGE_NUMBER != -1 */ + #if defined(MCUBOOT_SINGLE_APPLICATION_SLOT) || \ defined(MCUBOOT_FIRMWARE_LOADER) || \ defined(MCUBOOT_SINGLE_APPLICATION_SLOT_RAM_LOAD) diff --git a/boot/bootutil/src/loader.c b/boot/bootutil/src/loader.c index dabb562c9..a75d1a911 100644 --- a/boot/bootutil/src/loader.c +++ b/boot/bootutil/src/loader.c @@ -160,15 +160,15 @@ boot_read_image_headers(struct boot_loader_state *state, bool require_all, * * Failure to read any headers is a fatal error. */ -#ifdef PM_S1_ADDRESS +#if CONFIG_MCUBOOT_MCUBOOT_IMAGE_NUMBER != -1 /* Patch needed for NCS. The primary slot of the second image * (image 1) will not contain a valid image header until an upgrade * of mcuboot has happened (filling S1 with the new version). */ - if (BOOT_CURR_IMG(state) == 1 && i == 0) { + if (BOOT_CURR_IMG(state) == CONFIG_MCUBOOT_MCUBOOT_IMAGE_NUMBER && i == 0) { continue; } -#endif /* PM_S1_ADDRESS */ +#endif /* CONFIG_MCUBOOT_MCUBOOT_IMAGE_NUMBER != -1 */ if (i > 0 && !require_all) { return 0; } else { @@ -1176,7 +1176,7 @@ boot_validate_slot(struct boot_loader_state *state, int slot, #if defined(CONFIG_SOC_NRF5340_CPUAPP) && defined(CONFIG_NRF53_MULTI_IMAGE_UPDATE) \ && defined(CONFIG_PCD_APP) && defined(CONFIG_PCD_READ_NETCORE_APP_VERSION) - if (BOOT_CURR_IMG(state) == 1) { + if (BOOT_CURR_IMG(state) == CONFIG_MCUBOOT_NETWORK_CORE_IMAGE_NUMBER) { rc = pcd_version_cmp_net(fap, boot_img_hdr(state, BOOT_SECONDARY_SLOT)); } else { rc = boot_version_cmp( @@ -1247,35 +1247,54 @@ boot_validate_slot(struct boot_loader_state *state, int slot, struct image_header *secondary_hdr = boot_img_hdr(state, slot); uint32_t reset_value = 0; uint32_t reset_addr = secondary_hdr->ih_hdr_size + sizeof(reset_value); + uint32_t min_addr, max_addr; + bool check_addresses = false; if (flash_area_read(fap, reset_addr, &reset_value, sizeof(reset_value)) != 0) { fih_rc = FIH_NO_BOOTABLE_IMAGE; goto out; } - uint32_t min_addr, max_addr; - #ifdef PM_CPUNET_APP_ADDRESS /* The primary slot for the network core is emulated in RAM. * Its flash_area hasn't got relevant boundaries. * Therfore need to override its boundaries for the check. */ - if (BOOT_CURR_IMG(state) == 1) { + if (BOOT_CURR_IMG(state) == CONFIG_MCUBOOT_NETWORK_CORE_IMAGE_NUMBER) { min_addr = PM_CPUNET_APP_ADDRESS; max_addr = PM_CPUNET_APP_ADDRESS + PM_CPUNET_APP_SIZE; -#ifdef PM_S1_ADDRESS - } else if (BOOT_CURR_IMG(state) == 0) { + check_addresses = true; + } else +#endif +#if CONFIG_MCUBOOT_MCUBOOT_IMAGE_NUMBER != -1 + if (BOOT_CURR_IMG(state) == CONFIG_MCUBOOT_MCUBOOT_IMAGE_NUMBER) { +#if (CONFIG_NCS_IS_VARIANT_IMAGE) min_addr = PM_S0_ADDRESS; - max_addr = pri_fa->fa_off + pri_fa->fa_size; + max_addr = (PM_S0_ADDRESS + PM_S0_SIZE); +#else + min_addr = PM_S1_ADDRESS; + max_addr = (PM_S1_ADDRESS + PM_S1_SIZE); #endif + check_addresses = true; } else #endif - { + if (BOOT_CURR_IMG(state) == CONFIG_MCUBOOT_APPLICATION_IMAGE_NUMBER) { +#if CONFIG_MCUBOOT_MCUBOOT_IMAGE_NUMBER != -1 +#if (CONFIG_NCS_IS_VARIANT_IMAGE) + min_addr = MIN(pri_fa->fa_off, PM_S0_ADDRESS); + max_addr = MAX((pri_fa->fa_off + pri_fa->fa_size), (PM_S0_ADDRESS + PM_S0_SIZE)); +#else + min_addr = MIN(pri_fa->fa_off, PM_S1_ADDRESS); + max_addr = MAX((pri_fa->fa_off + pri_fa->fa_size), (PM_S1_ADDRESS + PM_S1_SIZE)); +#endif +#else min_addr = pri_fa->fa_off; max_addr = pri_fa->fa_off + pri_fa->fa_size; +#endif + check_addresses = true; } - if (reset_value < min_addr || reset_value> (max_addr)) { + if (check_addresses == true && (reset_value < min_addr || reset_value > max_addr)) { BOOT_LOG_ERR("Reset address of image in secondary slot is not in the primary slot"); BOOT_LOG_ERR("Erasing image from secondary slot"); @@ -1397,36 +1416,54 @@ boot_update_security_counter(struct boot_loader_state *state, int slot, int hdr_ #define SEC_SLOT_TOUCHED 1 #define SEC_SLOT_ASSIGNED 2 -#if (MCUBOOT_IMAGE_NUMBER == 2) && defined(PM_B0_ADDRESS) && \ - !defined(CONFIG_NRF53_MULTI_IMAGE_UPDATE) -/* This configuration is peculiar - the one physical secondary slot is - * mocking two logical secondary - */ -#define SEC_SLOT_PHYSICAL_CNT 1 +static uint8_t sec_slot_assignment[MCUBOOT_IMAGE_NUMBER] = {0}; + +#if CONFIG_MCUBOOT_MCUBOOT_IMAGE_NUMBER != -1 +static inline void sec_slot_untouch(struct boot_loader_state *state) +{ + sec_slot_assignment[CONFIG_MCUBOOT_APPLICATION_IMAGE_NUMBER] = SEC_SLOT_VIRGIN; + sec_slot_assignment[CONFIG_MCUBOOT_MCUBOOT_IMAGE_NUMBER] = SEC_SLOT_VIRGIN; +} #else -#define SEC_SLOT_PHYSICAL_CNT MCUBOOT_IMAGE_NUMBER +static inline void sec_slot_untouch(struct boot_loader_state *state) +{ +} #endif -static uint8_t sec_slot_assignmnet[SEC_SLOT_PHYSICAL_CNT] = {0}; - static inline void sec_slot_touch(struct boot_loader_state *state) { - uint8_t idx = (SEC_SLOT_PHYSICAL_CNT == 1) ? 0 : BOOT_CURR_IMG(state); +#if CONFIG_MCUBOOT_MCUBOOT_IMAGE_NUMBER != -1 + if (BOOT_CURR_IMG(state) == CONFIG_MCUBOOT_MCUBOOT_IMAGE_NUMBER) { + if (sec_slot_assignment[CONFIG_MCUBOOT_APPLICATION_IMAGE_NUMBER] == SEC_SLOT_VIRGIN) { + sec_slot_assignment[CONFIG_MCUBOOT_APPLICATION_IMAGE_NUMBER] = SEC_SLOT_TOUCHED; + } + } else if (BOOT_CURR_IMG(state) == CONFIG_MCUBOOT_APPLICATION_IMAGE_NUMBER) { + if (sec_slot_assignment[CONFIG_MCUBOOT_MCUBOOT_IMAGE_NUMBER] == SEC_SLOT_VIRGIN) { + sec_slot_assignment[CONFIG_MCUBOOT_MCUBOOT_IMAGE_NUMBER] = SEC_SLOT_TOUCHED; + } + } +#endif - if (SEC_SLOT_VIRGIN == sec_slot_assignmnet[idx]) { - sec_slot_assignmnet[idx] = SEC_SLOT_TOUCHED; + if (sec_slot_assignment[BOOT_CURR_IMG(state)] == SEC_SLOT_VIRGIN) { + sec_slot_assignment[BOOT_CURR_IMG(state)] = SEC_SLOT_TOUCHED; } } static inline void sec_slot_mark_assigned(struct boot_loader_state *state) { - uint8_t idx = (SEC_SLOT_PHYSICAL_CNT == 1) ? 0 : BOOT_CURR_IMG(state); +#if CONFIG_MCUBOOT_MCUBOOT_IMAGE_NUMBER != -1 + if (BOOT_CURR_IMG(state) == CONFIG_MCUBOOT_MCUBOOT_IMAGE_NUMBER) { + sec_slot_assignment[CONFIG_MCUBOOT_APPLICATION_IMAGE_NUMBER] = SEC_SLOT_ASSIGNED; + } else if (BOOT_CURR_IMG(state) == CONFIG_MCUBOOT_APPLICATION_IMAGE_NUMBER) { + sec_slot_assignment[CONFIG_MCUBOOT_MCUBOOT_IMAGE_NUMBER] = SEC_SLOT_ASSIGNED; + } +#endif - sec_slot_assignmnet[idx] = SEC_SLOT_ASSIGNED; + sec_slot_assignment[BOOT_CURR_IMG(state)] = SEC_SLOT_ASSIGNED; } /** - * Cleanu up all secondary slot which couldn't be assigned to any primary slot. + * Cleanup up all secondary slot which couldn't be assigned to any primary slot. * * This function erases content of each secondary slot which contains valid * header but couldn't be assigned to any of supported primary images. @@ -1438,8 +1475,8 @@ static void sec_slot_cleanup_if_unusable(void) { uint8_t idx; - for (idx = 0; idx < SEC_SLOT_PHYSICAL_CNT; idx++) { - if (SEC_SLOT_TOUCHED == sec_slot_assignmnet[idx]) { + for (idx = 0; idx < MCUBOOT_IMAGE_NUMBER; idx++) { + if (SEC_SLOT_TOUCHED == sec_slot_assignment[idx]) { const struct flash_area *secondary_fa; int rc; @@ -1448,17 +1485,20 @@ static void sec_slot_cleanup_if_unusable(void) if (!rc) { rc = flash_area_erase(secondary_fa, 0, secondary_fa->fa_size); if (!rc) { - BOOT_LOG_ERR("Cleaned-up secondary slot of %d. image.", idx); + BOOT_LOG_ERR("Cleaned-up secondary slot of image %d", idx); } } if (rc) { - BOOT_LOG_ERR("Can not cleanup secondary slot of %d. image.", idx); + BOOT_LOG_ERR("Failed to clean-up secondary slot of image %d: %d", idx, rc); } } } } #else +static inline void sec_slot_untouch(struct boot_loader_state *state) +{ +} static inline void sec_slot_touch(struct boot_loader_state *state) { } @@ -1490,7 +1530,7 @@ boot_validated_swap_type(struct boot_loader_state *state, owner_nsib[BOOT_CURR_IMG(state)] = false; #endif -#if defined(PM_S1_ADDRESS) || defined(CONFIG_SOC_NRF5340_CPUAPP) +#if defined(PM_S1_ADDRESS) || defined(PM_CPUNET_B0N_ADDRESS) const struct flash_area *secondary_fa = BOOT_IMG_AREA(state, BOOT_SECONDARY_SLOT); struct image_header *hdr = boot_img_hdr(state, BOOT_SECONDARY_SLOT); @@ -1528,31 +1568,31 @@ boot_validated_swap_type(struct boot_loader_state *state, } /* Check start and end of primary slot for current image */ - if (reset_addr < primary_fa->fa_off) { -#if defined(CONFIG_SOC_NRF5340_CPUAPP) && defined(CONFIG_NRF53_MULTI_IMAGE_UPDATE) - const struct flash_area *nsib_fa; - - /* NSIB upgrade slot */ - rc = flash_area_open((uint32_t)_image_1_primary_slot_id, - &nsib_fa); - - if (rc != 0) { - return BOOT_SWAP_TYPE_FAIL; - } - - /* Image is placed before Primary and within the NSIB slot */ - if (reset_addr > nsib_fa->fa_off - && reset_addr < (nsib_fa->fa_off + nsib_fa->fa_size)) { - /* Set primary to be NSIB upgrade slot */ - BOOT_IMG_AREA(state, 0) = nsib_fa; - owner_nsib[BOOT_CURR_IMG(state)] = true; - } +#if (CONFIG_NCS_IS_VARIANT_IMAGE) + if (reset_addr >= PM_S0_ADDRESS && reset_addr <= (PM_S0_ADDRESS + PM_S0_SIZE)) { #else - return BOOT_SWAP_TYPE_NONE; - + if (reset_addr >= PM_S1_ADDRESS && reset_addr <= (PM_S1_ADDRESS + PM_S1_SIZE)) { #endif + if (BOOT_CURR_IMG(state) == CONFIG_MCUBOOT_APPLICATION_IMAGE_NUMBER) { + /* This is not the s0/s1 upgrade image but the application image, pretend + * there is no image so the NSIB update can be loaded + */ + return BOOT_SWAP_TYPE_NONE; + } - } else if (reset_addr > (primary_fa->fa_off + primary_fa->fa_size)) { + owner_nsib[BOOT_CURR_IMG(state)] = true; +#if (CONFIG_NCS_IS_VARIANT_IMAGE) + } else if (reset_addr >= PM_S1_ADDRESS && reset_addr <= (PM_S1_ADDRESS + PM_S1_SIZE)) { +#else + } else if (reset_addr >= PM_S0_ADDRESS && reset_addr <= (PM_S0_ADDRESS + PM_S0_SIZE)) { +#endif + /* NSIB upgrade but for the wrong slot, must be erased */ + BOOT_LOG_ERR("Image in slot is for wrong s0/s1 image"); + flash_area_erase(secondary_fa, 0, secondary_fa->fa_size); + sec_slot_untouch(state); + BOOT_LOG_ERR("Cleaned-up secondary slot of image %d", BOOT_CURR_IMG(state)); + return BOOT_SWAP_TYPE_FAIL; + } else if (reset_addr < primary_fa->fa_off || reset_addr > (primary_fa->fa_off + primary_fa->fa_size)) { /* The image in the secondary slot is not intended for any */ return BOOT_SWAP_TYPE_NONE; } @@ -1565,7 +1605,7 @@ boot_validated_swap_type(struct boot_loader_state *state, sec_slot_mark_assigned(state); } -#endif /* PM_S1_ADDRESS || CONFIG_SOC_NRF5340_CPUAPP */ +#endif /* PM_S1_ADDRESS || PM_CPUNET_B0N_ADDRESS */ swap_type = boot_swap_type_multi(BOOT_CURR_IMG(state)); if (BOOT_IS_UPGRADE(swap_type)) { @@ -2237,7 +2277,22 @@ boot_swap_image(struct boot_loader_state *state, struct boot_status *bs) flash_area_close(fap); } - swap_run(state, bs, copy_size); +#if defined(PM_S1_ADDRESS) && CONFIG_MCUBOOT_MCUBOOT_IMAGE_NUMBER != -1 + if (owner_nsib[BOOT_CURR_IMG(state)]) { + if (BOOT_CURR_IMG(state) == CONFIG_MCUBOOT_MCUBOOT_IMAGE_NUMBER) { + /* For NSIB, move the image instead of swapping it */ + nsib_swap_run(state, bs); + +#if defined(CONFIG_REBOOT) + /* Should also reboot at this point so the new S0/S1 update is applied */ + sys_reboot(SYS_REBOOT_COLD); +#endif + } + } else +#endif + { + swap_run(state, bs, copy_size); + } #ifdef MCUBOOT_VALIDATE_PRIMARY_SLOT extern int boot_status_fails; @@ -2931,12 +2986,6 @@ context_boot_go(struct boot_loader_state *state, struct boot_rsp *rsp) rc = boot_perform_update(state, &bs); } assert(rc == 0); -#if defined(PM_S1_ADDRESS) && defined(CONFIG_REBOOT) - if (owner_nsib[BOOT_CURR_IMG(state)]) { - sys_reboot(SYS_REBOOT_COLD); - - } -#endif break; case BOOT_SWAP_TYPE_FAIL: @@ -3004,13 +3053,17 @@ context_boot_go(struct boot_loader_state *state, struct boot_rsp *rsp) */ } -#ifdef MCUBOOT_VALIDATE_PRIMARY_SLOT #ifdef PM_S1_ADDRESS /* Patch needed for NCS. Image 1 primary is the currently * executing MCUBoot image, and is therefore already validated by NSIB and * does not need to also be validated by MCUBoot. */ - bool image_validated_by_nsib = BOOT_CURR_IMG(state) == 1; + bool image_validated_by_nsib = BOOT_CURR_IMG(state) == + CONFIG_MCUBOOT_MCUBOOT_IMAGE_NUMBER; +#endif + +#ifdef MCUBOOT_VALIDATE_PRIMARY_SLOT +#ifdef PM_S1_ADDRESS if (!image_validated_by_nsib) #endif { diff --git a/boot/bootutil/src/swap_nsib.c b/boot/bootutil/src/swap_nsib.c new file mode 100644 index 000000000..079e193d5 --- /dev/null +++ b/boot/bootutil/src/swap_nsib.c @@ -0,0 +1,70 @@ +/* + * SPDX-License-Identifier: Apache-2.0 + * + * Copyright (c) 2024 Nordic Semiconductor ASA + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include +#include +#include +#include +#include "bootutil/bootutil.h" +#include "bootutil_priv.h" +#include "swap_priv.h" +#include "bootutil/bootutil_log.h" + +#include "mcuboot_config/mcuboot_config.h" + +BOOT_LOG_MODULE_DECLARE(mcuboot); + +void nsib_swap_run(struct boot_loader_state *state, struct boot_status *bs) +{ + uint32_t sector_sz; + uint8_t image_index; + const struct flash_area *fap_pri; + const struct flash_area *fap_sec; + int rc; + + BOOT_LOG_INF("Starting swap using nsib algorithm."); + + sector_sz = boot_img_sector_size(state, BOOT_SECONDARY_SLOT, 0); + +#if (CONFIG_NCS_IS_VARIANT_IMAGE) + rc = flash_area_open(PM_S0_ID, &fap_pri); +#else + rc = flash_area_open(PM_S1_ID, &fap_pri); +#endif + assert (rc == 0); + image_index = BOOT_CURR_IMG(state); + + rc = flash_area_open(FLASH_AREA_IMAGE_SECONDARY(image_index), &fap_sec); + assert (rc == 0); + + rc = boot_erase_region(fap_pri, 0, fap_pri->fa_size, false); + assert(rc == 0); + + rc = boot_copy_region(state, fap_sec, fap_pri, 0, 0, fap_pri->fa_size); + assert(rc == 0); + + rc = swap_scramble_trailer_sectors(state, fap_sec); + assert(rc == 0); + + rc = boot_scramble_region(fap_sec, 0, MIN((fap_pri->fa_size + sector_sz), fap_sec->fa_size), false); + assert(rc == 0); + + flash_area_close(fap_pri); + flash_area_close(fap_sec); +} diff --git a/boot/bootutil/src/swap_priv.h b/boot/bootutil/src/swap_priv.h index b564ea99e..90e0b3742 100644 --- a/boot/bootutil/src/swap_priv.h +++ b/boot/bootutil/src/swap_priv.h @@ -130,4 +130,12 @@ bool swap_write_block_size_check(struct boot_loader_state *state); */ int app_max_size(struct boot_loader_state *state); +#if defined(PM_S1_ADDRESS) && !defined(MCUBOOT_OVERWRITE_ONLY) && \ +(CONFIG_MCUBOOT_MCUBOOT_IMAGE_NUMBER != -1 || defined(LEGACY_CHILD_PARENT_S0_S1_UPDATE_ENABLED)) +/** + * Performs an NSIB update + */ +void nsib_swap_run(struct boot_loader_state *state, struct boot_status *bs); +#endif + #endif /* H_SWAP_PRIV_ */ diff --git a/boot/zephyr/CMakeLists.txt b/boot/zephyr/CMakeLists.txt index 1db4ed270..0bd0fb919 100644 --- a/boot/zephyr/CMakeLists.txt +++ b/boot/zephyr/CMakeLists.txt @@ -181,6 +181,12 @@ else() ) endif() endif() + + if(NOT CONFIG_MCUBOOT_MCUBOOT_IMAGE_NUMBER EQUAL "-1" AND NOT CONFIG_BOOT_UPGRADE_ONLY) + zephyr_library_sources( + ${BOOT_DIR}/bootutil/src/swap_nsib.c + ) + endif() endif() if(CONFIG_BOOT_SIGNATURE_TYPE_ECDSA_P256 OR CONFIG_BOOT_ENCRYPT_EC256) diff --git a/boot/zephyr/include/sysflash/pm_sysflash.h b/boot/zephyr/include/sysflash/pm_sysflash.h index db60ddd03..42f25182e 100644 --- a/boot/zephyr/include/sysflash/pm_sysflash.h +++ b/boot/zephyr/include/sysflash/pm_sysflash.h @@ -15,48 +15,36 @@ #ifndef CONFIG_SINGLE_APPLICATION_SLOT -#if (MCUBOOT_IMAGE_NUMBER == 2) && defined(PM_B0_ADDRESS) -/* If B0 is present then two bootloaders are present, and we must use - * a single secondary slot for both primary slots. - */ -extern uint32_t _image_1_primary_slot_id[]; -#endif /* (MCUBOOT_IMAGE_NUMBER == 2 && defined(PM_B0_ADDRESS) */ - -#if (MCUBOOT_IMAGE_NUMBER == 2) && defined(PM_B0_ADDRESS) && \ - !defined(CONFIG_NRF53_MULTI_IMAGE_UPDATE) - -#define FLASH_AREA_IMAGE_PRIMARY(x) \ - ((x == 0) ? \ - PM_MCUBOOT_PRIMARY_ID : \ - (x == 1) ? \ - (uint32_t)_image_1_primary_slot_id : \ - 255 ) - -#define FLASH_AREA_IMAGE_SECONDARY(x) \ - ((x == 0) ? \ - PM_MCUBOOT_SECONDARY_ID: \ - (x == 1) ? \ - PM_MCUBOOT_SECONDARY_ID: \ - 255 ) - -#else /* MCUBOOT_IMAGE_NUMBER == 2) && defined(PM_B0_ADDRESS) && \ - * !defined(CONFIG_NRF53_MULTI_IMAGE_UPDATE) - */ - /* Each pair of slots is separated by , and there is no terminating character */ -#define FLASH_AREA_IMAGE_0_SLOTS PM_MCUBOOT_PRIMARY_ID, PM_MCUBOOT_SECONDARY_ID -#define FLASH_AREA_IMAGE_1_SLOTS PM_MCUBOOT_PRIMARY_1_ID, PM_MCUBOOT_SECONDARY_1_ID -#define FLASH_AREA_IMAGE_2_SLOTS PM_MCUBOOT_PRIMARY_2_ID, PM_MCUBOOT_SECONDARY_2_ID +#define FLASH_AREA_IMAGE_0_SLOTS PM_MCUBOOT_PRIMARY_ID, PM_MCUBOOT_SECONDARY_ID, +#define FLASH_AREA_IMAGE_1_SLOTS PM_MCUBOOT_PRIMARY_1_ID, PM_MCUBOOT_SECONDARY_1_ID, +#define FLASH_AREA_IMAGE_2_SLOTS PM_MCUBOOT_PRIMARY_2_ID, PM_MCUBOOT_SECONDARY_2_ID, +#define FLASH_AREA_IMAGE_3_SLOTS PM_MCUBOOT_PRIMARY_3_ID, PM_MCUBOOT_SECONDARY_3_ID, + +#if CONFIG_MCUBOOT_MCUBOOT_IMAGE_NUMBER != -1 +#ifdef CONFIG_NCS_IS_VARIANT_IMAGE +#define MCUBOOT_S0_S1_SLOTS PM_S0_ID, PM_MCUBOOT_SECONDARY_ID, +#else +#define MCUBOOT_S0_S1_SLOTS PM_S1_ID, PM_MCUBOOT_SECONDARY_ID, +#endif +#else +#define MCUBOOT_S0_S1_SLOTS +#endif -#if (MCUBOOT_IMAGE_NUMBER == 1) +#if (MCUBOOT_IMAGE_NUMBER == 1) || (MCUBOOT_IMAGE_NUMBER == 2 && CONFIG_MCUBOOT_MCUBOOT_IMAGE_NUMBER != -1) #define ALL_AVAILABLE_SLOTS FLASH_AREA_IMAGE_0_SLOTS -#elif (MCUBOOT_IMAGE_NUMBER == 2) -#define ALL_AVAILABLE_SLOTS FLASH_AREA_IMAGE_0_SLOTS, \ +#elif (MCUBOOT_IMAGE_NUMBER == 2) || (MCUBOOT_IMAGE_NUMBER == 3 && CONFIG_MCUBOOT_MCUBOOT_IMAGE_NUMBER != -1) +#define ALL_AVAILABLE_SLOTS FLASH_AREA_IMAGE_0_SLOTS \ FLASH_AREA_IMAGE_1_SLOTS -#elif (MCUBOOT_IMAGE_NUMBER == 3) -#define ALL_AVAILABLE_SLOTS FLASH_AREA_IMAGE_0_SLOTS, \ - FLASH_AREA_IMAGE_1_SLOTS, \ +#elif (MCUBOOT_IMAGE_NUMBER == 3) || (MCUBOOT_IMAGE_NUMBER == 4 && CONFIG_MCUBOOT_MCUBOOT_IMAGE_NUMBER != -1) +#define ALL_AVAILABLE_SLOTS FLASH_AREA_IMAGE_0_SLOTS \ + FLASH_AREA_IMAGE_1_SLOTS \ FLASH_AREA_IMAGE_2_SLOTS +#elif (MCUBOOT_IMAGE_NUMBER == 4) +#define ALL_AVAILABLE_SLOTS FLASH_AREA_IMAGE_0_SLOTS \ + FLASH_AREA_IMAGE_1_SLOTS \ + FLASH_AREA_IMAGE_2_SLOTS \ + FLASH_AREA_IMAGE_3_SLOTS #else #error Unsupported number of images #endif @@ -65,6 +53,7 @@ static inline uint32_t __flash_area_ids_for_slot(int img, int slot) { static const int all_slots[] = { ALL_AVAILABLE_SLOTS + MCUBOOT_S0_S1_SLOTS }; return all_slots[img * 2 + slot]; }; @@ -72,6 +61,8 @@ static inline uint32_t __flash_area_ids_for_slot(int img, int slot) #undef FLASH_AREA_IMAGE_0_SLOTS #undef FLASH_AREA_IMAGE_1_SLOTS #undef FLASH_AREA_IMAGE_2_SLOTS +#undef FLASH_AREA_IMAGE_3_SLOTS +#undef MCUBOOT_S0_S1_SLOTS #undef ALL_AVAILABLE_SLOTS #define FLASH_AREA_IMAGE_PRIMARY(x) __flash_area_ids_for_slot(x, 0) @@ -81,10 +72,6 @@ static inline uint32_t __flash_area_ids_for_slot(int img, int slot) #define FLASH_AREA_IMAGE_SCRATCH PM_MCUBOOT_SCRATCH_ID #endif -#endif /* MCUBOOT_IMAGE_NUMBER == 2) && defined(PM_B0_ADDRESS) && \ - * !defined(CONFIG_NRF53_MULTI_IMAGE_UPDATE) - */ - #else /* CONFIG_SINGLE_APPLICATION_SLOT */ #define FLASH_AREA_IMAGE_PRIMARY(x) PM_MCUBOOT_PRIMARY_ID From d5f373adeb1c296c8d312ca8484f5f73414d7f48 Mon Sep 17 00:00:00 2001 From: Jamie McCrae Date: Tue, 15 Oct 2024 11:31:20 +0100 Subject: [PATCH 058/420] [nrf noup] boot: bootutil: loader: Add s0/s1 checking of MCUboot image Adds a check that will also check the s0/s1 package version of the currently running MCUboot against a MCUboot update image to ensure that an older version of MCUboot isn't loaded to the opposite slot Signed-off-by: Jamie McCrae (cherry picked from commit 9c834622b023e321350fca2aedb15a8a9570c63a) --- boot/bootutil/src/loader.c | 45 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 45 insertions(+) diff --git a/boot/bootutil/src/loader.c b/boot/bootutil/src/loader.c index a75d1a911..dd4853874 100644 --- a/boot/bootutil/src/loader.c +++ b/boot/bootutil/src/loader.c @@ -101,6 +101,17 @@ static struct sector_buffer_t sector_buffers; #endif #endif +#if CONFIG_MCUBOOT_MCUBOOT_IMAGE_NUMBER != -1 && defined(MCUBOOT_OVERWRITE_ONLY) && \ + defined(MCUBOOT_DOWNGRADE_PREVENTION) +/* s0/s1 package version of the current MCUboot image */ +static const struct image_version mcuboot_s0_s1_image_version = { + .iv_major = CONFIG_MCUBOOT_MCUBOOT_S0_S1_VERSION_MAJOR, + .iv_minor = CONFIG_MCUBOOT_MCUBOOT_S0_S1_VERSION_MINOR, + .iv_revision = CONFIG_MCUBOOT_MCUBOOT_S0_S1_VERSION_REVISION, + .iv_build_num = CONFIG_MCUBOOT_MCUBOOT_S0_S1_VERSION_BUILD_NUMBER, +}; +#endif + #if (BOOT_IMAGE_NUMBER > 1) #define IMAGES_ITER(x) for ((x) = 0; (x) < BOOT_IMAGE_NUMBER; ++(x)) #else @@ -1182,11 +1193,45 @@ boot_validate_slot(struct boot_loader_state *state, int slot, rc = boot_version_cmp( &boot_img_hdr(state, BOOT_SECONDARY_SLOT)->ih_ver, &boot_img_hdr(state, BOOT_PRIMARY_SLOT)->ih_ver); + +#if CONFIG_MCUBOOT_MCUBOOT_IMAGE_NUMBER != -1 + if (rc >= 0 && BOOT_CURR_IMG(state) == CONFIG_MCUBOOT_MCUBOOT_IMAGE_NUMBER) { + /* Also check the new version of MCUboot against that of the current s0/s1 MCUboot + * trailer version to prevent downgrades + */ + int version_check; + + version_check = boot_version_cmp(&boot_img_hdr(state, BOOT_SECONDARY_SLOT)->ih_ver, + &mcuboot_s0_s1_image_version); + + /* Only update rc if the currently running version is newer */ + if (version_check < rc) { + rc = version_check; + } + } +#endif } #else rc = boot_version_cmp( &boot_img_hdr(state, BOOT_SECONDARY_SLOT)->ih_ver, &boot_img_hdr(state, BOOT_PRIMARY_SLOT)->ih_ver); + +#if CONFIG_MCUBOOT_MCUBOOT_IMAGE_NUMBER != -1 + if (rc >= 0 && BOOT_CURR_IMG(state) == CONFIG_MCUBOOT_MCUBOOT_IMAGE_NUMBER) { + /* Also check the new version of MCUboot against that of the current s0/s1 MCUboot + * trailer version to prevent downgrades + */ + int version_check; + + version_check = boot_version_cmp(&boot_img_hdr(state, BOOT_SECONDARY_SLOT)->ih_ver, + &mcuboot_s0_s1_image_version); + + /* Only update rc if the currently running version is newer */ + if (version_check < rc) { + rc = version_check; + } + } +#endif #endif if (rc < 0 && boot_check_header_erased(state, BOOT_PRIMARY_SLOT)) { BOOT_LOG_ERR("insufficient version in secondary slot"); From be6d73eca89a94e990f57eac4acd8a6c60858a84 Mon Sep 17 00:00:00 2001 From: Maximilian Deubel Date: Wed, 23 Oct 2024 16:48:13 +0200 Subject: [PATCH 059/420] [nrf noup] boards: Thingy:91 X release config Update the configuration files for the Thingy:91 X targets to the ones used in production. Signed-off-by: Maximilian Deubel Signed-off-by: Michal Kozikowski (cherry picked from commit 8444d75ad1f76463f571f08d8088bcb5b88ae50c) --- boot/zephyr/boards/thingy91x_nrf5340_cpuapp.conf | 3 +++ boot/zephyr/boards/thingy91x_nrf9151.conf | 7 +++++-- boot/zephyr/boards/thingy91x_nrf9151.overlay | 4 ++++ 3 files changed, 12 insertions(+), 2 deletions(-) create mode 100644 boot/zephyr/boards/thingy91x_nrf9151.overlay diff --git a/boot/zephyr/boards/thingy91x_nrf5340_cpuapp.conf b/boot/zephyr/boards/thingy91x_nrf5340_cpuapp.conf index 37c7e95b1..d3e253b65 100644 --- a/boot/zephyr/boards/thingy91x_nrf5340_cpuapp.conf +++ b/boot/zephyr/boards/thingy91x_nrf5340_cpuapp.conf @@ -58,3 +58,6 @@ CONFIG_BOOT_SERIAL_IMG_GRP_IMAGE_STATE=y # Skip checks on the secondary image to make it possible to update MCUBoot on S1/S0 CONFIG_MCUBOOT_VERIFY_IMG_ADDRESS=n + +CONFIG_BOOT_SERIAL_NO_APPLICATION=y +CONFIG_FW_INFO_FIRMWARE_VERSION=2 diff --git a/boot/zephyr/boards/thingy91x_nrf9151.conf b/boot/zephyr/boards/thingy91x_nrf9151.conf index 2efe1e170..8088686e0 100644 --- a/boot/zephyr/boards/thingy91x_nrf9151.conf +++ b/boot/zephyr/boards/thingy91x_nrf9151.conf @@ -5,13 +5,16 @@ CONFIG_SPI=y CONFIG_SPI_NOR=y CONFIG_SPI_NOR_FLASH_LAYOUT_PAGE_SIZE=4096 CONFIG_SPI_NOR_SFDP_DEVICETREE=y -CONFIG_MULTITHREADING=y # Disable Zephyr console and use UART for MCUboot serial recovery instead CONFIG_CONSOLE=n CONFIG_CONSOLE_HANDLER=n CONFIG_UART_CONSOLE=n CONFIG_MCUBOOT_SERIAL=y - CONFIG_MCUBOOT_SERIAL_DIRECT_IMAGE_UPLOAD=y CONFIG_BOOT_SERIAL_IMG_GRP_IMAGE_STATE=y + +CONFIG_PM_EXTERNAL_FLASH_MCUBOOT_SECONDARY=y +CONFIG_PM_OVERRIDE_EXTERNAL_DRIVER_CHECK=y + +CONFIG_FW_INFO_FIRMWARE_VERSION=2 diff --git a/boot/zephyr/boards/thingy91x_nrf9151.overlay b/boot/zephyr/boards/thingy91x_nrf9151.overlay new file mode 100644 index 000000000..7f2818c0d --- /dev/null +++ b/boot/zephyr/boards/thingy91x_nrf9151.overlay @@ -0,0 +1,4 @@ +&uart0 { + status = "okay"; + current-speed = < 1000000 >; +}; From e40684941b5d29b21d9ae4d4afb56841b685f177 Mon Sep 17 00:00:00 2001 From: Carles Cufi Date: Fri, 25 Oct 2024 09:37:44 +0200 Subject: [PATCH 060/420] [nrf noup] workflows: Add a backport workflow Enable backporting of PRs. Signed-off-by: Carles Cufi (cherry picked from commit b1376c631a543e03b85e7da6bd473cfb43e973b0) --- .github/workflows/backport.yml | 31 +++++++++++++++++++++++++++++++ 1 file changed, 31 insertions(+) create mode 100644 .github/workflows/backport.yml diff --git a/.github/workflows/backport.yml b/.github/workflows/backport.yml new file mode 100644 index 000000000..e986738ff --- /dev/null +++ b/.github/workflows/backport.yml @@ -0,0 +1,31 @@ +name: Backport +on: + pull_request_target: + types: + - closed + - labeled + branches: + - main + +jobs: + backport: + name: Backport + runs-on: ubuntu-22.04 + # Only react to merged PRs for security reasons. + # See https://docs.github.com/en/actions/using-workflows/events-that-trigger-workflows#pull_request_target. + if: > + github.event.pull_request.merged && + ( + github.event.action == 'closed' || + ( + github.event.action == 'labeled' && + contains(github.event.label.name, 'backport') + ) + ) + steps: + - name: Backport + uses: zephyrproject-rtos/action-backport@v2.0.3-3 + with: + github_token: ${{ secrets.NCS_GITHUB_TOKEN }} + issue_labels: Backport + labels_template: '["Backport"]' From 835b63f3a179634b5c265aa1f39f4834b54bd9cc Mon Sep 17 00:00:00 2001 From: Mateusz Michalek Date: Thu, 7 Nov 2024 11:09:18 +0100 Subject: [PATCH 061/420] [nrf noup] boot/zephyr: add nrf54l15dk ext flash configs Moved configs from nrf54l15pdk. Turn protection on fprotect by default. Signed-off-by: Andrzej Puzdrowski Signed-off-by: Mateusz Michalek Signed-off-by: Michal Kozikowski Signed-off-by: Jamie McCrae (cherry picked from commit add70d4044cc2914197ac147af13384f15d80e64) --- .../boards/nrf54l15dk_nrf54l15_cpuapp.conf | 16 ------- .../nrf54l15dk_nrf54l15_cpuapp_ext_flash.conf | 9 ++++ ...f54l15dk_nrf54l15_cpuapp_ext_flash.overlay | 48 +++++++++++++++++++ boot/zephyr/prj.conf | 1 - .../nrf54l05_cpuapp.conf} | 2 - .../nrf54l10_cpuapp.conf} | 2 - boot/zephyr/socs/nrf54l15_cpuapp.conf | 14 ++++++ 7 files changed, 71 insertions(+), 21 deletions(-) delete mode 100644 boot/zephyr/boards/nrf54l15dk_nrf54l15_cpuapp.conf create mode 100644 boot/zephyr/boards/nrf54l15dk_nrf54l15_cpuapp_ext_flash.conf create mode 100644 boot/zephyr/boards/nrf54l15dk_nrf54l15_cpuapp_ext_flash.overlay rename boot/zephyr/{boards/nrf54l15dk_nrf54l05_cpuapp.conf => socs/nrf54l05_cpuapp.conf} (94%) rename boot/zephyr/{boards/nrf54l15dk_nrf54l10_cpuapp.conf => socs/nrf54l10_cpuapp.conf} (94%) diff --git a/boot/zephyr/boards/nrf54l15dk_nrf54l15_cpuapp.conf b/boot/zephyr/boards/nrf54l15dk_nrf54l15_cpuapp.conf deleted file mode 100644 index 1dbd7c1ab..000000000 --- a/boot/zephyr/boards/nrf54l15dk_nrf54l15_cpuapp.conf +++ /dev/null @@ -1,16 +0,0 @@ -# Copyright (c) 2024 Nordic Semiconductor ASA -# -# SPDX-License-Identifier: Apache-2.0 -# -CONFIG_BOOT_MAX_IMG_SECTORS=256 - -# Ensure that the SPI NOR driver is disabled by default -CONFIG_SPI_NOR=n - -# TODO: below are not yet supported and need fixing -CONFIG_FPROTECT=n - -CONFIG_BOOT_WATCHDOG_FEED=n - -# Ensure the fastest RRAM write operations -CONFIG_NRF_RRAM_WRITE_BUFFER_SIZE=32 diff --git a/boot/zephyr/boards/nrf54l15dk_nrf54l15_cpuapp_ext_flash.conf b/boot/zephyr/boards/nrf54l15dk_nrf54l15_cpuapp_ext_flash.conf new file mode 100644 index 000000000..ec944f828 --- /dev/null +++ b/boot/zephyr/boards/nrf54l15dk_nrf54l15_cpuapp_ext_flash.conf @@ -0,0 +1,9 @@ +CONFIG_SPI=y +CONFIG_SPI_NOR=y +CONFIG_FLASH=y +CONFIG_PM_PARTITION_SIZE_MCUBOOT=0x14000 +CONFIG_MAIN_STACK_SIZE=20480 +CONFIG_BOOT_MAX_IMG_SECTORS=512 +CONFIG_SPI_NOR_FLASH_LAYOUT_PAGE_SIZE=4096 +# Ensure that the qspi driver is disabled by default +CONFIG_NORDIC_QSPI_NOR=n diff --git a/boot/zephyr/boards/nrf54l15dk_nrf54l15_cpuapp_ext_flash.overlay b/boot/zephyr/boards/nrf54l15dk_nrf54l15_cpuapp_ext_flash.overlay new file mode 100644 index 000000000..ba6274221 --- /dev/null +++ b/boot/zephyr/boards/nrf54l15dk_nrf54l15_cpuapp_ext_flash.overlay @@ -0,0 +1,48 @@ +/ { + chosen { + nordic,pm-ext-flash = &mx25r64; + zephyr,code-partition = &boot_partition; + }; +}; + +/delete-node/ &boot_partition; +/delete-node/ &slot0_partition; +/delete-node/ &slot1_partition; + +/delete-node/ &storage_partition; + +&cpuapp_rram { + reg = < 0x0 DT_SIZE_K(1524) >; + + partitions { + boot_partition: partition@0 { + label = "mcuboot"; + reg = <0x000000000 0x00014000>; + }; + + slot0_partition: partition@14000 { + label = "image-0"; + reg = <0x000014000 0x0015A000>; + }; + + storage_partition: partition@16E000 { + label = "storage"; + reg = < 0x16E000 0x9000 >; + }; + }; +}; + +&mx25r64 { + status = "okay"; + + partitions { + compatible = "fixed-partitions"; + #address-cells = <1>; + #size-cells = <1>; + + slot1_partition: partition@0 { + label = "image-1"; + reg = <0x000000000 0x0015A000>; + }; + }; +}; diff --git a/boot/zephyr/prj.conf b/boot/zephyr/prj.conf index 9ff1ba274..eecc1cbca 100644 --- a/boot/zephyr/prj.conf +++ b/boot/zephyr/prj.conf @@ -18,7 +18,6 @@ CONFIG_BOOT_BOOTSTRAP=n # CONFIG_TINYCRYPT_SHA256 is not set CONFIG_FLASH=y -CONFIG_FPROTECT=y ### Various Zephyr boards enable features that we don't want. # CONFIG_BT is not set diff --git a/boot/zephyr/boards/nrf54l15dk_nrf54l05_cpuapp.conf b/boot/zephyr/socs/nrf54l05_cpuapp.conf similarity index 94% rename from boot/zephyr/boards/nrf54l15dk_nrf54l05_cpuapp.conf rename to boot/zephyr/socs/nrf54l05_cpuapp.conf index f911aa248..c8fcd32c3 100644 --- a/boot/zephyr/boards/nrf54l15dk_nrf54l05_cpuapp.conf +++ b/boot/zephyr/socs/nrf54l05_cpuapp.conf @@ -7,8 +7,6 @@ CONFIG_BOOT_MAX_IMG_SECTORS=256 # Ensure that the SPI NOR driver is disabled by default CONFIG_SPI_NOR=n -CONFIG_FPROTECT=y - CONFIG_BOOT_WATCHDOG_FEED=n # Ensure the fastest RRAM write operations diff --git a/boot/zephyr/boards/nrf54l15dk_nrf54l10_cpuapp.conf b/boot/zephyr/socs/nrf54l10_cpuapp.conf similarity index 94% rename from boot/zephyr/boards/nrf54l15dk_nrf54l10_cpuapp.conf rename to boot/zephyr/socs/nrf54l10_cpuapp.conf index f911aa248..c8fcd32c3 100644 --- a/boot/zephyr/boards/nrf54l15dk_nrf54l10_cpuapp.conf +++ b/boot/zephyr/socs/nrf54l10_cpuapp.conf @@ -7,8 +7,6 @@ CONFIG_BOOT_MAX_IMG_SECTORS=256 # Ensure that the SPI NOR driver is disabled by default CONFIG_SPI_NOR=n -CONFIG_FPROTECT=y - CONFIG_BOOT_WATCHDOG_FEED=n # Ensure the fastest RRAM write operations diff --git a/boot/zephyr/socs/nrf54l15_cpuapp.conf b/boot/zephyr/socs/nrf54l15_cpuapp.conf index 8db9d2d23..645325513 100644 --- a/boot/zephyr/socs/nrf54l15_cpuapp.conf +++ b/boot/zephyr/socs/nrf54l15_cpuapp.conf @@ -1,3 +1,17 @@ +# Copyright (c) 2024 Nordic Semiconductor ASA +# +# SPDX-License-Identifier: Apache-2.0 +# +CONFIG_BOOT_MAX_IMG_SECTORS=256 + +# Ensure that the SPI NOR driver is disabled by default +CONFIG_SPI_NOR=n + +CONFIG_BOOT_WATCHDOG_FEED=n + +# Ensure the fastest RRAM write operations +CONFIG_NRF_RRAM_WRITE_BUFFER_SIZE=32 + # Link Time Optimizations CONFIG_ISR_TABLES_LOCAL_DECLARATION=y CONFIG_LTO=y From a4457ac3dd0a734fb7ff2122fef2eadc3dc5b2ad Mon Sep 17 00:00:00 2001 From: Andrzej Puzdrowski Date: Thu, 19 Sep 2024 14:32:37 +0200 Subject: [PATCH 062/420] [nrf noup] boot/zephyr/Kconfig: conditionally disable BOOT_MAX_IMG_SECTORS_AUTO Automatic calculation are based on DTS data which are no the right source on partition layout in case Partition manager does the partitioning. Signed-off-by: Andrzej Puzdrowski Signed-off-by: Dominik Ermel (cherry picked from commit 19ac794b9c56162b8e59f07b8827ba1549c779de) --- boot/zephyr/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/boot/zephyr/Kconfig b/boot/zephyr/Kconfig index 89cda41bd..e482d9fab 100644 --- a/boot/zephyr/Kconfig +++ b/boot/zephyr/Kconfig @@ -709,7 +709,7 @@ config BOOT_ENCRYPTION_KEY_FILE config BOOT_MAX_IMG_SECTORS_AUTO bool "Calculate maximum sectors automatically" - default y + default y if !PARTITION_MANAGER_ENABLED help If this option is enabled then the maximum number of supported sectors per image will be calculated automatically from the flash erase sizes and size of each partition for From 2f3b28c09ebc156310732cc991d2c5995e62aed2 Mon Sep 17 00:00:00 2001 From: Jamie McCrae Date: Mon, 9 Dec 2024 12:27:38 +0000 Subject: [PATCH 063/420] [nrf noup] boot: zephyr: serial_recovery: Add nRF5340 Kconfig override Adds additional conditions that lets the direct upload option to be selected on nRF5340 to allow for uploading network core updates directly to the network core with the flash simulator Signed-off-by: Jamie McCrae (cherry picked from commit 2591ebdedca1d6deb2e94bb6d8617356d0d419be) --- boot/zephyr/Kconfig.serial_recovery | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/boot/zephyr/Kconfig.serial_recovery b/boot/zephyr/Kconfig.serial_recovery index 45d252408..5b4ba3e11 100644 --- a/boot/zephyr/Kconfig.serial_recovery +++ b/boot/zephyr/Kconfig.serial_recovery @@ -46,9 +46,14 @@ config BOOT_SERIAL_CDC_ACM endchoice +DT_COMPAT_SIM_FLASH:= zephyr,sim-flash +DT_SIM_FLASH_PATH := $(dt_nodelabel_path,flash_sim0) + config MCUBOOT_SERIAL_DIRECT_IMAGE_UPLOAD bool "Allow to select image number for DFU" - depends on !SINGLE_APPLICATION_SLOT + # Allow this option to be selected in cases where support for direct uploading to nRF5340 + # network core should be supported + depends on !SINGLE_APPLICATION_SLOT || (SINGLE_APPLICATION_SLOT && SOC_NRF5340_CPUAPP && BOOT_IMAGE_ACCESS_HOOK_NRF5340 && FLASH_SIMULATOR && $(dt_compat_enabled,$(DT_COMPAT_SIM_FLASH))) help With the option enabled, the mcuboot serial recovery will respect the "image" field in mcumgr image update frame From 9e2bba9806b33af0d52e1f62774de55a48d2538d Mon Sep 17 00:00:00 2001 From: Jamie McCrae Date: Thu, 5 Dec 2024 10:20:19 +0000 Subject: [PATCH 064/420] [nrf noup] boot: Remove child/parent references Removes stray child/parent references Signed-off-by: Jamie McCrae (cherry picked from commit 1e18f3cab16e601542e8ce7f620670d92db6e173) --- boot/bootutil/src/swap_priv.h | 2 +- boot/zephyr/pm.yml | 2 -- 2 files changed, 1 insertion(+), 3 deletions(-) diff --git a/boot/bootutil/src/swap_priv.h b/boot/bootutil/src/swap_priv.h index 90e0b3742..10473a9cc 100644 --- a/boot/bootutil/src/swap_priv.h +++ b/boot/bootutil/src/swap_priv.h @@ -131,7 +131,7 @@ bool swap_write_block_size_check(struct boot_loader_state *state); int app_max_size(struct boot_loader_state *state); #if defined(PM_S1_ADDRESS) && !defined(MCUBOOT_OVERWRITE_ONLY) && \ -(CONFIG_MCUBOOT_MCUBOOT_IMAGE_NUMBER != -1 || defined(LEGACY_CHILD_PARENT_S0_S1_UPDATE_ENABLED)) +CONFIG_MCUBOOT_MCUBOOT_IMAGE_NUMBER != -1 /** * Performs an NSIB update */ diff --git a/boot/zephyr/pm.yml b/boot/zephyr/pm.yml index 13ffc44aa..ab8f6d1c3 100644 --- a/boot/zephyr/pm.yml +++ b/boot/zephyr/pm.yml @@ -4,9 +4,7 @@ mcuboot: size: CONFIG_PM_PARTITION_SIZE_MCUBOOT placement: before: [mcuboot_primary] -#if defined(CONFIG_HIDE_CHILD_PARENT_CONFIG) align: {end: 0x1000} -#endif mcuboot_primary_app: # All images to be placed in MCUboot's slot 0 should be placed in this From 60dcc0d468fde468f36637a5603204a8ea972b9b Mon Sep 17 00:00:00 2001 From: Dominik Ermel Date: Wed, 15 Jan 2025 15:09:55 +0000 Subject: [PATCH 065/420] [nrf noup] sysflash: Add missing _FLASH_0_ID definitions MCUboot uses SOC_FLASH_0_ID and SPI_FLASH_0_ID to distinguish between internal and external boot device. These IDs are provided by sysflash.h, but the pm_sysflash.h overrides entire file, and was lacking that definitions. Signed-off-by: Dominik Ermel (cherry picked from commit 8a3f50821649cc71ac4cd68103eefb0ca7faa463) --- boot/zephyr/include/sysflash/pm_sysflash.h | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/boot/zephyr/include/sysflash/pm_sysflash.h b/boot/zephyr/include/sysflash/pm_sysflash.h index 42f25182e..0cb16292f 100644 --- a/boot/zephyr/include/sysflash/pm_sysflash.h +++ b/boot/zephyr/include/sysflash/pm_sysflash.h @@ -84,4 +84,12 @@ static inline uint32_t __flash_area_ids_for_slot(int img, int slot) #endif /* CONFIG_SINGLE_APPLICATION_SLOT */ +#ifndef SOC_FLASH_0_ID +#define SOC_FLASH_0_ID 0 +#endif + +#ifndef SPI_FLASH_0_ID +#define SPI_FLASH_0_ID 1 +#endif + #endif /* __PM_SYSFLASH_H__ */ From fd3ccd378677d6cd27df57dcb774698fa5adbdd9 Mon Sep 17 00:00:00 2001 From: Kamil Kasperczyk Date: Fri, 24 Jan 2025 08:59:31 +0100 Subject: [PATCH 066/420] [nrf noup] boot: zephyr: boards: Disabled NCS boot banner for thingy 53 Disabled NCS BOOT BANNER to save some flash, as Thingy:53 stopped to fit in the mcuboot partition. The boot banner is not used anyway, as logs are disabled. Signed-off-by: Kamil Kasperczyk (cherry picked from commit 2c73cb431579f6039cd18121d62e057a2ccc817f) --- boot/zephyr/boards/thingy53_nrf5340_cpuapp.conf | 1 + 1 file changed, 1 insertion(+) diff --git a/boot/zephyr/boards/thingy53_nrf5340_cpuapp.conf b/boot/zephyr/boards/thingy53_nrf5340_cpuapp.conf index d68509786..bbef18460 100644 --- a/boot/zephyr/boards/thingy53_nrf5340_cpuapp.conf +++ b/boot/zephyr/boards/thingy53_nrf5340_cpuapp.conf @@ -47,6 +47,7 @@ CONFIG_USB_CDC_ACM=y CONFIG_CBPRINTF_NANO=y CONFIG_TIMESLICING=n CONFIG_BOOT_BANNER=n +CONFIG_NCS_BOOT_BANNER=n CONFIG_CONSOLE=n CONFIG_CONSOLE_HANDLER=n CONFIG_UART_CONSOLE=n From 1f1b7be6c9500a53f9e55fe30a6b22898d5d478f Mon Sep 17 00:00:00 2001 From: Sigurd Hellesvik Date: Thu, 6 Feb 2025 08:47:39 +0100 Subject: [PATCH 067/420] [nrf noup] partition_manager: Add support for internal flash netcore DFU Adds check to region of mcuboot_secondary_1 to put it in external flash only if CONFIG_PM_EXTERNAL_FLASH_MCUBOOT_SECONDARY is set. This should allow for DFU from internal flash on the nRF5340 with dynamic partitioning. Also fixing a typo. Signed-off-by: Sigurd Hellesvik (cherry picked from commit 7911236b6da3cf291d98c40e87851d6666541027) --- boot/zephyr/pm.yml | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/boot/zephyr/pm.yml b/boot/zephyr/pm.yml index ab8f6d1c3..eec62473c 100644 --- a/boot/zephyr/pm.yml +++ b/boot/zephyr/pm.yml @@ -78,11 +78,17 @@ mcuboot_pad: mcuboot_primary_1: region: ram_flash size: CONFIG_NRF53_RAM_FLASH_SIZE -#endif /* CONFIG_NRF53_MULTI_IMAGE_UPDATE */ +#endif /* CONFIG_NRF53_MCUBOOT_PRIMARY_1_RAM_FLASH */ #if (CONFIG_NRF53_MULTI_IMAGE_UPDATE) mcuboot_secondary_1: +#if defined(CONFIG_PM_EXTERNAL_FLASH_MCUBOOT_SECONDARY) region: external_flash +#else + placement: + align: {start: CONFIG_FPROTECT_BLOCK_SIZE} + after: mcuboot_secondary +#endif size: CONFIG_NRF53_RAM_FLASH_SIZE #endif /* CONFIG_NRF53_MULTI_IMAGE_UPDATE */ From f471000c9946cbd678b25ce9b63427550d525450 Mon Sep 17 00:00:00 2001 From: Dominik Ermel Date: Tue, 4 Mar 2025 17:31:33 +0000 Subject: [PATCH 068/420] [nrf noup] zephyr: sdk-nrf specific overrides on PSA Kconfigs Select proper configuration and disable mbedTLS selection, as we are using NRF Security enabled Oberon. Signed-off-by: Dominik Ermel Signed-off-by: Artur Hadasz (cherry picked from commit 558d1c1dd10eecad9120582d63c79299698d180b) --- boot/bootutil/zephyr/CMakeLists.txt | 2 +- boot/zephyr/Kconfig | 18 +++++++++++------- 2 files changed, 12 insertions(+), 8 deletions(-) diff --git a/boot/bootutil/zephyr/CMakeLists.txt b/boot/bootutil/zephyr/CMakeLists.txt index f6d37441c..44f78f395 100644 --- a/boot/bootutil/zephyr/CMakeLists.txt +++ b/boot/bootutil/zephyr/CMakeLists.txt @@ -40,7 +40,7 @@ if(CONFIG_BOOT_USE_PSA_CRYPTO) ) endif() -if(CONFIG_BOOT_USE_MBEDTLS OR CONFIG_BOOT_USE_PSA_CRYPTO) +if(CONFIG_BOOT_USE_MBEDTLS OR CONFIG_BOOT_USE_PSA_CRYPTO AND NOT CONFIG_NRF_SECURITY) zephyr_link_libraries(mbedTLS) endif() endif() diff --git a/boot/zephyr/Kconfig b/boot/zephyr/Kconfig index e482d9fab..3d729d663 100644 --- a/boot/zephyr/Kconfig +++ b/boot/zephyr/Kconfig @@ -88,8 +88,7 @@ config BOOT_PSA_IMG_HASH_ALG_SHA512_DEPENDENCIES config BOOT_ED25519_PSA_DEPENDENCIES bool select PSA_WANT_ALG_PURE_EDDSA - # Seems that upstream mbedTLS does not have TE - #select PSA_WANT_ECC_TWISTED_EDWARDS_255 + select PSA_WANT_ECC_TWISTED_EDWARDS_255 select PSA_WANT_ECC_MONTGOMERY_255 select PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_IMPORT help @@ -119,7 +118,7 @@ endif # BOOT_ENCRYPT_IMAGE config BOOT_ECDSA_PSA_DEPENDENCIES bool select PSA_WANT_ALG_ECDSA - select PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_IMPORT + select PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_IMPORT if !PSA_CORE_LITE select PSA_WANT_ECC_SECP_R1_256 help Dependencies for ECDSA signature @@ -248,7 +247,8 @@ choice BOOT_SIGNATURE_TYPE config BOOT_SIGNATURE_TYPE_NONE bool "No signature; use only hash check" - select BOOT_USE_TINYCRYPT + select BOOT_USE_TINYCRYPT if !SOC_SERIES_NRF54LX + select BOOT_USE_PSA_CRYPTO if SOC_SERIES_NRF54LX select BOOT_IMG_HASH_ALG_SHA256_ALLOW config BOOT_SIGNATURE_TYPE_RSA @@ -280,6 +280,7 @@ config BOOT_SIGNATURE_TYPE_ECDSA_P256 if BOOT_SIGNATURE_TYPE_ECDSA_P256 choice BOOT_ECDSA_IMPLEMENTATION prompt "Ecdsa implementation" + default BOOT_ECDSA_PSA if NRF_SECURITY default BOOT_ECDSA_TINYCRYPT config BOOT_ECDSA_TINYCRYPT @@ -296,11 +297,12 @@ config BOOT_ECDSA_CC310 config BOOT_ECDSA_PSA bool "Use psa cryptoo" + depends on NRF_SECURITY select BOOT_USE_PSA_CRYPTO select PSA_CRYPTO_CLIENT select PSA_CRYPTO_C - select BOOT_IMG_HASH_ALG_SHA256_ALLOW - select BOOT_IMG_HASH_ALG_SHA512_ALLOW + select BOOT_IMG_HASH_ALG_SHA256_ALLOW if !PSA_CORE_LITE + select BOOT_IMG_HASH_ALG_SHA512_ALLOW if !PSA_CORE_LITE select BOOT_ECDSA_PSA_DEPENDENCIES endchoice # Ecdsa implementation @@ -332,6 +334,7 @@ config BOOT_SIGNATURE_TYPE_PURE choice BOOT_ED25519_IMPLEMENTATION prompt "Ecdsa implementation" + default BOOT_ED25519_PSA if NRF_SECURITY default BOOT_ED25519_TINYCRYPT config BOOT_ED25519_TINYCRYPT @@ -352,7 +355,7 @@ config BOOT_ED25519_MBEDTLS config BOOT_ED25519_PSA bool "Use PSA crypto" - select MBEDTLS + depends on NRF_SECURITY select BOOT_USE_PSA_CRYPTO select PSA_CRYPTO_CLIENT select PSA_CRYPTO_C @@ -429,6 +432,7 @@ config MBEDTLS_CFG_FILE # is used, but the fact is that Mbed TLS' ASN1 parse module is used # also when TinyCrypt is used as crypto backend. default "mcuboot-mbedtls-cfg.h" if BOOT_USE_TINYCRYPT + default "config-tls-generic.h" if NRF_SECURITY && (MBEDTLS_BUILTIN || BOOT_USE_PSA_CRYPTO) default "mcuboot-mbedtls-cfg.h" if BOOT_USE_MBEDTLS && !MBEDTLS_BUILTIN config BOOT_HW_KEY From 791dd599386c95e464c6958927fb98a88dd61e3e Mon Sep 17 00:00:00 2001 From: Jamie McCrae Date: Tue, 11 Jul 2023 08:42:49 +0100 Subject: [PATCH 069/420] [nrf noup] zephyr: Fix path variables Fixes path variables to use the proper Zephyr module variables Signed-off-by: Jamie McCrae Signed-off-by: Dominik Ermel (cherry picked from commit 63224e31afcd983f3d435f259372a6a3d853a46c) --- boot/zephyr/CMakeLists.txt | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/boot/zephyr/CMakeLists.txt b/boot/zephyr/CMakeLists.txt index 0bd0fb919..e2c981aae 100644 --- a/boot/zephyr/CMakeLists.txt +++ b/boot/zephyr/CMakeLists.txt @@ -35,21 +35,20 @@ if(NOT CONFIG_MBEDTLS_BUILTIN AND NOT CONFIG_BOOT_KEY_IMPORT_BYPASS_ASN) set(MBEDTLS_ASN1_DIR "${MCUBOOT_DIR}/ext/mbedtls-asn1") assert_exists(MBEDTLS_ASN1_DIR) endif() -set(NRF_DIR "${MCUBOOT_DIR}/ext/nrf") +set(MCUBOOT_NRF_EXT_DIR "${MCUBOOT_DIR}/ext/nrf") if(CONFIG_BOOT_USE_NRF_CC310_BL) -set(NRFXLIB_DIR ${ZEPHYR_BASE}/../nrfxlib) -if(NOT EXISTS ${NRFXLIB_DIR}) - message(FATAL_ERROR " + if(NOT EXISTS ${ZEPHYR_NRFXLIB_MODULE_DIR}) + message(FATAL_ERROR " ------------------------------------------------------------------------ - No such file or directory: ${NRFXLIB_DIR} + No such file or directory: ${ZEPHYR_NRFXLIB_MODULE_DIR} The current configuration enables nRF CC310 crypto accelerator hardware with the `CONFIG_BOOT_USE_NRF_CC310_BL` option. Please follow `ext/nrf/README.md` guide to fix your setup or use tinycrypt instead of the HW accelerator. To use the tinycrypt set `CONFIG_BOOT_ECDSA_TINYCRYPT` to y. ------------------------------------------------------------------------") -endif() + endif() endif() zephyr_library_include_directories( @@ -218,8 +217,8 @@ if(CONFIG_BOOT_SIGNATURE_TYPE_ECDSA_P256 OR CONFIG_BOOT_ENCRYPT_EC256) ${TINYCRYPT_DIR}/source/utils.c ) elseif(CONFIG_BOOT_USE_NRF_CC310_BL) - zephyr_library_sources(${NRF_DIR}/cc310_glue.c) - zephyr_library_include_directories(${NRF_DIR}) + zephyr_library_sources(${MCUBOOT_NRF_EXT_DIR}/cc310_glue.c) + zephyr_library_include_directories(${MCUBOOT_NRF_EXT_DIR}) zephyr_link_libraries(nrfxlib_crypto) elseif(CONFIG_BOOT_USE_NRF_EXTERNAL_CRYPTO) zephyr_include_directories(${BL_CRYPTO_DIR}/../include) From 7f674d9817e30c458a33af49211a34f21bb023da Mon Sep 17 00:00:00 2001 From: Dominik Ermel Date: Fri, 14 Mar 2025 17:51:23 +0000 Subject: [PATCH 070/420] [nrf noup] zephyr: Use mbedTLS specific C functions with RSA Use snprinf, alloc, calloc and free from mbedTLS rather than from Zephyr. Signed-off-by: Dominik Ermel (cherry picked from commit 7ff9d37234f071e8ee0442b03df8f45058e2c39f) --- boot/zephyr/Kconfig | 2 ++ 1 file changed, 2 insertions(+) diff --git a/boot/zephyr/Kconfig b/boot/zephyr/Kconfig index 3d729d663..5aee4f1eb 100644 --- a/boot/zephyr/Kconfig +++ b/boot/zephyr/Kconfig @@ -261,6 +261,8 @@ config BOOT_SIGNATURE_TYPE_RSA select MBEDTLS_PKCS1_V15 if MBEDTLS_BUILTIN select MBEDTLS_PKCS1_V21 if MBEDTLS_BUILTIN select MBEDTLS_KEY_EXCHANGE_RSA_ENABLED if MBEDTLS_BUILTIN + select MBEDTLS_PLATFORM_NO_STD_FUNCTIONS if MBEDTLS_BUILTIN + select MBEDTLS_PLATFORM_SNPRINTF_ALT if MBEDTLS_BUILTIN select BOOT_ENCRYPTION_SUPPORT select BOOT_IMG_HASH_ALG_SHA256_ALLOW select BOOT_AES_MBEDTLS_DEPENDENCIES if MBEDTLS_BUILTIN && BOOT_ENCRYPT_IMAGE From c872f6ab7bd026fe779543f24ede6d2b343202f3 Mon Sep 17 00:00:00 2001 From: Michal Kozikowski Date: Mon, 10 Mar 2025 17:23:37 +0100 Subject: [PATCH 071/420] [nrf noup] boot/zephyr: nrf54h20dk board support Added basic support for nrf54h20dk_nrf54h20_cpuapp_iron board. This commit turns off CONFIG_FPROTECT for this board build. Signed-off-by: Michal Kozikowski (cherry picked from commit b404bb106afc4705ffe9b92a63196f8881500195) --- boot/zephyr/boards/nrf54h20dk_nrf54h20_cpuapp_iron.conf | 3 +++ 1 file changed, 3 insertions(+) diff --git a/boot/zephyr/boards/nrf54h20dk_nrf54h20_cpuapp_iron.conf b/boot/zephyr/boards/nrf54h20dk_nrf54h20_cpuapp_iron.conf index 12c96ff0f..31666d9fe 100644 --- a/boot/zephyr/boards/nrf54h20dk_nrf54h20_cpuapp_iron.conf +++ b/boot/zephyr/boards/nrf54h20dk_nrf54h20_cpuapp_iron.conf @@ -6,4 +6,7 @@ # Ensure that the SPI NOR driver is disabled by default CONFIG_SPI_NOR=n +# TODO: below are not yet supported and need fixing +CONFIG_FPROTECT=n + CONFIG_BOOT_WATCHDOG_FEED=n From 31766fcae89baee588d1ac49802ce5b1fd7b544d Mon Sep 17 00:00:00 2001 From: Michal Kozikowski Date: Fri, 28 Mar 2025 17:46:28 +0100 Subject: [PATCH 072/420] [nrf noup] boot/zephyr: nrf54h20dk cleanup adaptations This commit removes NRF_CLOCK cleanup for this board build - for Lillium, there is no clock peripheral access from the app domain. Signed-off-by: Michal Kozikowski (cherry picked from commit ea5b6b6e8bda2c3570e509c18e18642c7d69c95a) --- boot/zephyr/nrf_cleanup.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/boot/zephyr/nrf_cleanup.c b/boot/zephyr/nrf_cleanup.c index 051705ec9..72c601db3 100644 --- a/boot/zephyr/nrf_cleanup.c +++ b/boot/zephyr/nrf_cleanup.c @@ -4,7 +4,9 @@ * SPDX-License-Identifier: LicenseRef-Nordic-5-Clause */ +#if !defined(CONFIG_SOC_SERIES_NRF54HX) #include +#endif #include #include #if defined(NRF_RTC0) || defined(NRF_RTC1) || defined(NRF_RTC2) @@ -62,10 +64,12 @@ static NRF_UARTE_Type *nrf_uarte_to_clean[] = { }; #endif +#if !defined(CONFIG_SOC_SERIES_NRF54HX) static void nrf_cleanup_clock(void) { nrf_clock_int_disable(NRF_CLOCK, 0xFFFFFFFF); } +#endif void nrf_cleanup_peripheral(void) { @@ -109,7 +113,10 @@ void nrf_cleanup_peripheral(void) #if defined(NRF_DPPIC) nrf_dppi_channels_disable_all(NRF_DPPIC); #endif + +#if !defined(CONFIG_SOC_SERIES_NRF54HX) nrf_cleanup_clock(); +#endif } #if USE_PARTITION_MANAGER \ From fac7ac4990fe9f28348bfb3e0e52ac4bf51c757a Mon Sep 17 00:00:00 2001 From: Andrzej Puzdrowski Date: Tue, 5 Mar 2024 18:44:13 +0100 Subject: [PATCH 073/420] [nrf noup] boot/zephyr/nrf_cleanup: cleanup uarte pins Added procedure which does configure UARTE pins to the default states. This allows to reduce power consumption if pin is floating. clean-up UARTE only if its driver was enabled Signed-off-by: Andrzej Puzdrowski (cherry picked from commit 1f19003bc37950ba4c42673beb98b514da974829) --- boot/zephyr/nrf_cleanup.c | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/boot/zephyr/nrf_cleanup.c b/boot/zephyr/nrf_cleanup.c index 72c601db3..1252334ca 100644 --- a/boot/zephyr/nrf_cleanup.c +++ b/boot/zephyr/nrf_cleanup.c @@ -9,6 +9,7 @@ #endif #include #include +#include #if defined(NRF_RTC0) || defined(NRF_RTC1) || defined(NRF_RTC2) #include #endif @@ -96,6 +97,21 @@ void nrf_cleanup_peripheral(void) nrfy_uarte_event_clear(current, NRF_UARTE_EVENT_RXTO); nrfy_uarte_disable(current); + uint32_t pin[4]; + + pin[0] = nrfy_uarte_tx_pin_get(current); + pin[1] = nrfy_uarte_rx_pin_get(current); + pin[2] = nrfy_uarte_rts_pin_get(current); + pin[3] = nrfy_uarte_cts_pin_get(current); + + nrfy_uarte_pins_disconnect(current); + + for (int j = 0; j < 4; j++) { + if (pin[j] != NRF_UARTE_PSEL_DISCONNECTED) { + nrfy_gpio_cfg_default(pin[i]); + } + } + #if defined(NRF_DPPIC) /* Clear all SUBSCRIBE configurations. */ memset((uint8_t *)current + NRF_UARTE_SUBSCRIBE_CONF_OFFS, 0, From c6e2585f8e382a3bc6f1700d892d3636a3155af5 Mon Sep 17 00:00:00 2001 From: Andrzej Puzdrowski Date: Tue, 1 Apr 2025 19:30:57 +0200 Subject: [PATCH 074/420] [nrf noup] boot/zephyr/Kconfig: fix MBEDTLS_CFG_FILE value Zephyr provides "mcuboot-mbedtls-cfg.h" as glue interface for configure mbedts. "config-tls-generic.h" default value was erroneously introduced during a meta codebase synchronization. Signed-off-by: Andrzej Puzdrowski (cherry picked from commit a5b259409ac74ed94b5bf304a4e9d756b465997f) --- boot/zephyr/Kconfig | 1 - 1 file changed, 1 deletion(-) diff --git a/boot/zephyr/Kconfig b/boot/zephyr/Kconfig index 5aee4f1eb..1c71f33eb 100644 --- a/boot/zephyr/Kconfig +++ b/boot/zephyr/Kconfig @@ -434,7 +434,6 @@ config MBEDTLS_CFG_FILE # is used, but the fact is that Mbed TLS' ASN1 parse module is used # also when TinyCrypt is used as crypto backend. default "mcuboot-mbedtls-cfg.h" if BOOT_USE_TINYCRYPT - default "config-tls-generic.h" if NRF_SECURITY && (MBEDTLS_BUILTIN || BOOT_USE_PSA_CRYPTO) default "mcuboot-mbedtls-cfg.h" if BOOT_USE_MBEDTLS && !MBEDTLS_BUILTIN config BOOT_HW_KEY From 5f6e119a726d9f17b3f65139540db838f2286bde Mon Sep 17 00:00:00 2001 From: Andrzej Puzdrowski Date: Fri, 11 Apr 2025 12:55:00 +0200 Subject: [PATCH 075/420] [nrf noup] nrf_cleanup: nRF54l: disable cleanup on UARTE pins Compile out code which does cleanup on UARTE pins as this cause issues on for some applications. ref.: NCSDK-33039 Signed-off-by: Andrzej Puzdrowski (cherry picked from commit 5717af4899216809cc1a9b84454c38179920246a) --- boot/zephyr/nrf_cleanup.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/boot/zephyr/nrf_cleanup.c b/boot/zephyr/nrf_cleanup.c index 1252334ca..f90a46af1 100644 --- a/boot/zephyr/nrf_cleanup.c +++ b/boot/zephyr/nrf_cleanup.c @@ -97,6 +97,12 @@ void nrf_cleanup_peripheral(void) nrfy_uarte_event_clear(current, NRF_UARTE_EVENT_RXTO); nrfy_uarte_disable(current); +#ifndef CONFIG_SOC_SERIES_NRF54LX + /* Disconnect pins UARTE pins + * causes issues on nRF54l SoCs, + * could be enabled once fix to NCSDK-33039 will be implemented. + */ + uint32_t pin[4]; pin[0] = nrfy_uarte_tx_pin_get(current); @@ -111,6 +117,7 @@ void nrf_cleanup_peripheral(void) nrfy_gpio_cfg_default(pin[i]); } } +#endif #if defined(NRF_DPPIC) /* Clear all SUBSCRIBE configurations. */ From 1aa8af0eae8d67f21cdccd81588f37cebde536c8 Mon Sep 17 00:00:00 2001 From: Mateusz Michalek Date: Wed, 23 Apr 2025 09:05:24 +0200 Subject: [PATCH 076/420] [nrf noup] boot: zephyr: boards: nrf54lm20pdk adding default configs. Signed-off-by: Mateusz Michalek (cherry picked from commit cc3d19b82c584e9759ba0cbc022a0d80747117ca) --- .../boards/nrf54lm20pdk_nrf54lm20a_cpuapp.conf | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) create mode 100644 boot/zephyr/boards/nrf54lm20pdk_nrf54lm20a_cpuapp.conf diff --git a/boot/zephyr/boards/nrf54lm20pdk_nrf54lm20a_cpuapp.conf b/boot/zephyr/boards/nrf54lm20pdk_nrf54lm20a_cpuapp.conf new file mode 100644 index 000000000..4944f7b13 --- /dev/null +++ b/boot/zephyr/boards/nrf54lm20pdk_nrf54lm20a_cpuapp.conf @@ -0,0 +1,16 @@ +# Copyright (c) 2025 Nordic Semiconductor ASA +# +# SPDX-License-Identifier: Apache-2.0 +# +CONFIG_BOOT_MAX_IMG_SECTORS=256 + +# Ensure that the SPI NOR driver is disabled by default +CONFIG_SPI_NOR=n + +# TODO: below are not yet supported and need fixing +CONFIG_FPROTECT=n + +CONFIG_BOOT_WATCHDOG_FEED=n + +CONFIG_PSA_CRYPTO_DRIVER_CRACEN=n +CONFIG_PSA_CRYPTO_DRIVER_OBERON=y From b6c992e20c51fd77c1761450aaae118fee3f097d Mon Sep 17 00:00:00 2001 From: Artur Hadasz Date: Mon, 28 Apr 2025 14:17:35 +0200 Subject: [PATCH 077/420] [nrf noup] nrf_cleanup: nRF54h: fix missing peripheral cleanup This commit adds cleanup for GRTC and UARTE peripherals. ref: NCSDK-32966 Signed-off-by: Artur Hadasz (cherry picked from commit df61bd1f2181a7ccc7f908afbd8cd26f6858edfc) --- boot/zephyr/nrf_cleanup.c | 23 ++++++++++++++++++++--- 1 file changed, 20 insertions(+), 3 deletions(-) diff --git a/boot/zephyr/nrf_cleanup.c b/boot/zephyr/nrf_cleanup.c index f90a46af1..39dfcbc41 100644 --- a/boot/zephyr/nrf_cleanup.c +++ b/boot/zephyr/nrf_cleanup.c @@ -4,7 +4,7 @@ * SPDX-License-Identifier: LicenseRef-Nordic-5-Clause */ -#if !defined(CONFIG_SOC_SERIES_NRF54HX) +#if defined(CONFIG_NRFX_CLOCK) #include #endif #include @@ -13,6 +13,9 @@ #if defined(NRF_RTC0) || defined(NRF_RTC1) || defined(NRF_RTC2) #include #endif +#if defined(CONFIG_NRF_GRTC_TIMER) + #include +#endif #if defined(NRF_PPI) #include #endif @@ -48,6 +51,13 @@ static inline void nrf_cleanup_rtc(NRF_RTC_Type * rtc_reg) } #endif +#if defined(CONFIG_NRF_GRTC_TIMER) +static inline void nrf_cleanup_grtc(void) +{ + nrfx_grtc_uninit(); +} +#endif + #if defined(NRF_UARTE_CLEANUP) static NRF_UARTE_Type *nrf_uarte_to_clean[] = { #if defined(NRF_UARTE0) @@ -62,10 +72,13 @@ static NRF_UARTE_Type *nrf_uarte_to_clean[] = { #if defined(NRF_UARTE30) NRF_UARTE30, #endif +#if defined(NRF_UARTE136) + NRF_UARTE136, +#endif }; #endif -#if !defined(CONFIG_SOC_SERIES_NRF54HX) +#if defined(CONFIG_NRFX_CLOCK) static void nrf_cleanup_clock(void) { nrf_clock_int_disable(NRF_CLOCK, 0xFFFFFFFF); @@ -84,6 +97,10 @@ void nrf_cleanup_peripheral(void) nrf_cleanup_rtc(NRF_RTC2); #endif +#if defined(CONFIG_NRF_GRTC_TIMER) + nrf_cleanup_grtc(); +#endif + #if defined(NRF_UARTE_CLEANUP) for (int i = 0; i < sizeof(nrf_uarte_to_clean) / sizeof(nrf_uarte_to_clean[0]); ++i) { NRF_UARTE_Type *current = nrf_uarte_to_clean[i]; @@ -137,7 +154,7 @@ void nrf_cleanup_peripheral(void) nrf_dppi_channels_disable_all(NRF_DPPIC); #endif -#if !defined(CONFIG_SOC_SERIES_NRF54HX) +#if defined(CONFIG_NRFX_CLOCK) nrf_cleanup_clock(); #endif } From 898b9bcb12baf499860ed7eb5d4754f1bbaa4284 Mon Sep 17 00:00:00 2001 From: Jamie McCrae Date: Thu, 22 Aug 2024 14:17:46 +0100 Subject: [PATCH 078/420] [nrf noup] zephyr: Add support for compressed image updates Adds support for LZMA-compressed firmware updates which also supports encrypted images and supports more than 1 updateable image Signed-off-by: Jamie McCrae Signed-off-by: Michal Kozikowski Signed-off-by: Dominik Ermel (cherry picked from commit c3ba62823648cd9ce3d933bcdeb08fc791033838) --- boot/bootutil/src/bootutil_misc.c | 80 +- boot/bootutil/src/image_validate.c | 223 ++- boot/bootutil/src/loader.c | 27 +- boot/zephyr/CMakeLists.txt | 6 + boot/zephyr/Kconfig | 9 +- boot/zephyr/decompression.c | 1505 +++++++++++++++++ .../include/compression/decompression.h | 103 ++ 7 files changed, 1929 insertions(+), 24 deletions(-) create mode 100644 boot/zephyr/decompression.c create mode 100644 boot/zephyr/include/compression/decompression.h diff --git a/boot/bootutil/src/bootutil_misc.c b/boot/bootutil/src/bootutil_misc.c index a88ad0dad..96be26692 100644 --- a/boot/bootutil/src/bootutil_misc.c +++ b/boot/bootutil/src/bootutil_misc.c @@ -47,6 +47,11 @@ #include "swap_priv.h" #endif +#if defined(MCUBOOT_DECOMPRESS_IMAGES) +#include +#include +#endif + BOOT_LOG_MODULE_DECLARE(mcuboot); /* Currently only used by imgmgr */ @@ -482,35 +487,76 @@ boot_read_image_size(struct boot_loader_state *state, int slot, uint32_t *size) fap = BOOT_IMG_AREA(state, slot); assert(fap != NULL); - off = BOOT_TLV_OFF(boot_img_hdr(state, slot)); +#ifdef MCUBOOT_DECOMPRESS_IMAGES + if (MUST_DECOMPRESS(fap, BOOT_CURR_IMG(state), boot_img_hdr(state, slot))) { + uint32_t tmp_size = 0; - if (flash_area_read(fap, off, &info, sizeof(info))) { - rc = BOOT_EFLASH; - goto done; - } + rc = bootutil_get_img_decomp_size(boot_img_hdr(state, slot), fap, &tmp_size); + + if (rc) { + rc = BOOT_EBADIMAGE; + goto done; + } + + off = boot_img_hdr(state, slot)->ih_hdr_size + tmp_size; + + rc = boot_size_protected_tlvs(boot_img_hdr(state, slot), fap, &tmp_size); - protect_tlv_size = boot_img_hdr(state, slot)->ih_protect_tlv_size; - if (info.it_magic == IMAGE_TLV_PROT_INFO_MAGIC) { - if (protect_tlv_size != info.it_tlv_tot) { + if (rc) { rc = BOOT_EBADIMAGE; goto done; } - if (flash_area_read(fap, off + info.it_tlv_tot, &info, sizeof(info))) { + off += tmp_size; + + if (flash_area_read(fap, (BOOT_TLV_OFF(boot_img_hdr(state, slot)) + + boot_img_hdr(state, slot)->ih_protect_tlv_size), &info, + sizeof(info))) { rc = BOOT_EFLASH; goto done; } - } else if (protect_tlv_size != 0) { - rc = BOOT_EBADIMAGE; - goto done; - } - if (info.it_magic != IMAGE_TLV_INFO_MAGIC) { - rc = BOOT_EBADIMAGE; - goto done; + if (info.it_magic != IMAGE_TLV_INFO_MAGIC) { + rc = BOOT_EBADIMAGE; + goto done; + } + + *size = off + info.it_tlv_tot; + } else { +#else + if (1) { +#endif + off = BOOT_TLV_OFF(boot_img_hdr(state, slot)); + + if (flash_area_read(fap, off, &info, sizeof(info))) { + rc = BOOT_EFLASH; + goto done; + } + + protect_tlv_size = boot_img_hdr(state, slot)->ih_protect_tlv_size; + if (info.it_magic == IMAGE_TLV_PROT_INFO_MAGIC) { + if (protect_tlv_size != info.it_tlv_tot) { + rc = BOOT_EBADIMAGE; + goto done; + } + + if (flash_area_read(fap, off + info.it_tlv_tot, &info, sizeof(info))) { + rc = BOOT_EFLASH; + goto done; + } + } else if (protect_tlv_size != 0) { + rc = BOOT_EBADIMAGE; + goto done; + } + + if (info.it_magic != IMAGE_TLV_INFO_MAGIC) { + rc = BOOT_EBADIMAGE; + goto done; + } + + *size = off + protect_tlv_size + info.it_tlv_tot; } - *size = off + protect_tlv_size + info.it_tlv_tot; rc = 0; done: diff --git a/boot/bootutil/src/image_validate.c b/boot/bootutil/src/image_validate.c index ade67cc4b..0875fd47b 100644 --- a/boot/bootutil/src/image_validate.c +++ b/boot/bootutil/src/image_validate.c @@ -45,6 +45,11 @@ BOOT_LOG_MODULE_DECLARE(mcuboot); +#if defined(MCUBOOT_DECOMPRESS_IMAGES) +#include +#include +#endif + #ifdef MCUBOOT_ENC_IMAGES #include "bootutil/enc_key.h" #endif @@ -507,7 +512,7 @@ bootutil_img_validate(struct boot_loader_state *state, #endif ) { -#if (defined(EXPECTED_KEY_TLV) && defined(MCUBOOT_HW_KEY)) || defined(MCUBOOT_HW_ROLLBACK_PROT) +#if (defined(EXPECTED_KEY_TLV) && defined(MCUBOOT_HW_KEY)) || defined(MCUBOOT_HW_ROLLBACK_PROT) || defined(MCUBOOT_DECOMPRESS_IMAGES) int image_index = (state == NULL ? 0 : BOOT_CURR_IMG(state)); #endif uint32_t off; @@ -552,6 +557,67 @@ bootutil_img_validate(struct boot_loader_state *state, #endif BOOT_LOG_DBG("bootutil_img_validate: flash area %p", fap); +#ifdef MCUBOOT_DECOMPRESS_IMAGES + /* If the image is compressed, the integrity of the image must also be validated */ + if (MUST_DECOMPRESS(fap, image_index, hdr)) { + bool found_decompressed_size = false; + bool found_decompressed_sha = false; + bool found_decompressed_signature = false; + + rc = bootutil_tlv_iter_begin(&it, hdr, fap, IMAGE_TLV_ANY, true); + if (rc) { + goto out; + } + + if (it.tlv_end > bootutil_max_image_size(state, fap)) { + rc = -1; + goto out; + } + + while (true) { + uint16_t expected_size = 0; + bool *found_flag = NULL; + + rc = bootutil_tlv_iter_next(&it, &off, &len, &type); + if (rc < 0) { + goto out; + } else if (rc > 0) { + break; + } + + switch (type) { + case IMAGE_TLV_DECOMP_SIZE: + expected_size = sizeof(size_t); + found_flag = &found_decompressed_size; + break; + case IMAGE_TLV_DECOMP_SHA: + expected_size = IMAGE_HASH_SIZE; + found_flag = &found_decompressed_sha; + break; + case IMAGE_TLV_DECOMP_SIGNATURE: + found_flag = &found_decompressed_signature; + break; + default: + continue; + }; + + if (type == IMAGE_TLV_DECOMP_SIGNATURE && !EXPECTED_SIG_LEN(len)) { + rc = -1; + goto out; + } else if (type != IMAGE_TLV_DECOMP_SIGNATURE && len != expected_size) { + rc = -1; + goto out; + } + + *found_flag = true; + } + + rc = (!found_decompressed_size || !found_decompressed_sha || !found_decompressed_signature); + if (rc) { + goto out; + } + } +#endif #if defined(EXPECTED_HASH_TLV) && !defined(MCUBOOT_SIGN_PURE) #if defined(MCUBOOT_SWAP_USING_OFFSET) && defined(MCUBOOT_SERIAL_RECOVERY) @@ -800,6 +866,161 @@ bootutil_img_validate(struct boot_loader_state *state, skip_security_counter_check: #endif +#ifdef MCUBOOT_DECOMPRESS_IMAGES + /* Only after all previous verifications have passed, perform a dry-run of the decompression + * and ensure the image is valid + */ + if (!rc && MUST_DECOMPRESS(fap, image_index, hdr)) { + image_hash_valid = 0; + FIH_SET(valid_signature, FIH_FAILURE); + + rc = bootutil_img_hash_decompress(state, hdr, fap, tmp_buf, tmp_buf_sz, + hash, seed, seed_len); + if (rc) { + goto out; + } + + rc = bootutil_tlv_iter_begin(&it, hdr, fap, IMAGE_TLV_DECOMP_SHA, true); + if (rc) { + goto out; + } + + if (it.tlv_end > bootutil_max_image_size(state, fap)) { + rc = -1; + goto out; + } + + while (true) { + rc = bootutil_tlv_iter_next(&it, &off, &len, &type); + if (rc < 0) { + goto out; + } else if (rc > 0) { + break; + } + + if (type == IMAGE_TLV_DECOMP_SHA) { + /* Verify the image hash. This must always be present. */ + if (len != sizeof(hash)) { + rc = -1; + goto out; + } + rc = LOAD_IMAGE_DATA(hdr, fap, off, buf, sizeof(hash)); + if (rc) { + goto out; + } + + FIH_CALL(boot_fih_memequal, fih_rc, hash, buf, sizeof(hash)); + if (FIH_NOT_EQ(fih_rc, FIH_SUCCESS)) { + FIH_SET(fih_rc, FIH_FAILURE); + goto out; + } + + image_hash_valid = 1; + } + } + + rc = !image_hash_valid; + if (rc) { + goto out; + } + +#ifdef EXPECTED_SIG_TLV +#ifdef EXPECTED_KEY_TLV + rc = bootutil_tlv_iter_begin(&it, hdr, fap, EXPECTED_KEY_TLV, false); + if (rc) { + goto out; + } + + if (it.tlv_end > bootutil_max_image_size(state, fap)) { + rc = -1; + goto out; + } + + while (true) { + rc = bootutil_tlv_iter_next(&it, &off, &len, &type); + if (rc < 0) { + goto out; + } else if (rc > 0) { + break; + } + + if (type == EXPECTED_KEY_TLV) { + /* + * Determine which key we should be checking. + */ + if (len > KEY_BUF_SIZE) { + rc = -1; + goto out; + } +#ifndef MCUBOOT_HW_KEY + rc = LOAD_IMAGE_DATA(hdr, fap, off, buf, len); + if (rc) { + goto out; + } + key_id = bootutil_find_key(buf, len); +#else + rc = LOAD_IMAGE_DATA(hdr, fap, off, key_buf, len); + if (rc) { + goto out; + } + key_id = bootutil_find_key(image_index, key_buf, len); +#endif /* !MCUBOOT_HW_KEY */ + /* + * The key may not be found, which is acceptable. There + * can be multiple signatures, each preceded by a key. + */ + } + } +#endif /* EXPECTED_KEY_TLV */ + + rc = bootutil_tlv_iter_begin(&it, hdr, fap, IMAGE_TLV_DECOMP_SIGNATURE, true); + if (rc) { + goto out; + } + + if (it.tlv_end > bootutil_max_image_size(state, fap)) { + rc = -1; + goto out; + } + + while (true) { + rc = bootutil_tlv_iter_next(&it, &off, &len, &type); + if (rc < 0) { + goto out; + } else if (rc > 0) { + rc = 0; + break; + } + + if (type == IMAGE_TLV_DECOMP_SIGNATURE) { + /* Ignore this signature if it is out of bounds. */ + if (key_id < 0 || key_id >= bootutil_key_cnt) { + key_id = -1; + continue; + } + + if (!EXPECTED_SIG_LEN(len) || len > sizeof(buf)) { + rc = -1; + goto out; + } + rc = LOAD_IMAGE_DATA(hdr, fap, off, buf, len); + if (rc) { + goto out; + } + + FIH_CALL(bootutil_verify_sig, valid_signature, hash, sizeof(hash), + buf, len, key_id); + key_id = -1; + } + } +#endif /* EXPECTED_SIG_TLV */ + } +#endif + +#ifdef EXPECTED_SIG_TLV + FIH_SET(fih_rc, valid_signature); +#endif + out: if (rc) { FIH_SET(fih_rc, FIH_FAILURE); diff --git a/boot/bootutil/src/loader.c b/boot/bootutil/src/loader.c index dd4853874..c074a00db 100644 --- a/boot/bootutil/src/loader.c +++ b/boot/bootutil/src/loader.c @@ -50,6 +50,11 @@ #include "bootutil/boot_hooks.h" #include "bootutil/mcuboot_status.h" +#if defined(MCUBOOT_DECOMPRESS_IMAGES) +#include +#include +#endif + #ifdef __ZEPHYR__ #include #endif @@ -1012,10 +1017,10 @@ boot_is_header_valid(const struct image_header *hdr, const struct flash_area *fa return false; } #else - if ((hdr->ih_flags & IMAGE_F_COMPRESSED_LZMA1) && - (hdr->ih_flags & IMAGE_F_COMPRESSED_LZMA2)) - { - return false; + if (MUST_DECOMPRESS(fap, BOOT_CURR_IMG(state), hdr)) { + if (!boot_is_compressed_header_valid(hdr, fap, state)) { + return false; + } } #endif @@ -1263,6 +1268,7 @@ boot_validate_slot(struct boot_loader_state *state, int slot, * attempts to validate and boot it. */ } + #if !defined(__BOOTSIM__) BOOT_LOG_ERR("Image in the %s slot is not valid!", (slot == BOOT_PRIMARY_SLOT) ? "primary" : "secondary"); @@ -1919,6 +1925,9 @@ boot_copy_region(struct boot_loader_state *state, #else (void)state; #endif +#if defined(MCUBOOT_DECOMPRESS_IMAGES) && !defined(MCUBOOT_ENC_IMAGES) + struct image_header *hdr; +#endif TARGET_STATIC uint8_t buf[BUF_SZ] __attribute__((aligned(4))); @@ -1944,6 +1953,16 @@ boot_copy_region(struct boot_loader_state *state, } #endif +#ifdef MCUBOOT_DECOMPRESS_IMAGES + hdr = boot_img_hdr(state, BOOT_SECONDARY_SLOT); + + if (MUST_DECOMPRESS(fap_src, BOOT_CURR_IMG(state), hdr)) { + /* Use alternative function for compressed images */ + return boot_copy_region_decompress(state, fap_src, fap_dst, off_src, off_dst, sz, buf, + BUF_SZ); + } +#endif + bytes_copied = 0; while (bytes_copied < sz) { if (sz - bytes_copied > sizeof buf) { diff --git a/boot/zephyr/CMakeLists.txt b/boot/zephyr/CMakeLists.txt index e2c981aae..957c6c50a 100644 --- a/boot/zephyr/CMakeLists.txt +++ b/boot/zephyr/CMakeLists.txt @@ -317,6 +317,12 @@ if(CONFIG_BOOT_ENCRYPT_EC256) ) endif() +if(CONFIG_BOOT_DECOMPRESSION) + zephyr_library_sources( + decompression.c + ) +endif() + if(CONFIG_MCUBOOT_SERIAL) zephyr_sources(${BOOT_DIR}/zephyr/serial_adapter.c) zephyr_sources(${BOOT_DIR}/boot_serial/src/boot_serial.c) diff --git a/boot/zephyr/Kconfig b/boot/zephyr/Kconfig index 1c71f33eb..e36fdd8e9 100644 --- a/boot/zephyr/Kconfig +++ b/boot/zephyr/Kconfig @@ -1101,6 +1101,9 @@ config BOOT_BANNER_STRING config BOOT_DECOMPRESSION_SUPPORT bool + depends on NRF_COMPRESS && NRF_COMPRESS_DECOMPRESSION && (NRF_COMPRESS_LZMA_VERSION_LZMA1 || NRF_COMPRESS_LZMA_VERSION_LZMA2) + depends on !SINGLE_APPLICATION_SLOT && BOOT_UPGRADE_ONLY + default y help Hidden symbol which should be selected if a system provided decompression support. @@ -1108,6 +1111,8 @@ if BOOT_DECOMPRESSION_SUPPORT menuconfig BOOT_DECOMPRESSION bool "Decompression" + select NRF_COMPRESS_CLEANUP + select PM_USE_CONFIG_SRAM_SIZE if SOC_NRF54L15_CPUAPP help If enabled, will include support for compressed images being loaded to the secondary slot which then get decompressed into the primary slot. This mode allows the secondary slot to @@ -1116,9 +1121,9 @@ menuconfig BOOT_DECOMPRESSION if BOOT_DECOMPRESSION config BOOT_DECOMPRESSION_BUFFER_SIZE - int "Write buffer size" + int range 16 16384 - default 4096 + default NRF_COMPRESS_CHUNK_SIZE help The size of a secondary buffer used for writing decompressed data to the storage device. diff --git a/boot/zephyr/decompression.c b/boot/zephyr/decompression.c new file mode 100644 index 000000000..87e3d3763 --- /dev/null +++ b/boot/zephyr/decompression.c @@ -0,0 +1,1505 @@ +/* + * Copyright (c) 2024 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: LicenseRef-Nordic-5-Clause + */ + +#include +#include "compression/decompression.h" +#include "bootutil/crypto/sha.h" +#include "bootutil/bootutil_log.h" + +#if !defined(__BOOTSIM__) +#define TARGET_STATIC static +#else +#define TARGET_STATIC +#endif + +#if defined(MCUBOOT_SIGN_RSA) +#if MCUBOOT_SIGN_RSA_LEN == 2048 +#define EXPECTED_SIG_TLV IMAGE_TLV_RSA2048_PSS +#elif MCUBOOT_SIGN_RSA_LEN == 3072 +#define EXPECTED_SIG_TLV IMAGE_TLV_RSA3072_PSS +#endif +#elif defined(MCUBOOT_SIGN_EC256) || \ + defined(MCUBOOT_SIGN_EC384) || \ + defined(MCUBOOT_SIGN_EC) +#define EXPECTED_SIG_TLV IMAGE_TLV_ECDSA_SIG +#elif defined(MCUBOOT_SIGN_ED25519) +#define EXPECTED_SIG_TLV IMAGE_TLV_ED25519 +#endif + +#define DECOMP_BUF_SIZE CONFIG_BOOT_DECOMPRESSION_BUFFER_SIZE +#if defined(CONFIG_NRF_COMPRESS_ARM_THUMB) +/* Extra buffer space for being able to writeback ARM thumb decompression output, + * which may be of +2 bytes more size than its input. + */ +#define DECOMP_BUF_EXTRA_SIZE 2 +#else +#define DECOMP_BUF_EXTRA_SIZE 0 +#endif +#define DECOMP_BUF_ALLOC_SIZE (DECOMP_BUF_SIZE + DECOMP_BUF_EXTRA_SIZE) + +#define DECRYPTION_BLOCK_SIZE_AES128 16 +#define DECRYPTION_BLOCK_SIZE_AES256 32 + +/* Number of times that consumed data by decompression system can be 0 in a row before aborting */ +#define OFFSET_ZERO_CHECK_TIMES 3 + +BOOT_LOG_MODULE_DECLARE(mcuboot); + +static int boot_sha_protected_tlvs(const struct image_header *hdr, + const struct flash_area *fap_src, uint32_t protected_size, + uint8_t *buf, size_t buf_size, bootutil_sha_context *sha_ctx); + +bool boot_is_compressed_header_valid(const struct image_header *hdr, const struct flash_area *fap, + struct boot_loader_state *state) +{ + /* Image is compressed in secondary slot, need to check if fits into the primary slot */ + bool opened_flash_area = false; + int primary_fa_id; + int rc; + int size_check; + int size; + uint32_t protected_tlvs_size; + uint32_t decompressed_size; + + primary_fa_id = flash_area_id_from_multi_image_slot(BOOT_CURR_IMG(state), BOOT_PRIMARY_SLOT); + + if (primary_fa_id == fap->fa_id) { + BOOT_LOG_ERR("Primary slots cannot be compressed, image: %d", BOOT_CURR_IMG(state)); + return false; + } + + if (BOOT_IMG_AREA(state, BOOT_PRIMARY_SLOT) == NULL) { + opened_flash_area = true; + } + + rc = flash_area_open(primary_fa_id, &BOOT_IMG_AREA(state, BOOT_PRIMARY_SLOT)); + assert(rc == 0); + + size_check = flash_area_get_size(BOOT_IMG_AREA(state, BOOT_PRIMARY_SLOT)); + + if (opened_flash_area) { + (void)flash_area_close(BOOT_IMG_AREA(state, BOOT_PRIMARY_SLOT)); + } + + rc = bootutil_get_img_decomp_size(hdr, fap, &decompressed_size); + + if (rc) { + return false; + } + + if (!boot_u32_safe_add(&size, decompressed_size, hdr->ih_hdr_size)) { + return false; + } + + rc = boot_size_protected_tlvs(hdr, fap, &protected_tlvs_size); + + if (rc) { + return false; + } + + if (!boot_u32_safe_add(&size, size, protected_tlvs_size)) { + return false; + } + + if (size >= size_check) { + BOOT_LOG_ERR("Compressed image too large, decompressed image size: 0x%x, slot size: 0x%x", + size, size_check); + return false; + } + + return true; +} + +static bool is_compression_object_valid(struct nrf_compress_implementation *compression) +{ + if (compression == NULL || compression->init == NULL || compression->deinit == NULL || + compression->decompress_bytes_needed == NULL || compression->decompress == NULL) { + return false; + } + + return true; +} + +#ifdef MCUBOOT_ENC_IMAGES +int bootutil_get_img_decrypted_comp_size(const struct image_header *hdr, + const struct flash_area *fap, uint32_t *img_comp_size) +{ + if (hdr == NULL || fap == NULL || img_comp_size == NULL) { + return BOOT_EBADARGS; + } else if (hdr->ih_protect_tlv_size == 0) { + return BOOT_EBADIMAGE; + } + + if (!IS_ENCRYPTED(hdr)) { + /* Update is not encrypted so use size from header */ + *img_comp_size = hdr->ih_img_size; + } else { + struct image_tlv_iter it; + uint32_t off; + uint16_t len; + int32_t rc; + + rc = bootutil_tlv_iter_begin(&it, hdr, fap, IMAGE_TLV_COMP_DEC_SIZE, true); + + if (rc) { + return rc; + } + + rc = bootutil_tlv_iter_next(&it, &off, &len, NULL); + + if (rc != 0) { + return -1; + } + + if (len != sizeof(*img_comp_size)) { + BOOT_LOG_ERR("Invalid decompressed image size TLV: %d", len); + return BOOT_EBADIMAGE; + } + + rc = LOAD_IMAGE_DATA(hdr, fap, off, img_comp_size, len); + + if (rc) { + BOOT_LOG_ERR("Image data load failed at offset: 0x%x, size: 0x%x, area: %d, rc: %d", + off, len, fap->fa_id, rc); + return BOOT_EFLASH; + } + } + + return 0; +} +#endif + +int bootutil_img_hash_decompress(struct boot_loader_state *state, struct image_header *hdr, + const struct flash_area *fap, uint8_t *tmp_buf, + uint32_t tmp_buf_sz, uint8_t *hash_result, + uint8_t *seed, int seed_len) +{ + int rc; + uint32_t read_pos = 0; + uint32_t write_pos = 0; + uint32_t protected_tlv_size = 0; + uint32_t decompressed_image_size; + uint32_t output_size_total = 0; + struct nrf_compress_implementation *compression_lzma = NULL; + struct nrf_compress_implementation *compression_arm_thumb = NULL; + TARGET_STATIC struct image_header modified_hdr; + bootutil_sha_context sha_ctx; + +#ifdef MCUBOOT_ENC_IMAGES + struct enc_key_data *enc_state; + int image_index; + uint32_t comp_size = 0; + uint8_t decryption_block_size = 0; + + rc = bootutil_get_img_decrypted_comp_size(hdr, fap, &comp_size); + + if (rc) { + BOOT_LOG_ERR("Invalid/missing image decrypted compressed size value"); + rc = BOOT_EBADIMAGE; + goto finish_end; + } + + if (state == NULL) { + enc_state = NULL; + image_index = 0; + } else { + enc_state = BOOT_CURR_ENC(state); + image_index = BOOT_CURR_IMG(state); + } + + /* Encrypted images only exist in the secondary slot */ + if (MUST_DECRYPT(fap, image_index, hdr) && + !boot_enc_valid(enc_state, 1)) { + return -1; + } + + if (MUST_DECRYPT(fap, image_index, hdr)) { + if (hdr->ih_flags & IMAGE_F_ENCRYPTED_AES128) { + decryption_block_size = DECRYPTION_BLOCK_SIZE_AES128; + } else if (hdr->ih_flags & IMAGE_F_ENCRYPTED_AES256) { + decryption_block_size = DECRYPTION_BLOCK_SIZE_AES256; + } else { + LOG_ERR("Unknown decryption block size"); + rc = BOOT_EBADIMAGE; + goto finish_end; + } + } +#endif + + bootutil_sha_init(&sha_ctx); + + /* Setup decompression system */ +#if CONFIG_NRF_COMPRESS_LZMA_VERSION_LZMA1 + if (!(hdr->ih_flags & IMAGE_F_COMPRESSED_LZMA1)) { +#elif CONFIG_NRF_COMPRESS_LZMA_VERSION_LZMA2 + if (!(hdr->ih_flags & IMAGE_F_COMPRESSED_LZMA2)) { +#endif + /* Compressed image does not use the correct compression type which is supported by this + * build + */ + BOOT_LOG_ERR("Invalid image compression flags: no supported compression found"); + rc = BOOT_EBADIMAGE; + goto finish_without_clean; + } + + compression_lzma = nrf_compress_implementation_find(NRF_COMPRESS_TYPE_LZMA); + compression_arm_thumb = nrf_compress_implementation_find(NRF_COMPRESS_TYPE_ARM_THUMB); + + if (!is_compression_object_valid(compression_lzma) || + !is_compression_object_valid(compression_arm_thumb)) { + /* Compression library missing or missing required function pointer */ + BOOT_LOG_ERR("Decompression library fatal error"); + rc = BOOT_EBADSTATUS; + goto finish_without_clean; + } + + rc = compression_lzma->init(NULL); + rc = compression_arm_thumb->init(NULL); + + if (rc) { + BOOT_LOG_ERR("Decompression library fatal error"); + rc = BOOT_EBADSTATUS; + goto finish_without_clean; + } + + /* We need a modified header which has the updated sizes, start with the original header */ + memcpy(&modified_hdr, hdr, sizeof(modified_hdr)); + + /* Extract the decompressed image size from the protected TLV, set it and remove the + * compressed image flags + */ + rc = bootutil_get_img_decomp_size(hdr, fap, &decompressed_image_size); + + if (rc) { + BOOT_LOG_ERR("Unable to determine decompressed size of compressed image"); + rc = BOOT_EBADIMAGE; + goto finish; + } + + modified_hdr.ih_flags &= ~COMPRESSIONFLAGS; + modified_hdr.ih_img_size = decompressed_image_size; + + /* Calculate the protected TLV size, these will not include the decompressed + * sha/size/signature entries + */ + rc = boot_size_protected_tlvs(hdr, fap, &protected_tlv_size); + + if (rc) { + BOOT_LOG_ERR("Unable to determine protected TLV size of compressed image"); + rc = BOOT_EBADIMAGE; + goto finish; + } + + modified_hdr.ih_protect_tlv_size = protected_tlv_size; + bootutil_sha_update(&sha_ctx, &modified_hdr, sizeof(modified_hdr)); + read_pos = sizeof(modified_hdr); + + while (read_pos < modified_hdr.ih_hdr_size) { + uint32_t copy_size = tmp_buf_sz; + + if ((read_pos + copy_size) > modified_hdr.ih_hdr_size) { + copy_size = modified_hdr.ih_hdr_size - read_pos; + } + + rc = flash_area_read(fap, read_pos, tmp_buf, copy_size); + + if (rc != 0) { + BOOT_LOG_ERR("Flash read failed at offset: 0x%x, size: 0x%x, area: %d, rc: %d", + (hdr->ih_hdr_size + read_pos), copy_size, fap->fa_id, rc); + rc = BOOT_EFLASH; + goto finish; + } + + bootutil_sha_update(&sha_ctx, tmp_buf, copy_size); + read_pos += copy_size; + } + + /* Read in compressed data, decompress and add to hash calculation */ + read_pos = 0; + +#ifdef MCUBOOT_ENC_IMAGES + while (read_pos < comp_size) { + uint32_t copy_size = comp_size - read_pos; +#else + while (read_pos < hdr->ih_img_size) { + uint32_t copy_size = hdr->ih_img_size - read_pos; +#endif + uint32_t tmp_off = 0; + uint8_t offset_zero_check = 0; + + if (copy_size > tmp_buf_sz) { + copy_size = tmp_buf_sz; + } + + rc = flash_area_read(fap, (hdr->ih_hdr_size + read_pos), tmp_buf, copy_size); + + if (rc != 0) { + BOOT_LOG_ERR("Flash read failed at offset: 0x%x, size: 0x%x, area: %d, rc: %d", + (hdr->ih_hdr_size + read_pos), copy_size, fap->fa_id, rc); + rc = BOOT_EFLASH; + goto finish; + } + +#ifdef MCUBOOT_ENC_IMAGES + if (MUST_DECRYPT(fap, image_index, hdr)) { + uint8_t dummy_bytes = 0; + + if ((copy_size % decryption_block_size)) { + dummy_bytes = decryption_block_size - (copy_size % decryption_block_size); + memset(&tmp_buf[copy_size], 0x00, dummy_bytes); + } + + boot_enc_decrypt(enc_state, 1, read_pos, (copy_size + dummy_bytes), (read_pos & 0xf), + tmp_buf); + } +#endif + + /* Decompress data in chunks, writing it back with a larger write offset of the primary + * slot than read size of the secondary slot + */ + while (tmp_off < copy_size) { + uint32_t offset = 0; + uint8_t *output = NULL; + uint32_t output_size = 0; + uint32_t chunk_size; + bool last_packet = false; + + chunk_size = compression_lzma->decompress_bytes_needed(NULL); + + if (chunk_size > (copy_size - tmp_off)) { + chunk_size = (copy_size - tmp_off); + } + +#ifdef MCUBOOT_ENC_IMAGES + if ((read_pos + tmp_off + chunk_size) >= comp_size) { +#else + if ((read_pos + tmp_off + chunk_size) >= hdr->ih_img_size) { +#endif + last_packet = true; + } + + rc = compression_lzma->decompress(NULL, &tmp_buf[tmp_off], chunk_size, last_packet, + &offset, &output, &output_size); + + if (rc) { + BOOT_LOG_ERR("Decompression error: %d", rc); + rc = BOOT_EBADSTATUS; + goto finish; + } + + write_pos += output_size; + + if (write_pos > decompressed_image_size) { + BOOT_LOG_ERR("Decompressed image larger than claimed TLV size, at least: %d", + write_pos); + rc = BOOT_EBADIMAGE; + goto finish; + } + + /* Additional dry-run validity checks */ + if (last_packet == true && write_pos == 0) { + /* Last packet and we still have no output, this is a faulty update */ + BOOT_LOG_ERR("All compressed data consumed without any output, image not valid"); + rc = BOOT_EBADIMAGE; + goto finish; + } + + if (offset == 0) { + /* If the decompression system continually consumes 0 bytes, then there is a + * problem with this update image, abort and mark image as bad + */ + if (offset_zero_check >= OFFSET_ZERO_CHECK_TIMES) { + BOOT_LOG_ERR("Decompression system returning no output data, image not valid"); + rc = BOOT_EBADIMAGE; + goto finish; + } + + ++offset_zero_check; + + break; + } else { + offset_zero_check = 0; + } + + /* Copy data to secondary buffer for calculating hash */ + if (output_size > 0) { + if (hdr->ih_flags & IMAGE_F_COMPRESSED_ARM_THUMB_FLT) { + /* Run this through the ARM thumb filter */ + uint32_t offset_arm_thumb = 0; + uint8_t *output_arm_thumb = NULL; + uint32_t processed_size = 0; + uint32_t output_size_arm_thumb = 0; + + while (processed_size < output_size) { + uint32_t current_size = output_size - processed_size; + bool arm_thumb_last_packet = false; + + if (current_size > CONFIG_NRF_COMPRESS_CHUNK_SIZE) { + current_size = CONFIG_NRF_COMPRESS_CHUNK_SIZE; + } + + if (last_packet && (processed_size + current_size) == + output_size) { + arm_thumb_last_packet = true; + } + + rc = compression_arm_thumb->decompress(NULL, &output[processed_size], + current_size, arm_thumb_last_packet, + &offset_arm_thumb, + &output_arm_thumb, + &output_size_arm_thumb); + + if (rc) { + BOOT_LOG_ERR("Decompression error: %d", rc); + rc = BOOT_EBADSTATUS; + goto finish; + } + + bootutil_sha_update(&sha_ctx, output_arm_thumb, output_size_arm_thumb); + output_size_total += output_size_arm_thumb; + processed_size += current_size; + } + } else { + bootutil_sha_update(&sha_ctx, output, output_size); + output_size_total += output_size; + } + } + + tmp_off += offset; + } + + read_pos += copy_size; + } + + if (modified_hdr.ih_img_size != output_size_total) { + BOOT_LOG_ERR("Decompression expected output_size mismatch: %d vs %d", + modified_hdr.ih_img_size, output_size_total); + rc = BOOT_EBADSTATUS; + goto finish; + } + + /* If there are any protected TLVs present, add them after the main decompressed image */ + if (modified_hdr.ih_protect_tlv_size > 0) { + rc = boot_sha_protected_tlvs(hdr, fap, modified_hdr.ih_protect_tlv_size, tmp_buf, + tmp_buf_sz, &sha_ctx); + } + + bootutil_sha_finish(&sha_ctx, hash_result); + +finish: + /* Clean up decompression system */ + (void)compression_lzma->deinit(NULL); + (void)compression_arm_thumb->deinit(NULL); + +finish_without_clean: + bootutil_sha_drop(&sha_ctx); + +#ifdef MCUBOOT_ENC_IMAGES +finish_end: +#endif + return rc; +} + +static int boot_copy_protected_tlvs(const struct image_header *hdr, + const struct flash_area *fap_src, + const struct flash_area *fap_dst, uint32_t off_dst, + uint32_t protected_size, uint8_t *buf, size_t buf_size, + uint16_t *buf_pos, uint32_t *written) +{ + int rc; + uint32_t off; + uint32_t write_pos = 0; + uint16_t len; + uint16_t type; + struct image_tlv_iter it; + struct image_tlv tlv_header; + struct image_tlv_info tlv_info_header = { + .it_magic = IMAGE_TLV_PROT_INFO_MAGIC, + .it_tlv_tot = protected_size, + }; + uint16_t info_size_left = sizeof(tlv_info_header); + + while (info_size_left > 0) { + uint16_t copy_size = buf_size - *buf_pos; + + if (info_size_left > 0 && copy_size > 0) { + uint16_t single_copy_size = copy_size; + uint8_t *tlv_info_header_address = (uint8_t *)&tlv_info_header; + + if (single_copy_size > info_size_left) { + single_copy_size = info_size_left; + } + + memcpy(&buf[*buf_pos], &tlv_info_header_address[sizeof(tlv_info_header) - + info_size_left], single_copy_size); + *buf_pos += single_copy_size; + info_size_left -= single_copy_size; + } + + if (*buf_pos == buf_size) { + rc = flash_area_write(fap_dst, (off_dst + write_pos), buf, *buf_pos); + + if (rc != 0) { + BOOT_LOG_ERR("Flash write failed at offset: 0x%x, size: 0x%x, area: %d, rc: %d", + (off_dst + write_pos), *buf_pos, fap_dst->fa_id, rc); + rc = BOOT_EFLASH; + goto out; + } + + write_pos += *buf_pos; + *buf_pos = 0; + } + } + + rc = bootutil_tlv_iter_begin(&it, hdr, fap_src, IMAGE_TLV_ANY, true); + + if (rc) { + goto out; + } + + while (true) { + rc = bootutil_tlv_iter_next(&it, &off, &len, &type); + + if (rc < 0) { + goto out; + } else if (rc > 0) { + rc = 0; + break; + } + + if (type == IMAGE_TLV_DECOMP_SIZE || type == IMAGE_TLV_DECOMP_SHA || + type == IMAGE_TLV_DECOMP_SIGNATURE || type == IMAGE_TLV_COMP_DEC_SIZE) { + /* Skip these TLVs as they are not needed */ + continue; + } else { + uint16_t header_size_left = sizeof(tlv_header); + uint16_t data_size_left = len; + + tlv_header.it_type = type; + tlv_header.it_len = len; + + while (header_size_left > 0 || data_size_left > 0) { + uint16_t copy_size = buf_size - *buf_pos; + uint8_t *tlv_header_address = (uint8_t *)&tlv_header; + + if (header_size_left > 0 && copy_size > 0) { + uint16_t single_copy_size = copy_size; + + if (single_copy_size > header_size_left) { + single_copy_size = header_size_left; + } + + memcpy(&buf[*buf_pos], &tlv_header_address[sizeof(tlv_header) - + header_size_left], + single_copy_size); + *buf_pos += single_copy_size; + copy_size -= single_copy_size; + header_size_left -= single_copy_size; + } + + if (data_size_left > 0 && copy_size > 0) { + uint16_t single_copy_size = copy_size; + + if (single_copy_size > data_size_left) { + single_copy_size = data_size_left; + } + + rc = LOAD_IMAGE_DATA(hdr, fap_src, (off + (len - data_size_left)), + &buf[*buf_pos], single_copy_size); + + if (rc) { + BOOT_LOG_ERR( + "Image data load failed at offset: 0x%x, size: 0x%x, area: %d, rc: %d", + (off + (len - data_size_left)), single_copy_size, fap_src->fa_id, rc); + goto out; + } + + *buf_pos += single_copy_size; + data_size_left -= single_copy_size; + } + + if (*buf_pos == buf_size) { + rc = flash_area_write(fap_dst, (off_dst + write_pos), buf, *buf_pos); + + if (rc != 0) { + BOOT_LOG_ERR( + "Flash write failed at offset: 0x%x, size: 0x%x, area: %d, rc: %d", + (off_dst + write_pos), *buf_pos, fap_dst->fa_id, rc); + rc = BOOT_EFLASH; + goto out; + } + + write_pos += *buf_pos; + *buf_pos = 0; + } + } + } + } + + *written = write_pos; + +out: + return rc; +} + +static int boot_sha_protected_tlvs(const struct image_header *hdr, + const struct flash_area *fap_src, uint32_t protected_size, + uint8_t *buf, size_t buf_size, bootutil_sha_context *sha_ctx) +{ + int rc; + uint32_t off; + uint16_t len; + uint16_t type; + struct image_tlv_iter it; + struct image_tlv tlv_header; + struct image_tlv_info tlv_info_header = { + .it_magic = IMAGE_TLV_PROT_INFO_MAGIC, + .it_tlv_tot = protected_size, + }; + + bootutil_sha_update(sha_ctx, &tlv_info_header, sizeof(tlv_info_header)); + + rc = bootutil_tlv_iter_begin(&it, hdr, fap_src, IMAGE_TLV_ANY, true); + if (rc) { + goto out; + } + + while (true) { + uint32_t read_off = 0; + + rc = bootutil_tlv_iter_next(&it, &off, &len, &type); + + if (rc < 0) { + goto out; + } else if (rc > 0) { + rc = 0; + break; + } + + if (type == IMAGE_TLV_DECOMP_SIZE || type == IMAGE_TLV_DECOMP_SHA || + type == IMAGE_TLV_DECOMP_SIGNATURE || type == IMAGE_TLV_COMP_DEC_SIZE) { + /* Skip these TLVs as they are not needed */ + continue; + } + + tlv_header.it_type = type; + tlv_header.it_len = len; + + bootutil_sha_update(sha_ctx, &tlv_header, sizeof(tlv_header)); + + while (read_off < len) { + uint32_t copy_size = buf_size; + + if (copy_size > (len - read_off)) { + copy_size = len - read_off; + } + + rc = LOAD_IMAGE_DATA(hdr, fap_src, (off + read_off), buf, copy_size); + + if (rc) { + BOOT_LOG_ERR( + "Image data load failed at offset: 0x%x, size: 0x%x, area: %d, rc: %d", + (off + read_off), copy_size, fap_src->fa_id, rc); + goto out; + } + + bootutil_sha_update(sha_ctx, buf, copy_size); + read_off += copy_size; + } + } + +out: + return rc; +} + +int boot_size_protected_tlvs(const struct image_header *hdr, const struct flash_area *fap, + uint32_t *sz) +{ + int rc = 0; + uint32_t tlv_size; + uint32_t off; + uint16_t len; + uint16_t type; + struct image_tlv_iter it; + + *sz = 0; + tlv_size = hdr->ih_protect_tlv_size; + + rc = bootutil_tlv_iter_begin(&it, hdr, fap, IMAGE_TLV_ANY, true); + + if (rc) { + goto out; + } + + while (true) { + rc = bootutil_tlv_iter_next(&it, &off, &len, &type); + + if (rc < 0) { + goto out; + } else if (rc > 0) { + rc = 0; + break; + } + + if (type == IMAGE_TLV_DECOMP_SIZE || type == IMAGE_TLV_DECOMP_SHA || + type == IMAGE_TLV_DECOMP_SIGNATURE || type == IMAGE_TLV_COMP_DEC_SIZE) { + /* Exclude these TLVs as they will be copied to the unprotected area */ + tlv_size -= len + sizeof(struct image_tlv); + } + } + + if (!rc) { + if (tlv_size == sizeof(struct image_tlv_info)) { + /* If there are no entries then omit protected TLV section entirely */ + tlv_size = 0; + } + + *sz = tlv_size; + } + +out: + return rc; +} + +int boot_size_unprotected_tlvs(const struct image_header *hdr, const struct flash_area *fap, + uint32_t *sz) +{ + int rc = 0; + uint32_t tlv_size; + uint32_t off; + uint16_t len; + uint16_t type; + struct image_tlv_iter it; + + *sz = 0; + tlv_size = sizeof(struct image_tlv_info); + + rc = bootutil_tlv_iter_begin(&it, hdr, fap, IMAGE_TLV_ANY, false); + + if (rc) { + goto out; + } + + while (true) { + rc = bootutil_tlv_iter_next(&it, &off, &len, &type); + + if (rc < 0) { + goto out; + } else if (rc > 0) { + rc = 0; + break; + } else if (bootutil_tlv_iter_is_prot(&it, off) && type != IMAGE_TLV_DECOMP_SHA && + type != IMAGE_TLV_DECOMP_SIGNATURE) { + /* Include size of protected hash and signature as these will be replacing the + * original ones + */ + continue; + } else if (type == EXPECTED_HASH_TLV || type == EXPECTED_SIG_TLV || type == IMAGE_TLV_COMP_DEC_SIZE) { + /* Exclude the original unprotected TLVs for signature and hash, the length of the + * signature of the compressed data might not be the same size as the signaute of the + * decompressed data, as is the case when using ECDSA-P256 + */ + continue; + } + + tlv_size += len + sizeof(struct image_tlv); + } + + if (!rc) { + if (tlv_size == sizeof(struct image_tlv_info)) { + /* If there are no entries in the unprotected TLV section then there is something wrong + * with this image + */ + BOOT_LOG_ERR("No unprotected TLVs in post-decompressed image output, image is invalid"); + rc = BOOT_EBADIMAGE; + goto out; + } + + *sz = tlv_size; + } + +out: + return rc; +} + +static int boot_copy_unprotected_tlvs(const struct image_header *hdr, + const struct flash_area *fap_src, + const struct flash_area *fap_dst, uint32_t off_dst, + uint32_t unprotected_size, uint8_t *buf, size_t buf_size, + uint16_t *buf_pos, uint32_t *written) +{ + int rc; + uint32_t write_pos = 0; + uint32_t off; + uint16_t len; + uint16_t type; + struct image_tlv_iter it; + struct image_tlv_iter it_protected; + struct image_tlv tlv_header; + struct image_tlv_info tlv_info_header = { + .it_magic = IMAGE_TLV_INFO_MAGIC, + .it_tlv_tot = unprotected_size, + }; + uint16_t info_size_left = sizeof(tlv_info_header); + + while (info_size_left > 0) { + uint16_t copy_size = buf_size - *buf_pos; + + if (info_size_left > 0 && copy_size > 0) { + uint16_t single_copy_size = copy_size; + uint8_t *tlv_info_header_address = (uint8_t *)&tlv_info_header; + + if (single_copy_size > info_size_left) { + single_copy_size = info_size_left; + } + + memcpy(&buf[*buf_pos], &tlv_info_header_address[sizeof(tlv_info_header) - + info_size_left], single_copy_size); + *buf_pos += single_copy_size; + info_size_left -= single_copy_size; + } + + if (*buf_pos == buf_size) { + rc = flash_area_write(fap_dst, (off_dst + write_pos), buf, *buf_pos); + + if (rc != 0) { + BOOT_LOG_ERR("Flash write failed at offset: 0x%x, size: 0x%x, area: %d, rc: %d", + (off_dst + write_pos), *buf_pos, fap_dst->fa_id, rc); + rc = BOOT_EFLASH; + goto out; + } + + write_pos += *buf_pos; + *buf_pos = 0; + } + } + + rc = bootutil_tlv_iter_begin(&it, hdr, fap_src, IMAGE_TLV_ANY, false); + if (rc) { + goto out; + } + + while (true) { + uint16_t header_size_left = sizeof(tlv_header); + uint16_t data_size_left; + + rc = bootutil_tlv_iter_next(&it, &off, &len, &type); + if (rc < 0) { + goto out; + } else if (rc > 0) { + rc = 0; + break; + } else if (bootutil_tlv_iter_is_prot(&it, off)) { + /* Skip protected TLVs */ + continue; + } + + /* Change the values of these fields from having the data in the compressed image + * unprotected TLV (which is valid only for the compressed image data) to having the + * fields in the protected TLV section (which is valid for the decompressed image data). + * The compressed data is no longer needed + */ + if (type == EXPECTED_HASH_TLV || type == EXPECTED_SIG_TLV) { + rc = bootutil_tlv_iter_begin(&it_protected, hdr, fap_src, (type == EXPECTED_HASH_TLV ? + IMAGE_TLV_DECOMP_SHA : + IMAGE_TLV_DECOMP_SIGNATURE), + true); + + if (rc) { + goto out; + } + + while (true) { + rc = bootutil_tlv_iter_next(&it_protected, &off, &len, &type); + if (rc < 0) { + goto out; + } else if (rc > 0) { + rc = 0; + break; + } + } + + if (type == IMAGE_TLV_DECOMP_SHA) { + type = EXPECTED_HASH_TLV; + } else { + type = EXPECTED_SIG_TLV; + } + } + + data_size_left = len; + tlv_header.it_type = type; + tlv_header.it_len = len; + + while (header_size_left > 0 || data_size_left > 0) { + uint16_t copy_size = buf_size - *buf_pos; + + if (header_size_left > 0 && copy_size > 0) { + uint16_t single_copy_size = copy_size; + uint8_t *tlv_header_address = (uint8_t *)&tlv_header; + + if (single_copy_size > header_size_left) { + single_copy_size = header_size_left; + } + + memcpy(&buf[*buf_pos], &tlv_header_address[sizeof(tlv_header) - header_size_left], + single_copy_size); + *buf_pos += single_copy_size; + copy_size -= single_copy_size; + header_size_left -= single_copy_size; + } + + if (data_size_left > 0 && copy_size > 0) { + uint16_t single_copy_size = copy_size; + + if (single_copy_size > data_size_left) { + single_copy_size = data_size_left; + } + + rc = LOAD_IMAGE_DATA(hdr, fap_src, (off + len - data_size_left), + &buf[*buf_pos], single_copy_size); + + if (rc) { + BOOT_LOG_ERR( + "Image data load failed at offset: 0x%x, size: 0x%x, area: %d, rc: %d", + (off + (len - data_size_left)), single_copy_size, fap_src->fa_id, rc); + goto out; + } + + *buf_pos += single_copy_size; + data_size_left -= single_copy_size; + } + + if (*buf_pos == buf_size) { + rc = flash_area_write(fap_dst, (off_dst + write_pos), buf, *buf_pos); + + if (rc != 0) { + BOOT_LOG_ERR( + "Flash write failed at offset: 0x%x, size: 0x%x, area: %d, rc: %d", + (off_dst + write_pos), *buf_pos, fap_dst->fa_id, rc); + rc = BOOT_EFLASH; + goto out; + } + + write_pos += *buf_pos; + *buf_pos = 0; + } + } + } + + *written = write_pos; + +out: + return rc; +} + +#if defined(CONFIG_NRF_COMPRESS_ARM_THUMB) +/** + * @brief Helper function for in-place ARM Thumb filtering. + * This function places the decompressed data back into the same buffer + * at the beginning, overwriting the compressed data. WARNING: because + * ARM Thumb filtering can return +-2 more/less bytes than the input, + * the buffer provided needs to have free DECOMP_BUF_EXTRA_SIZE bytes at + * the beginning and provide valid data for filtering after these. + * + * @param[in] arm_thumb_impl Pointer to the ARM Thumb decompression implementation. + * @param[in,out] buf Pointer to the buffer containing the compressed data / filtered data. + * @param[in] buf_size Size of the buffer (including DECOMP_BUF_EXTRA_SIZE bytes at the beginning). + * @param[out] out_size Pointer to a variable where the size of the filtered data will be stored. + * @param[in] last_part Indicates if this is the last part of the data to be filtered. + * + * @return 0 on success, BOOT_EBADSTATUS on error. + */ +static int boot_arm_thumb_filter(struct nrf_compress_implementation * const arm_thumb_impl, + uint8_t *buf, size_t buf_size, size_t *out_size, bool last_part) { + + uint32_t filter_writeback_pos = 0; + uint32_t processed_size = 0; + int rc; + + while (processed_size < (buf_size - DECOMP_BUF_EXTRA_SIZE)) { + uint32_t offset_arm_thumb = 0; + uint32_t output_size_arm_thumb = 0; + uint8_t *output_arm_thumb = NULL; + uint32_t current_size = (buf_size - DECOMP_BUF_EXTRA_SIZE - processed_size); + bool arm_thumb_last_packet = false; + + if (current_size > CONFIG_NRF_COMPRESS_CHUNK_SIZE) { + current_size = CONFIG_NRF_COMPRESS_CHUNK_SIZE; + } + + if (last_part && (processed_size + current_size) == (buf_size - DECOMP_BUF_EXTRA_SIZE)) { + arm_thumb_last_packet = true; + } + + rc = arm_thumb_impl->decompress(NULL, + &buf[processed_size + + DECOMP_BUF_EXTRA_SIZE], + current_size, + arm_thumb_last_packet, + &offset_arm_thumb, + &output_arm_thumb, + &output_size_arm_thumb); + + if (rc) { + BOOT_LOG_ERR("Decompression error: %d", rc); + return BOOT_EBADSTATUS; + } + + if (output_size_arm_thumb > (buf_size - filter_writeback_pos)) { + BOOT_LOG_ERR("Filter writeback position exceeds buffer size"); + return BOOT_EBADSTATUS; + } + + memcpy(&buf[filter_writeback_pos], output_arm_thumb, + output_size_arm_thumb); + filter_writeback_pos += output_size_arm_thumb; + processed_size += offset_arm_thumb; + } + *out_size = filter_writeback_pos; + + return 0; +} +#endif /* CONFIG_NRF_COMPRESS_ARM_THUMB */ + +int boot_copy_region_decompress(struct boot_loader_state *state, const struct flash_area *fap_src, + const struct flash_area *fap_dst, uint32_t off_src, + uint32_t off_dst, uint32_t sz, uint8_t *buf, size_t buf_size) +{ + int rc; + uint32_t pos = 0; + uint16_t decomp_buf_size = 0; + uint16_t write_alignment; + uint32_t write_pos = 0; + uint32_t protected_tlv_size = 0; + uint32_t unprotected_tlv_size = 0; + uint32_t tlv_write_size = 0; + uint32_t decompressed_image_size; + struct nrf_compress_implementation *compression_lzma = NULL; + struct nrf_compress_implementation *compression_arm_thumb = NULL; + struct image_header *hdr; + TARGET_STATIC uint8_t decomp_buf[DECOMP_BUF_ALLOC_SIZE] __attribute__((aligned(4))); + TARGET_STATIC struct image_header modified_hdr; + uint16_t decomp_buf_max_size; + +#if defined(CONFIG_NRF_COMPRESS_ARM_THUMB) + uint8_t unaligned_data_length = 0; +#endif + +#ifdef MCUBOOT_ENC_IMAGES + uint32_t comp_size = 0; + uint8_t decryption_block_size = 0; +#endif + + hdr = boot_img_hdr(state, BOOT_SECONDARY_SLOT); + +#ifdef MCUBOOT_ENC_IMAGES + rc = bootutil_get_img_decrypted_comp_size(hdr, fap_src, &comp_size); + + if (rc) { + BOOT_LOG_ERR("Invalid/missing image decrypted compressed size value"); + rc = BOOT_EBADIMAGE; + goto finish; + } + + if (IS_ENCRYPTED(hdr)) { + if (hdr->ih_flags & IMAGE_F_ENCRYPTED_AES128) { + decryption_block_size = DECRYPTION_BLOCK_SIZE_AES128; + } else if (hdr->ih_flags & IMAGE_F_ENCRYPTED_AES256) { + decryption_block_size = DECRYPTION_BLOCK_SIZE_AES256; + } + } +#endif + + /* Setup decompression system */ +#if CONFIG_NRF_COMPRESS_LZMA_VERSION_LZMA1 + if (!(hdr->ih_flags & IMAGE_F_COMPRESSED_LZMA1)) { +#elif CONFIG_NRF_COMPRESS_LZMA_VERSION_LZMA2 + if (!(hdr->ih_flags & IMAGE_F_COMPRESSED_LZMA2)) { +#endif + /* Compressed image does not use the correct compression type which is supported by this + * build + */ + BOOT_LOG_ERR("Invalid image compression flags: no supported compression found"); + rc = BOOT_EBADIMAGE; + goto finish; + } + + compression_lzma = nrf_compress_implementation_find(NRF_COMPRESS_TYPE_LZMA); + compression_arm_thumb = nrf_compress_implementation_find(NRF_COMPRESS_TYPE_ARM_THUMB); + + if (!is_compression_object_valid(compression_lzma) || + !is_compression_object_valid(compression_arm_thumb)) { + /* Compression library missing or missing required function pointer */ + BOOT_LOG_ERR("Decompression library fatal error"); + rc = BOOT_EBADSTATUS; + goto finish; + } + + rc = compression_lzma->init(NULL); + rc = compression_arm_thumb->init(NULL); + + if (rc) { + BOOT_LOG_ERR("Decompression library fatal error"); + rc = BOOT_EBADSTATUS; + goto finish; + } + + write_alignment = flash_area_align(fap_dst); + + decomp_buf_max_size = DECOMP_BUF_SIZE - (DECOMP_BUF_SIZE % write_alignment); + + memcpy(&modified_hdr, hdr, sizeof(modified_hdr)); + + rc = bootutil_get_img_decomp_size(hdr, fap_src, &decompressed_image_size); + + if (rc) { + BOOT_LOG_ERR("Unable to determine decompressed size of compressed image"); + rc = BOOT_EBADIMAGE; + goto finish; + } + + modified_hdr.ih_flags &= ~COMPRESSIONFLAGS; + modified_hdr.ih_img_size = decompressed_image_size; + + /* Calculate protected TLV size for target image once items are removed */ + rc = boot_size_protected_tlvs(hdr, fap_src, &protected_tlv_size); + + if (rc) { + BOOT_LOG_ERR("Unable to determine protected TLV size of compressed image"); + rc = BOOT_EBADIMAGE; + goto finish; + } + + modified_hdr.ih_protect_tlv_size = protected_tlv_size; + + rc = boot_size_unprotected_tlvs(hdr, fap_src, &unprotected_tlv_size); + + if (rc) { + BOOT_LOG_ERR("Unable to determine unprotected TLV size of compressed image"); + rc = BOOT_EBADIMAGE; + goto finish; + } + + /* Write out the image header first, this should be a multiple of the write size */ + rc = flash_area_write(fap_dst, off_dst, &modified_hdr, sizeof(modified_hdr)); + + if (rc != 0) { + BOOT_LOG_ERR("Flash write failed at offset: 0x%x, size: 0x%x, area: %d, rc: %d", + off_dst, sizeof(modified_hdr), fap_dst->fa_id, rc); + rc = BOOT_EFLASH; + goto finish; + } + + /* Read in, decompress and write out data */ +#ifdef MCUBOOT_ENC_IMAGES + while (pos < comp_size) { + uint32_t copy_size = comp_size - pos; +#else + while (pos < hdr->ih_img_size) { + uint32_t copy_size = hdr->ih_img_size - pos; +#endif + uint32_t tmp_off = 0; + + if (copy_size > buf_size) { + copy_size = buf_size; + } + + rc = flash_area_read(fap_src, off_src + hdr->ih_hdr_size + pos, buf, copy_size); + + if (rc != 0) { + BOOT_LOG_ERR("Flash read failed at offset: 0x%x, size: 0x%x, area: %d, rc: %d", + (off_src + hdr->ih_hdr_size + pos), copy_size, fap_src->fa_id, rc); + rc = BOOT_EFLASH; + goto finish; + } + +#ifdef MCUBOOT_ENC_IMAGES + if (IS_ENCRYPTED(hdr)) { + uint8_t dummy_bytes = 0; + + if ((copy_size % decryption_block_size)) { + dummy_bytes = decryption_block_size - (copy_size % decryption_block_size); + memset(&buf[copy_size], 0x00, dummy_bytes); + } + + boot_enc_decrypt(BOOT_CURR_ENC(state), 1, pos, (copy_size + dummy_bytes), (pos & 0xf), buf); + } +#endif + + /* Decompress data in chunks, writing it back with a larger write offset of the primary + * slot than read size of the secondary slot + */ + while (tmp_off < copy_size) { + uint32_t offset = 0; + uint32_t output_size = 0; + uint32_t chunk_size; + uint32_t compression_buffer_pos = 0; + uint8_t *output = NULL; + bool last_packet = false; + + chunk_size = compression_lzma->decompress_bytes_needed(NULL); + + if (chunk_size > (copy_size - tmp_off)) { + chunk_size = (copy_size - tmp_off); + } + +#ifdef MCUBOOT_ENC_IMAGES + if ((pos + tmp_off + chunk_size) >= comp_size) { +#else + if ((pos + tmp_off + chunk_size) >= hdr->ih_img_size) { +#endif + last_packet = true; + } + + rc = compression_lzma->decompress(NULL, &buf[tmp_off], chunk_size, last_packet, + &offset, &output, &output_size); + + if (rc) { + BOOT_LOG_ERR("Decompression error: %d", rc); + rc = BOOT_EBADSTATUS; + goto finish; + } + + /* Copy data to secondary buffer for writing out */ + while (output_size > 0) { + uint32_t data_size = (decomp_buf_max_size - decomp_buf_size); + + if (data_size > output_size) { + data_size = output_size; + } + +#if defined(CONFIG_NRF_COMPRESS_ARM_THUMB) + if (hdr->ih_flags & IMAGE_F_COMPRESSED_ARM_THUMB_FLT) { + memcpy(&decomp_buf[decomp_buf_size + DECOMP_BUF_EXTRA_SIZE], + &output[compression_buffer_pos], data_size); + } else +#endif + { + memcpy(&decomp_buf[decomp_buf_size], &output[compression_buffer_pos], + data_size); + } + + compression_buffer_pos += data_size; + + decomp_buf_size += data_size; + output_size -= data_size; + + /* Write data out from secondary buffer when it is full */ + if (decomp_buf_size == decomp_buf_max_size) { +#if defined(CONFIG_NRF_COMPRESS_ARM_THUMB) + if (hdr->ih_flags & IMAGE_F_COMPRESSED_ARM_THUMB_FLT) { + + uint32_t filter_output_size; + + /* Run this through the ARM thumb filter */ + rc = boot_arm_thumb_filter(compression_arm_thumb, + &decomp_buf[unaligned_data_length], + decomp_buf_size - unaligned_data_length + DECOMP_BUF_EXTRA_SIZE, + &filter_output_size, + last_packet && output_size == 0); + + if (rc) { + goto finish; + } + + decomp_buf_size = filter_output_size + unaligned_data_length; + unaligned_data_length = decomp_buf_size % write_alignment; + + rc = flash_area_write(fap_dst, + (off_dst + hdr->ih_hdr_size + write_pos), + decomp_buf, + (decomp_buf_size - unaligned_data_length)); + + if (rc != 0) { + BOOT_LOG_ERR( + "Flash write failed at offset: 0x%x, size: 0x%x, area: %d, rc: %d", + (off_dst + hdr->ih_hdr_size + write_pos), + (decomp_buf_size - unaligned_data_length), + fap_dst->fa_id, rc); + rc = BOOT_EFLASH; + goto finish; + } + + memmove(decomp_buf, + &decomp_buf[decomp_buf_size - unaligned_data_length], + unaligned_data_length); + write_pos += decomp_buf_size - unaligned_data_length; + decomp_buf_size = unaligned_data_length; + } else +#endif + { + rc = flash_area_write(fap_dst, (off_dst + hdr->ih_hdr_size + write_pos), + decomp_buf, decomp_buf_max_size); + + if (rc != 0) { + BOOT_LOG_ERR( + "Flash write failed at offset: 0x%x, size: 0x%x, area: %d, rc: %d", + (off_dst + hdr->ih_hdr_size + write_pos), decomp_buf_max_size, + fap_dst->fa_id, rc); + rc = BOOT_EFLASH; + goto finish; + } + + write_pos += decomp_buf_max_size; + decomp_buf_size = 0; + } + } + } + + tmp_off += offset; + } + + pos += copy_size; + } + +#if defined(CONFIG_NRF_COMPRESS_ARM_THUMB) + if (hdr->ih_flags & IMAGE_F_COMPRESSED_ARM_THUMB_FLT && decomp_buf_size > 0) { + /* Extra data that has not been written out that needs ARM thumb filter applied */ + + uint32_t filter_output_size; + + rc = boot_arm_thumb_filter(compression_arm_thumb, + &decomp_buf[unaligned_data_length], + decomp_buf_size - unaligned_data_length + DECOMP_BUF_EXTRA_SIZE, + &filter_output_size, + true); + + if (rc) { + goto finish; + } + + decomp_buf_size = filter_output_size + unaligned_data_length; + + if (decomp_buf_size > decomp_buf_max_size) { + /* It can happen if ARM thumb decompression returned +2 bytes and we had near full + * decomp_buf. We still can hold these additional 2 bytes because of + * DECOMP_BUF_EXTRA_SIZE allocated. */ + + rc = flash_area_write(fap_dst, (off_dst + hdr->ih_hdr_size + write_pos), + decomp_buf, decomp_buf_max_size); + + if (rc != 0) { + BOOT_LOG_ERR("Flash write failed at offset: 0x%x, size: 0x%x, area: %d, rc: %d", + (off_dst + hdr->ih_hdr_size + write_pos), decomp_buf_max_size, + fap_dst->fa_id, rc); + rc = BOOT_EFLASH; + goto finish; + } + memmove(decomp_buf, &decomp_buf[decomp_buf_max_size], + (decomp_buf_size - decomp_buf_max_size)); + + decomp_buf_size = decomp_buf_size - decomp_buf_max_size; + write_pos += decomp_buf_max_size; + } + } +#endif + + /* Clean up decompression system */ + (void)compression_lzma->deinit(NULL); + (void)compression_arm_thumb->deinit(NULL); + + if (protected_tlv_size > 0) { + rc = boot_copy_protected_tlvs(hdr, fap_src, fap_dst, (off_dst + hdr->ih_hdr_size + + write_pos), protected_tlv_size, + decomp_buf, decomp_buf_max_size, &decomp_buf_size, + &tlv_write_size); + + if (rc) { + BOOT_LOG_ERR("Protected TLV copy failure: %d", rc); + goto finish; + } + + write_pos += tlv_write_size; + } + + tlv_write_size = 0; + rc = boot_copy_unprotected_tlvs(hdr, fap_src, fap_dst, (off_dst + hdr->ih_hdr_size + + write_pos), unprotected_tlv_size, + decomp_buf, decomp_buf_max_size, &decomp_buf_size, + &tlv_write_size); + + if (rc) { + BOOT_LOG_ERR("Protected TLV copy failure: %d", rc); + goto finish; + } + + write_pos += tlv_write_size; + + /* Check if we have unwritten data buffered up and, if so, write it out */ + if (decomp_buf_size > 0) { + uint32_t write_padding_size = write_alignment - (decomp_buf_size % write_alignment); + + /* Check if additional write padding should be applied to meet the minimum write size */ + if (write_alignment > 1 && write_padding_size) { + uint8_t flash_erased_value; + + flash_erased_value = flash_area_erased_val(fap_dst); + memset(&decomp_buf[decomp_buf_size], flash_erased_value, write_padding_size); + decomp_buf_size += write_padding_size; + } + + rc = flash_area_write(fap_dst, (off_dst + hdr->ih_hdr_size + write_pos), decomp_buf, + decomp_buf_size); + + if (rc != 0) { + BOOT_LOG_ERR("Flash write failed at offset: 0x%x, size: 0x%x, area: %d, rc: %d", + (off_dst + hdr->ih_hdr_size + write_pos), decomp_buf_size, + fap_dst->fa_id, rc); + rc = BOOT_EFLASH; + goto finish; + } + + write_pos += decomp_buf_size; + decomp_buf_size = 0; + } + +finish: + memset(decomp_buf, 0, sizeof(decomp_buf)); + + return rc; +} + +int bootutil_get_img_decomp_size(const struct image_header *hdr, const struct flash_area *fap, + uint32_t *img_decomp_size) +{ + struct image_tlv_iter it; + uint32_t off; + uint16_t len; + int32_t rc; + + if (hdr == NULL || fap == NULL || img_decomp_size == NULL) { + return BOOT_EBADARGS; + } else if (hdr->ih_protect_tlv_size == 0) { + return BOOT_EBADIMAGE; + } + + rc = bootutil_tlv_iter_begin(&it, hdr, fap, IMAGE_TLV_DECOMP_SIZE, true); + + if (rc) { + return rc; + } + + rc = bootutil_tlv_iter_next(&it, &off, &len, NULL); + + if (rc != 0) { + return -1; + } + + if (len != sizeof(*img_decomp_size)) { + BOOT_LOG_ERR("Invalid decompressed image size TLV: %d", len); + return BOOT_EBADIMAGE; + } + + rc = LOAD_IMAGE_DATA(hdr, fap, off, img_decomp_size, len); + + if (rc) { + BOOT_LOG_ERR("Image data load failed at offset: 0x%x, size: 0x%x, area: %d, rc: %d", + off, len, fap->fa_id, rc); + return BOOT_EFLASH; + } + + return 0; +} diff --git a/boot/zephyr/include/compression/decompression.h b/boot/zephyr/include/compression/decompression.h new file mode 100644 index 000000000..2104c4eb6 --- /dev/null +++ b/boot/zephyr/include/compression/decompression.h @@ -0,0 +1,103 @@ +/* + * Copyright (c) 2024 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: LicenseRef-Nordic-5-Clause + */ + +#ifndef H_DECOMPRESSION_ +#define H_DECOMPRESSION_ + +#include +#include +#include +#include "bootutil/bootutil.h" +#include "bootutil/bootutil_public.h" +#include "bootutil/image.h" +#include "../src/bootutil_priv.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * Checks if a compressed image header is valid. + * + * @param hdr Image header. + * @param fap Flash area of the slot. + * @param state Bootloader state object. + * + * @return true if valid; false if invalid. + */ +bool boot_is_compressed_header_valid(const struct image_header *hdr, const struct flash_area *fap, + struct boot_loader_state *state); + +/** + * Reads in compressed image data from a slot, decompresses it and writes it out to a destination + * slot, including corresponding image headers and TLVs. + * + * @param state Bootloader state object. + * @param fap_src Flash area of the source slot. + * @param fap_dst Flash area of the destination slot. + * @param off_src Offset of the source slot to read from (should be 0). + * @param off_dst Offset of the destination slot to write to (should be 0). + * @param sz Size of the source slot data. + * @param buf Temporary buffer for reading data from. + * @param buf_size Size of temporary buffer. + * + * @return 0 on success; nonzero on failure. + */ +int boot_copy_region_decompress(struct boot_loader_state *state, const struct flash_area *fap_src, + const struct flash_area *fap_dst, uint32_t off_src, + uint32_t off_dst, uint32_t sz, uint8_t *buf, size_t buf_size); + +/** + * Gets the total data size (excluding headers and TLVs) of a compressed image when it is + * decompressed. + * + * @param hdr Image header. + * @param fap Flash area of the slot. + * @param img_decomp_size Pointer to variable that will be updated with the decompressed image + * size. + * + * @return 0 on success; nonzero on failure. + */ +int bootutil_get_img_decomp_size(const struct image_header *hdr, const struct flash_area *fap, + uint32_t *img_decomp_size); + +/** + * Calculate MCUboot-compatible image hash of compressed image slot. + * + * @param state MCUboot state. + * @param hdr Image header. + * @param fap Flash area of the slot. + * @param tmp_buf Temporary buffer for reading data from. + * @param tmp_buf_sz Size of temporary buffer. + * @param hash_result Pointer to a variable that will be updated with the image hash. + * @param seed Not currently used, set to NULL. + * @param seed_len Not currently used, set to 0. + * + * @return 0 on success; nonzero on failure. + */ +int bootutil_img_hash_decompress(struct boot_loader_state *state, struct image_header *hdr, + const struct flash_area *fap, uint8_t *tmp_buf, + uint32_t tmp_buf_sz, uint8_t *hash_result, + uint8_t *seed, int seed_len); + +/** + * Calculates the size that the compressed image protected TLV section will occupy once the image + * has been decompressed. + * + * @param hdr Image header. + * @param fap Flash area of the slot. + * @param sz Pointer to variable that will be updated with the protected TLV size. + * + * @return 0 on success; nonzero on failure. + */ +int boot_size_protected_tlvs(const struct image_header *hdr, const struct flash_area *fap_src, + uint32_t *sz); + +#ifdef __cplusplus +} +#endif + +#endif /* H_DECOMPRESSION_ */ From 0ae144127f7d9cfca4907e5cec167c8d6643bf28 Mon Sep 17 00:00:00 2001 From: Jamie McCrae Date: Thu, 7 Nov 2024 10:53:06 +0000 Subject: [PATCH 079/420] [nrf noup] boot: zephyr: Add experimental selection to compression Adds selecting the experimental Kconfig when compession is in use Signed-off-by: Jamie McCrae Signed-off-by: Dominik Ermel (cherry picked from commit 8cd14c1e992dc8af95c29a29baa837ef1f60df12) --- boot/zephyr/Kconfig | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/boot/zephyr/Kconfig b/boot/zephyr/Kconfig index e36fdd8e9..12fd9c5e4 100644 --- a/boot/zephyr/Kconfig +++ b/boot/zephyr/Kconfig @@ -1110,9 +1110,10 @@ config BOOT_DECOMPRESSION_SUPPORT if BOOT_DECOMPRESSION_SUPPORT menuconfig BOOT_DECOMPRESSION - bool "Decompression" + bool "Decompression [EXPERIMENTAL]" select NRF_COMPRESS_CLEANUP select PM_USE_CONFIG_SRAM_SIZE if SOC_NRF54L15_CPUAPP + select EXPERIMENTAL help If enabled, will include support for compressed images being loaded to the secondary slot which then get decompressed into the primary slot. This mode allows the secondary slot to From 002515b349bd8cd4e190af2807c50e88ef8605fd Mon Sep 17 00:00:00 2001 From: Michal Kozikowski Date: Tue, 13 May 2025 13:33:22 +0200 Subject: [PATCH 080/420] [nrf noup] decompression: Align to changes in nrfcompress API This commit aligns to the changes in the nrfcompress API, which now enables the caller to provide the expected size of the decompressed image. ref: NCSDK-32340 Signed-off-by: Michal Kozikowski Signed-off-by: Dominik Ermel (cherry picked from commit aa59badf3d04a18f35ad2b0e0ff2ad6ff15b5b7e) --- boot/zephyr/decompression.c | 65 ++++++++++++++++++++++++------------- 1 file changed, 42 insertions(+), 23 deletions(-) diff --git a/boot/zephyr/decompression.c b/boot/zephyr/decompression.c index 87e3d3763..ce4fe0b2b 100644 --- a/boot/zephyr/decompression.c +++ b/boot/zephyr/decompression.c @@ -256,15 +256,6 @@ int bootutil_img_hash_decompress(struct boot_loader_state *state, struct image_h goto finish_without_clean; } - rc = compression_lzma->init(NULL); - rc = compression_arm_thumb->init(NULL); - - if (rc) { - BOOT_LOG_ERR("Decompression library fatal error"); - rc = BOOT_EBADSTATUS; - goto finish_without_clean; - } - /* We need a modified header which has the updated sizes, start with the original header */ memcpy(&modified_hdr, hdr, sizeof(modified_hdr)); @@ -276,12 +267,28 @@ int bootutil_img_hash_decompress(struct boot_loader_state *state, struct image_h if (rc) { BOOT_LOG_ERR("Unable to determine decompressed size of compressed image"); rc = BOOT_EBADIMAGE; - goto finish; + goto finish_without_clean; } modified_hdr.ih_flags &= ~COMPRESSIONFLAGS; modified_hdr.ih_img_size = decompressed_image_size; + rc = compression_lzma->init(NULL, decompressed_image_size); + + if (rc) { + BOOT_LOG_ERR("Decompression library fatal error"); + rc = BOOT_EBADSTATUS; + goto finish_without_clean; + } + + rc = compression_arm_thumb->init(NULL, decompressed_image_size); + + if (rc) { + BOOT_LOG_ERR("Decompression library fatal error"); + rc = BOOT_EBADSTATUS; + goto finish; + } + /* Calculate the protected TLV size, these will not include the decompressed * sha/size/signature entries */ @@ -1101,7 +1108,7 @@ int boot_copy_region_decompress(struct boot_loader_state *state, const struct fl if (rc) { BOOT_LOG_ERR("Invalid/missing image decrypted compressed size value"); rc = BOOT_EBADIMAGE; - goto finish; + goto finish_without_clean; } if (IS_ENCRYPTED(hdr)) { @@ -1124,7 +1131,7 @@ int boot_copy_region_decompress(struct boot_loader_state *state, const struct fl */ BOOT_LOG_ERR("Invalid image compression flags: no supported compression found"); rc = BOOT_EBADIMAGE; - goto finish; + goto finish_without_clean; } compression_lzma = nrf_compress_implementation_find(NRF_COMPRESS_TYPE_LZMA); @@ -1135,16 +1142,7 @@ int boot_copy_region_decompress(struct boot_loader_state *state, const struct fl /* Compression library missing or missing required function pointer */ BOOT_LOG_ERR("Decompression library fatal error"); rc = BOOT_EBADSTATUS; - goto finish; - } - - rc = compression_lzma->init(NULL); - rc = compression_arm_thumb->init(NULL); - - if (rc) { - BOOT_LOG_ERR("Decompression library fatal error"); - rc = BOOT_EBADSTATUS; - goto finish; + goto finish_without_clean; } write_alignment = flash_area_align(fap_dst); @@ -1158,12 +1156,28 @@ int boot_copy_region_decompress(struct boot_loader_state *state, const struct fl if (rc) { BOOT_LOG_ERR("Unable to determine decompressed size of compressed image"); rc = BOOT_EBADIMAGE; - goto finish; + goto finish_without_clean; } modified_hdr.ih_flags &= ~COMPRESSIONFLAGS; modified_hdr.ih_img_size = decompressed_image_size; + rc = compression_lzma->init(NULL, decompressed_image_size); + + if (rc) { + BOOT_LOG_ERR("Decompression library fatal error"); + rc = BOOT_EBADSTATUS; + goto finish_without_clean; + } + + rc = compression_arm_thumb->init(NULL, decompressed_image_size); + + if (rc) { + BOOT_LOG_ERR("Decompression library fatal error"); + rc = BOOT_EBADSTATUS; + goto finish; + } + /* Calculate protected TLV size for target image once items are removed */ rc = boot_size_protected_tlvs(hdr, fap_src, &protected_tlv_size); @@ -1457,6 +1471,11 @@ int boot_copy_region_decompress(struct boot_loader_state *state, const struct fl } finish: + /* Clean up decompression system */ + (void)compression_lzma->deinit(NULL); + (void)compression_arm_thumb->deinit(NULL); + +finish_without_clean: memset(decomp_buf, 0, sizeof(decomp_buf)); return rc; From 9200785d3284a15f6a469a86efb79d95b68cce1c Mon Sep 17 00:00:00 2001 From: Jamie McCrae Date: Thu, 12 Jun 2025 08:38:15 +0100 Subject: [PATCH 081/420] [nrf noup] boot: zephyr: Add bm firmware loader code Adds firmware loader code for use in baremetal mode Signed-off-by: Jamie McCrae (cherry picked from commit f123819a1d3322fa230f7cacd6d8f1672d8651e7) --- boot/zephyr/CMakeLists.txt | 19 ++- boot/zephyr/firmware_loader_bm.c | 283 +++++++++++++++++++++++++++++++ boot/zephyr/io_bm.c | 198 +++++++++++++++++++++ 3 files changed, 496 insertions(+), 4 deletions(-) create mode 100644 boot/zephyr/firmware_loader_bm.c create mode 100644 boot/zephyr/io_bm.c diff --git a/boot/zephyr/CMakeLists.txt b/boot/zephyr/CMakeLists.txt index 957c6c50a..54deaf93b 100644 --- a/boot/zephyr/CMakeLists.txt +++ b/boot/zephyr/CMakeLists.txt @@ -64,12 +64,17 @@ endif() # Zephyr port-specific sources. zephyr_library_sources( main.c - io.c flash_map_extended.c os.c keys.c ) +if(CONFIG_NCS_BM) + zephyr_library_sources(io_bm.c) +else() + zephyr_library_sources(io.c) +endif() + if(DEFINED CONFIG_ENABLE_MGMT_PERUSER) zephyr_library_sources( boot_serial_extensions.c @@ -150,9 +155,15 @@ elseif(CONFIG_SINGLE_APPLICATION_SLOT) ) zephyr_library_include_directories(${BOOT_DIR}/bootutil/src) elseif(CONFIG_BOOT_FIRMWARE_LOADER) - zephyr_library_sources( - ${BOOT_DIR}/zephyr/firmware_loader.c - ) + if(CONFIG_NCS_BM) + zephyr_library_sources( + ${BOOT_DIR}/zephyr/firmware_loader_bm.c + ) + else() + zephyr_library_sources( + ${BOOT_DIR}/zephyr/firmware_loader.c + ) + endif() zephyr_library_include_directories(${BOOT_DIR}/bootutil/src) else() zephyr_library_sources( diff --git a/boot/zephyr/firmware_loader_bm.c b/boot/zephyr/firmware_loader_bm.c new file mode 100644 index 000000000..14d5c96bd --- /dev/null +++ b/boot/zephyr/firmware_loader_bm.c @@ -0,0 +1,283 @@ +/* + * Copyright (c) 2025 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +#include +#include +#include +#include "bootutil/image.h" +#include "bootutil_priv.h" +#include "bootutil/bootutil_log.h" +#include "bootutil/bootutil_public.h" +#include "bootutil/fault_injection_hardening.h" +#include + +#include "io/io.h" +#include "mcuboot_config/mcuboot_config.h" + +#define IMAGE_TLV_INSTALLER_IMAGE 0xa0 + +BOOT_LOG_MODULE_DECLARE(mcuboot); + +static struct flash_area fa_app_installer = { + .fa_id = 1, + .fa_off = FIXED_PARTITION_OFFSET(slot0_partition), + .fa_size = FIXED_PARTITION_SIZE(slot0_partition), + .fa_dev = DEVICE_DT_GET(DT_CHOSEN(zephyr_flash_controller)), +}; + +static struct image_header hdr_app_installer = { 0 }; + +static struct flash_area fa_softdevice = { + .fa_id = 2, + .fa_dev = DEVICE_DT_GET(DT_CHOSEN(zephyr_flash_controller)), +}; + +static struct image_header hdr_softdevice = { 0 }; + +#ifdef CONFIG_BOOT_FIRMWARE_LOADER +static struct flash_area fa_firmware_loader = { + .fa_id = 3, + .fa_dev = DEVICE_DT_GET(DT_CHOSEN(zephyr_flash_controller)), +}; + +static struct image_header hdr_firmware_loader = { 0 }; +#endif + +/** + * Validate hash of a primary boot image. + * + * @param[in] fa_p flash area pointer + * @param[in] hdr boot image header pointer + * + * @return FIH_SUCCESS on success, error code otherwise + */ +static fih_ret validate_image(const struct flash_area *fap, struct image_header *hdr) +{ + static uint8_t tmpbuf[BOOT_TMPBUF_SZ]; + FIH_DECLARE(fih_rc, FIH_FAILURE); + + FIH_CALL(bootutil_img_validate, fih_rc, NULL, hdr, fap, tmpbuf, BOOT_TMPBUF_SZ, NULL, 0, NULL); + FIH_RET(fih_rc); +} + +/** + * Gather information on image and prepare for booting. Will boot from main + * image if none of the enabled entrance modes for the firmware loader are set, + * otherwise will boot the firmware loader. Note: firmware loader must be a + * valid signed image with the same signing key as the application image. + * + * @param[out] rsp Parameters for booting image, on success + * + * @return FIH_SUCCESS on success; non-zero on failure. + */ +fih_ret +boot_go(struct boot_rsp *rsp) +{ + bool boot_firmware_loader = false; + FIH_DECLARE(fih_rc, FIH_FAILURE); + bool softdevice_area_valid = false; + bool firmware_loader_area_valid = false; + int rc; + bool app_installer_image_valid = false; + bool softdevice_image_valid = false; + bool firmware_loader_image_valid = false; + bool app_installer_is_installer_image = false; + + bm_installs_init(); + + if (bm_installs_is_valid()) { + off_t start_address = 0; + size_t image_size = 0; + + rc = bm_installs_get_image_data(BM_INSTALLS_IMAGE_INDEX_SOFTDEVICE, &start_address, + &image_size); + + if (!rc) { + fa_softdevice.fa_off = start_address; + fa_softdevice.fa_size = image_size; + + if (start_address < fa_app_installer.fa_off) { + /* Invalid start address for SoftDevice */ + goto invalid_softdevice; + } + + fa_app_installer.fa_size = start_address - fa_app_installer.fa_off; + + rc = boot_image_load_header(&fa_softdevice, &hdr_softdevice); + + if (!rc) { + softdevice_area_valid = true; + } + } + +invalid_softdevice: +#ifdef CONFIG_BOOT_FIRMWARE_LOADER + start_address = 0; + image_size = 0; + rc = bm_installs_get_image_data(BM_INSTALLS_IMAGE_INDEX_FIRMWARE_LOADER, &start_address, + &image_size); + + if (!rc) { + fa_firmware_loader.fa_off = start_address; + fa_firmware_loader.fa_size = image_size; + + if (start_address < fa_app_installer.fa_off) { + /* Invalid start address for firmware loader */ + goto invalid_firmware_loader; + } + + fa_app_installer.fa_size = start_address - fa_app_installer.fa_off; + + rc = boot_image_load_header(&fa_firmware_loader, &hdr_softdevice); + + if (!rc) { + firmware_loader_area_valid = true; + } + } +#endif + } + +invalid_firmware_loader: + rc = boot_image_load_header(&fa_app_installer, &hdr_app_installer); + + if (rc) { + BOOT_LOG_ERR("Failed loading application/installer image header: %d", rc); + } else { + FIH_CALL(validate_image, fih_rc, &fa_app_installer, &hdr_app_installer); + + if (FIH_EQ(fih_rc, FIH_SUCCESS)) { + struct image_tlv_iter it; + uint32_t off2; + uint16_t len2; + + app_installer_image_valid = true; + + if (hdr_app_installer.ih_protect_tlv_size > 0) { + rc = bootutil_tlv_iter_begin(&it, &hdr_app_installer, &fa_app_installer, + IMAGE_TLV_INSTALLER_IMAGE, true); + + if (rc == 0) { + rc = bootutil_tlv_iter_next(&it, &off2, &len2, NULL); + + if (rc == 0 && len2 == sizeof(app_installer_is_installer_image)) { + rc = LOAD_IMAGE_DATA(&hdr_app_installer, &fa_app_installer, off2, + &app_installer_is_installer_image, len2); + + if (rc != 0) { + app_installer_is_installer_image = false; + } + } + } + } + } + } + + if (softdevice_area_valid) { + fih_rc = FIH_FAILURE; + rc = boot_image_load_header(&fa_softdevice, &hdr_softdevice); + + if (rc) { + BOOT_LOG_ERR("Failed loading SoftDevice image header: %d", rc); + } else { + FIH_CALL(validate_image, fih_rc, &fa_softdevice, &hdr_softdevice); + + if (FIH_EQ(fih_rc, FIH_SUCCESS)) { + softdevice_image_valid = true; + } + } + } + +#ifdef CONFIG_BOOT_FIRMWARE_LOADER + if (firmware_loader_area_valid) { + fih_rc = FIH_FAILURE; + rc = boot_image_load_header(&fa_firmware_loader, &hdr_firmware_loader); + + if (rc) { + BOOT_LOG_ERR("Failed loading firmware loader image header: %d", rc); + } else { + FIH_CALL(validate_image, fih_rc, &fa_firmware_loader, &hdr_firmware_loader); + + if (FIH_EQ(fih_rc, FIH_SUCCESS)) { + firmware_loader_image_valid = true; + } + } + } +#endif + + BOOT_LOG_DBG("Application/installer partition offset: 0x%lx, size: 0x%x, type: %d", + fa_app_installer.fa_off, fa_app_installer.fa_size, + app_installer_is_installer_image); + BOOT_LOG_DBG("SoftDevice partition offset: 0x%lx, size: 0x%x", fa_softdevice.fa_off, + fa_softdevice.fa_size); +#ifdef CONFIG_BOOT_FIRMWARE_LOADER + BOOT_LOG_DBG("Firmware loader off: 0x%lx, size: 0x%x", fa_firmware_loader.fa_off, + fa_firmware_loader.fa_size); + BOOT_LOG_DBG("SoftDevice area valid: %d, Firmware loader area valid: %d, " + "Application/installer image valid: %d, SoftDevice image valid: %d, " + "Firmware loader image valid: %d", softdevice_area_valid, + firmware_loader_area_valid, app_installer_image_valid, softdevice_image_valid, + firmware_loader_image_valid); +#else + BOOT_LOG_DBG("SoftDevice area valid: %d, Application/installer image valid: %d, " + "SoftDevice image valid: %d", softdevice_area_valid, app_installer_image_valid, + softdevice_image_valid); +#endif + +#ifdef CONFIG_BOOT_FIRMWARE_LOADER_ENTRANCE_GPIO + if (io_detect_pin() && !io_boot_skip_serial_recovery()) { + BOOT_LOG_DBG("GPIO detected for firmware loader mode"); + boot_firmware_loader = true; + } +#endif + +#ifdef CONFIG_BOOT_FIRMWARE_LOADER_PIN_RESET + if (io_detect_pin_reset()) { + BOOT_LOG_DBG("Pin reset detected for firmware loader mode"); + boot_firmware_loader = true; + } +#endif + +#ifdef CONFIG_BOOT_FIRMWARE_LOADER_BOOT_MODE + if (io_detect_boot_mode()) { + BOOT_LOG_DBG("Boot mode detected for firmware loader mode"); + boot_firmware_loader = true; + } +#endif + + if (app_installer_image_valid == true && app_installer_is_installer_image == true) { + /* Installer image is present, this gets priority */ + BOOT_LOG_DBG("Booting installer"); + rsp->br_image_off = flash_area_get_off(&fa_app_installer); + rsp->br_hdr = &hdr_app_installer; + } else if (boot_firmware_loader == true && softdevice_image_valid == true && + firmware_loader_image_valid == true) { + /* Boot firmware loader */ + BOOT_LOG_INF("Booting firmware loader"); + rsp->br_image_off = flash_area_get_off(&fa_firmware_loader); + rsp->br_hdr = &hdr_firmware_loader; + } else if (app_installer_image_valid == true && softdevice_image_valid == true) { + /* Boot main application */ + BOOT_LOG_INF("Booting main application"); + rsp->br_image_off = flash_area_get_off(&fa_app_installer); + rsp->br_hdr = &hdr_app_installer; + } else if (app_installer_image_valid == false && softdevice_image_valid == true && + firmware_loader_image_valid == true) { + /* Boot firmware loader due to missing main image */ + BOOT_LOG_INF("Booting firmware loader due to missing application image"); + rsp->br_image_off = flash_area_get_off(&fa_firmware_loader); + rsp->br_hdr = &hdr_firmware_loader; + } else { + /* Cannot boot in this configuration */ + BOOT_LOG_ERR("Error: no bootable configuration found"); + return -1; + } + + rsp->br_flash_dev_id = flash_area_get_device_id(&fa_app_installer); + + return 0; +} diff --git a/boot/zephyr/io_bm.c b/boot/zephyr/io_bm.c new file mode 100644 index 000000000..3f65a5d0e --- /dev/null +++ b/boot/zephyr/io_bm.c @@ -0,0 +1,198 @@ +/* + * Copyright (c) 2012-2014 Wind River Systems, Inc. + * Copyright (c) 2020 Arm Limited + * Copyright (c) 2021-2025 Nordic Semiconductor ASA + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "target.h" +#include "bootutil/bootutil_log.h" + +#include +#include + +#if defined(CONFIG_BOOT_SERIAL_PIN_RESET) || defined(CONFIG_BOOT_FIRMWARE_LOADER_PIN_RESET) +#include +#endif + +#if defined(CONFIG_BOOT_SERIAL_BOOT_MODE) || defined(CONFIG_BOOT_FIRMWARE_LOADER_BOOT_MODE) +#include +#endif + +/* Validate serial recovery configuration */ +#ifdef CONFIG_MCUBOOT_SERIAL +#if !defined(CONFIG_BOOT_SERIAL_ENTRANCE_GPIO) && \ + !defined(CONFIG_BOOT_SERIAL_WAIT_FOR_DFU) && \ + !defined(CONFIG_BOOT_SERIAL_BOOT_MODE) && \ + !defined(CONFIG_BOOT_SERIAL_NO_APPLICATION) && \ + !defined(CONFIG_BOOT_SERIAL_PIN_RESET) +#error "Serial recovery selected without an entrance mode set" +#endif +#endif + +/* Validate firmware loader configuration */ +#ifdef CONFIG_BOOT_FIRMWARE_LOADER +#if !defined(CONFIG_BOOT_FIRMWARE_LOADER_ENTRANCE_GPIO) && \ + !defined(CONFIG_BOOT_FIRMWARE_LOADER_BOOT_MODE) && \ + !defined(CONFIG_BOOT_FIRMWARE_LOADER_NO_APPLICATION) && \ + !defined(CONFIG_BOOT_FIRMWARE_LOADER_PIN_RESET) +#error "Firmware loader selected without an entrance mode set" +#endif +#endif + +BOOT_LOG_MODULE_DECLARE(mcuboot); + +#ifdef CONFIG_MCUBOOT_INDICATION_LED + +void io_led_init(void) +{ + nrf_gpio_cfg_output(BOARD_PIN_LED_0); + nrf_gpio_pin_write(BOARD_PIN_LED_0, BOARD_LED_ACTIVE_STATE); +} + +void io_led_set(int value) +{ + nrf_gpio_pin_write(BOARD_PIN_LED_0, (value == 0 ? !BOARD_LED_ACTIVE_STATE : BOARD_LED_ACTIVE_STATE)); +} +#endif /* CONFIG_MCUBOOT_INDICATION_LED */ + +#if defined(CONFIG_BOOT_SERIAL_ENTRANCE_GPIO) || defined(CONFIG_BOOT_USB_DFU_GPIO) || \ + defined(CONFIG_BOOT_FIRMWARE_LOADER_ENTRANCE_GPIO) + +#if defined(CONFIG_MCUBOOT_SERIAL) +#define BUTTON_0_DETECT_DELAY CONFIG_BOOT_SERIAL_DETECT_DELAY +#elif defined(CONFIG_BOOT_FIRMWARE_LOADER) +#define BUTTON_0_DETECT_DELAY CONFIG_BOOT_FIRMWARE_LOADER_DETECT_DELAY +#else +#define BUTTON_0_DETECT_DELAY CONFIG_BOOT_USB_DFU_DETECT_DELAY +#endif + +bool io_detect_pin(void) +{ + int rc; + bool pin_active; + + rc = bm_buttons_init( + &(struct bm_buttons_config){ + .pin_number = BOARD_PIN_BTN_0, + .active_state = BM_BUTTONS_ACTIVE_LOW, + .pull_config = BM_BUTTONS_PIN_PULLUP, + }, + 1, + BM_BUTTONS_DETECTION_DELAY_MIN_US); + if (rc) { + BOOT_LOG_ERR("Failed to initialize buttons: %d", rc); + return false; + } + + rc = bm_buttons_enable(); + if (rc) { + BOOT_LOG_ERR("Failed to enable button detection: %d", rc); + return false; + } + + pin_active = bm_buttons_is_pressed(BOARD_PIN_BTN_0); + + if (pin_active) { + if (BUTTON_0_DETECT_DELAY > 0) { +#ifdef CONFIG_MULTITHREADING + k_sleep(K_MSEC(50)); +#else + k_busy_wait(50000); +#endif + + /* Get the uptime for debounce purposes. */ + int64_t timestamp = k_uptime_get(); + + for(;;) { + pin_active = bm_buttons_is_pressed(BOARD_PIN_BTN_0); + + /* Get delta from when this started */ + uint32_t delta = k_uptime_get() - timestamp; + + /* If not pressed OR if pressed > debounce period, stop. */ + if (delta >= BUTTON_0_DETECT_DELAY || !pin_active) { + break; + } + + /* Delay 1 ms */ +#ifdef CONFIG_MULTITHREADING + k_sleep(K_MSEC(1)); +#else + k_busy_wait(1000); +#endif + } + } + } + + rc = bm_buttons_disable(); + + if (rc) { + BOOT_LOG_ERR("Failed to disable buttons: %d", rc); + } + + rc = bm_buttons_deinit(); + if (rc) { + BOOT_LOG_ERR("Failed to de-initialize buttons: %d", rc); + } + + return (bool)pin_active; +} +#endif + +#if defined(CONFIG_BOOT_SERIAL_PIN_RESET) || defined(CONFIG_BOOT_FIRMWARE_LOADER_PIN_RESET) +bool io_detect_pin_reset(void) +{ + uint32_t reset_cause; + int rc; + + rc = hwinfo_get_reset_cause(&reset_cause); + + if (rc == 0 && (reset_cause & RESET_PIN)) { + (void)hwinfo_clear_reset_cause(); + return true; + } + + return false; +} +#endif + +#if defined(CONFIG_BOOT_SERIAL_BOOT_MODE) || defined(CONFIG_BOOT_FIRMWARE_LOADER_BOOT_MODE) +bool io_detect_boot_mode(void) +{ + int32_t boot_mode; + + boot_mode = bootmode_check(BOOT_MODE_TYPE_BOOTLOADER); + + if (boot_mode == 1) { + /* Boot mode to stay in bootloader, clear status and enter serial + * recovery mode + */ + bootmode_clear(); + + return true; + } + + return false; +} +#endif From 068718ae281e70cc5c771d51320f1f8707d8ea59 Mon Sep 17 00:00:00 2001 From: Tomasz Chyrowicz Date: Thu, 3 Jul 2025 12:52:05 +0200 Subject: [PATCH 082/420] [nrf noup] boot: Provide default configuration for nRF54H20 Enable ed25519 signature as well as direct hashing while building for nRF54H20DK. Ref: NCSDK-34304 Signed-off-by: Tomasz Chyrowicz (cherry picked from commit 29bcb744c54f93bc363b47e498afd31bbbdf2f6e) --- boot/zephyr/Kconfig | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/boot/zephyr/Kconfig b/boot/zephyr/Kconfig index 12fd9c5e4..de31262a4 100644 --- a/boot/zephyr/Kconfig +++ b/boot/zephyr/Kconfig @@ -185,6 +185,7 @@ config BOOT_IMG_HASH_ALG_SHA512_ALLOW config BOOT_IMG_HASH_DIRECTLY_ON_STORAGE bool "Hash calculation functions access storage through address space" + default y if NRF_SECURITY && SOC_NRF54H20 depends on !BOOT_ENCRYPT_IMAGE help When possible to map storage device, at least for read operations, @@ -242,7 +243,7 @@ config BOOT_SIGNATURE_TYPE_PURE_ALLOW choice BOOT_SIGNATURE_TYPE prompt "Signature type" - default BOOT_SIGNATURE_TYPE_ED25519 if SOC_NRF54L15_CPUAPP + default BOOT_SIGNATURE_TYPE_ED25519 if SOC_NRF54L15_CPUAPP || SOC_NRF54H20_CPUAPP default BOOT_SIGNATURE_TYPE_RSA config BOOT_SIGNATURE_TYPE_NONE From a9e70e43fa548c86bec946dc06210b8a2ba2b860 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Adam=20Szczygie=C5=82?= Date: Tue, 8 Jul 2025 09:05:18 +0200 Subject: [PATCH 083/420] [nrf noup] boot: Add retry for image verification MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Intended mainly for direct-xip mode. Allows to control: - number of image validation attempts performed before considering the image invalid - time before next attempt is made Signed-off-by: Adam Szczygieł (cherry picked from commit 25346815646625708b3269c46fe45089885da551) --- boot/bootutil/src/loader.c | 39 ++++++++++++++++++++++++++++++++++---- boot/zephyr/Kconfig | 17 +++++++++++++++++ 2 files changed, 52 insertions(+), 4 deletions(-) diff --git a/boot/bootutil/src/loader.c b/boot/bootutil/src/loader.c index c074a00db..5adbfcca0 100644 --- a/boot/bootutil/src/loader.c +++ b/boot/bootutil/src/loader.c @@ -57,6 +57,9 @@ #ifdef __ZEPHYR__ #include +#if defined(CONFIG_NRF_MCUBOOT_IMG_VALIDATE_ATTEMPT_WAIT_MS) +#include +#endif /* CONFIG_NRF_MCUBOOT_IMG_VALIDATE_ATTEMPT_WAIT_MS */ #endif #if defined(CONFIG_SOC_NRF5340_CPUAPP) && defined(PM_CPUNET_B0N_ADDRESS) && defined(CONFIG_PCD_APP) @@ -909,14 +912,42 @@ boot_image_check(struct boot_loader_state *state, struct image_header *hdr, } #endif + for (int i = 1; i <= CONFIG_NRF_MCUBOOT_IMG_VALIDATE_ATTEMPT_COUNT; i++ ) { +#if CONFIG_NRF_MCUBOOT_IMG_VALIDATE_ATTEMPT_COUNT > 1 + BOOT_LOG_DBG("Image validation attempt %d/%d", i, CONFIG_NRF_MCUBOOT_IMG_VALIDATE_ATTEMPT_COUNT); +#endif /* CONFIG_NRF_MCUBOOT_IMG_VALIDATE_ATTEMPT_COUNT > 1 */ + #if defined(MCUBOOT_SWAP_USING_OFFSET) && defined(MCUBOOT_SERIAL_RECOVERY) - FIH_CALL(bootutil_img_validate, fih_rc, state, hdr, fap, tmpbuf, BOOT_TMPBUF_SZ, - NULL, 0, NULL, 0); + FIH_CALL(bootutil_img_validate, fih_rc, state, hdr, fap, tmpbuf, BOOT_TMPBUF_SZ, + NULL, 0, NULL, 0); #else - FIH_CALL(bootutil_img_validate, fih_rc, state, hdr, fap, tmpbuf, BOOT_TMPBUF_SZ, - NULL, 0, NULL); + FIH_CALL(bootutil_img_validate, fih_rc, state, hdr, fap, tmpbuf, BOOT_TMPBUF_SZ, + NULL, 0, NULL); #endif + if (FIH_EQ(fih_rc, FIH_SUCCESS)) { +#if CONFIG_NRF_MCUBOOT_IMG_VALIDATE_ATTEMPT_COUNT > 1 + BOOT_LOG_DBG("Image validation attempt %d/%d success", i, CONFIG_NRF_MCUBOOT_IMG_VALIDATE_ATTEMPT_COUNT); +#endif /* CONFIG_NRF_MCUBOOT_IMG_VALIDATE_ATTEMPT_COUNT > 1 */ + break; + } else { +#if CONFIG_NRF_MCUBOOT_IMG_VALIDATE_ATTEMPT_COUNT > 1 + BOOT_LOG_WRN("Image validation attempt %d/%d failure: %d", + i, + CONFIG_NRF_MCUBOOT_IMG_VALIDATE_ATTEMPT_COUNT, fih_rc); +#endif /* CONFIG_NRF_MCUBOOT_IMG_VALIDATE_ATTEMPT_COUNT > 1 */ + + if (i < CONFIG_NRF_MCUBOOT_IMG_VALIDATE_ATTEMPT_COUNT) { +#if defined(CONFIG_NRF_MCUBOOT_IMG_VALIDATE_ATTEMPT_WAIT_MS) +#if CONFIG_NRF_MCUBOOT_IMG_VALIDATE_ATTEMPT_COUNT > 1 + BOOT_LOG_DBG("Waiting %d ms before next attempt", + CONFIG_NRF_MCUBOOT_IMG_VALIDATE_ATTEMPT_WAIT_MS); +#endif /* CONFIG_NRF_MCUBOOT_IMG_VALIDATE_ATTEMPT_COUNT > 1 */ + k_busy_wait(CONFIG_NRF_MCUBOOT_IMG_VALIDATE_ATTEMPT_WAIT_MS * 1000); +#endif /* CONFIG_NRF_MCUBOOT_IMG_VALIDATE_ATTEMPT_WAIT_MS */ + } + } + } FIH_RET(fih_rc); } diff --git a/boot/zephyr/Kconfig b/boot/zephyr/Kconfig index de31262a4..6bb236969 100644 --- a/boot/zephyr/Kconfig +++ b/boot/zephyr/Kconfig @@ -1251,4 +1251,21 @@ config MCUBOOT_VERIFY_IMG_ADDRESS also be useful when BOOT_DIRECT_XIP is enabled, to ensure that the image linked at the correct address is loaded. +config NRF_MCUBOOT_IMG_VALIDATE_ATTEMPT_COUNT + int "Number of image validation attempts" + default 1 + help + Number of image validation attempts performed before an image is considered invalid. + A wait is done between each attempt to allow for recovery from a temporary disruption. + This can prevent erasing an image when initial validation fails. + Wait time is controlled by MCUBOOT_IMG_VALIDATE_ATTEMPT_WAIT_MS. + +config NRF_MCUBOOT_IMG_VALIDATE_ATTEMPT_WAIT_MS + int "Time between image validation attempts" + depends on NRF_MCUBOOT_IMG_VALIDATE_ATTEMPT_COUNT > 1 + default 5000 + help + Time between image validation attempts, in milliseconds. + Allows for recovery from transient bit flips or similar situations. + source "Kconfig.zephyr" From 26192ca1c9986dd9f50b9e5537bfc38fd2953128 Mon Sep 17 00:00:00 2001 From: Dominik Ermel Date: Fri, 20 Sep 2024 16:34:00 +0000 Subject: [PATCH 084/420] [nrf noup] bootutil: Add support for KMU stored ED25519 signature key The commit adds verification of image using keys stored in KMU. Signed-off-by: Dominik Ermel (cherry picked from commit e28f5e98cf92b174412bf18dd633d035c84da5ac) --- boot/bootutil/src/ed25519_psa.c | 51 ++++++++++++++++++++++++++++++ boot/bootutil/src/image_ed25519.c | 9 +++++- boot/bootutil/src/image_validate.c | 12 +++++-- boot/zephyr/CMakeLists.txt | 2 +- boot/zephyr/Kconfig | 26 +++++++++++++++ 5 files changed, 96 insertions(+), 4 deletions(-) diff --git a/boot/bootutil/src/ed25519_psa.c b/boot/bootutil/src/ed25519_psa.c index 5b8a4ed7c..cd016158b 100644 --- a/boot/bootutil/src/ed25519_psa.c +++ b/boot/bootutil/src/ed25519_psa.c @@ -12,6 +12,9 @@ #include #include +#if defined(CONFIG_BOOT_SIGNATURE_USING_KMU) +#include +#endif BOOT_LOG_MODULE_REGISTER(ed25519_psa); @@ -19,6 +22,18 @@ BOOT_LOG_MODULE_REGISTER(ed25519_psa); #define EDDSA_KEY_LENGTH 32 #define EDDSA_SIGNAGURE_LENGTH 64 +#if defined(CONFIG_BOOT_SIGNATURE_USING_KMU) +/* List of KMU stored key ids available for MCUboot */ +#define MAKE_PSA_KMU_KEY_ID(id) PSA_KEY_HANDLE_FROM_CRACEN_KMU_SLOT(CRACEN_KMU_KEY_USAGE_SCHEME_RAW, id) +static psa_key_id_t kmu_key_ids[3] = { + MAKE_PSA_KMU_KEY_ID(226), + MAKE_PSA_KMU_KEY_ID(228), + MAKE_PSA_KMU_KEY_ID(230) +}; +#define KMU_KEY_COUNT (sizeof(kmu_key_ids)/sizeof(kmu_key_ids[0])) +#endif + +#if !defined(CONFIG_BOOT_SIGNATURE_USING_KMU) int ED25519_verify(const uint8_t *message, size_t message_len, const uint8_t signature[EDDSA_SIGNAGURE_LENGTH], const uint8_t public_key[EDDSA_KEY_LENGTH]) @@ -71,3 +86,39 @@ int ED25519_verify(const uint8_t *message, size_t message_len, return ret; } +#else +int ED25519_verify(const uint8_t *message, size_t message_len, + const uint8_t signature[EDDSA_SIGNAGURE_LENGTH], + const uint8_t public_key[EDDSA_KEY_LENGTH]) +{ + ARG_UNUSED(public_key); + /* Set to any error */ + psa_status_t status = PSA_ERROR_BAD_STATE; + int ret = 0; /* Fail by default */ + + /* Initialize PSA Crypto */ + status = psa_crypto_init(); + if (status != PSA_SUCCESS) { + BOOT_LOG_ERR("PSA crypto init failed %d", status); + return 0; + } + + status = PSA_ERROR_BAD_STATE; + + for (int i = 0; i < KMU_KEY_COUNT; ++i) { + psa_key_id_t kid = kmu_key_ids[i]; + + status = psa_verify_message(kid, PSA_ALG_PURE_EDDSA, message, + message_len, signature, + EDDSA_SIGNAGURE_LENGTH); + if (status == PSA_SUCCESS) { + ret = 1; + break; + } + + BOOT_LOG_ERR("ED25519 signature verification failed %d", status); + } + + return ret; +} +#endif diff --git a/boot/bootutil/src/image_ed25519.c b/boot/bootutil/src/image_ed25519.c index 4d83bb3d7..1a02811e3 100644 --- a/boot/bootutil/src/image_ed25519.c +++ b/boot/bootutil/src/image_ed25519.c @@ -34,6 +34,7 @@ extern int ED25519_verify(const uint8_t *message, size_t message_len, const uint8_t signature[EDDSA_SIGNATURE_LENGTH], const uint8_t public_key[NUM_ED25519_BYTES]); +#if !defined(CONFIG_BOOT_SIGNATURE_USING_KMU) #if !defined(MCUBOOT_KEY_IMPORT_BYPASS_ASN) /* * Parse the public key used for signing. @@ -76,6 +77,7 @@ bootutil_import_key(uint8_t **cp, uint8_t *end) return 0; } #endif /* !defined(MCUBOOT_KEY_IMPORT_BYPASS_ASN) */ +#endif /* Signature verification base function. * The function takes buffer of specified length and tries to verify @@ -90,8 +92,10 @@ bootutil_verify(uint8_t *buf, uint32_t blen, { int rc; FIH_DECLARE(fih_rc, FIH_FAILURE); - uint8_t *pubkey; + uint8_t *pubkey = NULL; +#if !defined(CONFIG_BOOT_SIGNATURE_USING_KMU) uint8_t *end; +#endif BOOT_LOG_DBG("bootutil_verify: ED25519 key_id %d", (int)key_id); @@ -102,6 +106,7 @@ bootutil_verify(uint8_t *buf, uint32_t blen, goto out; } +#if !defined(CONFIG_BOOT_SIGNATURE_USING_KMU) pubkey = (uint8_t *)bootutil_keys[key_id].key; end = pubkey + *bootutil_keys[key_id].len; @@ -125,6 +130,8 @@ bootutil_verify(uint8_t *buf, uint32_t blen, } pubkey = end - NUM_ED25519_BYTES; +#endif + #endif rc = ED25519_verify(buf, blen, sig, pubkey); diff --git a/boot/bootutil/src/image_validate.c b/boot/bootutil/src/image_validate.c index 0875fd47b..96c1853dd 100644 --- a/boot/bootutil/src/image_validate.c +++ b/boot/bootutil/src/image_validate.c @@ -292,6 +292,7 @@ bootutil_img_hash(struct boot_loader_state *state, # define KEY_BUF_SIZE (SIG_BUF_SIZE + 24) #endif /* !MCUBOOT_HW_KEY */ +#if !defined(CONFIG_BOOT_SIGNATURE_USING_KMU) #if !defined(MCUBOOT_HW_KEY) static int bootutil_find_key(uint8_t *keyhash, uint8_t keyhash_len) @@ -360,6 +361,7 @@ bootutil_find_key(uint8_t image_index, uint8_t *key, uint16_t key_len) } #endif /* !MCUBOOT_HW_KEY */ #endif /* !MCUBOOT_BUILTIN_KEY */ +#endif /* !defined(CONFIG_BOOT_SIGNATURE_USING_KMU) */ #endif /* EXPECTED_SIG_TLV */ /** @@ -729,6 +731,7 @@ bootutil_img_validate(struct boot_loader_state *state, break; } #endif /* defined(EXPECTED_HASH_TLV) && !defined(MCUBOOT_SIGN_PURE) */ +#if !defined(CONFIG_BOOT_SIGNATURE_USING_KMU) #ifdef EXPECTED_KEY_TLV case EXPECTED_KEY_TLV: { @@ -760,15 +763,18 @@ bootutil_img_validate(struct boot_loader_state *state, break; } #endif /* EXPECTED_KEY_TLV */ +#endif /* !defined(CONFIG_BOOT_SIGNATURE_USING_KMU) */ #ifdef EXPECTED_SIG_TLV case EXPECTED_SIG_TLV: { BOOT_LOG_DBG("bootutil_img_validate: EXPECTED_SIG_TLV == %d", EXPECTED_SIG_TLV); +#if !defined(CONFIG_BOOT_SIGNATURE_USING_KMU) /* Ignore this signature if it is out of bounds. */ if (key_id < 0 || key_id >= bootutil_key_cnt) { key_id = -1; continue; } +#endif /* !defined(CONFIG_BOOT_SIGNATURE_USING_KMU) */ if (!EXPECTED_SIG_LEN(len) || len > sizeof(buf)) { rc = -1; goto out; @@ -925,7 +931,7 @@ bootutil_img_validate(struct boot_loader_state *state, } #ifdef EXPECTED_SIG_TLV -#ifdef EXPECTED_KEY_TLV +#if !defined(CONFIG_BOOT_SIGNATURE_USING_KMU) && defined(EXPECTED_KEY_TLV) rc = bootutil_tlv_iter_begin(&it, hdr, fap, EXPECTED_KEY_TLV, false); if (rc) { goto out; @@ -971,7 +977,7 @@ bootutil_img_validate(struct boot_loader_state *state, */ } } -#endif /* EXPECTED_KEY_TLV */ +#endif /* !CONFIG_BOOT_SIGNATURE_USING_KMU && EXPECTED_KEY_TLV */ rc = bootutil_tlv_iter_begin(&it, hdr, fap, IMAGE_TLV_DECOMP_SIGNATURE, true); if (rc) { @@ -994,10 +1000,12 @@ bootutil_img_validate(struct boot_loader_state *state, if (type == IMAGE_TLV_DECOMP_SIGNATURE) { /* Ignore this signature if it is out of bounds. */ +#if !defined(CONFIG_BOOT_SIGNATURE_USING_KMU) if (key_id < 0 || key_id >= bootutil_key_cnt) { key_id = -1; continue; } +#endif if (!EXPECTED_SIG_LEN(len) || len > sizeof(buf)) { rc = -1; diff --git a/boot/zephyr/CMakeLists.txt b/boot/zephyr/CMakeLists.txt index 54deaf93b..ecb4ac704 100644 --- a/boot/zephyr/CMakeLists.txt +++ b/boot/zephyr/CMakeLists.txt @@ -355,7 +355,7 @@ if(CONFIG_MCUBOOT_SERIAL) endif() endif() -if(NOT CONFIG_BOOT_SIGNATURE_KEY_FILE STREQUAL "") +if(NOT CONFIG_BOOT_SIGNATURE_USING_KMU AND NOT CONFIG_BOOT_SIGNATURE_KEY_FILE STREQUAL "") # CONF_FILE points to the KConfig configuration files of the bootloader. foreach (filepath ${CONF_FILE}) file(READ ${filepath} temp_text) diff --git a/boot/zephyr/Kconfig b/boot/zephyr/Kconfig index 6bb236969..cddb1f9c3 100644 --- a/boot/zephyr/Kconfig +++ b/boot/zephyr/Kconfig @@ -384,6 +384,22 @@ endif endchoice +config BOOT_SIGNATURE_USING_KMU + bool "Use KMU stored keys for signature verification" + depends on NRF_SECURITY + depends on CRACEN_LIB_KMU + select PSA_WANT_ALG_GCM + select PSA_WANT_KEY_TYPE_AES + select PSA_WANT_AES_KEY_SIZE_256 + select PSA_WANT_ALG_SP800_108_COUNTER_CMAC + select PSA_WANT_ALG_CMAC + select PSA_WANT_ALG_ECB_NO_PADDING + help + MCUboot will use keys provisioned to the device key management unit for signature + verification instead of compiling in key data from a file. + +if !BOOT_SIGNATURE_USING_KMU + config BOOT_SIGNATURE_KEY_FILE string "PEM key file" default "root-ec-p256.pem" if BOOT_SIGNATURE_TYPE_ECDSA_P256 @@ -401,6 +417,8 @@ config BOOT_SIGNATURE_KEY_FILE with the public key information will be written in a format expected by MCUboot. +endif + config MCUBOOT_CLEANUP_ARM_CORE bool "Perform core cleanup before chain-load the application" depends on CPU_CORTEX_M @@ -430,6 +448,14 @@ config MCUBOOT_INFINITE_LOOP_AFTER_RAM_CLEANUP Verification option that keeps execution in infinite loop after RAM cleanup has been performed. +# Disable MBEDTLS from being selected if NRF_SECURITY is enabled, and use default NRF_SECURITY +# configuration file for MBEDTLS +config MBEDTLS + depends on !NRF_SECURITY + +config NRF_SECURITY + select MBEDTLS_PROMPTLESS + config MBEDTLS_CFG_FILE # It might be awkward to define an Mbed TLS header file when TinyCrypt # is used, but the fact is that Mbed TLS' ASN1 parse module is used From 373038be7dde47f025974e6591e91d0dad8ab355 Mon Sep 17 00:00:00 2001 From: Jamie McCrae Date: Mon, 2 Dec 2024 10:51:41 +0000 Subject: [PATCH 085/420] [nrf noup] boot: bootutil: Allow configuring number of KMU keys Adds a new Kconfig CONFIG_BOOT_SIGNATURE_KMU_SLOTS which allows specifying how many KMU key IDs are supported, the default is set to 1 instead of 3 which was set before NCSDK-30743 Signed-off-by: Jamie McCrae Signed-off-by: Dominik Ermel (cherry picked from commit e211d928110ca431a29613e2eb0def155e079ea5) --- boot/bootutil/src/ed25519_psa.c | 7 +++++-- boot/zephyr/Kconfig | 12 ++++++++++++ 2 files changed, 17 insertions(+), 2 deletions(-) diff --git a/boot/bootutil/src/ed25519_psa.c b/boot/bootutil/src/ed25519_psa.c index cd016158b..7665e4067 100644 --- a/boot/bootutil/src/ed25519_psa.c +++ b/boot/bootutil/src/ed25519_psa.c @@ -12,6 +12,7 @@ #include #include +#include #if defined(CONFIG_BOOT_SIGNATURE_USING_KMU) #include #endif @@ -30,7 +31,9 @@ static psa_key_id_t kmu_key_ids[3] = { MAKE_PSA_KMU_KEY_ID(228), MAKE_PSA_KMU_KEY_ID(230) }; -#define KMU_KEY_COUNT (sizeof(kmu_key_ids)/sizeof(kmu_key_ids[0])) + +BUILD_ASSERT(CONFIG_BOOT_SIGNATURE_KMU_SLOTS <= ARRAY_SIZE(kmu_key_ids), + "Invalid number of KMU slots, up to 3 are supported on nRF54L15"); #endif #if !defined(CONFIG_BOOT_SIGNATURE_USING_KMU) @@ -105,7 +108,7 @@ int ED25519_verify(const uint8_t *message, size_t message_len, status = PSA_ERROR_BAD_STATE; - for (int i = 0; i < KMU_KEY_COUNT; ++i) { + for (int i = 0; i < CONFIG_BOOT_SIGNATURE_KMU_SLOTS; ++i) { psa_key_id_t kid = kmu_key_ids[i]; status = psa_verify_message(kid, PSA_ALG_PURE_EDDSA, message, diff --git a/boot/zephyr/Kconfig b/boot/zephyr/Kconfig index cddb1f9c3..606d82ed4 100644 --- a/boot/zephyr/Kconfig +++ b/boot/zephyr/Kconfig @@ -398,6 +398,18 @@ config BOOT_SIGNATURE_USING_KMU MCUboot will use keys provisioned to the device key management unit for signature verification instead of compiling in key data from a file. +if BOOT_SIGNATURE_USING_KMU + +config BOOT_SIGNATURE_KMU_SLOTS + int "KMU key slots" + range 1 3 + default 1 + help + Selects the number of KMU key slots (also known as generations) to use when verifying + an image. + +endif + if !BOOT_SIGNATURE_USING_KMU config BOOT_SIGNATURE_KEY_FILE From 9dacf6dbff98acc4eb93312393eee8a197064ea2 Mon Sep 17 00:00:00 2001 From: Mateusz Michalek Date: Mon, 17 Mar 2025 21:25:41 +0100 Subject: [PATCH 086/420] [nrf noup] bootutil: key revocation Disable previous generation key when update comes with new valid key and application is confirmed. Signed-off-by: Mateusz Michalek Signed-off-by: Dominik Ermel (cherry picked from commit a378749369382ef9eeadaa51b10d0ed77831e0b2) --- .../include/bootutil/key_revocation.h | 30 ++++++++++++++ boot/bootutil/src/ed25519_psa.c | 41 +++++++++++++++++++ boot/bootutil/src/key_revocation.c | 24 +++++++++++ boot/bootutil/src/loader.c | 16 ++++++++ boot/zephyr/CMakeLists.txt | 6 +++ boot/zephyr/Kconfig | 12 ++++++ 6 files changed, 129 insertions(+) create mode 100644 boot/bootutil/include/bootutil/key_revocation.h create mode 100644 boot/bootutil/src/key_revocation.c diff --git a/boot/bootutil/include/bootutil/key_revocation.h b/boot/bootutil/include/bootutil/key_revocation.h new file mode 100644 index 000000000..d184c9579 --- /dev/null +++ b/boot/bootutil/include/bootutil/key_revocation.h @@ -0,0 +1,30 @@ +/* + * Copyright (c) 2025 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: LicenseRef-Nordic-5-Clause + */ + +#ifndef H_KEY_REVOCATION_ +#define H_KEY_REVOCATION_ + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +#define BOOT_KEY_REVOKE_OK 0 +#define BOOT_KEY_REVOKE_NOT_READY 1 +#define BOOT_KEY_REVOKE_INVALID 2 +#define BOOT_KEY_REVOKE_FAILED 2 + + +void allow_revoke(void); + +int revoke(void); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/boot/bootutil/src/ed25519_psa.c b/boot/bootutil/src/ed25519_psa.c index 7665e4067..6393d996e 100644 --- a/boot/bootutil/src/ed25519_psa.c +++ b/boot/bootutil/src/ed25519_psa.c @@ -32,6 +32,11 @@ static psa_key_id_t kmu_key_ids[3] = { MAKE_PSA_KMU_KEY_ID(230) }; +#if defined(CONFIG_BOOT_KMU_KEYS_REVOCATION) +#include +static psa_key_id_t *validated_with = NULL; +#endif + BUILD_ASSERT(CONFIG_BOOT_SIGNATURE_KMU_SLOTS <= ARRAY_SIZE(kmu_key_ids), "Invalid number of KMU slots, up to 3 are supported on nRF54L15"); #endif @@ -116,6 +121,9 @@ int ED25519_verify(const uint8_t *message, size_t message_len, EDDSA_SIGNAGURE_LENGTH); if (status == PSA_SUCCESS) { ret = 1; +#if defined(CONFIG_BOOT_KMU_KEYS_REVOCATION) + validated_with = kmu_key_ids + i; +#endif break; } @@ -124,4 +132,37 @@ int ED25519_verify(const uint8_t *message, size_t message_len, return ret; } +#if defined(CONFIG_BOOT_KMU_KEYS_REVOCATION) +int exec_revoke(void) +{ + int ret = BOOT_KEY_REVOKE_OK; + psa_status_t status = psa_crypto_init(); + + if (!validated_with) { + ret = BOOT_KEY_REVOKE_INVALID; + goto out; + } + + if (status != PSA_SUCCESS) { + BOOT_LOG_ERR("PSA crypto init failed with error %d", status); + ret = BOOT_KEY_REVOKE_FAILED; + goto out; + } + for (int i = 0; i < CONFIG_BOOT_SIGNATURE_KMU_SLOTS; i++) { + if ((kmu_key_ids + i) == validated_with) { + break; + } + BOOT_LOG_DBG("Invalidating key ID %d", i); + + status = psa_destroy_key(kmu_key_ids[i]); + if (status == PSA_SUCCESS) { + BOOT_LOG_DBG("Success on key ID %d", i); + } else { + BOOT_LOG_ERR("Key invalidation failed with: %d", status); + } + } +out: + return ret; +} +#endif /* CONFIG_BOOT_KMU_KEYS_REVOCATION */ #endif diff --git a/boot/bootutil/src/key_revocation.c b/boot/bootutil/src/key_revocation.c new file mode 100644 index 000000000..0768a3188 --- /dev/null +++ b/boot/bootutil/src/key_revocation.c @@ -0,0 +1,24 @@ +/* + * Copyright (c) 2025 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: LicenseRef-Nordic-5-Clause + */ + +#include + +extern int exec_revoke(void); + +static uint8_t ready_to_revoke; + +void allow_revoke(void) +{ + ready_to_revoke = 1; +} + +int revoke(void) +{ + if (ready_to_revoke) { + return exec_revoke(); + } + return BOOT_KEY_REVOKE_NOT_READY; +} diff --git a/boot/bootutil/src/loader.c b/boot/bootutil/src/loader.c index 5adbfcca0..366982246 100644 --- a/boot/bootutil/src/loader.c +++ b/boot/bootutil/src/loader.c @@ -80,6 +80,10 @@ int pcd_version_cmp_net(const struct flash_area *fap, struct image_header *hdr); #include "mcuboot_config/mcuboot_config.h" +#if defined(CONFIG_BOOT_KEYS_REVOCATION) +#include "bootutil/key_revocation.h" +#endif + BOOT_LOG_MODULE_DECLARE(mcuboot); static struct boot_loader_state boot_data; @@ -3110,6 +3114,11 @@ context_boot_go(struct boot_loader_state *state, struct boot_rsp *rsp) } } +#if defined(CONFIG_BOOT_KEYS_REVOCATION) + if (BOOT_SWAP_TYPE(state) == BOOT_SWAP_TYPE_NONE) { + allow_revoke(); + } +#endif /* Iterate over all the images. At this point all required update operations * have finished. By the end of the loop each image in the primary slot will * have been re-validated. @@ -3218,6 +3227,13 @@ context_boot_go(struct boot_loader_state *state, struct boot_rsp *rsp) fill_rsp(state, rsp); fih_rc = FIH_SUCCESS; +#if defined(CONFIG_BOOT_KEYS_REVOCATION) + rc = revoke(); + if (rc != BOOT_KEY_REVOKE_OK && + rc != BOOT_KEY_REVOKE_NOT_READY) { + FIH_SET(fih_rc, FIH_FAILURE); + } +#endif /* CONFIG_BOOT_KEYS_REVOCATION */ out: /* * Since the boot_status struct stores plaintext encryption keys, reset diff --git a/boot/zephyr/CMakeLists.txt b/boot/zephyr/CMakeLists.txt index ecb4ac704..2f47766e3 100644 --- a/boot/zephyr/CMakeLists.txt +++ b/boot/zephyr/CMakeLists.txt @@ -104,6 +104,12 @@ if(DEFINED CONFIG_BOOT_SHARE_BACKEND_RETENTION) ) endif() +if(DEFINED CONFIG_BOOT_KEYS_REVOCATION) + zephyr_library_sources( + ${BOOT_DIR}/bootutil/src/key_revocation.c +) +endif() + # Generic bootutil sources and includes. zephyr_library_include_directories(${BOOT_DIR}/bootutil/include) zephyr_library_sources( diff --git a/boot/zephyr/Kconfig b/boot/zephyr/Kconfig index 606d82ed4..2b998e9b9 100644 --- a/boot/zephyr/Kconfig +++ b/boot/zephyr/Kconfig @@ -410,6 +410,18 @@ config BOOT_SIGNATURE_KMU_SLOTS endif +config BOOT_KEYS_REVOCATION + bool "Auto revoke previous gen key" + help + Automatically revoke previous generation key upon new valid key usage. + +config BOOT_KMU_KEYS_REVOCATION + bool + depends on BOOT_KEYS_REVOCATION + default y if BOOT_SIGNATURE_USING_KMU + help + Enabling KMU key revocation backend. + if !BOOT_SIGNATURE_USING_KMU config BOOT_SIGNATURE_KEY_FILE From 2f7059edfa0140851289651fd9b69069a31051e2 Mon Sep 17 00:00:00 2001 From: Mateusz Michalek Date: Wed, 28 May 2025 15:09:33 +0200 Subject: [PATCH 087/420] [nrf noup] boot: zephyr: Kconfig dependencies for PSA LITE exclude certain crypto parts when PSA_CORE_LITE is selected. Signed-off-by: Mateusz Michalek Signed-off-by: Dominik Ermel (cherry picked from commit 23a25925c5ff278c0f8c7069fcea50f0ce719718) --- boot/zephyr/Kconfig | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/boot/zephyr/Kconfig b/boot/zephyr/Kconfig index 2b998e9b9..9a1f6633b 100644 --- a/boot/zephyr/Kconfig +++ b/boot/zephyr/Kconfig @@ -74,14 +74,14 @@ if BOOT_USE_PSA_CRYPTO config BOOT_PSA_IMG_HASH_ALG_SHA256_DEPENDENCIES bool default y if BOOT_SOMETHING_USES_SHA256 - select PSA_WANT_ALG_SHA_256 + select PSA_WANT_ALG_SHA_256 if !PSA_CORE_LITE help Dependencies for hashing with SHA256 config BOOT_PSA_IMG_HASH_ALG_SHA512_DEPENDENCIES bool default y if BOOT_SOMETHING_USES_SHA512 - select PSA_WANT_ALG_SHA_512 + select PSA_WANT_ALG_SHA_512 if !PSA_CORE_LITE help Dependencies for hashing with SHA512 @@ -90,7 +90,7 @@ config BOOT_ED25519_PSA_DEPENDENCIES select PSA_WANT_ALG_PURE_EDDSA select PSA_WANT_ECC_TWISTED_EDWARDS_255 select PSA_WANT_ECC_MONTGOMERY_255 - select PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_IMPORT + select PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_IMPORT if !PSA_CORE_LITE help Dependencies for ed25519 signature @@ -364,9 +364,9 @@ config BOOT_ED25519_PSA select PSA_CRYPTO_C select MBEDTLS_PSA_CRYPTO_C select MBEDTLS_ASN1_PARSE_C if MBEDTLS_BUILTIN - select MBEDTLS_ENABLE_HEAP - select BOOT_IMG_HASH_ALG_SHA256_ALLOW - select BOOT_IMG_HASH_ALG_SHA512_ALLOW + select MBEDTLS_ENABLE_HEAP if !PSA_CORE_LITE + select BOOT_IMG_HASH_ALG_SHA256_ALLOW if !PSA_CORE_LITE + select BOOT_IMG_HASH_ALG_SHA512_ALLOW if !PSA_CORE_LITE select BOOT_ED25519_PSA_DEPENDENCIES select BOOT_X25519_PSA_DEPENDENCIES if BOOT_ENCRYPT_IMAGE From d69621e3032f03ddf462eb3a9d2df5af03955898 Mon Sep 17 00:00:00 2001 From: Artur Hadasz Date: Thu, 24 Jul 2025 13:31:00 +0200 Subject: [PATCH 088/420] [nrf noup] Added BOOT_SIGNATURE_USING_ITS for ecdsa configuration This configuration has the purpose of using keys provisioned to the internal trusted storage (ITS). It makes use of the already existing parts of code for MCUBOOT_BUILTIN_KEY Signed-off-by: Artur Hadasz (cherry picked from commit 68379845127b83191fd3d06591e084f6a532a9a5) --- boot/bootutil/include/bootutil/crypto/ecdsa.h | 50 +++++++++++++++++++ boot/bootutil/src/image_validate.c | 3 +- boot/zephyr/Kconfig | 9 +++- .../include/mcuboot_config/mcuboot_config.h | 4 ++ 4 files changed, 64 insertions(+), 2 deletions(-) diff --git a/boot/bootutil/include/bootutil/crypto/ecdsa.h b/boot/bootutil/include/bootutil/crypto/ecdsa.h index a5d0f8b1b..31d7bec9a 100644 --- a/boot/bootutil/include/bootutil/crypto/ecdsa.h +++ b/boot/bootutil/include/bootutil/crypto/ecdsa.h @@ -473,6 +473,7 @@ static int bootutil_ecdsa_parse_public_key(bootutil_ecdsa_context *ctx, } #endif /* !MCUBOOT_BUILTIN_KEY */ +#if !defined(CONFIG_NRF_BOOT_SIGNATURE_USING_ITS) /* Verify the signature against the provided hash. The signature gets parsed from * the encoding first, then PSA Crypto has a dedicated API for ECDSA verification */ @@ -491,6 +492,55 @@ static inline int bootutil_ecdsa_verify(bootutil_ecdsa_context *ctx, return (int) psa_verify_hash(ctx->key_id, PSA_ALG_ECDSA(ctx->required_algorithm), hash, hlen, reformatted_signature, 2*ctx->curve_byte_count); } +#else /* !CONFIG_NRF_BOOT_SIGNATURE_USING_ITS */ + +static const psa_key_id_t builtin_key_ids[] = { + 0x40022100, + 0x40022101, + 0x40022102, + 0x40022103 +}; + +#define BOOT_SIGNATURE_BUILTIN_KEY_SLOTS ARRAY_SIZE(builtin_key_ids) + +static inline int bootutil_ecdsa_verify(bootutil_ecdsa_context *ctx, + uint8_t *pk, size_t pk_len, + uint8_t *hash, size_t hlen, + uint8_t *sig, size_t slen) +{ + (void)pk; + (void)pk_len; + (void)slen; + psa_status_t status = PSA_ERROR_BAD_STATE; + + /* Initialize PSA Crypto */ + status = psa_crypto_init(); + if (status != PSA_SUCCESS) { + BOOT_LOG_ERR("PSA crypto init failed %d", status); + return 1; + } + + uint8_t reformatted_signature[96] = {0}; /* Enough for P-384 signature sizes */ + parse_signature_from_rfc5480_encoding(sig, ctx->curve_byte_count, reformatted_signature); + + status = PSA_ERROR_BAD_STATE; + + for (int i = 0; i < BOOT_SIGNATURE_BUILTIN_KEY_SLOTS; ++i) { + psa_key_id_t kid = builtin_key_ids[i]; + + status = psa_verify_hash(kid, PSA_ALG_ECDSA(ctx->required_algorithm), + hash, hlen, reformatted_signature, 2*ctx->curve_byte_count); + if (status == PSA_SUCCESS) { + break; + } + BOOT_LOG_ERR("ECDSA signature verification failed %d", status); + } + + return status == PSA_SUCCESS ? 0 : 2; +} + +#endif /* !CONFIG_NRF_BOOT_SIGNATURE_USING_ITS */ + #elif defined(MCUBOOT_USE_MBED_TLS) typedef mbedtls_ecdsa_context bootutil_ecdsa_context; diff --git a/boot/bootutil/src/image_validate.c b/boot/bootutil/src/image_validate.c index 96c1853dd..522e5da2d 100644 --- a/boot/bootutil/src/image_validate.c +++ b/boot/bootutil/src/image_validate.c @@ -514,7 +514,8 @@ bootutil_img_validate(struct boot_loader_state *state, #endif ) { -#if (defined(EXPECTED_KEY_TLV) && defined(MCUBOOT_HW_KEY)) || defined(MCUBOOT_HW_ROLLBACK_PROT) || defined(MCUBOOT_DECOMPRESS_IMAGES) +#if (defined(EXPECTED_KEY_TLV) && defined(MCUBOOT_HW_KEY)) || defined(MCUBOOT_HW_ROLLBACK_PROT) || defined(MCUBOOT_DECOMPRESS_IMAGES) \ + || defined(MCUBOOT_BUILTIN_KEY) int image_index = (state == NULL ? 0 : BOOT_CURR_IMG(state)); #endif uint32_t off; diff --git a/boot/zephyr/Kconfig b/boot/zephyr/Kconfig index 9a1f6633b..2076ddc1f 100644 --- a/boot/zephyr/Kconfig +++ b/boot/zephyr/Kconfig @@ -422,7 +422,14 @@ config BOOT_KMU_KEYS_REVOCATION help Enabling KMU key revocation backend. -if !BOOT_SIGNATURE_USING_KMU +config NRF_BOOT_SIGNATURE_USING_ITS + bool "Use ITS stored keys for signature verification" + depends on NRF_SECURITY + help + MCUboot will use keys provisioned to the internal trusted storage for signature + verification instead of compiling in key data from a file. + +if !BOOT_SIGNATURE_USING_KMU && !NRF_BOOT_SIGNATURE_USING_ITS config BOOT_SIGNATURE_KEY_FILE string "PEM key file" diff --git a/boot/zephyr/include/mcuboot_config/mcuboot_config.h b/boot/zephyr/include/mcuboot_config/mcuboot_config.h index ae9571100..5223a3f44 100644 --- a/boot/zephyr/include/mcuboot_config/mcuboot_config.h +++ b/boot/zephyr/include/mcuboot_config/mcuboot_config.h @@ -68,6 +68,10 @@ #define MCUBOOT_HW_KEY #endif +#ifdef CONFIG_NRF_BOOT_SIGNATURE_USING_ITS +#define MCUBOOT_BUILTIN_KEY +#endif + #ifdef CONFIG_BOOT_VALIDATE_SLOT0 #define MCUBOOT_VALIDATE_PRIMARY_SLOT #endif From 31c8554d59b13f95558e0b91653629f810d69250 Mon Sep 17 00:00:00 2001 From: Dominik Ermel Date: Tue, 29 Jul 2025 16:17:11 +0000 Subject: [PATCH 089/420] [nrf fromtree] bootutil: Fix X25519 HMAC-SHA512 The MAC tag of encryption key has been incorrectly using only 32 bytes of HKDF for HMAC-SHA512 keyword. Signed-off-by: Dominik Ermel (cherry picked from commit 32db78869a173758f30a6a4592342edb34ca097e) --- boot/bootutil/src/encrypted_psa.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/boot/bootutil/src/encrypted_psa.c b/boot/bootutil/src/encrypted_psa.c index 0cfdc9768..7e53ed4a7 100644 --- a/boot/bootutil/src/encrypted_psa.c +++ b/boot/bootutil/src/encrypted_psa.c @@ -43,7 +43,11 @@ static const uint8_t ec_pubkey_oid[] = MBEDTLS_OID_ISO_IDENTIFIED_ORG \ #define HKDF_AES_KEY_SIZE (BOOT_ENC_KEY_SIZE) /* MAC feed */ #define HKDF_MAC_FEED_INDEX (HKDF_AES_KEY_INDEX + HKDF_AES_KEY_SIZE) -#define HKDF_MAC_FEED_SIZE (32) /* This is SHA independent */ +#if !defined(MCUBOOT_HMAC_SHA512) +#define HKDF_MAC_FEED_SIZE (32) +#else +#define HKDF_MAC_FEED_SIZE (64) +#endif /* Total size */ #define HKDF_SIZE (HKDF_AES_KEY_SIZE + HKDF_MAC_FEED_SIZE) From 2128ae512234af3b8eb0c6ecb6ac3270a69b098b Mon Sep 17 00:00:00 2001 From: Dominik Ermel Date: Tue, 29 Jul 2025 16:18:31 +0000 Subject: [PATCH 090/420] [nrf fromtree] imgtool: Fix x25519 TLV HMAC tag HMAC-SHA512 has been incorrectly fed only 32 bytes of password. Signed-off-by: Dominik Ermel (cherry picked from commit 94d85f91f98386a85a282c151a40527f342b8937) --- scripts/imgtool/image.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/imgtool/image.py b/scripts/imgtool/image.py index 4e2830370..b24e5de8d 100644 --- a/scripts/imgtool/image.py +++ b/scripts/imgtool/image.py @@ -444,7 +444,7 @@ def ecies_hkdf(self, enckey, plainkey, hmac_sha_alg): newpk = X25519PrivateKey.generate() shared = newpk.exchange(enckey._get_public()) derived_key = HKDF( - algorithm=hmac_sha_alg, length=48, salt=None, + algorithm=hmac_sha_alg, length=16 + hmac_sha_alg.digest_size, salt=None, info=b'MCUBoot_ECIES_v1', backend=default_backend()).derive(shared) encryptor = Cipher(algorithms.AES(derived_key[:16]), modes.CTR(bytes([0] * 16)), From 8b2d04cba336b40f97b1c5edbef80f4e58fa1a90 Mon Sep 17 00:00:00 2001 From: Dominik Ermel Date: Wed, 30 Jul 2025 14:09:32 +0000 Subject: [PATCH 091/420] [nrf noup] zephyr: Enforce HMAC-SHA512 for NRF54L with X25519 ECIES-X25519 key exchange on NRF54L will be using HMAC-SHA512 for MAC tagging encryption key. Signed-off-by: Dominik Ermel --- boot/zephyr/Kconfig | 1 + 1 file changed, 1 insertion(+) diff --git a/boot/zephyr/Kconfig b/boot/zephyr/Kconfig index 2076ddc1f..0a543a384 100644 --- a/boot/zephyr/Kconfig +++ b/boot/zephyr/Kconfig @@ -728,6 +728,7 @@ if BOOT_ENCRYPT_X25519 && BOOT_USE_PSA_CRYPTO choice BOOT_HMAC_SHA prompt "SHA used for HMAC and HKDF in encryption key exchange" + default BOOT_HMAC_SHA512 if BOOT_ENCRYPT_X25519 && (SOC_NRF54L15_CPUAPP || SOC_NRF54LM20A_ENGA_CPUAPP) default BOOT_HMAC_SHA256 help HMAC/HKDF sha algorithm may be selected to synchronize sha From 30e7326a49a20df7326d3996bec73cf3802745e2 Mon Sep 17 00:00:00 2001 From: Dominik Ermel Date: Thu, 31 Jul 2025 12:01:43 +0000 Subject: [PATCH 092/420] [nrf noup] boot: Use NCS_ prefix for sdk-nrf specific Kconfigs nrf-squash! [nrf noup] boot: Add retry for image verification Use NCS_ prefix, for Kconfigs added in noups, to avoid collisions. The NRF_ prefix will remain reserved for Kconfigs related to products or sdk-nrf subsystems. Signed-off-by: Dominik Ermel --- boot/bootutil/src/loader.c | 38 +++++++++++++++++++------------------- boot/zephyr/Kconfig | 6 +++--- 2 files changed, 22 insertions(+), 22 deletions(-) diff --git a/boot/bootutil/src/loader.c b/boot/bootutil/src/loader.c index 366982246..23a65d1ec 100644 --- a/boot/bootutil/src/loader.c +++ b/boot/bootutil/src/loader.c @@ -57,9 +57,9 @@ #ifdef __ZEPHYR__ #include -#if defined(CONFIG_NRF_MCUBOOT_IMG_VALIDATE_ATTEMPT_WAIT_MS) +#if defined(CONFIG_NCS_MCUBOOT_IMG_VALIDATE_ATTEMPT_WAIT_MS) #include -#endif /* CONFIG_NRF_MCUBOOT_IMG_VALIDATE_ATTEMPT_WAIT_MS */ +#endif /* CONFIG_NCS_MCUBOOT_IMG_VALIDATE_ATTEMPT_WAIT_MS */ #endif #if defined(CONFIG_SOC_NRF5340_CPUAPP) && defined(PM_CPUNET_B0N_ADDRESS) && defined(CONFIG_PCD_APP) @@ -916,10 +916,10 @@ boot_image_check(struct boot_loader_state *state, struct image_header *hdr, } #endif - for (int i = 1; i <= CONFIG_NRF_MCUBOOT_IMG_VALIDATE_ATTEMPT_COUNT; i++ ) { -#if CONFIG_NRF_MCUBOOT_IMG_VALIDATE_ATTEMPT_COUNT > 1 - BOOT_LOG_DBG("Image validation attempt %d/%d", i, CONFIG_NRF_MCUBOOT_IMG_VALIDATE_ATTEMPT_COUNT); -#endif /* CONFIG_NRF_MCUBOOT_IMG_VALIDATE_ATTEMPT_COUNT > 1 */ + for (int i = 1; i <= CONFIG_NCS_MCUBOOT_IMG_VALIDATE_ATTEMPT_COUNT; i++ ) { +#if CONFIG_NCS_MCUBOOT_IMG_VALIDATE_ATTEMPT_COUNT > 1 + BOOT_LOG_DBG("Image validation attempt %d/%d", i, CONFIG_NCS_MCUBOOT_IMG_VALIDATE_ATTEMPT_COUNT); +#endif /* CONFIG_NCS_MCUBOOT_IMG_VALIDATE_ATTEMPT_COUNT > 1 */ #if defined(MCUBOOT_SWAP_USING_OFFSET) && defined(MCUBOOT_SERIAL_RECOVERY) FIH_CALL(bootutil_img_validate, fih_rc, state, hdr, fap, tmpbuf, BOOT_TMPBUF_SZ, @@ -930,25 +930,25 @@ boot_image_check(struct boot_loader_state *state, struct image_header *hdr, #endif if (FIH_EQ(fih_rc, FIH_SUCCESS)) { -#if CONFIG_NRF_MCUBOOT_IMG_VALIDATE_ATTEMPT_COUNT > 1 - BOOT_LOG_DBG("Image validation attempt %d/%d success", i, CONFIG_NRF_MCUBOOT_IMG_VALIDATE_ATTEMPT_COUNT); -#endif /* CONFIG_NRF_MCUBOOT_IMG_VALIDATE_ATTEMPT_COUNT > 1 */ +#if CONFIG_NCS_MCUBOOT_IMG_VALIDATE_ATTEMPT_COUNT > 1 + BOOT_LOG_DBG("Image validation attempt %d/%d success", i, CONFIG_NCS_MCUBOOT_IMG_VALIDATE_ATTEMPT_COUNT); +#endif /* CONFIG_NCS_MCUBOOT_IMG_VALIDATE_ATTEMPT_COUNT > 1 */ break; } else { -#if CONFIG_NRF_MCUBOOT_IMG_VALIDATE_ATTEMPT_COUNT > 1 +#if CONFIG_NCS_MCUBOOT_IMG_VALIDATE_ATTEMPT_COUNT > 1 BOOT_LOG_WRN("Image validation attempt %d/%d failure: %d", i, - CONFIG_NRF_MCUBOOT_IMG_VALIDATE_ATTEMPT_COUNT, fih_rc); -#endif /* CONFIG_NRF_MCUBOOT_IMG_VALIDATE_ATTEMPT_COUNT > 1 */ + CONFIG_NCS_MCUBOOT_IMG_VALIDATE_ATTEMPT_COUNT, fih_rc); +#endif /* CONFIG_NCS_MCUBOOT_IMG_VALIDATE_ATTEMPT_COUNT > 1 */ - if (i < CONFIG_NRF_MCUBOOT_IMG_VALIDATE_ATTEMPT_COUNT) { -#if defined(CONFIG_NRF_MCUBOOT_IMG_VALIDATE_ATTEMPT_WAIT_MS) -#if CONFIG_NRF_MCUBOOT_IMG_VALIDATE_ATTEMPT_COUNT > 1 + if (i < CONFIG_NCS_MCUBOOT_IMG_VALIDATE_ATTEMPT_COUNT) { +#if defined(CONFIG_NCS_MCUBOOT_IMG_VALIDATE_ATTEMPT_WAIT_MS) +#if CONFIG_NCS_MCUBOOT_IMG_VALIDATE_ATTEMPT_COUNT > 1 BOOT_LOG_DBG("Waiting %d ms before next attempt", - CONFIG_NRF_MCUBOOT_IMG_VALIDATE_ATTEMPT_WAIT_MS); -#endif /* CONFIG_NRF_MCUBOOT_IMG_VALIDATE_ATTEMPT_COUNT > 1 */ - k_busy_wait(CONFIG_NRF_MCUBOOT_IMG_VALIDATE_ATTEMPT_WAIT_MS * 1000); -#endif /* CONFIG_NRF_MCUBOOT_IMG_VALIDATE_ATTEMPT_WAIT_MS */ + CONFIG_NCS_MCUBOOT_IMG_VALIDATE_ATTEMPT_WAIT_MS); +#endif /* CONFIG_NCS_MCUBOOT_IMG_VALIDATE_ATTEMPT_COUNT > 1 */ + k_busy_wait(CONFIG_NCS_MCUBOOT_IMG_VALIDATE_ATTEMPT_WAIT_MS * 1000); +#endif /* CONFIG_NCS_MCUBOOT_IMG_VALIDATE_ATTEMPT_WAIT_MS */ } } } diff --git a/boot/zephyr/Kconfig b/boot/zephyr/Kconfig index 0a543a384..fd3c09af8 100644 --- a/boot/zephyr/Kconfig +++ b/boot/zephyr/Kconfig @@ -1309,7 +1309,7 @@ config MCUBOOT_VERIFY_IMG_ADDRESS also be useful when BOOT_DIRECT_XIP is enabled, to ensure that the image linked at the correct address is loaded. -config NRF_MCUBOOT_IMG_VALIDATE_ATTEMPT_COUNT +config NCS_MCUBOOT_IMG_VALIDATE_ATTEMPT_COUNT int "Number of image validation attempts" default 1 help @@ -1318,9 +1318,9 @@ config NRF_MCUBOOT_IMG_VALIDATE_ATTEMPT_COUNT This can prevent erasing an image when initial validation fails. Wait time is controlled by MCUBOOT_IMG_VALIDATE_ATTEMPT_WAIT_MS. -config NRF_MCUBOOT_IMG_VALIDATE_ATTEMPT_WAIT_MS +config NCS_MCUBOOT_IMG_VALIDATE_ATTEMPT_WAIT_MS int "Time between image validation attempts" - depends on NRF_MCUBOOT_IMG_VALIDATE_ATTEMPT_COUNT > 1 + depends on NCS_MCUBOOT_IMG_VALIDATE_ATTEMPT_COUNT > 1 default 5000 help Time between image validation attempts, in milliseconds. From 4bfb139af4fadbc651ea61e27d21331834ce2307 Mon Sep 17 00:00:00 2001 From: Dominik Ermel Date: Fri, 1 Aug 2025 10:36:12 +0000 Subject: [PATCH 093/420] [nrf noup] boot: Use NCS_ prefix for sdk-nrf specific Kconfigs nrf-squash! [nrf noup] Added BOOT_SIGNATURE_USING_ITS for ecdsa configuration Replace NRF_BOOT_SIGNATURE_USING_ITS with NCS_BOOT_SIGNATURE_USING_ITS prefix. Signed-off-by: Dominik Ermel --- boot/bootutil/include/bootutil/crypto/ecdsa.h | 6 +++--- boot/zephyr/Kconfig | 4 ++-- boot/zephyr/include/mcuboot_config/mcuboot_config.h | 2 +- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/boot/bootutil/include/bootutil/crypto/ecdsa.h b/boot/bootutil/include/bootutil/crypto/ecdsa.h index 31d7bec9a..0e9205c29 100644 --- a/boot/bootutil/include/bootutil/crypto/ecdsa.h +++ b/boot/bootutil/include/bootutil/crypto/ecdsa.h @@ -473,7 +473,7 @@ static int bootutil_ecdsa_parse_public_key(bootutil_ecdsa_context *ctx, } #endif /* !MCUBOOT_BUILTIN_KEY */ -#if !defined(CONFIG_NRF_BOOT_SIGNATURE_USING_ITS) +#if !defined(CONFIG_NCS_BOOT_SIGNATURE_USING_ITS) /* Verify the signature against the provided hash. The signature gets parsed from * the encoding first, then PSA Crypto has a dedicated API for ECDSA verification */ @@ -492,7 +492,7 @@ static inline int bootutil_ecdsa_verify(bootutil_ecdsa_context *ctx, return (int) psa_verify_hash(ctx->key_id, PSA_ALG_ECDSA(ctx->required_algorithm), hash, hlen, reformatted_signature, 2*ctx->curve_byte_count); } -#else /* !CONFIG_NRF_BOOT_SIGNATURE_USING_ITS */ +#else /* !CONFIG_NCS_BOOT_SIGNATURE_USING_ITS */ static const psa_key_id_t builtin_key_ids[] = { 0x40022100, @@ -539,7 +539,7 @@ static inline int bootutil_ecdsa_verify(bootutil_ecdsa_context *ctx, return status == PSA_SUCCESS ? 0 : 2; } -#endif /* !CONFIG_NRF_BOOT_SIGNATURE_USING_ITS */ +#endif /* !CONFIG_NCS_BOOT_SIGNATURE_USING_ITS */ #elif defined(MCUBOOT_USE_MBED_TLS) diff --git a/boot/zephyr/Kconfig b/boot/zephyr/Kconfig index fd3c09af8..cdb4d29cc 100644 --- a/boot/zephyr/Kconfig +++ b/boot/zephyr/Kconfig @@ -422,14 +422,14 @@ config BOOT_KMU_KEYS_REVOCATION help Enabling KMU key revocation backend. -config NRF_BOOT_SIGNATURE_USING_ITS +config NCS_BOOT_SIGNATURE_USING_ITS bool "Use ITS stored keys for signature verification" depends on NRF_SECURITY help MCUboot will use keys provisioned to the internal trusted storage for signature verification instead of compiling in key data from a file. -if !BOOT_SIGNATURE_USING_KMU && !NRF_BOOT_SIGNATURE_USING_ITS +if !BOOT_SIGNATURE_USING_KMU && !NCS_BOOT_SIGNATURE_USING_ITS config BOOT_SIGNATURE_KEY_FILE string "PEM key file" diff --git a/boot/zephyr/include/mcuboot_config/mcuboot_config.h b/boot/zephyr/include/mcuboot_config/mcuboot_config.h index 5223a3f44..8ba030738 100644 --- a/boot/zephyr/include/mcuboot_config/mcuboot_config.h +++ b/boot/zephyr/include/mcuboot_config/mcuboot_config.h @@ -68,7 +68,7 @@ #define MCUBOOT_HW_KEY #endif -#ifdef CONFIG_NRF_BOOT_SIGNATURE_USING_ITS +#ifdef CONFIG_NCS_BOOT_SIGNATURE_USING_ITS #define MCUBOOT_BUILTIN_KEY #endif From 58175b6f71bdae10e1d10896c1c858520ab583ec Mon Sep 17 00:00:00 2001 From: Audun Korneliussen Date: Mon, 4 Aug 2025 15:50:33 +0200 Subject: [PATCH 094/420] [nrf noup] boot/zephyr/nrf_cleanup: fix index error nrf-squash! [nrf noup] boot/zephyr/nrf_cleanup: cleanup uarte pins Fix indexing variable mismatch. Signed-off-by: Audun Korneliussen --- boot/zephyr/nrf_cleanup.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/boot/zephyr/nrf_cleanup.c b/boot/zephyr/nrf_cleanup.c index 39dfcbc41..e261d1914 100644 --- a/boot/zephyr/nrf_cleanup.c +++ b/boot/zephyr/nrf_cleanup.c @@ -131,7 +131,7 @@ void nrf_cleanup_peripheral(void) for (int j = 0; j < 4; j++) { if (pin[j] != NRF_UARTE_PSEL_DISCONNECTED) { - nrfy_gpio_cfg_default(pin[i]); + nrfy_gpio_cfg_default(pin[j]); } } #endif From 37486f508fd7bc760732a67eab650d76590ebe86 Mon Sep 17 00:00:00 2001 From: Kari Hamalainen Date: Fri, 8 Aug 2025 09:32:03 +0300 Subject: [PATCH 095/420] [nrf noup] workflows: Add manifest PRs creation Adding action to create manifest PRs automatically. Signed-off-by: Kari Hamalainen --- .github/workflows/manifest-PR.yml | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) create mode 100644 .github/workflows/manifest-PR.yml diff --git a/.github/workflows/manifest-PR.yml b/.github/workflows/manifest-PR.yml new file mode 100644 index 000000000..a871aa381 --- /dev/null +++ b/.github/workflows/manifest-PR.yml @@ -0,0 +1,17 @@ +name: handle manifest PR +on: + pull_request_target: + types: [opened, synchronize, closed] + branches: + - main + + +jobs: + call-manifest-pr-action: + runs-on: ubuntu-latest + steps: + - name: handle manifest PR + uses: nrfconnect/action-manifest-pr@main + with: + token: ${{ secrets.NCS_GITHUB_TOKEN }} + manifest-pr-title-details: ${{ github.event.pull_request.title }} From bc5eb3f126f655b4dd51ce06952e126a8c54186d Mon Sep 17 00:00:00 2001 From: Jamie McCrae Date: Thu, 7 Aug 2025 11:54:42 +0100 Subject: [PATCH 096/420] [nrf fromlist] boot: zephyr: Fix including asn1 when ed25519 is used Fixes wrongly including the asn1 MBEDTLS file when the Kconfig is set to not include it Upstream PR #: 2416 Signed-off-by: Jamie McCrae --- boot/zephyr/CMakeLists.txt | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/boot/zephyr/CMakeLists.txt b/boot/zephyr/CMakeLists.txt index 2f47766e3..abb0f9a2d 100644 --- a/boot/zephyr/CMakeLists.txt +++ b/boot/zephyr/CMakeLists.txt @@ -309,8 +309,13 @@ elseif(CONFIG_BOOT_SIGNATURE_TYPE_ED25519 OR CONFIG_BOOT_ENCRYPT_X25519) ${FIAT_DIR}/src/curve25519.c ) else() + if(MBEDTLS_ASN1_DIR) + zephyr_library_sources( + ${MBEDTLS_ASN1_DIR}/src/asn1parse.c + ) + endif() + zephyr_library_sources( - ${MBEDTLS_ASN1_DIR}/src/asn1parse.c ${BOOT_DIR}/bootutil/src/ed25519_psa.c ) endif() From a184e32064cb04efdd49951088f8b2e802990e7e Mon Sep 17 00:00:00 2001 From: Jamie McCrae Date: Thu, 7 Aug 2025 11:58:29 +0100 Subject: [PATCH 097/420] [nrf noup] boot: zephyr: Fix bm IO button check nrf-squash! [nrf noup] boot: zephyr: Add bm firmware loader code Fixes IO in BM mode to use the hal directly rather than a library that increases the build size by 2.5KiB for a simple button check Signed-off-by: Jamie McCrae --- boot/zephyr/io_bm.c | 45 +++++++++------------------------------------ 1 file changed, 9 insertions(+), 36 deletions(-) diff --git a/boot/zephyr/io_bm.c b/boot/zephyr/io_bm.c index 3f65a5d0e..798cf7a3f 100644 --- a/boot/zephyr/io_bm.c +++ b/boot/zephyr/io_bm.c @@ -89,31 +89,13 @@ void io_led_set(int value) bool io_detect_pin(void) { - int rc; bool pin_active; - rc = bm_buttons_init( - &(struct bm_buttons_config){ - .pin_number = BOARD_PIN_BTN_0, - .active_state = BM_BUTTONS_ACTIVE_LOW, - .pull_config = BM_BUTTONS_PIN_PULLUP, - }, - 1, - BM_BUTTONS_DETECTION_DELAY_MIN_US); - if (rc) { - BOOT_LOG_ERR("Failed to initialize buttons: %d", rc); - return false; - } + nrf_gpio_cfg_input(BOARD_PIN_BTN_0, BM_BUTTONS_PIN_PULLUP); - rc = bm_buttons_enable(); - if (rc) { - BOOT_LOG_ERR("Failed to enable button detection: %d", rc); - return false; - } + pin_active = (bool)nrf_gpio_pin_read(BOARD_PIN_BTN_0); - pin_active = bm_buttons_is_pressed(BOARD_PIN_BTN_0); - - if (pin_active) { + if (!pin_active) { if (BUTTON_0_DETECT_DELAY > 0) { #ifdef CONFIG_MULTITHREADING k_sleep(K_MSEC(50)); @@ -125,13 +107,15 @@ bool io_detect_pin(void) int64_t timestamp = k_uptime_get(); for(;;) { - pin_active = bm_buttons_is_pressed(BOARD_PIN_BTN_0); + uint32_t delta; + + pin_active = (bool)nrf_gpio_pin_read(BOARD_PIN_BTN_0); /* Get delta from when this started */ - uint32_t delta = k_uptime_get() - timestamp; + delta = k_uptime_get() - timestamp; /* If not pressed OR if pressed > debounce period, stop. */ - if (delta >= BUTTON_0_DETECT_DELAY || !pin_active) { + if (delta >= BUTTON_0_DETECT_DELAY || pin_active) { break; } @@ -145,18 +129,7 @@ bool io_detect_pin(void) } } - rc = bm_buttons_disable(); - - if (rc) { - BOOT_LOG_ERR("Failed to disable buttons: %d", rc); - } - - rc = bm_buttons_deinit(); - if (rc) { - BOOT_LOG_ERR("Failed to de-initialize buttons: %d", rc); - } - - return (bool)pin_active; + return (bool)!pin_active; } #endif From edcad137cf026394c217487e1f35498f0a4178e6 Mon Sep 17 00:00:00 2001 From: Jamie McCrae Date: Thu, 7 Aug 2025 13:03:03 +0100 Subject: [PATCH 098/420] Revert "[nrf noup] boot: zephyr: Add NCS boot banner" This reverts commit c41b4a88811a7feeefea7146d44da3ecf9bafc24. Signed-off-by: Jamie McCrae --- boot/zephyr/prj.conf | 3 --- 1 file changed, 3 deletions(-) diff --git a/boot/zephyr/prj.conf b/boot/zephyr/prj.conf index eecc1cbca..51dc99b27 100644 --- a/boot/zephyr/prj.conf +++ b/boot/zephyr/prj.conf @@ -35,6 +35,3 @@ CONFIG_CBPRINTF_NANO=y ### Use the minimal C library to reduce flash usage CONFIG_MINIMAL_LIBC=y CONFIG_NRF_RTC_TIMER_USER_CHAN_COUNT=0 - -# NCS boot banner -CONFIG_NCS_APPLICATION_BOOT_BANNER_STRING="MCUboot" From b31a7c67942e3380bd24d172a27e59f062a78add Mon Sep 17 00:00:00 2001 From: Jamie McCrae Date: Thu, 7 Aug 2025 13:03:53 +0100 Subject: [PATCH 099/420] Revert "[nrf noup] zephyr: Restore default RTC user channel count" This reverts commit abaff579f26f58d9c8969ee5863d5e44d56bcc7e. Signed-off-by: Jamie McCrae --- boot/zephyr/prj.conf | 1 - 1 file changed, 1 deletion(-) diff --git a/boot/zephyr/prj.conf b/boot/zephyr/prj.conf index 51dc99b27..119e07579 100644 --- a/boot/zephyr/prj.conf +++ b/boot/zephyr/prj.conf @@ -34,4 +34,3 @@ CONFIG_MCUBOOT_LOG_LEVEL_INF=y CONFIG_CBPRINTF_NANO=y ### Use the minimal C library to reduce flash usage CONFIG_MINIMAL_LIBC=y -CONFIG_NRF_RTC_TIMER_USER_CHAN_COUNT=0 From edc1c7053f9acb65344fcda860aeb16a8c14d3ff Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Fri, 9 May 2025 17:20:18 -0700 Subject: [PATCH 100/420] [nrf fromtree] boot: Switch to picolibc Save some memory Signed-off-by: Keith Packard (cherry picked from commit 11982df962e2314f4e0c73b7ebc17172026c9266) --- boot/zephyr/prj.conf | 6 ++++-- boot/zephyr/socs/esp32_procpu.conf | 3 ++- boot/zephyr/socs/esp32c2.conf | 3 ++- boot/zephyr/socs/esp32c3.conf | 3 ++- boot/zephyr/socs/esp32c6.conf | 3 ++- boot/zephyr/socs/esp32s2.conf | 3 ++- boot/zephyr/socs/esp32s3_procpu.conf | 3 ++- 7 files changed, 16 insertions(+), 8 deletions(-) diff --git a/boot/zephyr/prj.conf b/boot/zephyr/prj.conf index 119e07579..02b27f1c4 100644 --- a/boot/zephyr/prj.conf +++ b/boot/zephyr/prj.conf @@ -32,5 +32,7 @@ CONFIG_LOG_DEFAULT_LEVEL=0 CONFIG_MCUBOOT_LOG_LEVEL_INF=y ### Decrease footprint by ~4 KB in comparison to CBPRINTF_COMPLETE=y CONFIG_CBPRINTF_NANO=y -### Use the minimal C library to reduce flash usage -CONFIG_MINIMAL_LIBC=y +### Use picolibc to reduce flash usage +CONFIG_PICOLIBC=y +### Disable malloc arena because we don't need it +CONFIG_COMMON_LIBC_MALLOC_ARENA_SIZE=0 diff --git a/boot/zephyr/socs/esp32_procpu.conf b/boot/zephyr/socs/esp32_procpu.conf index b2b405922..7d3368bad 100644 --- a/boot/zephyr/socs/esp32_procpu.conf +++ b/boot/zephyr/socs/esp32_procpu.conf @@ -16,4 +16,5 @@ CONFIG_LOG_DEFAULT_LEVEL=0 CONFIG_DEBUG=n CONFIG_HEAP_MEM_POOL_SIZE=4096 -CONFIG_MINIMAL_LIBC=y +CONFIG_PICOLIBC=y +CONFIG_COMMON_LIBC_MALLOC_ARENA_SIZE=0 diff --git a/boot/zephyr/socs/esp32c2.conf b/boot/zephyr/socs/esp32c2.conf index 5b49f163b..8fdaa8852 100644 --- a/boot/zephyr/socs/esp32c2.conf +++ b/boot/zephyr/socs/esp32c2.conf @@ -17,4 +17,5 @@ CONFIG_DEBUG=n CONFIG_XIP=n CONFIG_HEAP_MEM_POOL_SIZE=4096 -CONFIG_MINIMAL_LIBC=y +CONFIG_PICOLIBC=y +CONFIG_COMMON_LIBC_MALLOC_ARENA_SIZE=0 diff --git a/boot/zephyr/socs/esp32c3.conf b/boot/zephyr/socs/esp32c3.conf index 56298cd4f..96b81e797 100644 --- a/boot/zephyr/socs/esp32c3.conf +++ b/boot/zephyr/socs/esp32c3.conf @@ -17,4 +17,5 @@ CONFIG_DEBUG=n CONFIG_XIP=n CONFIG_HEAP_MEM_POOL_SIZE=4096 -CONFIG_MINIMAL_LIBC=y +CONFIG_PICOLIBC=y +CONFIG_COMMON_LIBC_MALLOC_ARENA_SIZE=0 diff --git a/boot/zephyr/socs/esp32c6.conf b/boot/zephyr/socs/esp32c6.conf index 5b49f163b..8fdaa8852 100644 --- a/boot/zephyr/socs/esp32c6.conf +++ b/boot/zephyr/socs/esp32c6.conf @@ -17,4 +17,5 @@ CONFIG_DEBUG=n CONFIG_XIP=n CONFIG_HEAP_MEM_POOL_SIZE=4096 -CONFIG_MINIMAL_LIBC=y +CONFIG_PICOLIBC=y +CONFIG_COMMON_LIBC_MALLOC_ARENA_SIZE=0 diff --git a/boot/zephyr/socs/esp32s2.conf b/boot/zephyr/socs/esp32s2.conf index b2b405922..7d3368bad 100644 --- a/boot/zephyr/socs/esp32s2.conf +++ b/boot/zephyr/socs/esp32s2.conf @@ -16,4 +16,5 @@ CONFIG_LOG_DEFAULT_LEVEL=0 CONFIG_DEBUG=n CONFIG_HEAP_MEM_POOL_SIZE=4096 -CONFIG_MINIMAL_LIBC=y +CONFIG_PICOLIBC=y +CONFIG_COMMON_LIBC_MALLOC_ARENA_SIZE=0 diff --git a/boot/zephyr/socs/esp32s3_procpu.conf b/boot/zephyr/socs/esp32s3_procpu.conf index b2b405922..7d3368bad 100644 --- a/boot/zephyr/socs/esp32s3_procpu.conf +++ b/boot/zephyr/socs/esp32s3_procpu.conf @@ -16,4 +16,5 @@ CONFIG_LOG_DEFAULT_LEVEL=0 CONFIG_DEBUG=n CONFIG_HEAP_MEM_POOL_SIZE=4096 -CONFIG_MINIMAL_LIBC=y +CONFIG_PICOLIBC=y +CONFIG_COMMON_LIBC_MALLOC_ARENA_SIZE=0 From 50e1caa7c6d9710a610537e97188e624d548dfca Mon Sep 17 00:00:00 2001 From: Damian Krolik Date: Mon, 21 Mar 2022 13:44:27 +0100 Subject: [PATCH 101/420] [nrf noup] zephyr: Restore default RTC user channel count The default value of CONFIG_NRF_RTC_TIMER_USER_CHAN_COUNT for nRF52 SOCs has been changed from 0 to 3, but it makes MCUBoot get stuck on erasing flash pages when swapping two images. Restore the previous value until the RTC issue is resolved (see NCSDK-14427) Signed-off-by: Damian Krolik Signed-off-by: Torsten Rasmussen Signed-off-by: Jamie McCrae Signed-off-by: Dominik Ermel (cherry picked from commit 3957a30521a42f1794dca54f3e8f383f8d69ce8a) --- boot/zephyr/prj.conf | 1 + 1 file changed, 1 insertion(+) diff --git a/boot/zephyr/prj.conf b/boot/zephyr/prj.conf index 02b27f1c4..26b9b4d65 100644 --- a/boot/zephyr/prj.conf +++ b/boot/zephyr/prj.conf @@ -36,3 +36,4 @@ CONFIG_CBPRINTF_NANO=y CONFIG_PICOLIBC=y ### Disable malloc arena because we don't need it CONFIG_COMMON_LIBC_MALLOC_ARENA_SIZE=0 +CONFIG_NRF_RTC_TIMER_USER_CHAN_COUNT=0 From 8d31ad7f5e284789e9dc3acb3cb223dfe4e4db09 Mon Sep 17 00:00:00 2001 From: Jamie McCrae Date: Tue, 11 Jun 2024 12:32:51 +0100 Subject: [PATCH 102/420] [nrf noup] boot: zephyr: Add NCS boot banner Adds a boot banner which shows as MCUboot Signed-off-by: Jamie McCrae (cherry picked from commit 4b3d6ab014bca42f57b25bfc1843a473f11cb898) --- boot/zephyr/prj.conf | 3 +++ 1 file changed, 3 insertions(+) diff --git a/boot/zephyr/prj.conf b/boot/zephyr/prj.conf index 26b9b4d65..87829ba63 100644 --- a/boot/zephyr/prj.conf +++ b/boot/zephyr/prj.conf @@ -37,3 +37,6 @@ CONFIG_PICOLIBC=y ### Disable malloc arena because we don't need it CONFIG_COMMON_LIBC_MALLOC_ARENA_SIZE=0 CONFIG_NRF_RTC_TIMER_USER_CHAN_COUNT=0 + +# NCS boot banner +CONFIG_NCS_APPLICATION_BOOT_BANNER_STRING="MCUboot" From c72ed153fb924203975c38dfea2853ae612e0a9a Mon Sep 17 00:00:00 2001 From: Andrzej Puzdrowski Date: Fri, 8 Aug 2025 13:30:10 +0200 Subject: [PATCH 103/420] [nrf fromlist] boot/boot_serial: build-time skip of the erasing of img status page For MCUboot's MCUBOOT_SINGLE_APPLICATION_SLOT, MCUBOOT_FIRMWARE_LOADER, MCUBOOT_SINGLE_APPLICATION_SLOT_RAM_LOAD modes there is not image run-time status data at the end on the image. Erase of that was done as the last image page erase - and was no harm before by luck. Following commit just reveled the issue: #35536633846b53ccdf01bea0594526de4b416fc0 Upstream PR #: 2417 Signed-off-by: Andrzej Puzdrowski --- boot/boot_serial/src/boot_serial.c | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/boot/boot_serial/src/boot_serial.c b/boot/boot_serial/src/boot_serial.c index 82e1abddb..fd1871b5e 100644 --- a/boot/boot_serial/src/boot_serial.c +++ b/boot/boot_serial/src/boot_serial.c @@ -77,6 +77,12 @@ BOOT_LOG_MODULE_DECLARE(mcuboot); +#if !(defined(MCUBOOT_SINGLE_APPLICATION_SLOT) || \ + defined(MCUBOOT_FIRMWARE_LOADER) || \ + defined(MCUBOOT_SINGLE_APPLICATION_SLOT_RAM_LOAD)) +#define BOOT_IMAGE_HAS_STATUS_FIELDS +#endif + #ifndef ARRAY_SIZE #define ARRAY_SIZE ZCBOR_ARRAY_SIZE #endif @@ -914,8 +920,10 @@ bs_upload(char *buf, int len) * erase has stopped to let us know whether erase * is needed to be able to write current chunk. */ +#ifdef BOOT_IMAGE_HAS_STATUS_FIELDS static struct flash_sector status_sector; #endif +#endif /* MCUBOOT_ERASE_PROGRESSIVELY */ #ifdef MCUBOOT_SWAP_USING_OFFSET static uint32_t start_off = 0; #endif @@ -988,7 +996,7 @@ bs_upload(char *buf, int len) #endif curr_off = 0; -#ifdef MCUBOOT_ERASE_PROGRESSIVELY +#if defined(MCUBOOT_ERASE_PROGRESSIVELY) && defined(BOOT_IMAGE_HAS_STATUS_FIELDS) /* Get trailer sector information; this is done early because inability to get * that sector information means that upload will not work anyway. * TODO: This is single occurrence issue, it should get detected during tests @@ -1167,7 +1175,7 @@ bs_upload(char *buf, int len) if (rc == 0) { curr_off += img_chunk_len + rem_bytes; if (curr_off == img_size) { -#ifdef MCUBOOT_ERASE_PROGRESSIVELY +#if defined(MCUBOOT_ERASE_PROGRESSIVELY) && defined(BOOT_IMAGE_HAS_STATUS_FIELDS) /* Assure that sector for image trailer was erased. */ /* Check whether it was erased during previous upload. */ off_t start = flash_sector_get_off(&status_sector); From 95d384ac85bb8c81c1102f4b94b90515264058ae Mon Sep 17 00:00:00 2001 From: Michal Kozikowski Date: Fri, 8 Aug 2025 16:42:15 +0200 Subject: [PATCH 104/420] [nrf fromtree] bootutil: Fix scratch scrambling This commit fixes the scrambling of the scratch area after persisting a trailer to the primary slot. Previous use of boot_erase_region() didn't guarantee that the scratch area is scrambled, as it only erases memory for devices that selects CONFIG_MCUBOOT_STORAGE_WITH_ERASE. Signed-off-by: Michal Kozikowski (cherry picked from commit 800868a951dd6042ba11de6d056dad5e76bbf738) --- boot/bootutil/src/swap_scratch.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/boot/bootutil/src/swap_scratch.c b/boot/bootutil/src/swap_scratch.c index 360dbe88c..6581b55a6 100644 --- a/boot/bootutil/src/swap_scratch.c +++ b/boot/bootutil/src/swap_scratch.c @@ -926,7 +926,7 @@ boot_swap_sectors(int idx, uint32_t sz, struct boot_loader_state *state, * happens then the scratch which is partially erased would be wrote back to the * primary slot, causing a corrupt unbootable image */ - rc = boot_erase_region(fap_scratch, 0, flash_area_get_size(fap_scratch), true); + rc = boot_scramble_region(fap_scratch, 0, flash_area_get_size(fap_scratch), true); assert(rc == 0); } } From 6c096b8ed7bfddf044b20dfb512c4c1fd06c2ef6 Mon Sep 17 00:00:00 2001 From: Georgios Vasilakis Date: Fri, 8 Aug 2025 12:52:24 +0200 Subject: [PATCH 105/420] [nrf noup] boot: zephyr: Adjust PSA requirements for PSA_CORE_LITE nrf-squash! [nrf noup] boot: zephyr: Kconfig dependencies for PSA LITE The PSA core lite now requires the PSA_WANTs for the hashing functions to be set in order to be used so select them as normal. Signed-off-by: Georgios Vasilakis --- boot/zephyr/Kconfig | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/boot/zephyr/Kconfig b/boot/zephyr/Kconfig index cdb4d29cc..4ddd138d7 100644 --- a/boot/zephyr/Kconfig +++ b/boot/zephyr/Kconfig @@ -74,14 +74,14 @@ if BOOT_USE_PSA_CRYPTO config BOOT_PSA_IMG_HASH_ALG_SHA256_DEPENDENCIES bool default y if BOOT_SOMETHING_USES_SHA256 - select PSA_WANT_ALG_SHA_256 if !PSA_CORE_LITE + select PSA_WANT_ALG_SHA_256 help Dependencies for hashing with SHA256 config BOOT_PSA_IMG_HASH_ALG_SHA512_DEPENDENCIES bool default y if BOOT_SOMETHING_USES_SHA512 - select PSA_WANT_ALG_SHA_512 if !PSA_CORE_LITE + select PSA_WANT_ALG_SHA_512 help Dependencies for hashing with SHA512 From 4e467978a6a1c2f0703e20fe956e4c34e94da700 Mon Sep 17 00:00:00 2001 From: Artur Hadasz Date: Wed, 6 Aug 2025 16:49:05 +0200 Subject: [PATCH 106/420] [nrf fromtree] bootutil: Fixed security counter overflow detected to late This commit fixes the issue, occuring when the maximum amount of security counter updates has been reached. This fact was only detected after a permament update already happened - the updated firmware was unable to boot, as it failed when trying to update the security counter after the permament swap. This commit adds the check if the security counter can be updated (i. e. free security counter slots are still available) before the swap is performed, fixing the issue. Signed-off-by: Artur Hadasz (cherry picked from commit fe8f9fc07a3b01e239fa2e999615227fa314520a) --- boot/bootutil/include/bootutil/security_cnt.h | 13 +++++++++++++ boot/bootutil/src/image_validate.c | 13 +++++++++++++ boot/zephyr/Kconfig | 11 +++++++++++ boot/zephyr/include/mcuboot_config/mcuboot_config.h | 4 ++++ 4 files changed, 41 insertions(+) diff --git a/boot/bootutil/include/bootutil/security_cnt.h b/boot/bootutil/include/bootutil/security_cnt.h index 7e1389618..ff3a7371c 100644 --- a/boot/bootutil/include/bootutil/security_cnt.h +++ b/boot/bootutil/include/bootutil/security_cnt.h @@ -72,6 +72,19 @@ fih_ret boot_nv_security_counter_get(uint32_t image_id, fih_int *security_cnt); int32_t boot_nv_security_counter_update(uint32_t image_id, uint32_t img_security_cnt); +/** + * This function verifies whether the security counter update to a given value is possible. + * The update might not be possible if the maximum amount of security counter updates + * was reached. + * + * @param image_id Index of the image (from 0). + * @param img_security_cnt New security counter value. + * + * @return FIH_SUCCESS if update is possible; FIH_FAILURE otherwise + */ +fih_ret boot_nv_security_counter_is_update_possible(uint32_t image_id, + uint32_t img_security_cnt); + #ifdef __cplusplus } #endif diff --git a/boot/bootutil/src/image_validate.c b/boot/bootutil/src/image_validate.c index 522e5da2d..ba31ddbf3 100644 --- a/boot/bootutil/src/image_validate.c +++ b/boot/bootutil/src/image_validate.c @@ -839,6 +839,19 @@ bootutil_img_validate(struct boot_loader_state *state, goto out; } +#ifdef MCUBOOT_HW_ROLLBACK_PROT_COUNTER_LIMITED + if (img_security_cnt > (uint32_t)fih_int_decode(security_cnt)) { + FIH_CALL(boot_nv_security_counter_is_update_possible, fih_rc, image_index, + img_security_cnt); + if (FIH_NOT_EQ(fih_rc, FIH_SUCCESS)) { + FIH_SET(fih_rc, FIH_FAILURE); + BOOT_LOG_ERR("Security counter update is not possible, possibly the maximum " + "number of security updates has been reached."); + goto out; + } + } +#endif + /* The image's security counter has been successfully verified. */ security_counter_valid = fih_rc; skip_security_counter_read: diff --git a/boot/zephyr/Kconfig b/boot/zephyr/Kconfig index 4ddd138d7..6534962ab 100644 --- a/boot/zephyr/Kconfig +++ b/boot/zephyr/Kconfig @@ -1076,6 +1076,17 @@ config MCUBOOT_HW_DOWNGRADE_PREVENTION Because of the acceptance of equal values it allows for software downgrade to some extent. +config MCUBOOT_HW_DOWNGRADE_PREVENTION_COUNTER_LIMITED + bool "HW based downgrade prevention counter has limited number of updates" + depends on MCUBOOT_HW_DOWNGRADE_PREVENTION + help + When this option is set, the hardware downgrade prevention counter + has limited number of updates. This option will enable checking + if it is possible to update the counter before performing + the upgrade. If an update package contains a security counter + value as a TLV but it is not possible to update the counter, + the update will be rejected. + endchoice config BOOT_WATCHDOG_FEED diff --git a/boot/zephyr/include/mcuboot_config/mcuboot_config.h b/boot/zephyr/include/mcuboot_config/mcuboot_config.h index 8ba030738..0c02f62bc 100644 --- a/boot/zephyr/include/mcuboot_config/mcuboot_config.h +++ b/boot/zephyr/include/mcuboot_config/mcuboot_config.h @@ -209,6 +209,10 @@ #define MCUBOOT_HW_ROLLBACK_PROT #endif +#ifdef CONFIG_MCUBOOT_HW_DOWNGRADE_PREVENTION_COUNTER_LIMITED +#define MCUBOOT_HW_ROLLBACK_PROT_COUNTER_LIMITED +#endif + #ifdef CONFIG_MEASURED_BOOT #define MCUBOOT_MEASURED_BOOT #endif From 0fadab126d9ba51365b3db1cdb6d55ed892c62b4 Mon Sep 17 00:00:00 2001 From: Artur Hadasz Date: Mon, 11 Aug 2025 14:23:04 +0200 Subject: [PATCH 107/420] [nrf noup] zephyr: hw security counter limited set by default This commit sets the MCUBOOT_HW_DOWNGRADE_PREVENTION_COUNTER_LIMITED by default for platforms which support the security counter. Signed-off-by: Artur Hadasz --- boot/zephyr/Kconfig | 1 + 1 file changed, 1 insertion(+) diff --git a/boot/zephyr/Kconfig b/boot/zephyr/Kconfig index 6534962ab..b6098fd09 100644 --- a/boot/zephyr/Kconfig +++ b/boot/zephyr/Kconfig @@ -1079,6 +1079,7 @@ config MCUBOOT_HW_DOWNGRADE_PREVENTION config MCUBOOT_HW_DOWNGRADE_PREVENTION_COUNTER_LIMITED bool "HW based downgrade prevention counter has limited number of updates" depends on MCUBOOT_HW_DOWNGRADE_PREVENTION + default y if SOC_NRF5340_CPUAPP || SOC_SERIES_NRF91X || SOC_SERIES_NRF54LX help When this option is set, the hardware downgrade prevention counter has limited number of updates. This option will enable checking From c03a815aa7ed2968ff296e82036980d180919974 Mon Sep 17 00:00:00 2001 From: Michal Kozikowski Date: Wed, 6 Aug 2025 15:12:20 +0200 Subject: [PATCH 108/420] [nrf fromlist] bootutil: Fix PureEdDSA when flash base is not 0x0 This commit introduces fix for PureEdDSA signature verification when the flash base address is not 0x0. The issue was that the flash base address was not taken into account when passing the image address to the signature verification function. Upstream PR #: 2414 Signed-off-by: Michal Kozikowski --- boot/bootutil/src/image_validate.c | 10 +++++++++- docs/release-notes.d/fix-pure-eddsa-base-address.md | 2 ++ 2 files changed, 11 insertions(+), 1 deletion(-) create mode 100644 docs/release-notes.d/fix-pure-eddsa-base-address.md diff --git a/boot/bootutil/src/image_validate.c b/boot/bootutil/src/image_validate.c index ba31ddbf3..ff6970b64 100644 --- a/boot/bootutil/src/image_validate.c +++ b/boot/bootutil/src/image_validate.c @@ -544,6 +544,9 @@ bootutil_img_validate(struct boot_loader_state *state, #endif int rc = 0; FIH_DECLARE(fih_rc, FIH_FAILURE); +#if defined(MCUBOOT_SIGN_PURE) + uintptr_t base = 0; +#endif #ifdef MCUBOOT_HW_ROLLBACK_PROT fih_int security_cnt = fih_int_encode(INT_MAX); uint32_t img_security_cnt = 0; @@ -788,11 +791,16 @@ bootutil_img_validate(struct boot_loader_state *state, FIH_CALL(bootutil_verify_sig, valid_signature, hash, sizeof(hash), buf, len, key_id); #else + rc = flash_device_base(flash_area_get_device_id(fap), &base); + if (rc != 0) { + goto out; + } + /* Directly check signature on the image, by using the mapping of * a device to memory. The pointer is beginning of image in flash, * so offset of area, the range is header + image + protected tlvs. */ - FIH_CALL(bootutil_verify_img, valid_signature, (void *)flash_area_get_off(fap), + FIH_CALL(bootutil_verify_img, valid_signature, (void *)(base + flash_area_get_off(fap)), hdr->ih_hdr_size + hdr->ih_img_size + hdr->ih_protect_tlv_size, buf, len, key_id); #endif diff --git a/docs/release-notes.d/fix-pure-eddsa-base-address.md b/docs/release-notes.d/fix-pure-eddsa-base-address.md new file mode 100644 index 000000000..4fe226792 --- /dev/null +++ b/docs/release-notes.d/fix-pure-eddsa-base-address.md @@ -0,0 +1,2 @@ + - Fixed issue in image_validate when `BOOT_SIGNATURE_TYPE_PURE` is enabled + for platforms with NVM memory that does not start at 0x00. From e032eb160eda49185351a35059193b0eece9efa3 Mon Sep 17 00:00:00 2001 From: Michal Kozikowski Date: Thu, 7 Aug 2025 15:31:02 +0200 Subject: [PATCH 109/420] [nrf fromlist] zephyr: Fix FLASH_DEVICE_ID for nRF54H20 platform FLASH_DEVICE_ID was incorrectly set to spi related flash id instead of SoC related. Upstream PR #: 2414 Signed-off-by: Michal Kozikowski --- boot/zephyr/flash_map_extended.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/boot/zephyr/flash_map_extended.c b/boot/zephyr/flash_map_extended.c index 3b95b1fd7..ac9ceba0b 100644 --- a/boot/zephyr/flash_map_extended.c +++ b/boot/zephyr/flash_map_extended.c @@ -38,7 +38,7 @@ BOOT_LOG_MODULE_DECLARE(mcuboot); #elif (defined(CONFIG_SOC_SERIES_NRF54HX) && DT_HAS_CHOSEN(zephyr_flash)) -#define FLASH_DEVICE_ID SPI_FLASH_0_ID +#define FLASH_DEVICE_ID SOC_FLASH_0_ID #define FLASH_DEVICE_BASE CONFIG_FLASH_BASE_ADDRESS #define FLASH_DEVICE_NODE DT_CHOSEN(zephyr_flash) From 1b102ec6654ac85b44a13b991db368f037f2f0af Mon Sep 17 00:00:00 2001 From: Artur Hadasz Date: Tue, 29 Jul 2025 15:15:10 +0200 Subject: [PATCH 110/420] [nrf fromtree] imgtool: Allow for AES256 encryption Modified code to correctly generate the TLV for AES256 Signed-off-by: Artur Hadasz (cherry picked from commit a5c48f3c842b339b55f4a67def122331844c56e0) --- scripts/imgtool/image.py | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) mode change 100644 => 100755 scripts/imgtool/image.py diff --git a/scripts/imgtool/image.py b/scripts/imgtool/image.py old mode 100644 new mode 100755 index b24e5de8d..112d2ef4e --- a/scripts/imgtool/image.py +++ b/scripts/imgtool/image.py @@ -443,14 +443,23 @@ def ecies_hkdf(self, enckey, plainkey, hmac_sha_alg): else: newpk = X25519PrivateKey.generate() shared = newpk.exchange(enckey._get_public()) + + # Detect AES key length from plainkey size + key_len = len(plainkey) # 16 for AES-128, 32 for AES-256 + + # Generate derived key with appropriate length (key_len + 32 bytes for HMAC) derived_key = HKDF( - algorithm=hmac_sha_alg, length=16 + hmac_sha_alg.digest_size, salt=None, + algorithm=hmac_sha_alg, length=key_len + hmac_sha_alg.digest_size, salt=None, info=b'MCUBoot_ECIES_v1', backend=default_backend()).derive(shared) - encryptor = Cipher(algorithms.AES(derived_key[:16]), + + # Use appropriate key length for AES encryption + encryptor = Cipher(algorithms.AES(derived_key[:key_len]), modes.CTR(bytes([0] * 16)), backend=default_backend()).encryptor() cipherkey = encryptor.update(plainkey) + encryptor.finalize() - mac = hmac.HMAC(derived_key[16:], hmac_sha_alg, + + # Use remaining bytes for HMAC (after the AES key) + mac = hmac.HMAC(derived_key[key_len:], hmac_sha_alg, backend=default_backend()) mac.update(cipherkey) ciphermac = mac.finalize() From 3b20ec38019dc0841062ba0622b4d7b6792193e5 Mon Sep 17 00:00:00 2001 From: Artur Hadasz Date: Tue, 29 Jul 2025 15:16:23 +0200 Subject: [PATCH 111/420] [nrf fromtree] zephyr: Add support for AES256 This commit adds the parts in the tooling allowing AES256 to work with MCUBoot in zephyr. Currently only in combination PSA + ED25519 Signed-off-by: Artur Hadasz (cherry picked from commit 268968f8e4a834ea3825d98439e4c321de0c6a78) --- boot/zephyr/Kconfig | 16 ++++++++++++++++ .../include/mcuboot_config/mcuboot_config.h | 8 ++++++++ 2 files changed, 24 insertions(+) diff --git a/boot/zephyr/Kconfig b/boot/zephyr/Kconfig index b6098fd09..97a6b6679 100644 --- a/boot/zephyr/Kconfig +++ b/boot/zephyr/Kconfig @@ -724,6 +724,22 @@ config BOOT_ENCRYPT_X25519 help Hidden option selecting x25519 encryption. +if BOOT_ENCRYPT_IMAGE + +choice BOOT_ENCRYPT_ALG + prompt "Algorithm used for image encryption" + default BOOT_ENCRYPT_ALG_AES_128 + +config BOOT_ENCRYPT_ALG_AES_128 + bool "Use AES-128 for image encryption" + +config BOOT_ENCRYPT_ALG_AES_256 + bool "Use AES-256 for image encryption" + +endchoice # BOOT_ENCRYPT_ALG + +endif # BOOT_ENCRYPT_IMAGE + if BOOT_ENCRYPT_X25519 && BOOT_USE_PSA_CRYPTO choice BOOT_HMAC_SHA diff --git a/boot/zephyr/include/mcuboot_config/mcuboot_config.h b/boot/zephyr/include/mcuboot_config/mcuboot_config.h index 0c02f62bc..3b8b0be3f 100644 --- a/boot/zephyr/include/mcuboot_config/mcuboot_config.h +++ b/boot/zephyr/include/mcuboot_config/mcuboot_config.h @@ -163,6 +163,14 @@ #define MCUBOOT_ENCRYPT_X25519 #endif +#ifdef CONFIG_BOOT_ENCRYPT_ALG_AES_128 +#define MCUBOOT_AES_128 +#endif + +#ifdef CONFIG_BOOT_ENCRYPT_ALG_AES_256 +#define MCUBOOT_AES_256 +#endif + /* Support for HMAC/HKDF using SHA512; this is used in key exchange where * HKDF is used for key expansion and HMAC is used for key verification. */ From 3adc1f232221dc8a6d77c378aa0d97fa24c9c0cb Mon Sep 17 00:00:00 2001 From: Mateusz Michalek Date: Tue, 19 Aug 2025 12:37:42 +0200 Subject: [PATCH 112/420] [nrf noup] boot: zephyr: remove nonsecure ram cleanup nrf-squash! [nrf noup] zephyr: Clean up non-secure RAM if enabled This leads to stack corruption. Signed-off-by: Mateusz Michalek --- boot/zephyr/CMakeLists.txt | 2 +- boot/zephyr/main.c | 5 +---- boot/zephyr/nrf_cleanup.c | 9 --------- 3 files changed, 2 insertions(+), 14 deletions(-) diff --git a/boot/zephyr/CMakeLists.txt b/boot/zephyr/CMakeLists.txt index abb0f9a2d..e8d79af7d 100644 --- a/boot/zephyr/CMakeLists.txt +++ b/boot/zephyr/CMakeLists.txt @@ -755,7 +755,7 @@ if(SYSBUILD) set(mcuboot_image_upgrade_footer_size ${required_upgrade_size} CACHE INTERNAL "Estimated MCUboot update image trailer size" FORCE) endif() -if(CONFIG_MCUBOOT_NRF_CLEANUP_PERIPHERAL OR CONFIG_MCUBOOT_CLEANUP_NONSECURE_RAM) +if(CONFIG_MCUBOOT_NRF_CLEANUP_PERIPHERAL) zephyr_library_sources( ${BOOT_DIR}/zephyr/nrf_cleanup.c ) diff --git a/boot/zephyr/main.c b/boot/zephyr/main.c index c51616dda..53a393401 100644 --- a/boot/zephyr/main.c +++ b/boot/zephyr/main.c @@ -144,7 +144,7 @@ K_SEM_DEFINE(boot_log_sem, 1, 1); #include #endif -#if CONFIG_MCUBOOT_NRF_CLEANUP_PERIPHERAL || CONFIG_MCUBOOT_NRF_CLEANUP_NONSECURE_RAM +#if CONFIG_MCUBOOT_NRF_CLEANUP_PERIPHERAL #include #endif @@ -224,9 +224,6 @@ static void do_boot(struct boot_rsp *rsp) #if CONFIG_MCUBOOT_NRF_CLEANUP_PERIPHERAL nrf_cleanup_peripheral(); #endif -#if CONFIG_MCUBOOT_NRF_CLEANUP_NONSECURE_RAM && defined(PM_SRAM_NONSECURE_NAME) - nrf_cleanup_ns_ram(); -#endif #if CONFIG_MCUBOOT_CLEANUP_ARM_CORE cleanup_arm_nvic(); /* cleanup NVIC registers */ diff --git a/boot/zephyr/nrf_cleanup.c b/boot/zephyr/nrf_cleanup.c index e261d1914..5ddc74a64 100644 --- a/boot/zephyr/nrf_cleanup.c +++ b/boot/zephyr/nrf_cleanup.c @@ -158,12 +158,3 @@ void nrf_cleanup_peripheral(void) nrf_cleanup_clock(); #endif } - -#if USE_PARTITION_MANAGER \ - && defined(CONFIG_ARM_TRUSTZONE_M) \ - && defined(PM_SRAM_NONSECURE_NAME) -void nrf_cleanup_ns_ram(void) -{ - memset((void *) PM_SRAM_NONSECURE_ADDRESS, 0, PM_SRAM_NONSECURE_SIZE); -} -#endif From 1b1a37fb7abf8b6e5f7d1e05daacd0081ce2844e Mon Sep 17 00:00:00 2001 From: Jamie McCrae Date: Tue, 19 Aug 2025 12:29:54 +0100 Subject: [PATCH 113/420] [nrf noup] boot: zephyr: Delay bm IO button check nrf-squash! [nrf noup] boot: zephyr: Add bm firmware loader code Delays checking IO button state by 5us after pull-up has been applied to allow time for it to be applied Signed-off-by: Jamie McCrae --- boot/zephyr/io_bm.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/boot/zephyr/io_bm.c b/boot/zephyr/io_bm.c index 798cf7a3f..788bfab9e 100644 --- a/boot/zephyr/io_bm.c +++ b/boot/zephyr/io_bm.c @@ -93,6 +93,9 @@ bool io_detect_pin(void) nrf_gpio_cfg_input(BOARD_PIN_BTN_0, BM_BUTTONS_PIN_PULLUP); + /* Delay 5 us for pull-up to be applied */ + k_busy_wait(5); + pin_active = (bool)nrf_gpio_pin_read(BOARD_PIN_BTN_0); if (!pin_active) { From f9e4ce08681b0360567ff4b049a991bf91b74054 Mon Sep 17 00:00:00 2001 From: Jamie McCrae Date: Tue, 26 Aug 2025 10:02:14 +0100 Subject: [PATCH 114/420] Revert "[nrf noup] boot: zephyr: Add NCS boot banner" This reverts commit 8d31ad7f5e284789e9dc3acb3cb223dfe4e4db09. Signed-off-by: Jamie McCrae --- boot/zephyr/prj.conf | 3 --- 1 file changed, 3 deletions(-) diff --git a/boot/zephyr/prj.conf b/boot/zephyr/prj.conf index 87829ba63..26b9b4d65 100644 --- a/boot/zephyr/prj.conf +++ b/boot/zephyr/prj.conf @@ -37,6 +37,3 @@ CONFIG_PICOLIBC=y ### Disable malloc arena because we don't need it CONFIG_COMMON_LIBC_MALLOC_ARENA_SIZE=0 CONFIG_NRF_RTC_TIMER_USER_CHAN_COUNT=0 - -# NCS boot banner -CONFIG_NCS_APPLICATION_BOOT_BANNER_STRING="MCUboot" From 446967f45450f972ecab3b76fc48ebbf497c968c Mon Sep 17 00:00:00 2001 From: Jamie McCrae Date: Tue, 26 Aug 2025 10:02:18 +0100 Subject: [PATCH 115/420] Revert "[nrf noup] zephyr: Restore default RTC user channel count" This reverts commit 50e1caa7c6d9710a610537e97188e624d548dfca. Signed-off-by: Jamie McCrae --- boot/zephyr/prj.conf | 1 - 1 file changed, 1 deletion(-) diff --git a/boot/zephyr/prj.conf b/boot/zephyr/prj.conf index 26b9b4d65..02b27f1c4 100644 --- a/boot/zephyr/prj.conf +++ b/boot/zephyr/prj.conf @@ -36,4 +36,3 @@ CONFIG_CBPRINTF_NANO=y CONFIG_PICOLIBC=y ### Disable malloc arena because we don't need it CONFIG_COMMON_LIBC_MALLOC_ARENA_SIZE=0 -CONFIG_NRF_RTC_TIMER_USER_CHAN_COUNT=0 From c85960801ddb83ca6cc2125bd5342139d3befa2c Mon Sep 17 00:00:00 2001 From: Jamie McCrae Date: Tue, 11 Jun 2024 12:32:51 +0100 Subject: [PATCH 116/420] [nrf noup] boot: zephyr: Add NCS boot banner Adds a boot banner which shows as MCUboot Signed-off-by: Jamie McCrae (cherry picked from commit 4b3d6ab014bca42f57b25bfc1843a473f11cb898) --- boot/zephyr/prj.conf | 3 +++ 1 file changed, 3 insertions(+) diff --git a/boot/zephyr/prj.conf b/boot/zephyr/prj.conf index 02b27f1c4..766762237 100644 --- a/boot/zephyr/prj.conf +++ b/boot/zephyr/prj.conf @@ -36,3 +36,6 @@ CONFIG_CBPRINTF_NANO=y CONFIG_PICOLIBC=y ### Disable malloc arena because we don't need it CONFIG_COMMON_LIBC_MALLOC_ARENA_SIZE=0 + +# NCS boot banner +CONFIG_NCS_APPLICATION_BOOT_BANNER_STRING="MCUboot" From ecc13ac1b0336c5ff39fc00075d34b55ab619752 Mon Sep 17 00:00:00 2001 From: Jamie McCrae Date: Tue, 26 Aug 2025 10:22:04 +0100 Subject: [PATCH 117/420] [nrf noup] boot: zephyr: firmware_loader: Allow GPIO usage in BM Allows GPIO entrance mode when bare metal is used, this is needed because the zephyr GPIO drivers are not used, therefore the Kconfig will not be enabled Signed-off-by: Jamie McCrae --- boot/zephyr/Kconfig.firmware_loader | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/boot/zephyr/Kconfig.firmware_loader b/boot/zephyr/Kconfig.firmware_loader index 1ba223949..036da98eb 100644 --- a/boot/zephyr/Kconfig.firmware_loader +++ b/boot/zephyr/Kconfig.firmware_loader @@ -8,7 +8,7 @@ menu "Firmware loader entrance methods" menuconfig BOOT_FIRMWARE_LOADER_ENTRANCE_GPIO bool "GPIO" - depends on GPIO + depends on GPIO || NCS_BM help Use a GPIO to enter firmware loader mode. From 285fd59f4386a0317e476da5484f67b906073296 Mon Sep 17 00:00:00 2001 From: Mateusz Michalek Date: Tue, 5 Aug 2025 15:55:31 +0200 Subject: [PATCH 118/420] [nrf noup] boot: zephyr: Disable self RWX Disables read write and execute on mcuboots NVM at the end of execution. Signed-off-by: Mateusz Michalek --- boot/zephyr/Kconfig | 7 +++ boot/zephyr/main.c | 129 +++++++++++++++++++++++++++++++++----------- 2 files changed, 105 insertions(+), 31 deletions(-) diff --git a/boot/zephyr/Kconfig b/boot/zephyr/Kconfig index 97a6b6679..3c3c508b1 100644 --- a/boot/zephyr/Kconfig +++ b/boot/zephyr/Kconfig @@ -472,6 +472,13 @@ config MCUBOOT_CLEANUP_RAM help Sets contents of memory to 0 before jumping to application. +config NCS_MCUBOOT_DISABLE_SELF_RWX + bool "Disable read and execution on self NVM" + depends on (SOC_NRF54L15_CPUAPP || SOC_NRF54L10_CPUAPP || SOC_NRF54L05_CPUAPP) && !FPROTECT + help + Sets RRAMC's region no.4 protection before jumping to application. + It disables reads writes and execution memory area which holds MCUBOOT. + config MCUBOOT_INFINITE_LOOP_AFTER_RAM_CLEANUP bool "Infinite loop after RAM cleanup" depends on MCUBOOT_CLEANUP_RAM diff --git a/boot/zephyr/main.c b/boot/zephyr/main.c index 53a393401..fa3eeff90 100644 --- a/boot/zephyr/main.c +++ b/boot/zephyr/main.c @@ -148,6 +148,25 @@ K_SEM_DEFINE(boot_log_sem, 1, 1); #include #endif +#include +#define CLEANUP_RAM_GAP_START ((int)__ramfunc_region_start) +#define CLEANUP_RAM_GAP_SIZE ((int) (__ramfunc_end - __ramfunc_region_start)) + +#if defined(CONFIG_NCS_MCUBOOT_DISABLE_SELF_RWX) +/* Disabling R_X has to be done while running from RAM for obvious reasons. + * Moreover as a last step before jumping to application it must work even after + * RAM has been cleared, therefore these operations are performed while executing from RAM. + * RAM cleanup ommits portion of the memory where code lives. + */ +#include + +#define RRAMC_REGION_RWX_LSB 0 +#define RRAMC_REGION_RWX_WIDTH 3 +#define RRAMC_REGION_TO_LOCK_ADDR NRF_RRAMC->REGION[4].CONFIG +#define RRAMC_REGION_TO_LOCK_ADDR_H (((uint32_t)(&(RRAMC_REGION_TO_LOCK_ADDR))) >> 16) +#define RRAMC_REGION_TO_LOCK_ADDR_L (((uint32_t)(&(RRAMC_REGION_TO_LOCK_ADDR))) & 0x0000fffful) +#endif /* CONFIG_NCS_MCUBOOT_DISABLE_SELF_RWX */ + BOOT_LOG_MODULE_REGISTER(mcuboot); void os_heap_init(void); @@ -163,6 +182,84 @@ struct arm_vector_table { uint32_t reset; }; +static void __ramfunc jump_in(uint32_t reset) +{ + __asm__ volatile ( + /* reset -> r0 */ + " mov r0, %0\n" +#ifdef CONFIG_MCUBOOT_CLEANUP_RAM + /* Base to write -> r1 */ + " mov r1, %1\n" + /* Size to write -> r2 */ + " mov r2, %2\n" + /* Value to write -> r3 */ + " movw r3, %5\n" + /* gap start */ + " mov r4, %3\n" + /* gap size */ + " mov r5, %4\n" + "clear:\n" + " subs r6, r4, r1\n" + " cbnz r6, skip_gap\n" + " add r1, r5\n" + "skip_gap:\n" + " str r3, [r1]\n" + " add r1, r1, #1\n" + " sub r2, r2, #1\n" + " cbz r2, clear_end\n" + " b clear\n" + "clear_end:\n" + " dsb\n" +#ifdef CONFIG_MCUBOOT_INFINITE_LOOP_AFTER_RAM_CLEANUP + " b clear_end\n" +#endif /* CONFIG_MCUBOOT_INFINITE_LOOP_AFTER_RAM_CLEANUP */ +#endif /* CONFIG_MCUBOOT_CLEANUP_RAM */ + +#ifdef CONFIG_NCS_MCUBOOT_DISABLE_SELF_RWX + ".thumb_func\n" + "region_disable_rwx:\n" + " movw r1, %6\n" + " movt r1, %7\n" + " ldr r2, [r1]\n" + /* Size of the region should be set at this point + * by NSIB's DISABLE_NEXT_W. + * If not, set it according partition size. + */ + " ands r4, r2, %12\n" + " cbnz r4, clear_rwx\n" + " movt r2, %8\n" + "clear_rwx:\n" + " bfc r2, %9, %10\n" + /* Disallow further modifications */ + " orr r2, %11\n" + " str r2, [r1]\n" + " dsb\n" + /* Next assembly line is important for current function */ + + #endif /* CONFIG_NCS_MCUBOOT_DISABLE_SELF_RWX */ + + /* Jump to reset vector of an app */ + " bx r0\n" + : + : "r" (reset), + "r" (CONFIG_SRAM_BASE_ADDRESS), + "i" (CONFIG_SRAM_SIZE * 1024), + "r" (CLEANUP_RAM_GAP_START), + "r" (CLEANUP_RAM_GAP_SIZE), + "i" (0) +#ifdef CONFIG_NCS_MCUBOOT_DISABLE_SELF_RWX + , "i" (RRAMC_REGION_TO_LOCK_ADDR_L), + "i" (RRAMC_REGION_TO_LOCK_ADDR_H), + "i" (CONFIG_PM_PARTITION_SIZE_B0_IMAGE / 1024), + "i" (RRAMC_REGION_RWX_LSB), + "i" (RRAMC_REGION_RWX_WIDTH), + "i" (RRAMC_REGION_CONFIG_LOCK_Msk), + "i" (RRAMC_REGION_CONFIG_SIZE_Msk) +#endif /* CONFIG_NCS_MCUBOOT_DISABLE_SELF_RWX */ + : "r0", "r1", "r2", "r3", "r4", "r5", "r6", "memory" + ); +} + static void do_boot(struct boot_rsp *rsp) { /* vt is static as it shall not land on the stack, @@ -273,37 +370,7 @@ static void do_boot(struct boot_rsp *rsp) __set_CONTROL(0x00); /* application will configures core on its own */ __ISB(); #endif -#if CONFIG_MCUBOOT_CLEANUP_RAM - __asm__ volatile ( - /* vt->reset -> r0 */ - " mov r0, %0\n" - /* base to write -> r1 */ - " mov r1, %1\n" - /* size to write -> r2 */ - " mov r2, %2\n" - /* value to write -> r3 */ - " mov r3, %3\n" - "clear:\n" - " str r3, [r1]\n" - " add r1, r1, #4\n" - " sub r2, r2, #4\n" - " cbz r2, out\n" - " b clear\n" - "out:\n" - " dsb\n" -#if CONFIG_MCUBOOT_INFINITE_LOOP_AFTER_RAM_CLEANUP - " b out\n" -#endif /*CONFIG_MCUBOOT_INFINITE_LOOP_AFTER_RAM_CLEANUP */ - /* jump to reset vector of an app */ - " bx r0\n" - : - : "r" (vt->reset), "i" (CONFIG_SRAM_BASE_ADDRESS), - "i" (CONFIG_SRAM_SIZE * 1024), "i" (0) - : "r0", "r1", "r2", "r3", "memory" - ); -#else - ((void (*)(void))vt->reset)(); -#endif + jump_in(vt->reset); } #elif defined(CONFIG_XTENSA) || defined(CONFIG_RISCV) From d8a2e457f25f4d8b3924e3da69b54965e1690678 Mon Sep 17 00:00:00 2001 From: Mateusz Michalek Date: Tue, 26 Aug 2025 12:42:56 +0200 Subject: [PATCH 119/420] [nrf noup] zephyr: boards: nrf54lm20dk_nrf54lm20a_cpuapp.conf adding DK default configuration and fixing PDK configuration. Signed-off-by: Mateusz Michalek --- .../boards/nrf54lm20dk_nrf54lm20a_cpuapp.conf | 13 +++++++++++++ .../boards/nrf54lm20pdk_nrf54lm20a_cpuapp.conf | 3 --- 2 files changed, 13 insertions(+), 3 deletions(-) create mode 100644 boot/zephyr/boards/nrf54lm20dk_nrf54lm20a_cpuapp.conf diff --git a/boot/zephyr/boards/nrf54lm20dk_nrf54lm20a_cpuapp.conf b/boot/zephyr/boards/nrf54lm20dk_nrf54lm20a_cpuapp.conf new file mode 100644 index 000000000..816560405 --- /dev/null +++ b/boot/zephyr/boards/nrf54lm20dk_nrf54lm20a_cpuapp.conf @@ -0,0 +1,13 @@ +# Copyright (c) 2025 Nordic Semiconductor ASA +# +# SPDX-License-Identifier: Apache-2.0 +# +CONFIG_BOOT_MAX_IMG_SECTORS=256 + +# Ensure that the SPI NOR driver is disabled by default +CONFIG_SPI_NOR=n + +# TODO: below are not yet supported and need fixing +CONFIG_FPROTECT=n + +CONFIG_BOOT_WATCHDOG_FEED=n diff --git a/boot/zephyr/boards/nrf54lm20pdk_nrf54lm20a_cpuapp.conf b/boot/zephyr/boards/nrf54lm20pdk_nrf54lm20a_cpuapp.conf index 4944f7b13..816560405 100644 --- a/boot/zephyr/boards/nrf54lm20pdk_nrf54lm20a_cpuapp.conf +++ b/boot/zephyr/boards/nrf54lm20pdk_nrf54lm20a_cpuapp.conf @@ -11,6 +11,3 @@ CONFIG_SPI_NOR=n CONFIG_FPROTECT=n CONFIG_BOOT_WATCHDOG_FEED=n - -CONFIG_PSA_CRYPTO_DRIVER_CRACEN=n -CONFIG_PSA_CRYPTO_DRIVER_OBERON=y From c13c65257af74ef087920082d50b040d5d435669 Mon Sep 17 00:00:00 2001 From: Tomasz Chyrowicz Date: Wed, 30 Jul 2025 12:09:57 +0200 Subject: [PATCH 120/420] [nrf fromtree] loader: Add boot hook for slot selection Add a bootloader hook to alter the logic of the active slot selection in Direct XIP modes. Signed-off-by: Tomasz Chyrowicz (cherry picked from commit 7c4ec9ab153d105e6e966cecef6806be7b9e6a25) --- boot/bootutil/include/bootutil/boot_hooks.h | 24 +++++++++++++++++++++ boot/bootutil/src/loader.c | 14 ++++++++++-- 2 files changed, 36 insertions(+), 2 deletions(-) diff --git a/boot/bootutil/include/bootutil/boot_hooks.h b/boot/bootutil/include/bootutil/boot_hooks.h index ef7a89b28..f5b10e8c7 100644 --- a/boot/bootutil/include/bootutil/boot_hooks.h +++ b/boot/bootutil/include/bootutil/boot_hooks.h @@ -82,6 +82,18 @@ #endif /* MCUBOOT_BOOT_GO_HOOKS */ +#ifdef MCUBOOT_FIND_NEXT_SLOT_HOOKS + +#define BOOT_HOOK_FIND_SLOT_CALL(f, ret_default, ...) \ + DO_HOOK_CALL(f, ret_default, __VA_ARGS__) + +#else + +#define BOOT_HOOK_FIND_SLOT_CALL(f, ret_default, ...) \ + HOOK_CALL_NOP(f, ret_default, __VA_ARGS__) + +#endif /* MCUBOOT_FIND_NEXT_SLOT_HOOKS */ + #ifdef MCUBOOT_FLASH_AREA_HOOKS #define BOOT_HOOK_FLASH_AREA_CALL(f, ret_default, ...) \ @@ -260,4 +272,16 @@ int flash_area_get_device_id_hook(const struct flash_area *fa, #define BOOT_RESET_REQUEST_HOOK_CHECK_FAILED 3 #define BOOT_RESET_REQUEST_HOOK_INTERNAL_ERROR 4 +/** + * Finds the preferred slot containing the image. + * + * @param[in] state Boot loader status information. + * @param[in] image Image, for which the slot should be found. + * @param[out] active_slot Number of the preferred slot. + * + * @return 0 if a slot was requested; + * BOOT_HOOK_REGULAR follow the normal execution path. + */ +int boot_find_next_slot_hook(struct boot_loader_state *state, uint8_t image, uint32_t *active_slot); + #endif /*H_BOOTUTIL_HOOKS*/ diff --git a/boot/bootutil/src/loader.c b/boot/bootutil/src/loader.c index 23a65d1ec..1a2290769 100644 --- a/boot/bootutil/src/loader.c +++ b/boot/bootutil/src/loader.c @@ -3605,7 +3605,12 @@ boot_load_and_validate_images(struct boot_loader_state *state) break; } - active_slot = find_slot_with_highest_version(state); + rc = BOOT_HOOK_FIND_SLOT_CALL(boot_find_next_slot_hook, BOOT_HOOK_REGULAR, + state, BOOT_CURR_IMG(state), &active_slot); + if (rc == BOOT_HOOK_REGULAR) { + active_slot = find_slot_with_highest_version(state); + } + if (active_slot == NO_ACTIVE_SLOT) { BOOT_LOG_INF("No slot to load for image %d", BOOT_CURR_IMG(state)); @@ -3652,7 +3657,12 @@ boot_load_and_validate_images(struct boot_loader_state *state) break; } - active_slot = find_slot_with_highest_version(state); + rc = BOOT_HOOK_FIND_SLOT_CALL(boot_find_next_slot_hook, BOOT_HOOK_REGULAR, + state, BOOT_CURR_IMG(state), &active_slot); + if (rc == BOOT_HOOK_REGULAR) { + active_slot = find_slot_with_highest_version(state); + } + if (active_slot == NO_ACTIVE_SLOT) { BOOT_LOG_INF("No slot to load for image %d", BOOT_CURR_IMG(state)); From 301ab3359addfcab53539623d866dd83a8d202bf Mon Sep 17 00:00:00 2001 From: Tomasz Chyrowicz Date: Wed, 30 Jul 2025 12:10:31 +0200 Subject: [PATCH 121/420] [nrf fromtree] zephyr: Add support for slot selection boot hook Add a Kconfig option to enable a bootloader hook to alter the logic of the active slot selection in Direct XIP modes. Signed-off-by: Tomasz Chyrowicz (cherry picked from commit d5f84b49cd3e2d51c51f9a1ddd5d60002d297cbc) --- boot/zephyr/Kconfig | 7 +++++++ boot/zephyr/hooks_sample.c | 5 +++++ boot/zephyr/include/mcuboot_config/mcuboot_config.h | 4 ++++ 3 files changed, 16 insertions(+) diff --git a/boot/zephyr/Kconfig b/boot/zephyr/Kconfig index 3c3c508b1..d1f5be182 100644 --- a/boot/zephyr/Kconfig +++ b/boot/zephyr/Kconfig @@ -1165,6 +1165,13 @@ config MCUBOOT_ACTION_HOOKS 'mcuboot_status_type_t' is listed in boot/bootutil/include/bootutil/mcuboot_status.h +config FIND_NEXT_SLOT_HOOKS + bool "Enable hooks for finding the next active slot" + help + Allow to provide procedures for override or extend the search policy + for the best slot to boot in the Direct XIP mode. + By default a slot with the highest version is selected. + config BOOT_DISABLE_CACHES bool "Disable I/D caches before chain-loading application" depends on CPU_HAS_ICACHE || CPU_HAS_DCACHE diff --git a/boot/zephyr/hooks_sample.c b/boot/zephyr/hooks_sample.c index a5a729314..fc7bd2fa4 100644 --- a/boot/zephyr/hooks_sample.c +++ b/boot/zephyr/hooks_sample.c @@ -93,3 +93,8 @@ int boot_img_install_stat_hook(int image_index, int slot, int *img_install_stat) { return BOOT_HOOK_REGULAR; } + +int boot_find_next_slot_hook(struct boot_loader_state *state, uint8_t image, uint32_t *active_slot) +{ + return BOOT_HOOK_REGULAR; +} diff --git a/boot/zephyr/include/mcuboot_config/mcuboot_config.h b/boot/zephyr/include/mcuboot_config/mcuboot_config.h index 3b8b0be3f..d8a8462e0 100644 --- a/boot/zephyr/include/mcuboot_config/mcuboot_config.h +++ b/boot/zephyr/include/mcuboot_config/mcuboot_config.h @@ -283,6 +283,10 @@ #define MCUBOOT_FLASH_AREA_HOOKS #endif +#ifdef CONFIG_FIND_NEXT_SLOT_HOOKS +#define MCUBOOT_FIND_NEXT_SLOT_HOOKS +#endif + #ifdef CONFIG_MCUBOOT_VERIFY_IMG_ADDRESS #define MCUBOOT_VERIFY_IMG_ADDRESS #endif From e1f2ab3806ce7ebc7ef34b3fc04272e747590745 Mon Sep 17 00:00:00 2001 From: Tomasz Chyrowicz Date: Mon, 28 Jul 2025 12:46:20 +0200 Subject: [PATCH 122/420] [nrf noup] bootloader: Add bootloader requests Add a capability inside the Zephyr bootloader to handle memory-based bootloader requests to: - Boot recovery firmware - Boot firmware loader - Confirm an image - Set the slot preference Ref: NCSDK-34429 Signed-off-by: Tomasz Chyrowicz --- boot/bootutil/include/bootutil/boot_request.h | 105 ++++++ boot/bootutil/src/bootutil_public.c | 84 ++++- boot/bootutil/zephyr/CMakeLists.txt | 5 + .../zephyr/src/boot_request_retention.c | 346 ++++++++++++++++++ boot/zephyr/Kconfig | 4 + boot/zephyr/Kconfig.firmware_loader | 6 + boot/zephyr/Kconfig.serial_recovery | 6 + boot/zephyr/firmware_loader.c | 9 + boot/zephyr/main.c | 53 +++ 9 files changed, 613 insertions(+), 5 deletions(-) create mode 100644 boot/bootutil/include/bootutil/boot_request.h create mode 100644 boot/bootutil/zephyr/src/boot_request_retention.c diff --git a/boot/bootutil/include/bootutil/boot_request.h b/boot/bootutil/include/bootutil/boot_request.h new file mode 100644 index 000000000..b1e8f891e --- /dev/null +++ b/boot/bootutil/include/bootutil/boot_request.h @@ -0,0 +1,105 @@ +/* + * SPDX-License-Identifier: Apache-2.0 + * + * Copyright (c) 2025 Nordic Semiconductor ASA + */ + +#ifndef __BOOT_REQUEST_H__ +#define __BOOT_REQUEST_H__ + +#ifdef __cplusplus +extern "C" { +#endif + +#include +#include + +/** Special value, indicating that there is no preferred slot. */ +#define BOOT_REQUEST_NO_PREFERRED_SLOT UINT32_MAX + +/** + * @brief Request a bootloader to confirm the specified slot of an image. + * + * @param[in] image Image number. + * @param[in] slot Slot number. + * + * @return 0 if requested, negative error code otherwise. + */ +int boot_request_confirm_slot(uint8_t image, uint32_t slot); + +/** + * @brief Request a bootloader to boot the specified slot of an image. + * + * @param[in] image Image number. + * @param[in] slot Slot number. + * + * @return 0 if requested, negative error code otherwise. + */ +int boot_request_set_preferred_slot(uint8_t image, uint32_t slot); + +/** + * @brief Request a bootloader to boot recovery image. + * + * @return 0 if requested, negative error code otherwise. + */ +int boot_request_enter_recovery(void); + +/** + * @brief Request a bootloader to boot firmware loader image. + * + * @return 0 if requested, negative error code otherwise. + */ +int boot_request_enter_firmware_loader(void); + +/** + * @brief Check if there is a request to confirm the specified slot of an image. + * + * @param[in] image Image number. + * @param[in] slot Slot number. + * + * @return true if requested, false otherwise. + */ +bool boot_request_check_confirmed_slot(uint8_t image, uint32_t slot); + +/** + * @brief Find if there is a request to boot certain slot of the specified image. + * + * @param[in] image Image number. + * + * @return slot number if requested, BOOT_REQUEST_NO_PREFERRED_SLOT otherwise. + */ +uint32_t boot_request_get_preferred_slot(uint8_t image); + +/** + * @brief Check if there is a request to boot recovery image. + * + * @return true if requested, false otherwise. + */ +bool boot_request_detect_recovery(void); + +/** + * @brief Check if there is a request to boot firmware loader image. + * + * @return true if requested, false otherwise. + */ +bool boot_request_detect_firmware_loader(void); + +/** + * @brief Initialize boot requests module. + * + * @return 0 if successful, negative error code otherwise. + */ +int boot_request_init(void); + +/** + * @brief Clear/drop all requests. + * + * @return 0 if successful, negative error code otherwise. + */ +int boot_request_clear(void); + +#ifdef __cplusplus +} +#endif + +#endif /* __BOOT_REQUEST_H__ */ diff --git a/boot/bootutil/src/bootutil_public.c b/boot/bootutil/src/bootutil_public.c index 8860fca41..7371a9fe9 100644 --- a/boot/bootutil/src/bootutil_public.c +++ b/boot/bootutil/src/bootutil_public.c @@ -51,6 +51,11 @@ #include "bootutil_priv.h" #include "bootutil_misc.h" +#if defined(CONFIG_NRF_MCUBOOT_BOOT_REQUEST) && !defined(CONFIG_MCUBOOT) +#include +#define SEND_BOOT_REQUEST +#endif /* CONFIG_NRF_MCUBOOT_BOOT_REQUEST && !CONFIG_MCUBOOT */ + #ifdef CONFIG_MCUBOOT BOOT_LOG_MODULE_DECLARE(mcuboot); #else @@ -503,16 +508,47 @@ boot_write_copy_done(const struct flash_area *fap) return boot_write_trailer_flag(fap, off, BOOT_FLAG_SET); } -#ifndef MCUBOOT_BOOTUTIL_LIB_FOR_DIRECT_XIP +#ifdef SEND_BOOT_REQUEST +static int +send_boot_request(uint8_t magic, bool confirm, int image_id, uint32_t slot_id) +{ + int rc = BOOT_EBADIMAGE; -static int flash_area_to_image(const struct flash_area *fa) + /* Handle write-protected active image. */ + if ((magic == BOOT_MAGIC_GOOD) || (magic == BOOT_MAGIC_UNSET)) { + if (confirm) { + BOOT_LOG_DBG("Confirm image: %d, %d", image_id, slot_id); + rc = boot_request_confirm_slot(image_id, slot_id); + } else { + BOOT_LOG_DBG("Set image preference: %d, %d", image_id, slot_id); + rc = boot_request_set_preferred_slot(image_id, slot_id); + } + if (rc != 0) { + rc = BOOT_EBADIMAGE; + } + } + + return rc; +} +#endif /* SEND_BOOT_REQUEST */ + +#if defined(SEND_BOOT_REQUEST) || (!defined(MCUBOOT_BOOTUTIL_LIB_FOR_DIRECT_XIP)) +static int flash_area_to_image_slot(const struct flash_area *fa, uint32_t *slot) { + int id = flash_area_get_id(fa); #if BOOT_IMAGE_NUMBER > 1 uint8_t i = 0; - int id = flash_area_get_id(fa); while (i < BOOT_IMAGE_NUMBER) { - if (FLASH_AREA_IMAGE_PRIMARY(i) == id || (FLASH_AREA_IMAGE_SECONDARY(i) == id)) { + if (FLASH_AREA_IMAGE_PRIMARY(i) == id) { + if (slot != NULL) { + *slot = 0; + } + return i; + } else if (FLASH_AREA_IMAGE_SECONDARY(i) == id) { + if (slot != NULL) { + *slot = 1; + } return i; } @@ -520,15 +556,31 @@ static int flash_area_to_image(const struct flash_area *fa) } #else (void)fa; + if (slot != NULL) { + if (FLASH_AREA_IMAGE_PRIMARY(0) == id) { + *slot = 0; + } else if (FLASH_AREA_IMAGE_SECONDARY(0) == id) { + *slot = 1; + } else { + *slot = UINT32_MAX; + } + } #endif return 0; } +#endif /* defined(SEND_BOOT_REQUEST) || (!defined(MCUBOOT_BOOTUTIL_LIB_FOR_DIRECT_XIP)) */ +#ifndef MCUBOOT_BOOTUTIL_LIB_FOR_DIRECT_XIP int boot_set_next(const struct flash_area *fa, bool active, bool confirm) { struct boot_swap_state slot_state; int rc; + int image_id; + uint32_t slot_id; + + BOOT_LOG_DBG("boot_set_next: fa %p active == %d, confirm == %d", + fa, (int)active, (int)confirm); if (active) { confirm = true; @@ -539,6 +591,15 @@ boot_set_next(const struct flash_area *fa, bool active, bool confirm) return rc; } + image_id = flash_area_to_image_slot(fa, &slot_id); + +#ifdef SEND_BOOT_REQUEST + rc = send_boot_request(slot_state.magic, confirm, image_id, slot_id); + if ((rc != 0) || active) { + return rc; + } +#endif + switch (slot_state.magic) { case BOOT_MAGIC_GOOD: /* If non-active then swap already scheduled, else confirm needed.*/ @@ -569,7 +630,7 @@ boot_set_next(const struct flash_area *fa, bool active, bool confirm) } else { swap_type = BOOT_SWAP_TYPE_TEST; } - rc = boot_write_swap_info(fa, swap_type, flash_area_to_image(fa)); + rc = boot_write_swap_info(fa, swap_type, image_id); } } break; @@ -600,6 +661,10 @@ boot_set_next(const struct flash_area *fa, bool active, bool confirm) { struct boot_swap_state slot_state; int rc; +#ifdef SEND_BOOT_REQUEST + int image_id; + uint32_t slot_id; +#endif BOOT_LOG_DBG("boot_set_next: fa %p active == %d, confirm == %d", fa, (int)active, (int)confirm); @@ -618,6 +683,15 @@ boot_set_next(const struct flash_area *fa, bool active, bool confirm) return rc; } +#ifdef SEND_BOOT_REQUEST + image_id = flash_area_to_image_slot(fa, &slot_id); + + rc = send_boot_request(slot_state.magic, confirm, image_id, slot_id); + if ((rc != 0) || active) { + return rc; + } +#endif + switch (slot_state.magic) { case BOOT_MAGIC_UNSET: /* Magic is needed for MCUboot to even consider booting an image */ diff --git a/boot/bootutil/zephyr/CMakeLists.txt b/boot/bootutil/zephyr/CMakeLists.txt index 44f78f395..111cf4f1d 100644 --- a/boot/bootutil/zephyr/CMakeLists.txt +++ b/boot/bootutil/zephyr/CMakeLists.txt @@ -16,6 +16,11 @@ zephyr_library_named(mcuboot_util) zephyr_library_sources( ../src/bootutil_public.c ) +if(CONFIG_NRF_MCUBOOT_BOOT_REQUEST) + zephyr_library_sources_ifdef(CONFIG_NRF_MCUBOOT_BOOT_REQUEST_IMPL_RETENTION + src/boot_request_retention.c + ) +endif() # Sensitivity to the TEST_BOOT_IMAGE_ACCESS_HOOKS define is implemented for # allowing the test-build with the hooks feature enabled. diff --git a/boot/bootutil/zephyr/src/boot_request_retention.c b/boot/bootutil/zephyr/src/boot_request_retention.c new file mode 100644 index 000000000..023f5af5e --- /dev/null +++ b/boot/bootutil/zephyr/src/boot_request_retention.c @@ -0,0 +1,346 @@ +/* + * SPDX-License-Identifier: Apache-2.0 + * + * Copyright (c) 2025 Nordic Semiconductor ASA + */ +#include + +#include "bootutil/bootutil_log.h" +#include + +/** Special value of image number, indicating a request to the bootloader. */ +#define BOOT_REQUEST_IMG_BOOTLOADER 0xFF + +/** Additional memory used by the retention subsystem (2B - prefix, 4B - CRC).*/ +#define BOOT_REQUEST_ENTRY_METADATA_SIZE (2 + 4) + +MCUBOOT_LOG_MODULE_REGISTER(bootloader_request); + +static const struct device *bootloader_request_dev = + DEVICE_DT_GET(DT_CHOSEN(nrf_bootloader_request)); + +enum boot_request_type { + /** Invalid request. */ + BOOT_REQUEST_INVALID = 0, + + /** Request a change in the bootloader boot mode. + * + * @details Use @p boot_request_mode as argument. + * @p BOOT_REQUEST_IMG_BOOTLOADER as image number. + * + * @note Used to trigger recovery through i.e. retention sybsystem. + */ + BOOT_REQUEST_BOOT_MODE = 1, + + /** Select the preferred image to be selected during boot or update. + * + * @details Use @p boot_request_slot_t as argument. + * + * @note Used in the Direct XIP mode. + */ + BOOT_REQUEST_IMG_PREFERENCE = 2, + + /** Request a confirmation of an image. + * + * @details Use @p boot_request_slot_t as argument. + * + * @note Used if the code cannot modify the image trailer directly. + */ + BOOT_REQUEST_IMG_CONFIRM = 3, +}; + +/* Entries inside the boot request shared memory. */ +enum boot_request_entry { + BOOT_REQUEST_ENTRY_BOOT_MODE = 0, + BOOT_REQUEST_ENTRY_IMAGE_0_PREFERENCE = 1, + BOOT_REQUEST_ENTRY_IMAGE_0_CONFIRM = 2, + BOOT_REQUEST_ENTRY_IMAGE_1_PREFERENCE = 3, + BOOT_REQUEST_ENTRY_IMAGE_1_CONFIRM = 4, + BOOT_REQUEST_ENTRY_MAX = 5, +}; + +/* Assert that all requests will fit within the retention area. */ +BUILD_ASSERT((BOOT_REQUEST_ENTRY_METADATA_SIZE + BOOT_REQUEST_ENTRY_MAX * sizeof(uint8_t)) < + DT_REG_SIZE_BY_IDX(DT_CHOSEN(nrf_bootloader_request), 0), + "nrf,bootloader-request area is too small for bootloader request struct"); + +enum boot_request_slot { + /** Unsupported value. */ + BOOT_REQUEST_SLOT_INVALID = 0, + /** Primary slot. */ + BOOT_REQUEST_SLOT_PRIMARY = 1, + /** Secondary slot. */ + BOOT_REQUEST_SLOT_SECONDARY = 2, +}; + +/** Alias type for the image and number. */ +typedef uint8_t boot_request_slot_t; + +enum boot_request_mode { + /** Execute a regular boot logic. */ + BOOT_REQUEST_MODE_REGULAR = 0, + /** Execute the recovery boot logic. */ + BOOT_REQUEST_MODE_RECOVERY = 1, + /** Execute the firmware loader logic. */ + BOOT_REQUEST_MODE_FIRMWARE_LOADER = 2, + /** Unsupported value. */ + BOOT_REQUEST_MODE_INVALID = 0xFF, +}; + +/** Alias type for the image number. */ +typedef uint8_t boot_request_img_t; + +/** + * @brief Find an entry for a given request. + * + * @param[in] type Type of request. + * @param[in] image Image number. Use @p BOOT_REQUEST_IMG_BOOTLOADER for generic requests. + * @param[out] entry Entry to use. + * + * @return 0 on success; nonzero on failure. + */ +static int boot_request_entry_find(enum boot_request_type type, boot_request_img_t image, + size_t *entry) +{ + if (entry == NULL) { + return -EINVAL; + } + + switch (type) { + case BOOT_REQUEST_BOOT_MODE: + *entry = BOOT_REQUEST_ENTRY_BOOT_MODE; + break; + case BOOT_REQUEST_IMG_PREFERENCE: + switch (image) { + case 0: + *entry = BOOT_REQUEST_ENTRY_IMAGE_0_PREFERENCE; + break; + case 1: + *entry = BOOT_REQUEST_ENTRY_IMAGE_1_PREFERENCE; + break; + default: + return -EINVAL; + } + break; + case BOOT_REQUEST_IMG_CONFIRM: + switch (image) { + case 0: + *entry = BOOT_REQUEST_ENTRY_IMAGE_0_CONFIRM; + break; + case 1: + *entry = BOOT_REQUEST_ENTRY_IMAGE_1_CONFIRM; + break; + default: + return -EINVAL; + } + break; + default: + return -EINVAL; + } + + return 0; +} + +int boot_request_init(void) +{ + if (!device_is_ready(bootloader_request_dev)) { + return -EIO; + } + + return 0; +} + +int boot_request_clear(void) +{ + return retention_clear(bootloader_request_dev); +} + +int boot_request_confirm_slot(uint8_t image, uint32_t slot) +{ + uint8_t value = BOOT_REQUEST_SLOT_INVALID; + size_t req_entry; + int ret; + + ret = boot_request_entry_find(BOOT_REQUEST_IMG_CONFIRM, image, &req_entry); + if (ret != 0) { + return ret; + } + + switch (slot) { + case 0: + value = BOOT_REQUEST_SLOT_PRIMARY; + break; + case 1: + value = BOOT_REQUEST_SLOT_SECONDARY; + break; + default: + return -EINVAL; + } + + return retention_write(bootloader_request_dev, req_entry * sizeof(value), (void *)&value, + sizeof(value)); +} + +bool boot_request_check_confirmed_slot(uint8_t image, uint32_t slot) +{ + uint8_t value = BOOT_REQUEST_SLOT_INVALID; + size_t req_entry; + int ret; + + ret = boot_request_entry_find(BOOT_REQUEST_IMG_CONFIRM, image, &req_entry); + if (ret != 0) { + return false; + } + + ret = retention_read(bootloader_request_dev, req_entry * sizeof(value), (void *)&value, + sizeof(value)); + if (ret != 0) { + return false; + } + + switch (value) { + case BOOT_REQUEST_SLOT_PRIMARY: + return (slot == 0); + case BOOT_REQUEST_SLOT_SECONDARY: + return (slot == 1); + default: + break; + } + + return false; +} + +int boot_request_set_preferred_slot(uint8_t image, uint32_t slot) +{ + uint8_t value = BOOT_REQUEST_SLOT_INVALID; + size_t req_entry; + int ret; + + ret = boot_request_entry_find(BOOT_REQUEST_IMG_PREFERENCE, image, &req_entry); + if (ret != 0) { + return ret; + } + + switch (slot) { + case 0: + value = BOOT_REQUEST_SLOT_PRIMARY; + break; + case 1: + value = BOOT_REQUEST_SLOT_SECONDARY; + break; + default: + return -EINVAL; + } + + return retention_write(bootloader_request_dev, req_entry * sizeof(value), (void *)&value, + sizeof(value)); +} + +#ifdef CONFIG_FIND_NEXT_SLOT_HOOKS +uint32_t boot_request_get_preferred_slot(uint8_t image) +{ + uint8_t value = BOOT_REQUEST_SLOT_INVALID; + size_t req_entry; + int ret; + + ret = boot_request_entry_find(BOOT_REQUEST_IMG_PREFERENCE, image, &req_entry); + if (ret != 0) { + return BOOT_REQUEST_NO_PREFERRED_SLOT; + } + + ret = retention_read(bootloader_request_dev, req_entry * sizeof(value), (void *)&value, + sizeof(value)); + if (ret != 0) { + return BOOT_REQUEST_NO_PREFERRED_SLOT; + } + + switch (value) { + case BOOT_REQUEST_SLOT_PRIMARY: + return 0; + case BOOT_REQUEST_SLOT_SECONDARY: + return 1; + default: + break; + } + + return BOOT_REQUEST_NO_PREFERRED_SLOT; +} +#endif /* CONFIG_FIND_NEXT_SLOT_HOOKS */ + +int boot_request_enter_recovery(void) +{ + uint8_t value = BOOT_REQUEST_MODE_RECOVERY; + size_t req_entry; + int ret; + + ret = boot_request_entry_find(BOOT_REQUEST_BOOT_MODE, BOOT_REQUEST_IMG_BOOTLOADER, + &req_entry); + if (ret != 0) { + return ret; + } + + return retention_write(bootloader_request_dev, req_entry * sizeof(value), (void *)&value, + sizeof(value)); +} + +#ifdef CONFIG_NRF_BOOT_SERIAL_BOOT_REQ +bool boot_request_detect_recovery(void) +{ + uint8_t value = BOOT_REQUEST_MODE_INVALID; + size_t req_entry; + int ret; + + ret = boot_request_entry_find(BOOT_REQUEST_BOOT_MODE, BOOT_REQUEST_IMG_BOOTLOADER, + &req_entry); + if (ret != 0) { + return false; + } + + ret = retention_read(bootloader_request_dev, req_entry * sizeof(value), (void *)&value, + sizeof(value)); + if ((ret == 0) && (value == BOOT_REQUEST_MODE_RECOVERY)) { + return true; + } + + return false; +} +#endif /* CONFIG_NRF_BOOT_SERIAL_BOOT_REQ */ + +int boot_request_enter_firmware_loader(void) +{ + uint8_t value = BOOT_REQUEST_MODE_FIRMWARE_LOADER; + size_t req_entry; + int ret; + + ret = boot_request_entry_find(BOOT_REQUEST_BOOT_MODE, BOOT_REQUEST_IMG_BOOTLOADER, + &req_entry); + if (ret != 0) { + return ret; + } + + return retention_write(bootloader_request_dev, req_entry * sizeof(value), (void *)&value, + sizeof(value)); +} + +#ifdef CONFIG_NRF_BOOT_FIRMWARE_LOADER_BOOT_REQ +bool boot_request_detect_firmware_loader(void) +{ + uint8_t value = BOOT_REQUEST_MODE_INVALID; + size_t req_entry; + int ret; + + ret = boot_request_entry_find(BOOT_REQUEST_BOOT_MODE, BOOT_REQUEST_IMG_BOOTLOADER, + &req_entry); + if (ret != 0) { + return false; + } + + ret = retention_read(bootloader_request_dev, req_entry * sizeof(value), (void *)&value, + sizeof(value)); + if ((ret == 0) && (value == BOOT_REQUEST_MODE_FIRMWARE_LOADER)) { + return true; + } + + return false; +} +#endif /* CONFIG_NRF_BOOT_FIRMWARE_LOADER_BOOT_REQ */ diff --git a/boot/zephyr/Kconfig b/boot/zephyr/Kconfig index d1f5be182..a94c7e1e5 100644 --- a/boot/zephyr/Kconfig +++ b/boot/zephyr/Kconfig @@ -1333,6 +1333,10 @@ config USB_DEVICE_PRODUCT config MCUBOOT_BOOTUTIL_LIB_OWN_LOG bool +config NRF_MCUBOOT_BOOT_REQUEST + bool + imply FIND_NEXT_SLOT_HOOKS if BOOT_DIRECT_XIP || BOOT_RAM_LOAD + config MCUBOOT_VERIFY_IMG_ADDRESS bool "Verify reset address of image in secondary slot" depends on UPDATEABLE_IMAGE_NUMBER > 1 diff --git a/boot/zephyr/Kconfig.firmware_loader b/boot/zephyr/Kconfig.firmware_loader index 036da98eb..376dc06f7 100644 --- a/boot/zephyr/Kconfig.firmware_loader +++ b/boot/zephyr/Kconfig.firmware_loader @@ -42,6 +42,12 @@ config BOOT_FIRMWARE_LOADER_PIN_RESET Checks if the module reset was caused by the reset pin and will remain in bootloader firmware loader mode if it was. +config NRF_BOOT_FIRMWARE_LOADER_BOOT_REQ + bool "Check boot mode via bootloader request" + depends on NRF_MCUBOOT_BOOT_REQUEST + help + Allows for entering firmware loader mode by using bootloader rquests. + endmenu endif diff --git a/boot/zephyr/Kconfig.serial_recovery b/boot/zephyr/Kconfig.serial_recovery index 5b4ba3e11..b6c71e5e0 100644 --- a/boot/zephyr/Kconfig.serial_recovery +++ b/boot/zephyr/Kconfig.serial_recovery @@ -191,6 +191,12 @@ config BOOT_SERIAL_PIN_RESET Checks if the module reset was caused by the reset pin and will remain in bootloader serial recovery mode if it was. +config NRF_BOOT_SERIAL_BOOT_REQ + bool "Check boot mode via bootloader request subsystem" + depends on NRF_MCUBOOT_BOOT_REQUEST + help + Allows for entering serial recovery mode by using bootloader requests. + endmenu config BOOT_SERIAL_IMG_GRP_HASH diff --git a/boot/zephyr/firmware_loader.c b/boot/zephyr/firmware_loader.c index 1df848634..834dc6341 100644 --- a/boot/zephyr/firmware_loader.c +++ b/boot/zephyr/firmware_loader.c @@ -17,6 +17,9 @@ #include "io/io.h" #include "mcuboot_config/mcuboot_config.h" +#ifdef CONFIG_NRF_MCUBOOT_BOOT_REQUEST +#include +#endif /* CONFIG_NRF_MCUBOOT_BOOT_REQUEST */ BOOT_LOG_MODULE_DECLARE(mcuboot); @@ -183,6 +186,12 @@ boot_go(struct boot_rsp *rsp) } #endif +#ifdef CONFIG_NRF_BOOT_FIRMWARE_LOADER_BOOT_REQ + if (boot_request_detect_firmware_loader()) { + boot_firmware_loader = true; + } +#endif + /* Check if firmware loader button is pressed. TODO: check all entrance methods */ if (boot_firmware_loader == true) { FIH_CALL(validate_image_slot, fih_rc, FLASH_AREA_IMAGE_SECONDARY(0), rsp); diff --git a/boot/zephyr/main.c b/boot/zephyr/main.c index fa3eeff90..38640aa97 100644 --- a/boot/zephyr/main.c +++ b/boot/zephyr/main.c @@ -46,6 +46,12 @@ #include "bootutil/fault_injection_hardening.h" #include "bootutil/mcuboot_status.h" #include "flash_map_backend/flash_map_backend.h" +#ifdef CONFIG_NRF_MCUBOOT_BOOT_REQUEST +#include + +/** Number of image slots. */ +#define BOOT_REQUEST_NUM_SLOTS 2 +#endif /* CONFIG_NRF_MCUBOOT_BOOT_REQUEST */ /* Check if Espressif target is supported */ #ifdef CONFIG_SOC_FAMILY_ESPRESSIF_ESP32 @@ -543,6 +549,37 @@ static void boot_serial_enter() } #endif +static int boot_prevalidate(void) +{ +#ifdef CONFIG_NRF_MCUBOOT_BOOT_REQUEST + uint8_t image_index; + uint32_t slot; + uint32_t area_id; + const struct flash_area *fap; + int rc = boot_request_init(); + + if (rc != 0) { + return rc; + } + + for (image_index = 0; image_index < BOOT_IMAGE_NUMBER; ++image_index) { + for (slot = 0; slot < BOOT_REQUEST_NUM_SLOTS; slot++) { + if (boot_request_check_confirmed_slot(image_index, slot)) { + BOOT_LOG_DBG("Confirm image: %d slot: %d due to bootloader request.", + image_index, slot); + + area_id = flash_area_id_from_multi_image_slot(image_index, slot); + rc = flash_area_open(area_id, &fap); + if (rc == 0) { + rc = boot_set_next(fap, true, true); + } + } + } + } +#endif + return 0; +} + int main(void) { struct boot_rsp rsp; @@ -574,6 +611,11 @@ int main(void) mcuboot_status_change(MCUBOOT_STATUS_STARTUP); + rc = boot_prevalidate(); + if (rc) { + BOOT_LOG_ERR("Failed to prevalidate the state: %d", rc); + } + #ifdef CONFIG_BOOT_SERIAL_ENTRANCE_GPIO BOOT_LOG_DBG("Checking GPIO for serial recovery"); if (io_detect_pin() && @@ -589,6 +631,13 @@ int main(void) } #endif +#ifdef CONFIG_NRF_BOOT_SERIAL_BOOT_REQ + if (boot_request_detect_recovery()) { + BOOT_LOG_DBG("Staying in serial recovery"); + boot_serial_enter(); + } +#endif + #if defined(CONFIG_BOOT_USB_DFU_GPIO) BOOT_LOG_DBG("Checking GPIO for USB DFU request"); if (io_detect_pin()) { @@ -649,6 +698,10 @@ int main(void) } BOOT_LOG_DBG("Left boot_go with success == %d", FIH_EQ(fih_rc, FIH_SUCCESS) ? 1 : 0); +#ifdef CONFIG_NRF_MCUBOOT_BOOT_REQUEST + (void)boot_request_clear(); +#endif + #ifdef CONFIG_BOOT_SERIAL_BOOT_MODE if (io_detect_boot_mode()) { /* Boot mode to stay in bootloader, clear status and enter serial From 5af259f253d5e11a3ab6b99de122b2e8db6fa5c7 Mon Sep 17 00:00:00 2001 From: Dominik Ermel Date: Tue, 12 Aug 2025 09:27:35 +0000 Subject: [PATCH 123/420] [nrf fromtree] bootutil: Fix bootutil_aes_ctr_drop memset usage memset was given incorrectly pointer size, instead of object size. Signed-off-by: Dominik Ermel (cherry picked from commit aa229135b30e6ce9a24c9ae2cf3a85591d1aa7d6) --- boot/bootutil/include/bootutil/crypto/aes_ctr.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/boot/bootutil/include/bootutil/crypto/aes_ctr.h b/boot/bootutil/include/bootutil/crypto/aes_ctr.h index e5416dca0..88ae87c39 100644 --- a/boot/bootutil/include/bootutil/crypto/aes_ctr.h +++ b/boot/bootutil/include/bootutil/crypto/aes_ctr.h @@ -58,7 +58,7 @@ void bootutil_aes_ctr_init(bootutil_aes_ctr_context *ctx); static inline void bootutil_aes_ctr_drop(bootutil_aes_ctr_context *ctx) { - memset(ctx, 0, sizeof(ctx)); + memset(ctx, 0, sizeof(*ctx)); } static inline int bootutil_aes_ctr_set_key(bootutil_aes_ctr_context *ctx, const uint8_t *k) From d79a412144f2cbeadb3037883edc4677819102ae Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Adam=20Szczygie=C5=82?= Date: Fri, 5 Sep 2025 07:30:25 +0200 Subject: [PATCH 124/420] Revert "[nrf noup] zephyr: add 'minimal' configuration files" MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This reverts commit 54f21298ed294b707b5c78f6da81b5e2d262e95b. nrf-squash! [nrf noup] zephyr: add 'minimal' configuration files The minimal configuration is now deprecated: - it is not minimal configuration anymore - built image cannot fit into flash memory - smp_svr_mini_boot sample is a new reference for minimal config Signed-off-by: Adam Szczygieł --- .../nrf5340dk_nrf5340_cpuapp_minimal.conf | 13 ------ boot/zephyr/prj_minimal.conf | 41 ------------------- 2 files changed, 54 deletions(-) delete mode 100644 boot/zephyr/boards/nrf5340dk_nrf5340_cpuapp_minimal.conf delete mode 100644 boot/zephyr/prj_minimal.conf diff --git a/boot/zephyr/boards/nrf5340dk_nrf5340_cpuapp_minimal.conf b/boot/zephyr/boards/nrf5340dk_nrf5340_cpuapp_minimal.conf deleted file mode 100644 index dd5468106..000000000 --- a/boot/zephyr/boards/nrf5340dk_nrf5340_cpuapp_minimal.conf +++ /dev/null @@ -1,13 +0,0 @@ -# -# Copyright (c) 2021 Nordic Semiconductor ASA -# -# SPDX-License-Identifier: LicenseRef-Nordic-5-Clause -# - -# CC3xx is currently not used for nrf53 -CONFIG_HW_CC3XX=n -CONFIG_NRF_CC3XX_PLATFORM=n - -# Required for kernel operation -CONFIG_CLOCK_CONTROL=y -CONFIG_SYS_CLOCK_EXISTS=y diff --git a/boot/zephyr/prj_minimal.conf b/boot/zephyr/prj_minimal.conf deleted file mode 100644 index 91cf1bc96..000000000 --- a/boot/zephyr/prj_minimal.conf +++ /dev/null @@ -1,41 +0,0 @@ -# -# Copyright (c) 2021 Nordic Semiconductor ASA -# -# SPDX-License-Identifier: LicenseRef-Nordic-5-Clause -# - -CONFIG_MAIN_STACK_SIZE=10240 -CONFIG_MBEDTLS_CFG_FILE="mcuboot-mbedtls-cfg.h" - -CONFIG_FLASH=y -CONFIG_FPROTECT=y -CONFIG_PM=n - -CONFIG_BOOT_SWAP_SAVE_ENCTLV=n -CONFIG_BOOT_ENCRYPT_IMAGE=n - -CONFIG_BOOT_BOOTSTRAP=n -CONFIG_BOOT_UPGRADE_ONLY=n - -### Minimal Configurations ### -CONFIG_BOOT_USE_MIN_PARTITION_SIZE=y -CONFIG_ASSERT=n -CONFIG_BOOT_BANNER=n -CONFIG_NCS_BOOT_BANNER=n -CONFIG_CLOCK_CONTROL=n -CONFIG_CONSOLE=n -CONFIG_CONSOLE_HANDLER=n -CONFIG_GPIO=n -CONFIG_KERNEL_MEM_POOL=n -CONFIG_LOG=n -CONFIG_COMMON_LIBC_CALLOC=n -CONFIG_COMMON_LIBC_MALLOC=n -CONFIG_COMMON_LIBC_REALLOCARRAY=n -CONFIG_NCS_SAMPLES_DEFAULTS=n -CONFIG_NO_RUNTIME_CHECKS=y -CONFIG_NRF_RTC_TIMER=n -CONFIG_PRINTK=n -CONFIG_SERIAL=n -CONFIG_SIZE_OPTIMIZATIONS=y -CONFIG_SYS_CLOCK_EXISTS=n -CONFIG_UART_CONSOLE=n From 9b605606969bfa12d66f39bd50656dfe9d73dd52 Mon Sep 17 00:00:00 2001 From: Artur Hadasz Date: Mon, 25 Aug 2025 16:16:31 +0200 Subject: [PATCH 125/420] [nrf fromtree] boot: Enable Encryption with PSA + ECDSA This configuration was not supported until now. Signed-off-by: Artur Hadasz (cherry picked from commit e375252c3d98e8bb1f2e219c172b56f052ab9310) --- boot/bootutil/src/encrypted.c | 65 ++++++++++----------- boot/bootutil/src/encrypted_psa.c | 96 +++++++++++++++++++++++++++++-- boot/zephyr/CMakeLists.txt | 9 +-- 3 files changed, 130 insertions(+), 40 deletions(-) diff --git a/boot/bootutil/src/encrypted.c b/boot/bootutil/src/encrypted.c index cf6f380e2..9792a9038 100644 --- a/boot/bootutil/src/encrypted.c +++ b/boot/bootutil/src/encrypted.c @@ -22,11 +22,11 @@ #include "bootutil/crypto/aes_kw.h" #endif +#if !defined(MCUBOOT_USE_PSA_CRYPTO) #if defined(MCUBOOT_ENCRYPT_EC256) #include "bootutil/crypto/ecdh_p256.h" #endif -#if !defined(MCUBOOT_USE_PSA_CRYPTO) #if defined(MCUBOOT_ENCRYPT_X25519) #include "bootutil/crypto/ecdh_x25519.h" #endif @@ -50,7 +50,7 @@ BOOT_LOG_MODULE_DECLARE(mcuboot); #include "bootutil_priv.h" /* NOUP Fixme: */ -#if !defined(CONFIG_BOOT_ED25519_PSA) +#if !defined(CONFIG_BOOT_ED25519_PSA) && !defined(CONFIG_BOOT_ECDSA_PSA) #if defined(MCUBOOT_ENCRYPT_EC256) || defined(MCUBOOT_ENCRYPT_X25519) #if defined(_compare) static inline int bootutil_constant_time_compare(const uint8_t *a, const uint8_t *b, size_t size) @@ -105,65 +105,64 @@ static const uint8_t ec_secp256r1_oid[] = MBEDTLS_OID_EC_GRP_SECP256R1; * curve keypair. See RFC5208 and RFC5915. */ static int -parse_ec256_enckey(uint8_t **p, uint8_t *end, uint8_t *private_key) +parse_priv_enckey(uint8_t **p, uint8_t *end, uint8_t *private_key) { - int rc; size_t len; int version; mbedtls_asn1_buf alg; mbedtls_asn1_buf param; - if ((rc = mbedtls_asn1_get_tag(p, end, &len, - MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)) != 0) { + if (mbedtls_asn1_get_tag(p, end, &len, + MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE) != 0) { return -1; } if (*p + len != end) { - return -2; + return -1; } version = 0; if (mbedtls_asn1_get_int(p, end, &version) || version != 0) { - return -3; + return -1; } - if ((rc = mbedtls_asn1_get_alg(p, end, &alg, ¶m)) != 0) { - return -5; + if (mbedtls_asn1_get_alg(p, end, &alg, ¶m) != 0) { + return -1; } if (alg.ASN1_CONTEXT_MEMBER(len) != sizeof(ec_pubkey_oid) - 1 || memcmp(alg.ASN1_CONTEXT_MEMBER(p), ec_pubkey_oid, sizeof(ec_pubkey_oid) - 1)) { - return -6; + return -1; } if (param.ASN1_CONTEXT_MEMBER(len) != sizeof(ec_secp256r1_oid) - 1 || memcmp(param.ASN1_CONTEXT_MEMBER(p), ec_secp256r1_oid, sizeof(ec_secp256r1_oid) - 1)) { - return -7; + return -1; } - if ((rc = mbedtls_asn1_get_tag(p, end, &len, MBEDTLS_ASN1_OCTET_STRING)) != 0) { - return -8; + if (mbedtls_asn1_get_tag(p, end, &len, MBEDTLS_ASN1_OCTET_STRING) != 0) { + return -1; } /* RFC5915 - ECPrivateKey */ - if ((rc = mbedtls_asn1_get_tag(p, end, &len, - MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)) != 0) { - return -9; + if (mbedtls_asn1_get_tag(p, end, &len, + MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE) != 0) { + return -1; } version = 0; if (mbedtls_asn1_get_int(p, end, &version) || version != 1) { - return -10; + return -1; } /* privateKey */ - if ((rc = mbedtls_asn1_get_tag(p, end, &len, MBEDTLS_ASN1_OCTET_STRING)) != 0) { - return -11; + if (mbedtls_asn1_get_tag(p, end, &len, MBEDTLS_ASN1_OCTET_STRING) != 0) { + return -1; } if (len != NUM_ECC_BYTES) { - return -12; + return -1; } memcpy(private_key, *p, len); @@ -180,7 +179,7 @@ static const uint8_t ec_pubkey_oid[] = MBEDTLS_OID_ISO_IDENTIFIED_ORG \ MBEDTLS_OID_ORG_GOV X25519_OID; static int -parse_x25519_enckey(uint8_t **p, uint8_t *end, uint8_t *private_key) +parse_priv_enckey(uint8_t **p, uint8_t *end, uint8_t *private_key) { size_t len; int version; @@ -193,33 +192,33 @@ parse_x25519_enckey(uint8_t **p, uint8_t *end, uint8_t *private_key) } if (*p + len != end) { - return -2; + return -1; } version = 0; if (mbedtls_asn1_get_int(p, end, &version) || version != 0) { - return -3; + return -1; } if (mbedtls_asn1_get_alg(p, end, &alg, ¶m) != 0) { - return -4; + return -1; } if (alg.ASN1_CONTEXT_MEMBER(len) != sizeof(ec_pubkey_oid) - 1 || memcmp(alg.ASN1_CONTEXT_MEMBER(p), ec_pubkey_oid, sizeof(ec_pubkey_oid) - 1)) { - return -5; + return -1; } if (mbedtls_asn1_get_tag(p, end, &len, MBEDTLS_ASN1_OCTET_STRING) != 0) { - return -6; + return -1; } if (mbedtls_asn1_get_tag(p, end, &len, MBEDTLS_ASN1_OCTET_STRING) != 0) { - return -7; + return -1; } if (len != EC_PRIVK_LEN) { - return -8; + return -1; } memcpy(private_key, *p, EC_PRIVK_LEN); @@ -455,8 +454,9 @@ boot_decrypt_key(const uint8_t *buf, uint8_t *enckey) * Load the stored EC256 decryption private key */ - rc = parse_ec256_enckey(&cp, cpend, private_key); + rc = parse_priv_enckey(&cp, cpend, private_key); if (rc) { + BOOT_LOG_ERR("Failed to parse ASN1 private key"); return rc; } @@ -482,8 +482,9 @@ boot_decrypt_key(const uint8_t *buf, uint8_t *enckey) * Load the stored X25519 decryption private key */ - rc = parse_x25519_enckey(&cp, cpend, private_key); + rc = parse_priv_enckey(&cp, cpend, private_key); if (rc) { + BOOT_LOG_ERR("Failed to parse ASN1 private key"); return rc; } @@ -580,7 +581,7 @@ boot_decrypt_key(const uint8_t *buf, uint8_t *enckey) return rc; } -#endif /* CONFIG_BOOT_ED25519_PSA */ +#endif /* CONFIG_BOOT_ED25519_PSA && CONFIG_BOOT_ECDSA_PSA */ /* * Load encryption key. diff --git a/boot/bootutil/src/encrypted_psa.c b/boot/bootutil/src/encrypted_psa.c index 7e53ed4a7..55f7f6f2d 100644 --- a/boot/bootutil/src/encrypted_psa.c +++ b/boot/bootutil/src/encrypted_psa.c @@ -33,9 +33,18 @@ BOOT_LOG_MODULE_DECLARE(mcuboot_psa_enc); #define PSA_HMAC_HKDF_SHA PSA_ALG_SHA_256 #endif +#if defined(MCUBOOT_ENCRYPT_EC256) +#define NUM_ECC_BYTES (256 / 8) +static const uint8_t ec_pubkey_oid[] = MBEDTLS_OID_EC_ALG_UNRESTRICTED; +static const uint8_t ec_secp256r1_oid[] = MBEDTLS_OID_EC_GRP_SECP256R1; +#define ECC_FAMILY PSA_ECC_FAMILY_SECP_R1 +#endif /* defined(MCUBOOT_ENCRYPT_EC256) */ +#if defined(MCUBOOT_ENCRYPT_X25519) #define X25519_OID "\x6e" static const uint8_t ec_pubkey_oid[] = MBEDTLS_OID_ISO_IDENTIFIED_ORG \ MBEDTLS_OID_ORG_GOV X25519_OID; +#define ECC_FAMILY PSA_ECC_FAMILY_MONTGOMERY +#endif /* defined(MCUBOOT_ENCRYPT_X25519) */ /* Partitioning of HKDF derived material, from the exchange derived key */ /* AES key encryption key */ @@ -51,9 +60,86 @@ static const uint8_t ec_pubkey_oid[] = MBEDTLS_OID_ISO_IDENTIFIED_ORG \ /* Total size */ #define HKDF_SIZE (HKDF_AES_KEY_SIZE + HKDF_MAC_FEED_SIZE) +#if defined(MCUBOOT_ENCRYPT_EC256) +/* Fixme: This duplicates code from encrypted.c and depends on mbedtls */ + +/* + * Parses the output of `imgtool keygen`, which produces a PKCS#8 elliptic + * curve keypair. See RFC5208 and RFC5915. + */ +static int +parse_priv_enckey(uint8_t **p, uint8_t *end, uint8_t *private_key) +{ + size_t len; + int version; + mbedtls_asn1_buf alg; + mbedtls_asn1_buf param; + + if (mbedtls_asn1_get_tag(p, end, &len, + MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE) != 0) { + return -1; + } + + if (*p + len != end) { + return -1; + } + + version = 0; + if (mbedtls_asn1_get_int(p, end, &version) || version != 0) { + return -1; + } + + if (mbedtls_asn1_get_alg(p, end, &alg, ¶m) != 0) { + return -1; + } + + if (alg.ASN1_CONTEXT_MEMBER(len) != sizeof(ec_pubkey_oid) - 1 || + memcmp(alg.ASN1_CONTEXT_MEMBER(p), ec_pubkey_oid, sizeof(ec_pubkey_oid) - 1)) { + return -1; + } + if (param.ASN1_CONTEXT_MEMBER(len) != sizeof(ec_secp256r1_oid) - 1 || + memcmp(param.ASN1_CONTEXT_MEMBER(p), ec_secp256r1_oid, sizeof(ec_secp256r1_oid) - 1)) { + return -1; + } + + if (mbedtls_asn1_get_tag(p, end, &len, MBEDTLS_ASN1_OCTET_STRING) != 0) { + return -1; + } + + /* RFC5915 - ECPrivateKey */ + + if (mbedtls_asn1_get_tag(p, end, &len, + MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE) != 0) { + return -1; + } + + version = 0; + if (mbedtls_asn1_get_int(p, end, &version) || version != 1) { + return -1; + } + + /* privateKey */ + + if (mbedtls_asn1_get_tag(p, end, &len, MBEDTLS_ASN1_OCTET_STRING) != 0) { + return -1; + } + + if (len != NUM_ECC_BYTES) { + return -1; + } + + memcpy(private_key, *p, len); + + /* publicKey usually follows but is not parsed here */ + + return 0; +} +#endif /* defined(MCUBOOT_ENCRYPT_EC256) */ + +#if defined(MCUBOOT_ENCRYPT_X25519) /* Fixme: This duplicates code from encrypted.c and depends on mbedtls */ static int -parse_x25519_enckey(uint8_t **p, uint8_t *end, uint8_t *private_key) +parse_priv_enckey(uint8_t **p, uint8_t *end, uint8_t *private_key) { size_t len; int version; @@ -98,6 +184,7 @@ parse_x25519_enckey(uint8_t **p, uint8_t *end, uint8_t *private_key) memcpy(private_key, *p, EC_PRIVK_LEN); return 0; } +#endif /* defined(MCUBOOT_ENCRYPT_X25519) */ void bootutil_aes_ctr_init(bootutil_aes_ctr_context *ctx) { @@ -153,14 +240,15 @@ boot_decrypt_key(const uint8_t *buf, uint8_t *enckey) } /* - * Load the stored X25519 decryption private key + * * Load the stored decryption private key */ - rc = parse_x25519_enckey(&cp, cpend, private_key); + rc = parse_priv_enckey(&cp, cpend, private_key); if (rc) { + BOOT_LOG_ERR("Failed to parse ASN1 private key"); return rc; } - psa_set_key_type(&kattr, PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_MONTGOMERY)); + psa_set_key_type(&kattr, PSA_KEY_TYPE_ECC_KEY_PAIR(ECC_FAMILY)); psa_set_key_usage_flags(&kattr, PSA_KEY_USAGE_DERIVE); psa_set_key_algorithm(&kattr, PSA_ALG_ECDH); diff --git a/boot/zephyr/CMakeLists.txt b/boot/zephyr/CMakeLists.txt index e8d79af7d..f9e0e70bc 100644 --- a/boot/zephyr/CMakeLists.txt +++ b/boot/zephyr/CMakeLists.txt @@ -123,11 +123,12 @@ zephyr_library_sources( ${BOOT_DIR}/bootutil/src/fault_injection_hardening.c ) -if(DEFINED CONFIG_BOOT_ENCRYPT_X25519 AND DEFINED CONFIG_BOOT_ED25519_PSA) +if((CONFIG_BOOT_ENCRYPT_X25519 AND CONFIG_BOOT_ED25519_PSA) + OR (CONFIG_BOOT_ENCRYPT_EC256 AND CONFIG_BOOT_ECDSA_PSA)) zephyr_library_sources(${BOOT_DIR}/bootutil/src/encrypted_psa.c) endif() -if(DEFINED CONFIG_MEASURED_BOOT OR DEFINED CONFIG_BOOT_SHARE_DATA) +if(CONFIG_MEASURED_BOOT OR CONFIG_BOOT_SHARE_DATA) zephyr_library_sources( ${BOOT_DIR}/bootutil/src/boot_record.c ) @@ -321,7 +322,7 @@ elseif(CONFIG_BOOT_SIGNATURE_TYPE_ED25519 OR CONFIG_BOOT_ENCRYPT_X25519) endif() endif() -if(NOT CONFIG_BOOT_ED25519_PSA) +if(NOT CONFIG_BOOT_ED25519_PSA AND NOT CONFIG_BOOT_ECDSA_PSA) if(CONFIG_BOOT_ENCRYPT_EC256 OR CONFIG_BOOT_ENCRYPT_X25519) zephyr_library_sources( ${TINYCRYPT_DIR}/source/aes_encrypt.c @@ -333,7 +334,7 @@ if(NOT CONFIG_BOOT_ED25519_PSA) endif() endif() -if(CONFIG_BOOT_ENCRYPT_EC256) +if(CONFIG_BOOT_ENCRYPT_EC256 AND NOT CONFIG_BOOT_ECDSA_PSA) zephyr_library_sources( ${TINYCRYPT_DIR}/source/ecc_dh.c ) From 4292905fb054418de6f43c8437ce9833691f6687 Mon Sep 17 00:00:00 2001 From: Tomasz Chyrowicz Date: Thu, 4 Sep 2025 13:42:12 +0200 Subject: [PATCH 126/420] [nrf noup] boot: Improve bootloader request handling nrf-squash! [nrf noup] bootloader: Add bootloader requests Improve logic that handles sending bootloader requests as a result of issuing the MCUmgr commands. Signed-off-by: Tomasz Chyrowicz --- boot/bootutil/src/bootutil_public.c | 17 +++++++++++++---- boot/zephyr/Kconfig | 11 +++++++++++ 2 files changed, 24 insertions(+), 4 deletions(-) diff --git a/boot/bootutil/src/bootutil_public.c b/boot/bootutil/src/bootutil_public.c index 7371a9fe9..750157e82 100644 --- a/boot/bootutil/src/bootutil_public.c +++ b/boot/bootutil/src/bootutil_public.c @@ -510,7 +510,8 @@ boot_write_copy_done(const struct flash_area *fap) #ifdef SEND_BOOT_REQUEST static int -send_boot_request(uint8_t magic, bool confirm, int image_id, uint32_t slot_id) +send_boot_request(uint8_t magic, uint8_t image_ok, bool confirm, int image_id, + uint32_t slot_id) { int rc = BOOT_EBADIMAGE; @@ -518,10 +519,16 @@ send_boot_request(uint8_t magic, bool confirm, int image_id, uint32_t slot_id) if ((magic == BOOT_MAGIC_GOOD) || (magic == BOOT_MAGIC_UNSET)) { if (confirm) { BOOT_LOG_DBG("Confirm image: %d, %d", image_id, slot_id); - rc = boot_request_confirm_slot(image_id, slot_id); + if ((image_ok != BOOT_FLAG_SET) || (magic != BOOT_MAGIC_GOOD)) { + rc = boot_request_confirm_slot(image_id, slot_id); + } else { + rc = 0; + } +#ifdef CONFIG_NCS_MCUBOOT_BOOT_REQUEST_TEST_SETS_BOOT_PREFERENCE } else { BOOT_LOG_DBG("Set image preference: %d, %d", image_id, slot_id); rc = boot_request_set_preferred_slot(image_id, slot_id); +#endif /* CONFIG_NCS_MCUBOOT_BOOT_REQUEST_TEST_SETS_BOOT_PREFERENCE */ } if (rc != 0) { rc = BOOT_EBADIMAGE; @@ -594,7 +601,8 @@ boot_set_next(const struct flash_area *fa, bool active, bool confirm) image_id = flash_area_to_image_slot(fa, &slot_id); #ifdef SEND_BOOT_REQUEST - rc = send_boot_request(slot_state.magic, confirm, image_id, slot_id); + rc = send_boot_request(slot_state.magic, slot_state.image_ok, confirm, + image_id, slot_id); if ((rc != 0) || active) { return rc; } @@ -686,7 +694,8 @@ boot_set_next(const struct flash_area *fa, bool active, bool confirm) #ifdef SEND_BOOT_REQUEST image_id = flash_area_to_image_slot(fa, &slot_id); - rc = send_boot_request(slot_state.magic, confirm, image_id, slot_id); + rc = send_boot_request(slot_state.magic, slot_state.image_ok, confirm, + image_id, slot_id); if ((rc != 0) || active) { return rc; } diff --git a/boot/zephyr/Kconfig b/boot/zephyr/Kconfig index a94c7e1e5..3679373f5 100644 --- a/boot/zephyr/Kconfig +++ b/boot/zephyr/Kconfig @@ -1372,4 +1372,15 @@ config NCS_MCUBOOT_IMG_VALIDATE_ATTEMPT_WAIT_MS Time between image validation attempts, in milliseconds. Allows for recovery from transient bit flips or similar situations. +config NCS_MCUBOOT_BOOT_REQUEST_TEST_SETS_BOOT_PREFERENCE + bool "Set boot preference if a slot is marked for test" + help + This option allows to verify boot preference requests through issuing + the image test. + Using this option is not recommended in production systems, because + it will boot any newly transferred image, even if it has a lower + version than the current one. + The rollback protection (using security counters) will still be + effective. + source "Kconfig.zephyr" From 391f093019ebcf74bf460b1be4120f2816fa9eb9 Mon Sep 17 00:00:00 2001 From: Michal Kozikowski Date: Fri, 22 Aug 2025 12:59:08 +0200 Subject: [PATCH 127/420] [nrf noup] Support for ed25519 signature verification using ITS Thic commit introduces support for ed25519 signature verification when CONFIG_NCS_BOOT_SIGNATURE_USING_ITS is set (through PSA API). Signed-off-by: Michal Kozikowski --- boot/bootutil/src/ed25519_psa.c | 38 ++++++++++++++++++++---------- boot/bootutil/src/image_ed25519.c | 6 +++-- boot/bootutil/src/image_validate.c | 6 ++--- 3 files changed, 32 insertions(+), 18 deletions(-) diff --git a/boot/bootutil/src/ed25519_psa.c b/boot/bootutil/src/ed25519_psa.c index 6393d996e..8460da7c8 100644 --- a/boot/bootutil/src/ed25519_psa.c +++ b/boot/bootutil/src/ed25519_psa.c @@ -26,22 +26,35 @@ BOOT_LOG_MODULE_REGISTER(ed25519_psa); #if defined(CONFIG_BOOT_SIGNATURE_USING_KMU) /* List of KMU stored key ids available for MCUboot */ #define MAKE_PSA_KMU_KEY_ID(id) PSA_KEY_HANDLE_FROM_CRACEN_KMU_SLOT(CRACEN_KMU_KEY_USAGE_SCHEME_RAW, id) -static psa_key_id_t kmu_key_ids[3] = { +static psa_key_id_t key_ids[] = { MAKE_PSA_KMU_KEY_ID(226), MAKE_PSA_KMU_KEY_ID(228), MAKE_PSA_KMU_KEY_ID(230) }; +#define KEY_SLOTS_COUNT CONFIG_BOOT_SIGNATURE_KMU_SLOTS + #if defined(CONFIG_BOOT_KMU_KEYS_REVOCATION) #include static psa_key_id_t *validated_with = NULL; #endif -BUILD_ASSERT(CONFIG_BOOT_SIGNATURE_KMU_SLOTS <= ARRAY_SIZE(kmu_key_ids), +BUILD_ASSERT(CONFIG_BOOT_SIGNATURE_KMU_SLOTS <= ARRAY_SIZE(key_ids), "Invalid number of KMU slots, up to 3 are supported on nRF54L15"); #endif -#if !defined(CONFIG_BOOT_SIGNATURE_USING_KMU) +#if defined(CONFIG_NCS_BOOT_SIGNATURE_USING_ITS) +static const psa_key_id_t key_ids[] = { + 0x40022100, + 0x40022101, + 0x40022102, + 0x40022103 +}; + +#define KEY_SLOTS_COUNT ARRAY_SIZE(key_ids) +#endif + +#if !defined(CONFIG_BOOT_SIGNATURE_USING_KMU) && !defined(CONFIG_NCS_BOOT_SIGNATURE_USING_ITS) int ED25519_verify(const uint8_t *message, size_t message_len, const uint8_t signature[EDDSA_SIGNAGURE_LENGTH], const uint8_t public_key[EDDSA_KEY_LENGTH]) @@ -102,7 +115,6 @@ int ED25519_verify(const uint8_t *message, size_t message_len, ARG_UNUSED(public_key); /* Set to any error */ psa_status_t status = PSA_ERROR_BAD_STATE; - int ret = 0; /* Fail by default */ /* Initialize PSA Crypto */ status = psa_crypto_init(); @@ -113,24 +125,24 @@ int ED25519_verify(const uint8_t *message, size_t message_len, status = PSA_ERROR_BAD_STATE; - for (int i = 0; i < CONFIG_BOOT_SIGNATURE_KMU_SLOTS; ++i) { - psa_key_id_t kid = kmu_key_ids[i]; + for (int i = 0; i < KEY_SLOTS_COUNT; ++i) { + psa_key_id_t kid = key_ids[i]; status = psa_verify_message(kid, PSA_ALG_PURE_EDDSA, message, message_len, signature, EDDSA_SIGNAGURE_LENGTH); if (status == PSA_SUCCESS) { - ret = 1; #if defined(CONFIG_BOOT_KMU_KEYS_REVOCATION) - validated_with = kmu_key_ids + i; + validated_with = key_ids + i; #endif - break; + return 1; } - BOOT_LOG_ERR("ED25519 signature verification failed %d", status); } - return ret; + BOOT_LOG_ERR("ED25519 signature verification failed %d", status); + + return 0; } #if defined(CONFIG_BOOT_KMU_KEYS_REVOCATION) int exec_revoke(void) @@ -149,12 +161,12 @@ int exec_revoke(void) goto out; } for (int i = 0; i < CONFIG_BOOT_SIGNATURE_KMU_SLOTS; i++) { - if ((kmu_key_ids + i) == validated_with) { + if ((key_ids + i) == validated_with) { break; } BOOT_LOG_DBG("Invalidating key ID %d", i); - status = psa_destroy_key(kmu_key_ids[i]); + status = psa_destroy_key(key_ids[i]); if (status == PSA_SUCCESS) { BOOT_LOG_DBG("Success on key ID %d", i); } else { diff --git a/boot/bootutil/src/image_ed25519.c b/boot/bootutil/src/image_ed25519.c index 1a02811e3..177550749 100644 --- a/boot/bootutil/src/image_ed25519.c +++ b/boot/bootutil/src/image_ed25519.c @@ -36,6 +36,7 @@ extern int ED25519_verify(const uint8_t *message, size_t message_len, #if !defined(CONFIG_BOOT_SIGNATURE_USING_KMU) #if !defined(MCUBOOT_KEY_IMPORT_BYPASS_ASN) +#if !defined(CONFIG_NCS_BOOT_SIGNATURE_USING_ITS) /* * Parse the public key used for signing. */ @@ -78,6 +79,7 @@ bootutil_import_key(uint8_t **cp, uint8_t *end) } #endif /* !defined(MCUBOOT_KEY_IMPORT_BYPASS_ASN) */ #endif +#endif /* Signature verification base function. * The function takes buffer of specified length and tries to verify @@ -93,7 +95,7 @@ bootutil_verify(uint8_t *buf, uint32_t blen, int rc; FIH_DECLARE(fih_rc, FIH_FAILURE); uint8_t *pubkey = NULL; -#if !defined(CONFIG_BOOT_SIGNATURE_USING_KMU) +#if !defined(CONFIG_BOOT_SIGNATURE_USING_KMU) && !defined(CONFIG_NCS_BOOT_SIGNATURE_USING_ITS) uint8_t *end; #endif @@ -106,7 +108,7 @@ bootutil_verify(uint8_t *buf, uint32_t blen, goto out; } -#if !defined(CONFIG_BOOT_SIGNATURE_USING_KMU) +#if !defined(CONFIG_BOOT_SIGNATURE_USING_KMU) && !defined(CONFIG_NCS_BOOT_SIGNATURE_USING_ITS) pubkey = (uint8_t *)bootutil_keys[key_id].key; end = pubkey + *bootutil_keys[key_id].len; diff --git a/boot/bootutil/src/image_validate.c b/boot/bootutil/src/image_validate.c index ff6970b64..e7d8d0c19 100644 --- a/boot/bootutil/src/image_validate.c +++ b/boot/bootutil/src/image_validate.c @@ -772,13 +772,13 @@ bootutil_img_validate(struct boot_loader_state *state, case EXPECTED_SIG_TLV: { BOOT_LOG_DBG("bootutil_img_validate: EXPECTED_SIG_TLV == %d", EXPECTED_SIG_TLV); -#if !defined(CONFIG_BOOT_SIGNATURE_USING_KMU) +#if !defined(CONFIG_BOOT_SIGNATURE_USING_KMU) && !defined(CONFIG_NCS_BOOT_SIGNATURE_USING_ITS) /* Ignore this signature if it is out of bounds. */ if (key_id < 0 || key_id >= bootutil_key_cnt) { key_id = -1; continue; } -#endif /* !defined(CONFIG_BOOT_SIGNATURE_USING_KMU) */ +#endif /* !defined(CONFIG_BOOT_SIGNATURE_USING_KMU) && !defined(CONFIG_NCS_BOOT_SIGNATURE_USING_ITS) */ if (!EXPECTED_SIG_LEN(len) || len > sizeof(buf)) { rc = -1; goto out; @@ -1022,7 +1022,7 @@ bootutil_img_validate(struct boot_loader_state *state, if (type == IMAGE_TLV_DECOMP_SIGNATURE) { /* Ignore this signature if it is out of bounds. */ -#if !defined(CONFIG_BOOT_SIGNATURE_USING_KMU) +#if !defined(CONFIG_BOOT_SIGNATURE_USING_KMU) && !defined(CONFIG_NCS_BOOT_SIGNATURE_USING_ITS) if (key_id < 0 || key_id >= bootutil_key_cnt) { key_id = -1; continue; From ad057063149fc695fc32cc9d68872a78a8c647a9 Mon Sep 17 00:00:00 2001 From: Tomasz Chyrowicz Date: Wed, 10 Sep 2025 09:14:04 +0200 Subject: [PATCH 128/420] Revert "[nrf noup] Support for ed25519 signature verification using ITS" This reverts commit 391f093019ebcf74bf460b1be4120f2816fa9eb9. Signed-off-by: Tomasz Chyrowicz --- boot/bootutil/src/ed25519_psa.c | 38 ++++++++++-------------------- boot/bootutil/src/image_ed25519.c | 6 ++--- boot/bootutil/src/image_validate.c | 6 ++--- 3 files changed, 18 insertions(+), 32 deletions(-) diff --git a/boot/bootutil/src/ed25519_psa.c b/boot/bootutil/src/ed25519_psa.c index 8460da7c8..6393d996e 100644 --- a/boot/bootutil/src/ed25519_psa.c +++ b/boot/bootutil/src/ed25519_psa.c @@ -26,35 +26,22 @@ BOOT_LOG_MODULE_REGISTER(ed25519_psa); #if defined(CONFIG_BOOT_SIGNATURE_USING_KMU) /* List of KMU stored key ids available for MCUboot */ #define MAKE_PSA_KMU_KEY_ID(id) PSA_KEY_HANDLE_FROM_CRACEN_KMU_SLOT(CRACEN_KMU_KEY_USAGE_SCHEME_RAW, id) -static psa_key_id_t key_ids[] = { +static psa_key_id_t kmu_key_ids[3] = { MAKE_PSA_KMU_KEY_ID(226), MAKE_PSA_KMU_KEY_ID(228), MAKE_PSA_KMU_KEY_ID(230) }; -#define KEY_SLOTS_COUNT CONFIG_BOOT_SIGNATURE_KMU_SLOTS - #if defined(CONFIG_BOOT_KMU_KEYS_REVOCATION) #include static psa_key_id_t *validated_with = NULL; #endif -BUILD_ASSERT(CONFIG_BOOT_SIGNATURE_KMU_SLOTS <= ARRAY_SIZE(key_ids), +BUILD_ASSERT(CONFIG_BOOT_SIGNATURE_KMU_SLOTS <= ARRAY_SIZE(kmu_key_ids), "Invalid number of KMU slots, up to 3 are supported on nRF54L15"); #endif -#if defined(CONFIG_NCS_BOOT_SIGNATURE_USING_ITS) -static const psa_key_id_t key_ids[] = { - 0x40022100, - 0x40022101, - 0x40022102, - 0x40022103 -}; - -#define KEY_SLOTS_COUNT ARRAY_SIZE(key_ids) -#endif - -#if !defined(CONFIG_BOOT_SIGNATURE_USING_KMU) && !defined(CONFIG_NCS_BOOT_SIGNATURE_USING_ITS) +#if !defined(CONFIG_BOOT_SIGNATURE_USING_KMU) int ED25519_verify(const uint8_t *message, size_t message_len, const uint8_t signature[EDDSA_SIGNAGURE_LENGTH], const uint8_t public_key[EDDSA_KEY_LENGTH]) @@ -115,6 +102,7 @@ int ED25519_verify(const uint8_t *message, size_t message_len, ARG_UNUSED(public_key); /* Set to any error */ psa_status_t status = PSA_ERROR_BAD_STATE; + int ret = 0; /* Fail by default */ /* Initialize PSA Crypto */ status = psa_crypto_init(); @@ -125,24 +113,24 @@ int ED25519_verify(const uint8_t *message, size_t message_len, status = PSA_ERROR_BAD_STATE; - for (int i = 0; i < KEY_SLOTS_COUNT; ++i) { - psa_key_id_t kid = key_ids[i]; + for (int i = 0; i < CONFIG_BOOT_SIGNATURE_KMU_SLOTS; ++i) { + psa_key_id_t kid = kmu_key_ids[i]; status = psa_verify_message(kid, PSA_ALG_PURE_EDDSA, message, message_len, signature, EDDSA_SIGNAGURE_LENGTH); if (status == PSA_SUCCESS) { + ret = 1; #if defined(CONFIG_BOOT_KMU_KEYS_REVOCATION) - validated_with = key_ids + i; + validated_with = kmu_key_ids + i; #endif - return 1; + break; } + BOOT_LOG_ERR("ED25519 signature verification failed %d", status); } - BOOT_LOG_ERR("ED25519 signature verification failed %d", status); - - return 0; + return ret; } #if defined(CONFIG_BOOT_KMU_KEYS_REVOCATION) int exec_revoke(void) @@ -161,12 +149,12 @@ int exec_revoke(void) goto out; } for (int i = 0; i < CONFIG_BOOT_SIGNATURE_KMU_SLOTS; i++) { - if ((key_ids + i) == validated_with) { + if ((kmu_key_ids + i) == validated_with) { break; } BOOT_LOG_DBG("Invalidating key ID %d", i); - status = psa_destroy_key(key_ids[i]); + status = psa_destroy_key(kmu_key_ids[i]); if (status == PSA_SUCCESS) { BOOT_LOG_DBG("Success on key ID %d", i); } else { diff --git a/boot/bootutil/src/image_ed25519.c b/boot/bootutil/src/image_ed25519.c index 177550749..1a02811e3 100644 --- a/boot/bootutil/src/image_ed25519.c +++ b/boot/bootutil/src/image_ed25519.c @@ -36,7 +36,6 @@ extern int ED25519_verify(const uint8_t *message, size_t message_len, #if !defined(CONFIG_BOOT_SIGNATURE_USING_KMU) #if !defined(MCUBOOT_KEY_IMPORT_BYPASS_ASN) -#if !defined(CONFIG_NCS_BOOT_SIGNATURE_USING_ITS) /* * Parse the public key used for signing. */ @@ -79,7 +78,6 @@ bootutil_import_key(uint8_t **cp, uint8_t *end) } #endif /* !defined(MCUBOOT_KEY_IMPORT_BYPASS_ASN) */ #endif -#endif /* Signature verification base function. * The function takes buffer of specified length and tries to verify @@ -95,7 +93,7 @@ bootutil_verify(uint8_t *buf, uint32_t blen, int rc; FIH_DECLARE(fih_rc, FIH_FAILURE); uint8_t *pubkey = NULL; -#if !defined(CONFIG_BOOT_SIGNATURE_USING_KMU) && !defined(CONFIG_NCS_BOOT_SIGNATURE_USING_ITS) +#if !defined(CONFIG_BOOT_SIGNATURE_USING_KMU) uint8_t *end; #endif @@ -108,7 +106,7 @@ bootutil_verify(uint8_t *buf, uint32_t blen, goto out; } -#if !defined(CONFIG_BOOT_SIGNATURE_USING_KMU) && !defined(CONFIG_NCS_BOOT_SIGNATURE_USING_ITS) +#if !defined(CONFIG_BOOT_SIGNATURE_USING_KMU) pubkey = (uint8_t *)bootutil_keys[key_id].key; end = pubkey + *bootutil_keys[key_id].len; diff --git a/boot/bootutil/src/image_validate.c b/boot/bootutil/src/image_validate.c index e7d8d0c19..ff6970b64 100644 --- a/boot/bootutil/src/image_validate.c +++ b/boot/bootutil/src/image_validate.c @@ -772,13 +772,13 @@ bootutil_img_validate(struct boot_loader_state *state, case EXPECTED_SIG_TLV: { BOOT_LOG_DBG("bootutil_img_validate: EXPECTED_SIG_TLV == %d", EXPECTED_SIG_TLV); -#if !defined(CONFIG_BOOT_SIGNATURE_USING_KMU) && !defined(CONFIG_NCS_BOOT_SIGNATURE_USING_ITS) +#if !defined(CONFIG_BOOT_SIGNATURE_USING_KMU) /* Ignore this signature if it is out of bounds. */ if (key_id < 0 || key_id >= bootutil_key_cnt) { key_id = -1; continue; } -#endif /* !defined(CONFIG_BOOT_SIGNATURE_USING_KMU) && !defined(CONFIG_NCS_BOOT_SIGNATURE_USING_ITS) */ +#endif /* !defined(CONFIG_BOOT_SIGNATURE_USING_KMU) */ if (!EXPECTED_SIG_LEN(len) || len > sizeof(buf)) { rc = -1; goto out; @@ -1022,7 +1022,7 @@ bootutil_img_validate(struct boot_loader_state *state, if (type == IMAGE_TLV_DECOMP_SIGNATURE) { /* Ignore this signature if it is out of bounds. */ -#if !defined(CONFIG_BOOT_SIGNATURE_USING_KMU) && !defined(CONFIG_NCS_BOOT_SIGNATURE_USING_ITS) +#if !defined(CONFIG_BOOT_SIGNATURE_USING_KMU) if (key_id < 0 || key_id >= bootutil_key_cnt) { key_id = -1; continue; From e48db320f8dd42d4fd2f60a0ad7a0f36e212c3fc Mon Sep 17 00:00:00 2001 From: Tomasz Chyrowicz Date: Mon, 25 Aug 2025 15:22:31 +0200 Subject: [PATCH 129/420] Revert "[nrf noup] boot: Use NCS_ prefix for sdk-nrf specific Kconfigs" This reverts commit 4bfb139af4fadbc651ea61e27d21331834ce2307. Signed-off-by: Tomasz Chyrowicz --- boot/bootutil/include/bootutil/crypto/ecdsa.h | 6 +++--- boot/zephyr/Kconfig | 4 ++-- boot/zephyr/include/mcuboot_config/mcuboot_config.h | 2 +- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/boot/bootutil/include/bootutil/crypto/ecdsa.h b/boot/bootutil/include/bootutil/crypto/ecdsa.h index 0e9205c29..31d7bec9a 100644 --- a/boot/bootutil/include/bootutil/crypto/ecdsa.h +++ b/boot/bootutil/include/bootutil/crypto/ecdsa.h @@ -473,7 +473,7 @@ static int bootutil_ecdsa_parse_public_key(bootutil_ecdsa_context *ctx, } #endif /* !MCUBOOT_BUILTIN_KEY */ -#if !defined(CONFIG_NCS_BOOT_SIGNATURE_USING_ITS) +#if !defined(CONFIG_NRF_BOOT_SIGNATURE_USING_ITS) /* Verify the signature against the provided hash. The signature gets parsed from * the encoding first, then PSA Crypto has a dedicated API for ECDSA verification */ @@ -492,7 +492,7 @@ static inline int bootutil_ecdsa_verify(bootutil_ecdsa_context *ctx, return (int) psa_verify_hash(ctx->key_id, PSA_ALG_ECDSA(ctx->required_algorithm), hash, hlen, reformatted_signature, 2*ctx->curve_byte_count); } -#else /* !CONFIG_NCS_BOOT_SIGNATURE_USING_ITS */ +#else /* !CONFIG_NRF_BOOT_SIGNATURE_USING_ITS */ static const psa_key_id_t builtin_key_ids[] = { 0x40022100, @@ -539,7 +539,7 @@ static inline int bootutil_ecdsa_verify(bootutil_ecdsa_context *ctx, return status == PSA_SUCCESS ? 0 : 2; } -#endif /* !CONFIG_NCS_BOOT_SIGNATURE_USING_ITS */ +#endif /* !CONFIG_NRF_BOOT_SIGNATURE_USING_ITS */ #elif defined(MCUBOOT_USE_MBED_TLS) diff --git a/boot/zephyr/Kconfig b/boot/zephyr/Kconfig index 3679373f5..758c65212 100644 --- a/boot/zephyr/Kconfig +++ b/boot/zephyr/Kconfig @@ -422,14 +422,14 @@ config BOOT_KMU_KEYS_REVOCATION help Enabling KMU key revocation backend. -config NCS_BOOT_SIGNATURE_USING_ITS +config NRF_BOOT_SIGNATURE_USING_ITS bool "Use ITS stored keys for signature verification" depends on NRF_SECURITY help MCUboot will use keys provisioned to the internal trusted storage for signature verification instead of compiling in key data from a file. -if !BOOT_SIGNATURE_USING_KMU && !NCS_BOOT_SIGNATURE_USING_ITS +if !BOOT_SIGNATURE_USING_KMU && !NRF_BOOT_SIGNATURE_USING_ITS config BOOT_SIGNATURE_KEY_FILE string "PEM key file" diff --git a/boot/zephyr/include/mcuboot_config/mcuboot_config.h b/boot/zephyr/include/mcuboot_config/mcuboot_config.h index d8a8462e0..a269f88b2 100644 --- a/boot/zephyr/include/mcuboot_config/mcuboot_config.h +++ b/boot/zephyr/include/mcuboot_config/mcuboot_config.h @@ -68,7 +68,7 @@ #define MCUBOOT_HW_KEY #endif -#ifdef CONFIG_NCS_BOOT_SIGNATURE_USING_ITS +#ifdef CONFIG_NRF_BOOT_SIGNATURE_USING_ITS #define MCUBOOT_BUILTIN_KEY #endif From 3021ef1b85d2929a549a438210574aaae0702dec Mon Sep 17 00:00:00 2001 From: Tomasz Chyrowicz Date: Mon, 25 Aug 2025 15:24:02 +0200 Subject: [PATCH 130/420] Revert "[nrf noup] Added BOOT_SIGNATURE_USING_ITS for ecdsa configuration" This reverts commit d69621e3032f03ddf462eb3a9d2df5af03955898. Signed-off-by: Tomasz Chyrowicz --- boot/bootutil/include/bootutil/crypto/ecdsa.h | 50 ------------------- boot/bootutil/src/image_validate.c | 3 +- boot/zephyr/Kconfig | 9 +--- .../include/mcuboot_config/mcuboot_config.h | 4 -- 4 files changed, 2 insertions(+), 64 deletions(-) diff --git a/boot/bootutil/include/bootutil/crypto/ecdsa.h b/boot/bootutil/include/bootutil/crypto/ecdsa.h index 31d7bec9a..a5d0f8b1b 100644 --- a/boot/bootutil/include/bootutil/crypto/ecdsa.h +++ b/boot/bootutil/include/bootutil/crypto/ecdsa.h @@ -473,7 +473,6 @@ static int bootutil_ecdsa_parse_public_key(bootutil_ecdsa_context *ctx, } #endif /* !MCUBOOT_BUILTIN_KEY */ -#if !defined(CONFIG_NRF_BOOT_SIGNATURE_USING_ITS) /* Verify the signature against the provided hash. The signature gets parsed from * the encoding first, then PSA Crypto has a dedicated API for ECDSA verification */ @@ -492,55 +491,6 @@ static inline int bootutil_ecdsa_verify(bootutil_ecdsa_context *ctx, return (int) psa_verify_hash(ctx->key_id, PSA_ALG_ECDSA(ctx->required_algorithm), hash, hlen, reformatted_signature, 2*ctx->curve_byte_count); } -#else /* !CONFIG_NRF_BOOT_SIGNATURE_USING_ITS */ - -static const psa_key_id_t builtin_key_ids[] = { - 0x40022100, - 0x40022101, - 0x40022102, - 0x40022103 -}; - -#define BOOT_SIGNATURE_BUILTIN_KEY_SLOTS ARRAY_SIZE(builtin_key_ids) - -static inline int bootutil_ecdsa_verify(bootutil_ecdsa_context *ctx, - uint8_t *pk, size_t pk_len, - uint8_t *hash, size_t hlen, - uint8_t *sig, size_t slen) -{ - (void)pk; - (void)pk_len; - (void)slen; - psa_status_t status = PSA_ERROR_BAD_STATE; - - /* Initialize PSA Crypto */ - status = psa_crypto_init(); - if (status != PSA_SUCCESS) { - BOOT_LOG_ERR("PSA crypto init failed %d", status); - return 1; - } - - uint8_t reformatted_signature[96] = {0}; /* Enough for P-384 signature sizes */ - parse_signature_from_rfc5480_encoding(sig, ctx->curve_byte_count, reformatted_signature); - - status = PSA_ERROR_BAD_STATE; - - for (int i = 0; i < BOOT_SIGNATURE_BUILTIN_KEY_SLOTS; ++i) { - psa_key_id_t kid = builtin_key_ids[i]; - - status = psa_verify_hash(kid, PSA_ALG_ECDSA(ctx->required_algorithm), - hash, hlen, reformatted_signature, 2*ctx->curve_byte_count); - if (status == PSA_SUCCESS) { - break; - } - BOOT_LOG_ERR("ECDSA signature verification failed %d", status); - } - - return status == PSA_SUCCESS ? 0 : 2; -} - -#endif /* !CONFIG_NRF_BOOT_SIGNATURE_USING_ITS */ - #elif defined(MCUBOOT_USE_MBED_TLS) typedef mbedtls_ecdsa_context bootutil_ecdsa_context; diff --git a/boot/bootutil/src/image_validate.c b/boot/bootutil/src/image_validate.c index ff6970b64..7fe7ac771 100644 --- a/boot/bootutil/src/image_validate.c +++ b/boot/bootutil/src/image_validate.c @@ -514,8 +514,7 @@ bootutil_img_validate(struct boot_loader_state *state, #endif ) { -#if (defined(EXPECTED_KEY_TLV) && defined(MCUBOOT_HW_KEY)) || defined(MCUBOOT_HW_ROLLBACK_PROT) || defined(MCUBOOT_DECOMPRESS_IMAGES) \ - || defined(MCUBOOT_BUILTIN_KEY) +#if (defined(EXPECTED_KEY_TLV) && defined(MCUBOOT_HW_KEY)) || defined(MCUBOOT_HW_ROLLBACK_PROT) || defined(MCUBOOT_DECOMPRESS_IMAGES) int image_index = (state == NULL ? 0 : BOOT_CURR_IMG(state)); #endif uint32_t off; diff --git a/boot/zephyr/Kconfig b/boot/zephyr/Kconfig index 758c65212..8081d3618 100644 --- a/boot/zephyr/Kconfig +++ b/boot/zephyr/Kconfig @@ -422,14 +422,7 @@ config BOOT_KMU_KEYS_REVOCATION help Enabling KMU key revocation backend. -config NRF_BOOT_SIGNATURE_USING_ITS - bool "Use ITS stored keys for signature verification" - depends on NRF_SECURITY - help - MCUboot will use keys provisioned to the internal trusted storage for signature - verification instead of compiling in key data from a file. - -if !BOOT_SIGNATURE_USING_KMU && !NRF_BOOT_SIGNATURE_USING_ITS +if !BOOT_SIGNATURE_USING_KMU config BOOT_SIGNATURE_KEY_FILE string "PEM key file" diff --git a/boot/zephyr/include/mcuboot_config/mcuboot_config.h b/boot/zephyr/include/mcuboot_config/mcuboot_config.h index a269f88b2..d565a6aaf 100644 --- a/boot/zephyr/include/mcuboot_config/mcuboot_config.h +++ b/boot/zephyr/include/mcuboot_config/mcuboot_config.h @@ -68,10 +68,6 @@ #define MCUBOOT_HW_KEY #endif -#ifdef CONFIG_NRF_BOOT_SIGNATURE_USING_ITS -#define MCUBOOT_BUILTIN_KEY -#endif - #ifdef CONFIG_BOOT_VALIDATE_SLOT0 #define MCUBOOT_VALIDATE_PRIMARY_SLOT #endif From e589566d02c1325f578d5a4485daa17eb0813536 Mon Sep 17 00:00:00 2001 From: Tomasz Chyrowicz Date: Fri, 1 Aug 2025 17:28:16 +0200 Subject: [PATCH 131/420] Revert "[nrf noup] bootutil: key revocation" This reverts commit 9dacf6dbff98acc4eb93312393eee8a197064ea2. Signed-off-by: Tomasz Chyrowicz --- .../include/bootutil/key_revocation.h | 30 -------------- boot/bootutil/src/ed25519_psa.c | 41 ------------------- boot/bootutil/src/key_revocation.c | 24 ----------- boot/bootutil/src/loader.c | 16 -------- boot/zephyr/CMakeLists.txt | 6 --- boot/zephyr/Kconfig | 12 ------ 6 files changed, 129 deletions(-) delete mode 100644 boot/bootutil/include/bootutil/key_revocation.h delete mode 100644 boot/bootutil/src/key_revocation.c diff --git a/boot/bootutil/include/bootutil/key_revocation.h b/boot/bootutil/include/bootutil/key_revocation.h deleted file mode 100644 index d184c9579..000000000 --- a/boot/bootutil/include/bootutil/key_revocation.h +++ /dev/null @@ -1,30 +0,0 @@ -/* - * Copyright (c) 2025 Nordic Semiconductor ASA - * - * SPDX-License-Identifier: LicenseRef-Nordic-5-Clause - */ - -#ifndef H_KEY_REVOCATION_ -#define H_KEY_REVOCATION_ - -#include - -#ifdef __cplusplus -extern "C" { -#endif - -#define BOOT_KEY_REVOKE_OK 0 -#define BOOT_KEY_REVOKE_NOT_READY 1 -#define BOOT_KEY_REVOKE_INVALID 2 -#define BOOT_KEY_REVOKE_FAILED 2 - - -void allow_revoke(void); - -int revoke(void); - -#ifdef __cplusplus -} -#endif - -#endif diff --git a/boot/bootutil/src/ed25519_psa.c b/boot/bootutil/src/ed25519_psa.c index 6393d996e..7665e4067 100644 --- a/boot/bootutil/src/ed25519_psa.c +++ b/boot/bootutil/src/ed25519_psa.c @@ -32,11 +32,6 @@ static psa_key_id_t kmu_key_ids[3] = { MAKE_PSA_KMU_KEY_ID(230) }; -#if defined(CONFIG_BOOT_KMU_KEYS_REVOCATION) -#include -static psa_key_id_t *validated_with = NULL; -#endif - BUILD_ASSERT(CONFIG_BOOT_SIGNATURE_KMU_SLOTS <= ARRAY_SIZE(kmu_key_ids), "Invalid number of KMU slots, up to 3 are supported on nRF54L15"); #endif @@ -121,9 +116,6 @@ int ED25519_verify(const uint8_t *message, size_t message_len, EDDSA_SIGNAGURE_LENGTH); if (status == PSA_SUCCESS) { ret = 1; -#if defined(CONFIG_BOOT_KMU_KEYS_REVOCATION) - validated_with = kmu_key_ids + i; -#endif break; } @@ -132,37 +124,4 @@ int ED25519_verify(const uint8_t *message, size_t message_len, return ret; } -#if defined(CONFIG_BOOT_KMU_KEYS_REVOCATION) -int exec_revoke(void) -{ - int ret = BOOT_KEY_REVOKE_OK; - psa_status_t status = psa_crypto_init(); - - if (!validated_with) { - ret = BOOT_KEY_REVOKE_INVALID; - goto out; - } - - if (status != PSA_SUCCESS) { - BOOT_LOG_ERR("PSA crypto init failed with error %d", status); - ret = BOOT_KEY_REVOKE_FAILED; - goto out; - } - for (int i = 0; i < CONFIG_BOOT_SIGNATURE_KMU_SLOTS; i++) { - if ((kmu_key_ids + i) == validated_with) { - break; - } - BOOT_LOG_DBG("Invalidating key ID %d", i); - - status = psa_destroy_key(kmu_key_ids[i]); - if (status == PSA_SUCCESS) { - BOOT_LOG_DBG("Success on key ID %d", i); - } else { - BOOT_LOG_ERR("Key invalidation failed with: %d", status); - } - } -out: - return ret; -} -#endif /* CONFIG_BOOT_KMU_KEYS_REVOCATION */ #endif diff --git a/boot/bootutil/src/key_revocation.c b/boot/bootutil/src/key_revocation.c deleted file mode 100644 index 0768a3188..000000000 --- a/boot/bootutil/src/key_revocation.c +++ /dev/null @@ -1,24 +0,0 @@ -/* - * Copyright (c) 2025 Nordic Semiconductor ASA - * - * SPDX-License-Identifier: LicenseRef-Nordic-5-Clause - */ - -#include - -extern int exec_revoke(void); - -static uint8_t ready_to_revoke; - -void allow_revoke(void) -{ - ready_to_revoke = 1; -} - -int revoke(void) -{ - if (ready_to_revoke) { - return exec_revoke(); - } - return BOOT_KEY_REVOKE_NOT_READY; -} diff --git a/boot/bootutil/src/loader.c b/boot/bootutil/src/loader.c index 1a2290769..3e199ad4a 100644 --- a/boot/bootutil/src/loader.c +++ b/boot/bootutil/src/loader.c @@ -80,10 +80,6 @@ int pcd_version_cmp_net(const struct flash_area *fap, struct image_header *hdr); #include "mcuboot_config/mcuboot_config.h" -#if defined(CONFIG_BOOT_KEYS_REVOCATION) -#include "bootutil/key_revocation.h" -#endif - BOOT_LOG_MODULE_DECLARE(mcuboot); static struct boot_loader_state boot_data; @@ -3114,11 +3110,6 @@ context_boot_go(struct boot_loader_state *state, struct boot_rsp *rsp) } } -#if defined(CONFIG_BOOT_KEYS_REVOCATION) - if (BOOT_SWAP_TYPE(state) == BOOT_SWAP_TYPE_NONE) { - allow_revoke(); - } -#endif /* Iterate over all the images. At this point all required update operations * have finished. By the end of the loop each image in the primary slot will * have been re-validated. @@ -3227,13 +3218,6 @@ context_boot_go(struct boot_loader_state *state, struct boot_rsp *rsp) fill_rsp(state, rsp); fih_rc = FIH_SUCCESS; -#if defined(CONFIG_BOOT_KEYS_REVOCATION) - rc = revoke(); - if (rc != BOOT_KEY_REVOKE_OK && - rc != BOOT_KEY_REVOKE_NOT_READY) { - FIH_SET(fih_rc, FIH_FAILURE); - } -#endif /* CONFIG_BOOT_KEYS_REVOCATION */ out: /* * Since the boot_status struct stores plaintext encryption keys, reset diff --git a/boot/zephyr/CMakeLists.txt b/boot/zephyr/CMakeLists.txt index f9e0e70bc..fddf35927 100644 --- a/boot/zephyr/CMakeLists.txt +++ b/boot/zephyr/CMakeLists.txt @@ -104,12 +104,6 @@ if(DEFINED CONFIG_BOOT_SHARE_BACKEND_RETENTION) ) endif() -if(DEFINED CONFIG_BOOT_KEYS_REVOCATION) - zephyr_library_sources( - ${BOOT_DIR}/bootutil/src/key_revocation.c -) -endif() - # Generic bootutil sources and includes. zephyr_library_include_directories(${BOOT_DIR}/bootutil/include) zephyr_library_sources( diff --git a/boot/zephyr/Kconfig b/boot/zephyr/Kconfig index 8081d3618..9b389671b 100644 --- a/boot/zephyr/Kconfig +++ b/boot/zephyr/Kconfig @@ -410,18 +410,6 @@ config BOOT_SIGNATURE_KMU_SLOTS endif -config BOOT_KEYS_REVOCATION - bool "Auto revoke previous gen key" - help - Automatically revoke previous generation key upon new valid key usage. - -config BOOT_KMU_KEYS_REVOCATION - bool - depends on BOOT_KEYS_REVOCATION - default y if BOOT_SIGNATURE_USING_KMU - help - Enabling KMU key revocation backend. - if !BOOT_SIGNATURE_USING_KMU config BOOT_SIGNATURE_KEY_FILE From 3b3436214ce19f62f7eef14543d9da4a6c94ac8c Mon Sep 17 00:00:00 2001 From: Tomasz Chyrowicz Date: Fri, 1 Aug 2025 17:29:48 +0200 Subject: [PATCH 132/420] Revert "[nrf noup] boot: bootutil: Allow configuring number of KMU keys" This reverts commit 373038be7dde47f025974e6591e91d0dad8ab355. Signed-off-by: Tomasz Chyrowicz --- boot/bootutil/src/ed25519_psa.c | 7 ++----- boot/zephyr/Kconfig | 12 ------------ 2 files changed, 2 insertions(+), 17 deletions(-) diff --git a/boot/bootutil/src/ed25519_psa.c b/boot/bootutil/src/ed25519_psa.c index 7665e4067..cd016158b 100644 --- a/boot/bootutil/src/ed25519_psa.c +++ b/boot/bootutil/src/ed25519_psa.c @@ -12,7 +12,6 @@ #include #include -#include #if defined(CONFIG_BOOT_SIGNATURE_USING_KMU) #include #endif @@ -31,9 +30,7 @@ static psa_key_id_t kmu_key_ids[3] = { MAKE_PSA_KMU_KEY_ID(228), MAKE_PSA_KMU_KEY_ID(230) }; - -BUILD_ASSERT(CONFIG_BOOT_SIGNATURE_KMU_SLOTS <= ARRAY_SIZE(kmu_key_ids), - "Invalid number of KMU slots, up to 3 are supported on nRF54L15"); +#define KMU_KEY_COUNT (sizeof(kmu_key_ids)/sizeof(kmu_key_ids[0])) #endif #if !defined(CONFIG_BOOT_SIGNATURE_USING_KMU) @@ -108,7 +105,7 @@ int ED25519_verify(const uint8_t *message, size_t message_len, status = PSA_ERROR_BAD_STATE; - for (int i = 0; i < CONFIG_BOOT_SIGNATURE_KMU_SLOTS; ++i) { + for (int i = 0; i < KMU_KEY_COUNT; ++i) { psa_key_id_t kid = kmu_key_ids[i]; status = psa_verify_message(kid, PSA_ALG_PURE_EDDSA, message, diff --git a/boot/zephyr/Kconfig b/boot/zephyr/Kconfig index 9b389671b..9c2f2871e 100644 --- a/boot/zephyr/Kconfig +++ b/boot/zephyr/Kconfig @@ -398,18 +398,6 @@ config BOOT_SIGNATURE_USING_KMU MCUboot will use keys provisioned to the device key management unit for signature verification instead of compiling in key data from a file. -if BOOT_SIGNATURE_USING_KMU - -config BOOT_SIGNATURE_KMU_SLOTS - int "KMU key slots" - range 1 3 - default 1 - help - Selects the number of KMU key slots (also known as generations) to use when verifying - an image. - -endif - if !BOOT_SIGNATURE_USING_KMU config BOOT_SIGNATURE_KEY_FILE From ca06ffbaf6d5ca3d83c18502aee9fc3e952ae766 Mon Sep 17 00:00:00 2001 From: Tomasz Chyrowicz Date: Fri, 1 Aug 2025 17:30:14 +0200 Subject: [PATCH 133/420] Revert "[nrf noup] bootutil: Add support for KMU stored ED25519 signature key" This reverts commit 26192ca1c9986dd9f50b9e5537bfc38fd2953128. Signed-off-by: Tomasz Chyrowicz --- boot/bootutil/src/ed25519_psa.c | 51 ------------------------------ boot/bootutil/src/image_ed25519.c | 9 +----- boot/bootutil/src/image_validate.c | 12 ++----- boot/zephyr/CMakeLists.txt | 2 +- boot/zephyr/Kconfig | 26 --------------- 5 files changed, 4 insertions(+), 96 deletions(-) diff --git a/boot/bootutil/src/ed25519_psa.c b/boot/bootutil/src/ed25519_psa.c index cd016158b..5b8a4ed7c 100644 --- a/boot/bootutil/src/ed25519_psa.c +++ b/boot/bootutil/src/ed25519_psa.c @@ -12,9 +12,6 @@ #include #include -#if defined(CONFIG_BOOT_SIGNATURE_USING_KMU) -#include -#endif BOOT_LOG_MODULE_REGISTER(ed25519_psa); @@ -22,18 +19,6 @@ BOOT_LOG_MODULE_REGISTER(ed25519_psa); #define EDDSA_KEY_LENGTH 32 #define EDDSA_SIGNAGURE_LENGTH 64 -#if defined(CONFIG_BOOT_SIGNATURE_USING_KMU) -/* List of KMU stored key ids available for MCUboot */ -#define MAKE_PSA_KMU_KEY_ID(id) PSA_KEY_HANDLE_FROM_CRACEN_KMU_SLOT(CRACEN_KMU_KEY_USAGE_SCHEME_RAW, id) -static psa_key_id_t kmu_key_ids[3] = { - MAKE_PSA_KMU_KEY_ID(226), - MAKE_PSA_KMU_KEY_ID(228), - MAKE_PSA_KMU_KEY_ID(230) -}; -#define KMU_KEY_COUNT (sizeof(kmu_key_ids)/sizeof(kmu_key_ids[0])) -#endif - -#if !defined(CONFIG_BOOT_SIGNATURE_USING_KMU) int ED25519_verify(const uint8_t *message, size_t message_len, const uint8_t signature[EDDSA_SIGNAGURE_LENGTH], const uint8_t public_key[EDDSA_KEY_LENGTH]) @@ -86,39 +71,3 @@ int ED25519_verify(const uint8_t *message, size_t message_len, return ret; } -#else -int ED25519_verify(const uint8_t *message, size_t message_len, - const uint8_t signature[EDDSA_SIGNAGURE_LENGTH], - const uint8_t public_key[EDDSA_KEY_LENGTH]) -{ - ARG_UNUSED(public_key); - /* Set to any error */ - psa_status_t status = PSA_ERROR_BAD_STATE; - int ret = 0; /* Fail by default */ - - /* Initialize PSA Crypto */ - status = psa_crypto_init(); - if (status != PSA_SUCCESS) { - BOOT_LOG_ERR("PSA crypto init failed %d", status); - return 0; - } - - status = PSA_ERROR_BAD_STATE; - - for (int i = 0; i < KMU_KEY_COUNT; ++i) { - psa_key_id_t kid = kmu_key_ids[i]; - - status = psa_verify_message(kid, PSA_ALG_PURE_EDDSA, message, - message_len, signature, - EDDSA_SIGNAGURE_LENGTH); - if (status == PSA_SUCCESS) { - ret = 1; - break; - } - - BOOT_LOG_ERR("ED25519 signature verification failed %d", status); - } - - return ret; -} -#endif diff --git a/boot/bootutil/src/image_ed25519.c b/boot/bootutil/src/image_ed25519.c index 1a02811e3..4d83bb3d7 100644 --- a/boot/bootutil/src/image_ed25519.c +++ b/boot/bootutil/src/image_ed25519.c @@ -34,7 +34,6 @@ extern int ED25519_verify(const uint8_t *message, size_t message_len, const uint8_t signature[EDDSA_SIGNATURE_LENGTH], const uint8_t public_key[NUM_ED25519_BYTES]); -#if !defined(CONFIG_BOOT_SIGNATURE_USING_KMU) #if !defined(MCUBOOT_KEY_IMPORT_BYPASS_ASN) /* * Parse the public key used for signing. @@ -77,7 +76,6 @@ bootutil_import_key(uint8_t **cp, uint8_t *end) return 0; } #endif /* !defined(MCUBOOT_KEY_IMPORT_BYPASS_ASN) */ -#endif /* Signature verification base function. * The function takes buffer of specified length and tries to verify @@ -92,10 +90,8 @@ bootutil_verify(uint8_t *buf, uint32_t blen, { int rc; FIH_DECLARE(fih_rc, FIH_FAILURE); - uint8_t *pubkey = NULL; -#if !defined(CONFIG_BOOT_SIGNATURE_USING_KMU) + uint8_t *pubkey; uint8_t *end; -#endif BOOT_LOG_DBG("bootutil_verify: ED25519 key_id %d", (int)key_id); @@ -106,7 +102,6 @@ bootutil_verify(uint8_t *buf, uint32_t blen, goto out; } -#if !defined(CONFIG_BOOT_SIGNATURE_USING_KMU) pubkey = (uint8_t *)bootutil_keys[key_id].key; end = pubkey + *bootutil_keys[key_id].len; @@ -130,8 +125,6 @@ bootutil_verify(uint8_t *buf, uint32_t blen, } pubkey = end - NUM_ED25519_BYTES; -#endif - #endif rc = ED25519_verify(buf, blen, sig, pubkey); diff --git a/boot/bootutil/src/image_validate.c b/boot/bootutil/src/image_validate.c index 7fe7ac771..972580945 100644 --- a/boot/bootutil/src/image_validate.c +++ b/boot/bootutil/src/image_validate.c @@ -292,7 +292,6 @@ bootutil_img_hash(struct boot_loader_state *state, # define KEY_BUF_SIZE (SIG_BUF_SIZE + 24) #endif /* !MCUBOOT_HW_KEY */ -#if !defined(CONFIG_BOOT_SIGNATURE_USING_KMU) #if !defined(MCUBOOT_HW_KEY) static int bootutil_find_key(uint8_t *keyhash, uint8_t keyhash_len) @@ -361,7 +360,6 @@ bootutil_find_key(uint8_t image_index, uint8_t *key, uint16_t key_len) } #endif /* !MCUBOOT_HW_KEY */ #endif /* !MCUBOOT_BUILTIN_KEY */ -#endif /* !defined(CONFIG_BOOT_SIGNATURE_USING_KMU) */ #endif /* EXPECTED_SIG_TLV */ /** @@ -734,7 +732,6 @@ bootutil_img_validate(struct boot_loader_state *state, break; } #endif /* defined(EXPECTED_HASH_TLV) && !defined(MCUBOOT_SIGN_PURE) */ -#if !defined(CONFIG_BOOT_SIGNATURE_USING_KMU) #ifdef EXPECTED_KEY_TLV case EXPECTED_KEY_TLV: { @@ -766,18 +763,15 @@ bootutil_img_validate(struct boot_loader_state *state, break; } #endif /* EXPECTED_KEY_TLV */ -#endif /* !defined(CONFIG_BOOT_SIGNATURE_USING_KMU) */ #ifdef EXPECTED_SIG_TLV case EXPECTED_SIG_TLV: { BOOT_LOG_DBG("bootutil_img_validate: EXPECTED_SIG_TLV == %d", EXPECTED_SIG_TLV); -#if !defined(CONFIG_BOOT_SIGNATURE_USING_KMU) /* Ignore this signature if it is out of bounds. */ if (key_id < 0 || key_id >= bootutil_key_cnt) { key_id = -1; continue; } -#endif /* !defined(CONFIG_BOOT_SIGNATURE_USING_KMU) */ if (!EXPECTED_SIG_LEN(len) || len > sizeof(buf)) { rc = -1; goto out; @@ -952,7 +946,7 @@ bootutil_img_validate(struct boot_loader_state *state, } #ifdef EXPECTED_SIG_TLV -#if !defined(CONFIG_BOOT_SIGNATURE_USING_KMU) && defined(EXPECTED_KEY_TLV) +#ifdef EXPECTED_KEY_TLV rc = bootutil_tlv_iter_begin(&it, hdr, fap, EXPECTED_KEY_TLV, false); if (rc) { goto out; @@ -998,7 +992,7 @@ bootutil_img_validate(struct boot_loader_state *state, */ } } -#endif /* !CONFIG_BOOT_SIGNATURE_USING_KMU && EXPECTED_KEY_TLV */ +#endif /* EXPECTED_KEY_TLV */ rc = bootutil_tlv_iter_begin(&it, hdr, fap, IMAGE_TLV_DECOMP_SIGNATURE, true); if (rc) { @@ -1021,12 +1015,10 @@ bootutil_img_validate(struct boot_loader_state *state, if (type == IMAGE_TLV_DECOMP_SIGNATURE) { /* Ignore this signature if it is out of bounds. */ -#if !defined(CONFIG_BOOT_SIGNATURE_USING_KMU) if (key_id < 0 || key_id >= bootutil_key_cnt) { key_id = -1; continue; } -#endif if (!EXPECTED_SIG_LEN(len) || len > sizeof(buf)) { rc = -1; diff --git a/boot/zephyr/CMakeLists.txt b/boot/zephyr/CMakeLists.txt index fddf35927..4d1cd5301 100644 --- a/boot/zephyr/CMakeLists.txt +++ b/boot/zephyr/CMakeLists.txt @@ -361,7 +361,7 @@ if(CONFIG_MCUBOOT_SERIAL) endif() endif() -if(NOT CONFIG_BOOT_SIGNATURE_USING_KMU AND NOT CONFIG_BOOT_SIGNATURE_KEY_FILE STREQUAL "") +if(NOT CONFIG_BOOT_SIGNATURE_KEY_FILE STREQUAL "") # CONF_FILE points to the KConfig configuration files of the bootloader. foreach (filepath ${CONF_FILE}) file(READ ${filepath} temp_text) diff --git a/boot/zephyr/Kconfig b/boot/zephyr/Kconfig index 9c2f2871e..4794bf53b 100644 --- a/boot/zephyr/Kconfig +++ b/boot/zephyr/Kconfig @@ -384,22 +384,6 @@ endif endchoice -config BOOT_SIGNATURE_USING_KMU - bool "Use KMU stored keys for signature verification" - depends on NRF_SECURITY - depends on CRACEN_LIB_KMU - select PSA_WANT_ALG_GCM - select PSA_WANT_KEY_TYPE_AES - select PSA_WANT_AES_KEY_SIZE_256 - select PSA_WANT_ALG_SP800_108_COUNTER_CMAC - select PSA_WANT_ALG_CMAC - select PSA_WANT_ALG_ECB_NO_PADDING - help - MCUboot will use keys provisioned to the device key management unit for signature - verification instead of compiling in key data from a file. - -if !BOOT_SIGNATURE_USING_KMU - config BOOT_SIGNATURE_KEY_FILE string "PEM key file" default "root-ec-p256.pem" if BOOT_SIGNATURE_TYPE_ECDSA_P256 @@ -417,8 +401,6 @@ config BOOT_SIGNATURE_KEY_FILE with the public key information will be written in a format expected by MCUboot. -endif - config MCUBOOT_CLEANUP_ARM_CORE bool "Perform core cleanup before chain-load the application" depends on CPU_CORTEX_M @@ -455,14 +437,6 @@ config MCUBOOT_INFINITE_LOOP_AFTER_RAM_CLEANUP Verification option that keeps execution in infinite loop after RAM cleanup has been performed. -# Disable MBEDTLS from being selected if NRF_SECURITY is enabled, and use default NRF_SECURITY -# configuration file for MBEDTLS -config MBEDTLS - depends on !NRF_SECURITY - -config NRF_SECURITY - select MBEDTLS_PROMPTLESS - config MBEDTLS_CFG_FILE # It might be awkward to define an Mbed TLS header file when TinyCrypt # is used, but the fact is that Mbed TLS' ASN1 parse module is used From a681ca162450cd16fec8b27d82a6415855eb36ac Mon Sep 17 00:00:00 2001 From: Tomasz Chyrowicz Date: Fri, 1 Aug 2025 17:33:03 +0200 Subject: [PATCH 134/420] Revert "[nrf noup] boot: zephyr: Add experimental selection to compression" This reverts commit 0ae144127f7d9cfca4907e5cec167c8d6643bf28. Signed-off-by: Tomasz Chyrowicz --- boot/zephyr/Kconfig | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/boot/zephyr/Kconfig b/boot/zephyr/Kconfig index 4794bf53b..a3f480168 100644 --- a/boot/zephyr/Kconfig +++ b/boot/zephyr/Kconfig @@ -1154,10 +1154,9 @@ config BOOT_DECOMPRESSION_SUPPORT if BOOT_DECOMPRESSION_SUPPORT menuconfig BOOT_DECOMPRESSION - bool "Decompression [EXPERIMENTAL]" + bool "Decompression" select NRF_COMPRESS_CLEANUP select PM_USE_CONFIG_SRAM_SIZE if SOC_NRF54L15_CPUAPP - select EXPERIMENTAL help If enabled, will include support for compressed images being loaded to the secondary slot which then get decompressed into the primary slot. This mode allows the secondary slot to From e2ca25935f9b2737e7869a2401c827639eb097a0 Mon Sep 17 00:00:00 2001 From: Tomasz Chyrowicz Date: Fri, 1 Aug 2025 17:37:46 +0200 Subject: [PATCH 135/420] Revert "[nrf noup] decompression: Align to changes in nrfcompress API" This reverts commit 002515b349bd8cd4e190af2807c50e88ef8605fd. Signed-off-by: Tomasz Chyrowicz --- boot/zephyr/decompression.c | 65 +++++++++++++------------------------ 1 file changed, 23 insertions(+), 42 deletions(-) diff --git a/boot/zephyr/decompression.c b/boot/zephyr/decompression.c index ce4fe0b2b..87e3d3763 100644 --- a/boot/zephyr/decompression.c +++ b/boot/zephyr/decompression.c @@ -256,6 +256,15 @@ int bootutil_img_hash_decompress(struct boot_loader_state *state, struct image_h goto finish_without_clean; } + rc = compression_lzma->init(NULL); + rc = compression_arm_thumb->init(NULL); + + if (rc) { + BOOT_LOG_ERR("Decompression library fatal error"); + rc = BOOT_EBADSTATUS; + goto finish_without_clean; + } + /* We need a modified header which has the updated sizes, start with the original header */ memcpy(&modified_hdr, hdr, sizeof(modified_hdr)); @@ -267,28 +276,12 @@ int bootutil_img_hash_decompress(struct boot_loader_state *state, struct image_h if (rc) { BOOT_LOG_ERR("Unable to determine decompressed size of compressed image"); rc = BOOT_EBADIMAGE; - goto finish_without_clean; + goto finish; } modified_hdr.ih_flags &= ~COMPRESSIONFLAGS; modified_hdr.ih_img_size = decompressed_image_size; - rc = compression_lzma->init(NULL, decompressed_image_size); - - if (rc) { - BOOT_LOG_ERR("Decompression library fatal error"); - rc = BOOT_EBADSTATUS; - goto finish_without_clean; - } - - rc = compression_arm_thumb->init(NULL, decompressed_image_size); - - if (rc) { - BOOT_LOG_ERR("Decompression library fatal error"); - rc = BOOT_EBADSTATUS; - goto finish; - } - /* Calculate the protected TLV size, these will not include the decompressed * sha/size/signature entries */ @@ -1108,7 +1101,7 @@ int boot_copy_region_decompress(struct boot_loader_state *state, const struct fl if (rc) { BOOT_LOG_ERR("Invalid/missing image decrypted compressed size value"); rc = BOOT_EBADIMAGE; - goto finish_without_clean; + goto finish; } if (IS_ENCRYPTED(hdr)) { @@ -1131,7 +1124,7 @@ int boot_copy_region_decompress(struct boot_loader_state *state, const struct fl */ BOOT_LOG_ERR("Invalid image compression flags: no supported compression found"); rc = BOOT_EBADIMAGE; - goto finish_without_clean; + goto finish; } compression_lzma = nrf_compress_implementation_find(NRF_COMPRESS_TYPE_LZMA); @@ -1142,7 +1135,16 @@ int boot_copy_region_decompress(struct boot_loader_state *state, const struct fl /* Compression library missing or missing required function pointer */ BOOT_LOG_ERR("Decompression library fatal error"); rc = BOOT_EBADSTATUS; - goto finish_without_clean; + goto finish; + } + + rc = compression_lzma->init(NULL); + rc = compression_arm_thumb->init(NULL); + + if (rc) { + BOOT_LOG_ERR("Decompression library fatal error"); + rc = BOOT_EBADSTATUS; + goto finish; } write_alignment = flash_area_align(fap_dst); @@ -1156,28 +1158,12 @@ int boot_copy_region_decompress(struct boot_loader_state *state, const struct fl if (rc) { BOOT_LOG_ERR("Unable to determine decompressed size of compressed image"); rc = BOOT_EBADIMAGE; - goto finish_without_clean; + goto finish; } modified_hdr.ih_flags &= ~COMPRESSIONFLAGS; modified_hdr.ih_img_size = decompressed_image_size; - rc = compression_lzma->init(NULL, decompressed_image_size); - - if (rc) { - BOOT_LOG_ERR("Decompression library fatal error"); - rc = BOOT_EBADSTATUS; - goto finish_without_clean; - } - - rc = compression_arm_thumb->init(NULL, decompressed_image_size); - - if (rc) { - BOOT_LOG_ERR("Decompression library fatal error"); - rc = BOOT_EBADSTATUS; - goto finish; - } - /* Calculate protected TLV size for target image once items are removed */ rc = boot_size_protected_tlvs(hdr, fap_src, &protected_tlv_size); @@ -1471,11 +1457,6 @@ int boot_copy_region_decompress(struct boot_loader_state *state, const struct fl } finish: - /* Clean up decompression system */ - (void)compression_lzma->deinit(NULL); - (void)compression_arm_thumb->deinit(NULL); - -finish_without_clean: memset(decomp_buf, 0, sizeof(decomp_buf)); return rc; From 744c2b16a8d3f51b8e5e5b5409e1f5d1ca0ed86e Mon Sep 17 00:00:00 2001 From: Tomasz Chyrowicz Date: Fri, 1 Aug 2025 17:38:12 +0200 Subject: [PATCH 136/420] Revert "[nrf noup] zephyr: Add support for compressed image updates" This reverts commit 898b9bcb12baf499860ed7eb5d4754f1bbaa4284. Signed-off-by: Tomasz Chyrowicz --- boot/bootutil/src/bootutil_misc.c | 80 +- boot/bootutil/src/image_validate.c | 223 +-- boot/bootutil/src/loader.c | 27 +- boot/zephyr/CMakeLists.txt | 6 - boot/zephyr/Kconfig | 9 +- boot/zephyr/decompression.c | 1505 ----------------- .../include/compression/decompression.h | 103 -- 7 files changed, 24 insertions(+), 1929 deletions(-) delete mode 100644 boot/zephyr/decompression.c delete mode 100644 boot/zephyr/include/compression/decompression.h diff --git a/boot/bootutil/src/bootutil_misc.c b/boot/bootutil/src/bootutil_misc.c index 96be26692..a88ad0dad 100644 --- a/boot/bootutil/src/bootutil_misc.c +++ b/boot/bootutil/src/bootutil_misc.c @@ -47,11 +47,6 @@ #include "swap_priv.h" #endif -#if defined(MCUBOOT_DECOMPRESS_IMAGES) -#include -#include -#endif - BOOT_LOG_MODULE_DECLARE(mcuboot); /* Currently only used by imgmgr */ @@ -487,76 +482,35 @@ boot_read_image_size(struct boot_loader_state *state, int slot, uint32_t *size) fap = BOOT_IMG_AREA(state, slot); assert(fap != NULL); -#ifdef MCUBOOT_DECOMPRESS_IMAGES - if (MUST_DECOMPRESS(fap, BOOT_CURR_IMG(state), boot_img_hdr(state, slot))) { - uint32_t tmp_size = 0; - - rc = bootutil_get_img_decomp_size(boot_img_hdr(state, slot), fap, &tmp_size); - - if (rc) { - rc = BOOT_EBADIMAGE; - goto done; - } - - off = boot_img_hdr(state, slot)->ih_hdr_size + tmp_size; - - rc = boot_size_protected_tlvs(boot_img_hdr(state, slot), fap, &tmp_size); + off = BOOT_TLV_OFF(boot_img_hdr(state, slot)); - if (rc) { - rc = BOOT_EBADIMAGE; - goto done; - } - - off += tmp_size; - - if (flash_area_read(fap, (BOOT_TLV_OFF(boot_img_hdr(state, slot)) + - boot_img_hdr(state, slot)->ih_protect_tlv_size), &info, - sizeof(info))) { - rc = BOOT_EFLASH; - goto done; - } + if (flash_area_read(fap, off, &info, sizeof(info))) { + rc = BOOT_EFLASH; + goto done; + } - if (info.it_magic != IMAGE_TLV_INFO_MAGIC) { + protect_tlv_size = boot_img_hdr(state, slot)->ih_protect_tlv_size; + if (info.it_magic == IMAGE_TLV_PROT_INFO_MAGIC) { + if (protect_tlv_size != info.it_tlv_tot) { rc = BOOT_EBADIMAGE; goto done; } - *size = off + info.it_tlv_tot; - } else { -#else - if (1) { -#endif - off = BOOT_TLV_OFF(boot_img_hdr(state, slot)); - - if (flash_area_read(fap, off, &info, sizeof(info))) { + if (flash_area_read(fap, off + info.it_tlv_tot, &info, sizeof(info))) { rc = BOOT_EFLASH; goto done; } + } else if (protect_tlv_size != 0) { + rc = BOOT_EBADIMAGE; + goto done; + } - protect_tlv_size = boot_img_hdr(state, slot)->ih_protect_tlv_size; - if (info.it_magic == IMAGE_TLV_PROT_INFO_MAGIC) { - if (protect_tlv_size != info.it_tlv_tot) { - rc = BOOT_EBADIMAGE; - goto done; - } - - if (flash_area_read(fap, off + info.it_tlv_tot, &info, sizeof(info))) { - rc = BOOT_EFLASH; - goto done; - } - } else if (protect_tlv_size != 0) { - rc = BOOT_EBADIMAGE; - goto done; - } - - if (info.it_magic != IMAGE_TLV_INFO_MAGIC) { - rc = BOOT_EBADIMAGE; - goto done; - } - - *size = off + protect_tlv_size + info.it_tlv_tot; + if (info.it_magic != IMAGE_TLV_INFO_MAGIC) { + rc = BOOT_EBADIMAGE; + goto done; } + *size = off + protect_tlv_size + info.it_tlv_tot; rc = 0; done: diff --git a/boot/bootutil/src/image_validate.c b/boot/bootutil/src/image_validate.c index 972580945..ac7ad2a04 100644 --- a/boot/bootutil/src/image_validate.c +++ b/boot/bootutil/src/image_validate.c @@ -45,11 +45,6 @@ BOOT_LOG_MODULE_DECLARE(mcuboot); -#if defined(MCUBOOT_DECOMPRESS_IMAGES) -#include -#include -#endif - #ifdef MCUBOOT_ENC_IMAGES #include "bootutil/enc_key.h" #endif @@ -512,7 +507,7 @@ bootutil_img_validate(struct boot_loader_state *state, #endif ) { -#if (defined(EXPECTED_KEY_TLV) && defined(MCUBOOT_HW_KEY)) || defined(MCUBOOT_HW_ROLLBACK_PROT) || defined(MCUBOOT_DECOMPRESS_IMAGES) +#if (defined(EXPECTED_KEY_TLV) && defined(MCUBOOT_HW_KEY)) || defined(MCUBOOT_HW_ROLLBACK_PROT) int image_index = (state == NULL ? 0 : BOOT_CURR_IMG(state)); #endif uint32_t off; @@ -560,67 +555,6 @@ bootutil_img_validate(struct boot_loader_state *state, #endif BOOT_LOG_DBG("bootutil_img_validate: flash area %p", fap); -#ifdef MCUBOOT_DECOMPRESS_IMAGES - /* If the image is compressed, the integrity of the image must also be validated */ - if (MUST_DECOMPRESS(fap, image_index, hdr)) { - bool found_decompressed_size = false; - bool found_decompressed_sha = false; - bool found_decompressed_signature = false; - - rc = bootutil_tlv_iter_begin(&it, hdr, fap, IMAGE_TLV_ANY, true); - if (rc) { - goto out; - } - - if (it.tlv_end > bootutil_max_image_size(state, fap)) { - rc = -1; - goto out; - } - - while (true) { - uint16_t expected_size = 0; - bool *found_flag = NULL; - - rc = bootutil_tlv_iter_next(&it, &off, &len, &type); - if (rc < 0) { - goto out; - } else if (rc > 0) { - break; - } - - switch (type) { - case IMAGE_TLV_DECOMP_SIZE: - expected_size = sizeof(size_t); - found_flag = &found_decompressed_size; - break; - case IMAGE_TLV_DECOMP_SHA: - expected_size = IMAGE_HASH_SIZE; - found_flag = &found_decompressed_sha; - break; - case IMAGE_TLV_DECOMP_SIGNATURE: - found_flag = &found_decompressed_signature; - break; - default: - continue; - }; - - if (type == IMAGE_TLV_DECOMP_SIGNATURE && !EXPECTED_SIG_LEN(len)) { - rc = -1; - goto out; - } else if (type != IMAGE_TLV_DECOMP_SIGNATURE && len != expected_size) { - rc = -1; - goto out; - } - - *found_flag = true; - } - - rc = (!found_decompressed_size || !found_decompressed_sha || !found_decompressed_signature); - if (rc) { - goto out; - } - } -#endif #if defined(EXPECTED_HASH_TLV) && !defined(MCUBOOT_SIGN_PURE) #if defined(MCUBOOT_SWAP_USING_OFFSET) && defined(MCUBOOT_SERIAL_RECOVERY) @@ -887,161 +821,6 @@ bootutil_img_validate(struct boot_loader_state *state, skip_security_counter_check: #endif -#ifdef MCUBOOT_DECOMPRESS_IMAGES - /* Only after all previous verifications have passed, perform a dry-run of the decompression - * and ensure the image is valid - */ - if (!rc && MUST_DECOMPRESS(fap, image_index, hdr)) { - image_hash_valid = 0; - FIH_SET(valid_signature, FIH_FAILURE); - - rc = bootutil_img_hash_decompress(state, hdr, fap, tmp_buf, tmp_buf_sz, - hash, seed, seed_len); - if (rc) { - goto out; - } - - rc = bootutil_tlv_iter_begin(&it, hdr, fap, IMAGE_TLV_DECOMP_SHA, true); - if (rc) { - goto out; - } - - if (it.tlv_end > bootutil_max_image_size(state, fap)) { - rc = -1; - goto out; - } - - while (true) { - rc = bootutil_tlv_iter_next(&it, &off, &len, &type); - if (rc < 0) { - goto out; - } else if (rc > 0) { - break; - } - - if (type == IMAGE_TLV_DECOMP_SHA) { - /* Verify the image hash. This must always be present. */ - if (len != sizeof(hash)) { - rc = -1; - goto out; - } - rc = LOAD_IMAGE_DATA(hdr, fap, off, buf, sizeof(hash)); - if (rc) { - goto out; - } - - FIH_CALL(boot_fih_memequal, fih_rc, hash, buf, sizeof(hash)); - if (FIH_NOT_EQ(fih_rc, FIH_SUCCESS)) { - FIH_SET(fih_rc, FIH_FAILURE); - goto out; - } - - image_hash_valid = 1; - } - } - - rc = !image_hash_valid; - if (rc) { - goto out; - } - -#ifdef EXPECTED_SIG_TLV -#ifdef EXPECTED_KEY_TLV - rc = bootutil_tlv_iter_begin(&it, hdr, fap, EXPECTED_KEY_TLV, false); - if (rc) { - goto out; - } - - if (it.tlv_end > bootutil_max_image_size(state, fap)) { - rc = -1; - goto out; - } - - while (true) { - rc = bootutil_tlv_iter_next(&it, &off, &len, &type); - if (rc < 0) { - goto out; - } else if (rc > 0) { - break; - } - - if (type == EXPECTED_KEY_TLV) { - /* - * Determine which key we should be checking. - */ - if (len > KEY_BUF_SIZE) { - rc = -1; - goto out; - } -#ifndef MCUBOOT_HW_KEY - rc = LOAD_IMAGE_DATA(hdr, fap, off, buf, len); - if (rc) { - goto out; - } - key_id = bootutil_find_key(buf, len); -#else - rc = LOAD_IMAGE_DATA(hdr, fap, off, key_buf, len); - if (rc) { - goto out; - } - key_id = bootutil_find_key(image_index, key_buf, len); -#endif /* !MCUBOOT_HW_KEY */ - /* - * The key may not be found, which is acceptable. There - * can be multiple signatures, each preceded by a key. - */ - } - } -#endif /* EXPECTED_KEY_TLV */ - - rc = bootutil_tlv_iter_begin(&it, hdr, fap, IMAGE_TLV_DECOMP_SIGNATURE, true); - if (rc) { - goto out; - } - - if (it.tlv_end > bootutil_max_image_size(state, fap)) { - rc = -1; - goto out; - } - - while (true) { - rc = bootutil_tlv_iter_next(&it, &off, &len, &type); - if (rc < 0) { - goto out; - } else if (rc > 0) { - rc = 0; - break; - } - - if (type == IMAGE_TLV_DECOMP_SIGNATURE) { - /* Ignore this signature if it is out of bounds. */ - if (key_id < 0 || key_id >= bootutil_key_cnt) { - key_id = -1; - continue; - } - - if (!EXPECTED_SIG_LEN(len) || len > sizeof(buf)) { - rc = -1; - goto out; - } - rc = LOAD_IMAGE_DATA(hdr, fap, off, buf, len); - if (rc) { - goto out; - } - - FIH_CALL(bootutil_verify_sig, valid_signature, hash, sizeof(hash), - buf, len, key_id); - key_id = -1; - } - } -#endif /* EXPECTED_SIG_TLV */ - } -#endif - -#ifdef EXPECTED_SIG_TLV - FIH_SET(fih_rc, valid_signature); -#endif - out: if (rc) { FIH_SET(fih_rc, FIH_FAILURE); diff --git a/boot/bootutil/src/loader.c b/boot/bootutil/src/loader.c index 3e199ad4a..71fc7d535 100644 --- a/boot/bootutil/src/loader.c +++ b/boot/bootutil/src/loader.c @@ -50,11 +50,6 @@ #include "bootutil/boot_hooks.h" #include "bootutil/mcuboot_status.h" -#if defined(MCUBOOT_DECOMPRESS_IMAGES) -#include -#include -#endif - #ifdef __ZEPHYR__ #include #if defined(CONFIG_NCS_MCUBOOT_IMG_VALIDATE_ATTEMPT_WAIT_MS) @@ -1048,10 +1043,10 @@ boot_is_header_valid(const struct image_header *hdr, const struct flash_area *fa return false; } #else - if (MUST_DECOMPRESS(fap, BOOT_CURR_IMG(state), hdr)) { - if (!boot_is_compressed_header_valid(hdr, fap, state)) { - return false; - } + if ((hdr->ih_flags & IMAGE_F_COMPRESSED_LZMA1) && + (hdr->ih_flags & IMAGE_F_COMPRESSED_LZMA2)) + { + return false; } #endif @@ -1299,7 +1294,6 @@ boot_validate_slot(struct boot_loader_state *state, int slot, * attempts to validate and boot it. */ } - #if !defined(__BOOTSIM__) BOOT_LOG_ERR("Image in the %s slot is not valid!", (slot == BOOT_PRIMARY_SLOT) ? "primary" : "secondary"); @@ -1956,9 +1950,6 @@ boot_copy_region(struct boot_loader_state *state, #else (void)state; #endif -#if defined(MCUBOOT_DECOMPRESS_IMAGES) && !defined(MCUBOOT_ENC_IMAGES) - struct image_header *hdr; -#endif TARGET_STATIC uint8_t buf[BUF_SZ] __attribute__((aligned(4))); @@ -1984,16 +1975,6 @@ boot_copy_region(struct boot_loader_state *state, } #endif -#ifdef MCUBOOT_DECOMPRESS_IMAGES - hdr = boot_img_hdr(state, BOOT_SECONDARY_SLOT); - - if (MUST_DECOMPRESS(fap_src, BOOT_CURR_IMG(state), hdr)) { - /* Use alternative function for compressed images */ - return boot_copy_region_decompress(state, fap_src, fap_dst, off_src, off_dst, sz, buf, - BUF_SZ); - } -#endif - bytes_copied = 0; while (bytes_copied < sz) { if (sz - bytes_copied > sizeof buf) { diff --git a/boot/zephyr/CMakeLists.txt b/boot/zephyr/CMakeLists.txt index 4d1cd5301..e4b5ff0ad 100644 --- a/boot/zephyr/CMakeLists.txt +++ b/boot/zephyr/CMakeLists.txt @@ -334,12 +334,6 @@ if(CONFIG_BOOT_ENCRYPT_EC256 AND NOT CONFIG_BOOT_ECDSA_PSA) ) endif() -if(CONFIG_BOOT_DECOMPRESSION) - zephyr_library_sources( - decompression.c - ) -endif() - if(CONFIG_MCUBOOT_SERIAL) zephyr_sources(${BOOT_DIR}/zephyr/serial_adapter.c) zephyr_sources(${BOOT_DIR}/boot_serial/src/boot_serial.c) diff --git a/boot/zephyr/Kconfig b/boot/zephyr/Kconfig index a3f480168..eeb78f300 100644 --- a/boot/zephyr/Kconfig +++ b/boot/zephyr/Kconfig @@ -1145,9 +1145,6 @@ config BOOT_BANNER_STRING config BOOT_DECOMPRESSION_SUPPORT bool - depends on NRF_COMPRESS && NRF_COMPRESS_DECOMPRESSION && (NRF_COMPRESS_LZMA_VERSION_LZMA1 || NRF_COMPRESS_LZMA_VERSION_LZMA2) - depends on !SINGLE_APPLICATION_SLOT && BOOT_UPGRADE_ONLY - default y help Hidden symbol which should be selected if a system provided decompression support. @@ -1155,8 +1152,6 @@ if BOOT_DECOMPRESSION_SUPPORT menuconfig BOOT_DECOMPRESSION bool "Decompression" - select NRF_COMPRESS_CLEANUP - select PM_USE_CONFIG_SRAM_SIZE if SOC_NRF54L15_CPUAPP help If enabled, will include support for compressed images being loaded to the secondary slot which then get decompressed into the primary slot. This mode allows the secondary slot to @@ -1165,9 +1160,9 @@ menuconfig BOOT_DECOMPRESSION if BOOT_DECOMPRESSION config BOOT_DECOMPRESSION_BUFFER_SIZE - int + int "Write buffer size" range 16 16384 - default NRF_COMPRESS_CHUNK_SIZE + default 4096 help The size of a secondary buffer used for writing decompressed data to the storage device. diff --git a/boot/zephyr/decompression.c b/boot/zephyr/decompression.c deleted file mode 100644 index 87e3d3763..000000000 --- a/boot/zephyr/decompression.c +++ /dev/null @@ -1,1505 +0,0 @@ -/* - * Copyright (c) 2024 Nordic Semiconductor ASA - * - * SPDX-License-Identifier: LicenseRef-Nordic-5-Clause - */ - -#include -#include "compression/decompression.h" -#include "bootutil/crypto/sha.h" -#include "bootutil/bootutil_log.h" - -#if !defined(__BOOTSIM__) -#define TARGET_STATIC static -#else -#define TARGET_STATIC -#endif - -#if defined(MCUBOOT_SIGN_RSA) -#if MCUBOOT_SIGN_RSA_LEN == 2048 -#define EXPECTED_SIG_TLV IMAGE_TLV_RSA2048_PSS -#elif MCUBOOT_SIGN_RSA_LEN == 3072 -#define EXPECTED_SIG_TLV IMAGE_TLV_RSA3072_PSS -#endif -#elif defined(MCUBOOT_SIGN_EC256) || \ - defined(MCUBOOT_SIGN_EC384) || \ - defined(MCUBOOT_SIGN_EC) -#define EXPECTED_SIG_TLV IMAGE_TLV_ECDSA_SIG -#elif defined(MCUBOOT_SIGN_ED25519) -#define EXPECTED_SIG_TLV IMAGE_TLV_ED25519 -#endif - -#define DECOMP_BUF_SIZE CONFIG_BOOT_DECOMPRESSION_BUFFER_SIZE -#if defined(CONFIG_NRF_COMPRESS_ARM_THUMB) -/* Extra buffer space for being able to writeback ARM thumb decompression output, - * which may be of +2 bytes more size than its input. - */ -#define DECOMP_BUF_EXTRA_SIZE 2 -#else -#define DECOMP_BUF_EXTRA_SIZE 0 -#endif -#define DECOMP_BUF_ALLOC_SIZE (DECOMP_BUF_SIZE + DECOMP_BUF_EXTRA_SIZE) - -#define DECRYPTION_BLOCK_SIZE_AES128 16 -#define DECRYPTION_BLOCK_SIZE_AES256 32 - -/* Number of times that consumed data by decompression system can be 0 in a row before aborting */ -#define OFFSET_ZERO_CHECK_TIMES 3 - -BOOT_LOG_MODULE_DECLARE(mcuboot); - -static int boot_sha_protected_tlvs(const struct image_header *hdr, - const struct flash_area *fap_src, uint32_t protected_size, - uint8_t *buf, size_t buf_size, bootutil_sha_context *sha_ctx); - -bool boot_is_compressed_header_valid(const struct image_header *hdr, const struct flash_area *fap, - struct boot_loader_state *state) -{ - /* Image is compressed in secondary slot, need to check if fits into the primary slot */ - bool opened_flash_area = false; - int primary_fa_id; - int rc; - int size_check; - int size; - uint32_t protected_tlvs_size; - uint32_t decompressed_size; - - primary_fa_id = flash_area_id_from_multi_image_slot(BOOT_CURR_IMG(state), BOOT_PRIMARY_SLOT); - - if (primary_fa_id == fap->fa_id) { - BOOT_LOG_ERR("Primary slots cannot be compressed, image: %d", BOOT_CURR_IMG(state)); - return false; - } - - if (BOOT_IMG_AREA(state, BOOT_PRIMARY_SLOT) == NULL) { - opened_flash_area = true; - } - - rc = flash_area_open(primary_fa_id, &BOOT_IMG_AREA(state, BOOT_PRIMARY_SLOT)); - assert(rc == 0); - - size_check = flash_area_get_size(BOOT_IMG_AREA(state, BOOT_PRIMARY_SLOT)); - - if (opened_flash_area) { - (void)flash_area_close(BOOT_IMG_AREA(state, BOOT_PRIMARY_SLOT)); - } - - rc = bootutil_get_img_decomp_size(hdr, fap, &decompressed_size); - - if (rc) { - return false; - } - - if (!boot_u32_safe_add(&size, decompressed_size, hdr->ih_hdr_size)) { - return false; - } - - rc = boot_size_protected_tlvs(hdr, fap, &protected_tlvs_size); - - if (rc) { - return false; - } - - if (!boot_u32_safe_add(&size, size, protected_tlvs_size)) { - return false; - } - - if (size >= size_check) { - BOOT_LOG_ERR("Compressed image too large, decompressed image size: 0x%x, slot size: 0x%x", - size, size_check); - return false; - } - - return true; -} - -static bool is_compression_object_valid(struct nrf_compress_implementation *compression) -{ - if (compression == NULL || compression->init == NULL || compression->deinit == NULL || - compression->decompress_bytes_needed == NULL || compression->decompress == NULL) { - return false; - } - - return true; -} - -#ifdef MCUBOOT_ENC_IMAGES -int bootutil_get_img_decrypted_comp_size(const struct image_header *hdr, - const struct flash_area *fap, uint32_t *img_comp_size) -{ - if (hdr == NULL || fap == NULL || img_comp_size == NULL) { - return BOOT_EBADARGS; - } else if (hdr->ih_protect_tlv_size == 0) { - return BOOT_EBADIMAGE; - } - - if (!IS_ENCRYPTED(hdr)) { - /* Update is not encrypted so use size from header */ - *img_comp_size = hdr->ih_img_size; - } else { - struct image_tlv_iter it; - uint32_t off; - uint16_t len; - int32_t rc; - - rc = bootutil_tlv_iter_begin(&it, hdr, fap, IMAGE_TLV_COMP_DEC_SIZE, true); - - if (rc) { - return rc; - } - - rc = bootutil_tlv_iter_next(&it, &off, &len, NULL); - - if (rc != 0) { - return -1; - } - - if (len != sizeof(*img_comp_size)) { - BOOT_LOG_ERR("Invalid decompressed image size TLV: %d", len); - return BOOT_EBADIMAGE; - } - - rc = LOAD_IMAGE_DATA(hdr, fap, off, img_comp_size, len); - - if (rc) { - BOOT_LOG_ERR("Image data load failed at offset: 0x%x, size: 0x%x, area: %d, rc: %d", - off, len, fap->fa_id, rc); - return BOOT_EFLASH; - } - } - - return 0; -} -#endif - -int bootutil_img_hash_decompress(struct boot_loader_state *state, struct image_header *hdr, - const struct flash_area *fap, uint8_t *tmp_buf, - uint32_t tmp_buf_sz, uint8_t *hash_result, - uint8_t *seed, int seed_len) -{ - int rc; - uint32_t read_pos = 0; - uint32_t write_pos = 0; - uint32_t protected_tlv_size = 0; - uint32_t decompressed_image_size; - uint32_t output_size_total = 0; - struct nrf_compress_implementation *compression_lzma = NULL; - struct nrf_compress_implementation *compression_arm_thumb = NULL; - TARGET_STATIC struct image_header modified_hdr; - bootutil_sha_context sha_ctx; - -#ifdef MCUBOOT_ENC_IMAGES - struct enc_key_data *enc_state; - int image_index; - uint32_t comp_size = 0; - uint8_t decryption_block_size = 0; - - rc = bootutil_get_img_decrypted_comp_size(hdr, fap, &comp_size); - - if (rc) { - BOOT_LOG_ERR("Invalid/missing image decrypted compressed size value"); - rc = BOOT_EBADIMAGE; - goto finish_end; - } - - if (state == NULL) { - enc_state = NULL; - image_index = 0; - } else { - enc_state = BOOT_CURR_ENC(state); - image_index = BOOT_CURR_IMG(state); - } - - /* Encrypted images only exist in the secondary slot */ - if (MUST_DECRYPT(fap, image_index, hdr) && - !boot_enc_valid(enc_state, 1)) { - return -1; - } - - if (MUST_DECRYPT(fap, image_index, hdr)) { - if (hdr->ih_flags & IMAGE_F_ENCRYPTED_AES128) { - decryption_block_size = DECRYPTION_BLOCK_SIZE_AES128; - } else if (hdr->ih_flags & IMAGE_F_ENCRYPTED_AES256) { - decryption_block_size = DECRYPTION_BLOCK_SIZE_AES256; - } else { - LOG_ERR("Unknown decryption block size"); - rc = BOOT_EBADIMAGE; - goto finish_end; - } - } -#endif - - bootutil_sha_init(&sha_ctx); - - /* Setup decompression system */ -#if CONFIG_NRF_COMPRESS_LZMA_VERSION_LZMA1 - if (!(hdr->ih_flags & IMAGE_F_COMPRESSED_LZMA1)) { -#elif CONFIG_NRF_COMPRESS_LZMA_VERSION_LZMA2 - if (!(hdr->ih_flags & IMAGE_F_COMPRESSED_LZMA2)) { -#endif - /* Compressed image does not use the correct compression type which is supported by this - * build - */ - BOOT_LOG_ERR("Invalid image compression flags: no supported compression found"); - rc = BOOT_EBADIMAGE; - goto finish_without_clean; - } - - compression_lzma = nrf_compress_implementation_find(NRF_COMPRESS_TYPE_LZMA); - compression_arm_thumb = nrf_compress_implementation_find(NRF_COMPRESS_TYPE_ARM_THUMB); - - if (!is_compression_object_valid(compression_lzma) || - !is_compression_object_valid(compression_arm_thumb)) { - /* Compression library missing or missing required function pointer */ - BOOT_LOG_ERR("Decompression library fatal error"); - rc = BOOT_EBADSTATUS; - goto finish_without_clean; - } - - rc = compression_lzma->init(NULL); - rc = compression_arm_thumb->init(NULL); - - if (rc) { - BOOT_LOG_ERR("Decompression library fatal error"); - rc = BOOT_EBADSTATUS; - goto finish_without_clean; - } - - /* We need a modified header which has the updated sizes, start with the original header */ - memcpy(&modified_hdr, hdr, sizeof(modified_hdr)); - - /* Extract the decompressed image size from the protected TLV, set it and remove the - * compressed image flags - */ - rc = bootutil_get_img_decomp_size(hdr, fap, &decompressed_image_size); - - if (rc) { - BOOT_LOG_ERR("Unable to determine decompressed size of compressed image"); - rc = BOOT_EBADIMAGE; - goto finish; - } - - modified_hdr.ih_flags &= ~COMPRESSIONFLAGS; - modified_hdr.ih_img_size = decompressed_image_size; - - /* Calculate the protected TLV size, these will not include the decompressed - * sha/size/signature entries - */ - rc = boot_size_protected_tlvs(hdr, fap, &protected_tlv_size); - - if (rc) { - BOOT_LOG_ERR("Unable to determine protected TLV size of compressed image"); - rc = BOOT_EBADIMAGE; - goto finish; - } - - modified_hdr.ih_protect_tlv_size = protected_tlv_size; - bootutil_sha_update(&sha_ctx, &modified_hdr, sizeof(modified_hdr)); - read_pos = sizeof(modified_hdr); - - while (read_pos < modified_hdr.ih_hdr_size) { - uint32_t copy_size = tmp_buf_sz; - - if ((read_pos + copy_size) > modified_hdr.ih_hdr_size) { - copy_size = modified_hdr.ih_hdr_size - read_pos; - } - - rc = flash_area_read(fap, read_pos, tmp_buf, copy_size); - - if (rc != 0) { - BOOT_LOG_ERR("Flash read failed at offset: 0x%x, size: 0x%x, area: %d, rc: %d", - (hdr->ih_hdr_size + read_pos), copy_size, fap->fa_id, rc); - rc = BOOT_EFLASH; - goto finish; - } - - bootutil_sha_update(&sha_ctx, tmp_buf, copy_size); - read_pos += copy_size; - } - - /* Read in compressed data, decompress and add to hash calculation */ - read_pos = 0; - -#ifdef MCUBOOT_ENC_IMAGES - while (read_pos < comp_size) { - uint32_t copy_size = comp_size - read_pos; -#else - while (read_pos < hdr->ih_img_size) { - uint32_t copy_size = hdr->ih_img_size - read_pos; -#endif - uint32_t tmp_off = 0; - uint8_t offset_zero_check = 0; - - if (copy_size > tmp_buf_sz) { - copy_size = tmp_buf_sz; - } - - rc = flash_area_read(fap, (hdr->ih_hdr_size + read_pos), tmp_buf, copy_size); - - if (rc != 0) { - BOOT_LOG_ERR("Flash read failed at offset: 0x%x, size: 0x%x, area: %d, rc: %d", - (hdr->ih_hdr_size + read_pos), copy_size, fap->fa_id, rc); - rc = BOOT_EFLASH; - goto finish; - } - -#ifdef MCUBOOT_ENC_IMAGES - if (MUST_DECRYPT(fap, image_index, hdr)) { - uint8_t dummy_bytes = 0; - - if ((copy_size % decryption_block_size)) { - dummy_bytes = decryption_block_size - (copy_size % decryption_block_size); - memset(&tmp_buf[copy_size], 0x00, dummy_bytes); - } - - boot_enc_decrypt(enc_state, 1, read_pos, (copy_size + dummy_bytes), (read_pos & 0xf), - tmp_buf); - } -#endif - - /* Decompress data in chunks, writing it back with a larger write offset of the primary - * slot than read size of the secondary slot - */ - while (tmp_off < copy_size) { - uint32_t offset = 0; - uint8_t *output = NULL; - uint32_t output_size = 0; - uint32_t chunk_size; - bool last_packet = false; - - chunk_size = compression_lzma->decompress_bytes_needed(NULL); - - if (chunk_size > (copy_size - tmp_off)) { - chunk_size = (copy_size - tmp_off); - } - -#ifdef MCUBOOT_ENC_IMAGES - if ((read_pos + tmp_off + chunk_size) >= comp_size) { -#else - if ((read_pos + tmp_off + chunk_size) >= hdr->ih_img_size) { -#endif - last_packet = true; - } - - rc = compression_lzma->decompress(NULL, &tmp_buf[tmp_off], chunk_size, last_packet, - &offset, &output, &output_size); - - if (rc) { - BOOT_LOG_ERR("Decompression error: %d", rc); - rc = BOOT_EBADSTATUS; - goto finish; - } - - write_pos += output_size; - - if (write_pos > decompressed_image_size) { - BOOT_LOG_ERR("Decompressed image larger than claimed TLV size, at least: %d", - write_pos); - rc = BOOT_EBADIMAGE; - goto finish; - } - - /* Additional dry-run validity checks */ - if (last_packet == true && write_pos == 0) { - /* Last packet and we still have no output, this is a faulty update */ - BOOT_LOG_ERR("All compressed data consumed without any output, image not valid"); - rc = BOOT_EBADIMAGE; - goto finish; - } - - if (offset == 0) { - /* If the decompression system continually consumes 0 bytes, then there is a - * problem with this update image, abort and mark image as bad - */ - if (offset_zero_check >= OFFSET_ZERO_CHECK_TIMES) { - BOOT_LOG_ERR("Decompression system returning no output data, image not valid"); - rc = BOOT_EBADIMAGE; - goto finish; - } - - ++offset_zero_check; - - break; - } else { - offset_zero_check = 0; - } - - /* Copy data to secondary buffer for calculating hash */ - if (output_size > 0) { - if (hdr->ih_flags & IMAGE_F_COMPRESSED_ARM_THUMB_FLT) { - /* Run this through the ARM thumb filter */ - uint32_t offset_arm_thumb = 0; - uint8_t *output_arm_thumb = NULL; - uint32_t processed_size = 0; - uint32_t output_size_arm_thumb = 0; - - while (processed_size < output_size) { - uint32_t current_size = output_size - processed_size; - bool arm_thumb_last_packet = false; - - if (current_size > CONFIG_NRF_COMPRESS_CHUNK_SIZE) { - current_size = CONFIG_NRF_COMPRESS_CHUNK_SIZE; - } - - if (last_packet && (processed_size + current_size) == - output_size) { - arm_thumb_last_packet = true; - } - - rc = compression_arm_thumb->decompress(NULL, &output[processed_size], - current_size, arm_thumb_last_packet, - &offset_arm_thumb, - &output_arm_thumb, - &output_size_arm_thumb); - - if (rc) { - BOOT_LOG_ERR("Decompression error: %d", rc); - rc = BOOT_EBADSTATUS; - goto finish; - } - - bootutil_sha_update(&sha_ctx, output_arm_thumb, output_size_arm_thumb); - output_size_total += output_size_arm_thumb; - processed_size += current_size; - } - } else { - bootutil_sha_update(&sha_ctx, output, output_size); - output_size_total += output_size; - } - } - - tmp_off += offset; - } - - read_pos += copy_size; - } - - if (modified_hdr.ih_img_size != output_size_total) { - BOOT_LOG_ERR("Decompression expected output_size mismatch: %d vs %d", - modified_hdr.ih_img_size, output_size_total); - rc = BOOT_EBADSTATUS; - goto finish; - } - - /* If there are any protected TLVs present, add them after the main decompressed image */ - if (modified_hdr.ih_protect_tlv_size > 0) { - rc = boot_sha_protected_tlvs(hdr, fap, modified_hdr.ih_protect_tlv_size, tmp_buf, - tmp_buf_sz, &sha_ctx); - } - - bootutil_sha_finish(&sha_ctx, hash_result); - -finish: - /* Clean up decompression system */ - (void)compression_lzma->deinit(NULL); - (void)compression_arm_thumb->deinit(NULL); - -finish_without_clean: - bootutil_sha_drop(&sha_ctx); - -#ifdef MCUBOOT_ENC_IMAGES -finish_end: -#endif - return rc; -} - -static int boot_copy_protected_tlvs(const struct image_header *hdr, - const struct flash_area *fap_src, - const struct flash_area *fap_dst, uint32_t off_dst, - uint32_t protected_size, uint8_t *buf, size_t buf_size, - uint16_t *buf_pos, uint32_t *written) -{ - int rc; - uint32_t off; - uint32_t write_pos = 0; - uint16_t len; - uint16_t type; - struct image_tlv_iter it; - struct image_tlv tlv_header; - struct image_tlv_info tlv_info_header = { - .it_magic = IMAGE_TLV_PROT_INFO_MAGIC, - .it_tlv_tot = protected_size, - }; - uint16_t info_size_left = sizeof(tlv_info_header); - - while (info_size_left > 0) { - uint16_t copy_size = buf_size - *buf_pos; - - if (info_size_left > 0 && copy_size > 0) { - uint16_t single_copy_size = copy_size; - uint8_t *tlv_info_header_address = (uint8_t *)&tlv_info_header; - - if (single_copy_size > info_size_left) { - single_copy_size = info_size_left; - } - - memcpy(&buf[*buf_pos], &tlv_info_header_address[sizeof(tlv_info_header) - - info_size_left], single_copy_size); - *buf_pos += single_copy_size; - info_size_left -= single_copy_size; - } - - if (*buf_pos == buf_size) { - rc = flash_area_write(fap_dst, (off_dst + write_pos), buf, *buf_pos); - - if (rc != 0) { - BOOT_LOG_ERR("Flash write failed at offset: 0x%x, size: 0x%x, area: %d, rc: %d", - (off_dst + write_pos), *buf_pos, fap_dst->fa_id, rc); - rc = BOOT_EFLASH; - goto out; - } - - write_pos += *buf_pos; - *buf_pos = 0; - } - } - - rc = bootutil_tlv_iter_begin(&it, hdr, fap_src, IMAGE_TLV_ANY, true); - - if (rc) { - goto out; - } - - while (true) { - rc = bootutil_tlv_iter_next(&it, &off, &len, &type); - - if (rc < 0) { - goto out; - } else if (rc > 0) { - rc = 0; - break; - } - - if (type == IMAGE_TLV_DECOMP_SIZE || type == IMAGE_TLV_DECOMP_SHA || - type == IMAGE_TLV_DECOMP_SIGNATURE || type == IMAGE_TLV_COMP_DEC_SIZE) { - /* Skip these TLVs as they are not needed */ - continue; - } else { - uint16_t header_size_left = sizeof(tlv_header); - uint16_t data_size_left = len; - - tlv_header.it_type = type; - tlv_header.it_len = len; - - while (header_size_left > 0 || data_size_left > 0) { - uint16_t copy_size = buf_size - *buf_pos; - uint8_t *tlv_header_address = (uint8_t *)&tlv_header; - - if (header_size_left > 0 && copy_size > 0) { - uint16_t single_copy_size = copy_size; - - if (single_copy_size > header_size_left) { - single_copy_size = header_size_left; - } - - memcpy(&buf[*buf_pos], &tlv_header_address[sizeof(tlv_header) - - header_size_left], - single_copy_size); - *buf_pos += single_copy_size; - copy_size -= single_copy_size; - header_size_left -= single_copy_size; - } - - if (data_size_left > 0 && copy_size > 0) { - uint16_t single_copy_size = copy_size; - - if (single_copy_size > data_size_left) { - single_copy_size = data_size_left; - } - - rc = LOAD_IMAGE_DATA(hdr, fap_src, (off + (len - data_size_left)), - &buf[*buf_pos], single_copy_size); - - if (rc) { - BOOT_LOG_ERR( - "Image data load failed at offset: 0x%x, size: 0x%x, area: %d, rc: %d", - (off + (len - data_size_left)), single_copy_size, fap_src->fa_id, rc); - goto out; - } - - *buf_pos += single_copy_size; - data_size_left -= single_copy_size; - } - - if (*buf_pos == buf_size) { - rc = flash_area_write(fap_dst, (off_dst + write_pos), buf, *buf_pos); - - if (rc != 0) { - BOOT_LOG_ERR( - "Flash write failed at offset: 0x%x, size: 0x%x, area: %d, rc: %d", - (off_dst + write_pos), *buf_pos, fap_dst->fa_id, rc); - rc = BOOT_EFLASH; - goto out; - } - - write_pos += *buf_pos; - *buf_pos = 0; - } - } - } - } - - *written = write_pos; - -out: - return rc; -} - -static int boot_sha_protected_tlvs(const struct image_header *hdr, - const struct flash_area *fap_src, uint32_t protected_size, - uint8_t *buf, size_t buf_size, bootutil_sha_context *sha_ctx) -{ - int rc; - uint32_t off; - uint16_t len; - uint16_t type; - struct image_tlv_iter it; - struct image_tlv tlv_header; - struct image_tlv_info tlv_info_header = { - .it_magic = IMAGE_TLV_PROT_INFO_MAGIC, - .it_tlv_tot = protected_size, - }; - - bootutil_sha_update(sha_ctx, &tlv_info_header, sizeof(tlv_info_header)); - - rc = bootutil_tlv_iter_begin(&it, hdr, fap_src, IMAGE_TLV_ANY, true); - if (rc) { - goto out; - } - - while (true) { - uint32_t read_off = 0; - - rc = bootutil_tlv_iter_next(&it, &off, &len, &type); - - if (rc < 0) { - goto out; - } else if (rc > 0) { - rc = 0; - break; - } - - if (type == IMAGE_TLV_DECOMP_SIZE || type == IMAGE_TLV_DECOMP_SHA || - type == IMAGE_TLV_DECOMP_SIGNATURE || type == IMAGE_TLV_COMP_DEC_SIZE) { - /* Skip these TLVs as they are not needed */ - continue; - } - - tlv_header.it_type = type; - tlv_header.it_len = len; - - bootutil_sha_update(sha_ctx, &tlv_header, sizeof(tlv_header)); - - while (read_off < len) { - uint32_t copy_size = buf_size; - - if (copy_size > (len - read_off)) { - copy_size = len - read_off; - } - - rc = LOAD_IMAGE_DATA(hdr, fap_src, (off + read_off), buf, copy_size); - - if (rc) { - BOOT_LOG_ERR( - "Image data load failed at offset: 0x%x, size: 0x%x, area: %d, rc: %d", - (off + read_off), copy_size, fap_src->fa_id, rc); - goto out; - } - - bootutil_sha_update(sha_ctx, buf, copy_size); - read_off += copy_size; - } - } - -out: - return rc; -} - -int boot_size_protected_tlvs(const struct image_header *hdr, const struct flash_area *fap, - uint32_t *sz) -{ - int rc = 0; - uint32_t tlv_size; - uint32_t off; - uint16_t len; - uint16_t type; - struct image_tlv_iter it; - - *sz = 0; - tlv_size = hdr->ih_protect_tlv_size; - - rc = bootutil_tlv_iter_begin(&it, hdr, fap, IMAGE_TLV_ANY, true); - - if (rc) { - goto out; - } - - while (true) { - rc = bootutil_tlv_iter_next(&it, &off, &len, &type); - - if (rc < 0) { - goto out; - } else if (rc > 0) { - rc = 0; - break; - } - - if (type == IMAGE_TLV_DECOMP_SIZE || type == IMAGE_TLV_DECOMP_SHA || - type == IMAGE_TLV_DECOMP_SIGNATURE || type == IMAGE_TLV_COMP_DEC_SIZE) { - /* Exclude these TLVs as they will be copied to the unprotected area */ - tlv_size -= len + sizeof(struct image_tlv); - } - } - - if (!rc) { - if (tlv_size == sizeof(struct image_tlv_info)) { - /* If there are no entries then omit protected TLV section entirely */ - tlv_size = 0; - } - - *sz = tlv_size; - } - -out: - return rc; -} - -int boot_size_unprotected_tlvs(const struct image_header *hdr, const struct flash_area *fap, - uint32_t *sz) -{ - int rc = 0; - uint32_t tlv_size; - uint32_t off; - uint16_t len; - uint16_t type; - struct image_tlv_iter it; - - *sz = 0; - tlv_size = sizeof(struct image_tlv_info); - - rc = bootutil_tlv_iter_begin(&it, hdr, fap, IMAGE_TLV_ANY, false); - - if (rc) { - goto out; - } - - while (true) { - rc = bootutil_tlv_iter_next(&it, &off, &len, &type); - - if (rc < 0) { - goto out; - } else if (rc > 0) { - rc = 0; - break; - } else if (bootutil_tlv_iter_is_prot(&it, off) && type != IMAGE_TLV_DECOMP_SHA && - type != IMAGE_TLV_DECOMP_SIGNATURE) { - /* Include size of protected hash and signature as these will be replacing the - * original ones - */ - continue; - } else if (type == EXPECTED_HASH_TLV || type == EXPECTED_SIG_TLV || type == IMAGE_TLV_COMP_DEC_SIZE) { - /* Exclude the original unprotected TLVs for signature and hash, the length of the - * signature of the compressed data might not be the same size as the signaute of the - * decompressed data, as is the case when using ECDSA-P256 - */ - continue; - } - - tlv_size += len + sizeof(struct image_tlv); - } - - if (!rc) { - if (tlv_size == sizeof(struct image_tlv_info)) { - /* If there are no entries in the unprotected TLV section then there is something wrong - * with this image - */ - BOOT_LOG_ERR("No unprotected TLVs in post-decompressed image output, image is invalid"); - rc = BOOT_EBADIMAGE; - goto out; - } - - *sz = tlv_size; - } - -out: - return rc; -} - -static int boot_copy_unprotected_tlvs(const struct image_header *hdr, - const struct flash_area *fap_src, - const struct flash_area *fap_dst, uint32_t off_dst, - uint32_t unprotected_size, uint8_t *buf, size_t buf_size, - uint16_t *buf_pos, uint32_t *written) -{ - int rc; - uint32_t write_pos = 0; - uint32_t off; - uint16_t len; - uint16_t type; - struct image_tlv_iter it; - struct image_tlv_iter it_protected; - struct image_tlv tlv_header; - struct image_tlv_info tlv_info_header = { - .it_magic = IMAGE_TLV_INFO_MAGIC, - .it_tlv_tot = unprotected_size, - }; - uint16_t info_size_left = sizeof(tlv_info_header); - - while (info_size_left > 0) { - uint16_t copy_size = buf_size - *buf_pos; - - if (info_size_left > 0 && copy_size > 0) { - uint16_t single_copy_size = copy_size; - uint8_t *tlv_info_header_address = (uint8_t *)&tlv_info_header; - - if (single_copy_size > info_size_left) { - single_copy_size = info_size_left; - } - - memcpy(&buf[*buf_pos], &tlv_info_header_address[sizeof(tlv_info_header) - - info_size_left], single_copy_size); - *buf_pos += single_copy_size; - info_size_left -= single_copy_size; - } - - if (*buf_pos == buf_size) { - rc = flash_area_write(fap_dst, (off_dst + write_pos), buf, *buf_pos); - - if (rc != 0) { - BOOT_LOG_ERR("Flash write failed at offset: 0x%x, size: 0x%x, area: %d, rc: %d", - (off_dst + write_pos), *buf_pos, fap_dst->fa_id, rc); - rc = BOOT_EFLASH; - goto out; - } - - write_pos += *buf_pos; - *buf_pos = 0; - } - } - - rc = bootutil_tlv_iter_begin(&it, hdr, fap_src, IMAGE_TLV_ANY, false); - if (rc) { - goto out; - } - - while (true) { - uint16_t header_size_left = sizeof(tlv_header); - uint16_t data_size_left; - - rc = bootutil_tlv_iter_next(&it, &off, &len, &type); - if (rc < 0) { - goto out; - } else if (rc > 0) { - rc = 0; - break; - } else if (bootutil_tlv_iter_is_prot(&it, off)) { - /* Skip protected TLVs */ - continue; - } - - /* Change the values of these fields from having the data in the compressed image - * unprotected TLV (which is valid only for the compressed image data) to having the - * fields in the protected TLV section (which is valid for the decompressed image data). - * The compressed data is no longer needed - */ - if (type == EXPECTED_HASH_TLV || type == EXPECTED_SIG_TLV) { - rc = bootutil_tlv_iter_begin(&it_protected, hdr, fap_src, (type == EXPECTED_HASH_TLV ? - IMAGE_TLV_DECOMP_SHA : - IMAGE_TLV_DECOMP_SIGNATURE), - true); - - if (rc) { - goto out; - } - - while (true) { - rc = bootutil_tlv_iter_next(&it_protected, &off, &len, &type); - if (rc < 0) { - goto out; - } else if (rc > 0) { - rc = 0; - break; - } - } - - if (type == IMAGE_TLV_DECOMP_SHA) { - type = EXPECTED_HASH_TLV; - } else { - type = EXPECTED_SIG_TLV; - } - } - - data_size_left = len; - tlv_header.it_type = type; - tlv_header.it_len = len; - - while (header_size_left > 0 || data_size_left > 0) { - uint16_t copy_size = buf_size - *buf_pos; - - if (header_size_left > 0 && copy_size > 0) { - uint16_t single_copy_size = copy_size; - uint8_t *tlv_header_address = (uint8_t *)&tlv_header; - - if (single_copy_size > header_size_left) { - single_copy_size = header_size_left; - } - - memcpy(&buf[*buf_pos], &tlv_header_address[sizeof(tlv_header) - header_size_left], - single_copy_size); - *buf_pos += single_copy_size; - copy_size -= single_copy_size; - header_size_left -= single_copy_size; - } - - if (data_size_left > 0 && copy_size > 0) { - uint16_t single_copy_size = copy_size; - - if (single_copy_size > data_size_left) { - single_copy_size = data_size_left; - } - - rc = LOAD_IMAGE_DATA(hdr, fap_src, (off + len - data_size_left), - &buf[*buf_pos], single_copy_size); - - if (rc) { - BOOT_LOG_ERR( - "Image data load failed at offset: 0x%x, size: 0x%x, area: %d, rc: %d", - (off + (len - data_size_left)), single_copy_size, fap_src->fa_id, rc); - goto out; - } - - *buf_pos += single_copy_size; - data_size_left -= single_copy_size; - } - - if (*buf_pos == buf_size) { - rc = flash_area_write(fap_dst, (off_dst + write_pos), buf, *buf_pos); - - if (rc != 0) { - BOOT_LOG_ERR( - "Flash write failed at offset: 0x%x, size: 0x%x, area: %d, rc: %d", - (off_dst + write_pos), *buf_pos, fap_dst->fa_id, rc); - rc = BOOT_EFLASH; - goto out; - } - - write_pos += *buf_pos; - *buf_pos = 0; - } - } - } - - *written = write_pos; - -out: - return rc; -} - -#if defined(CONFIG_NRF_COMPRESS_ARM_THUMB) -/** - * @brief Helper function for in-place ARM Thumb filtering. - * This function places the decompressed data back into the same buffer - * at the beginning, overwriting the compressed data. WARNING: because - * ARM Thumb filtering can return +-2 more/less bytes than the input, - * the buffer provided needs to have free DECOMP_BUF_EXTRA_SIZE bytes at - * the beginning and provide valid data for filtering after these. - * - * @param[in] arm_thumb_impl Pointer to the ARM Thumb decompression implementation. - * @param[in,out] buf Pointer to the buffer containing the compressed data / filtered data. - * @param[in] buf_size Size of the buffer (including DECOMP_BUF_EXTRA_SIZE bytes at the beginning). - * @param[out] out_size Pointer to a variable where the size of the filtered data will be stored. - * @param[in] last_part Indicates if this is the last part of the data to be filtered. - * - * @return 0 on success, BOOT_EBADSTATUS on error. - */ -static int boot_arm_thumb_filter(struct nrf_compress_implementation * const arm_thumb_impl, - uint8_t *buf, size_t buf_size, size_t *out_size, bool last_part) { - - uint32_t filter_writeback_pos = 0; - uint32_t processed_size = 0; - int rc; - - while (processed_size < (buf_size - DECOMP_BUF_EXTRA_SIZE)) { - uint32_t offset_arm_thumb = 0; - uint32_t output_size_arm_thumb = 0; - uint8_t *output_arm_thumb = NULL; - uint32_t current_size = (buf_size - DECOMP_BUF_EXTRA_SIZE - processed_size); - bool arm_thumb_last_packet = false; - - if (current_size > CONFIG_NRF_COMPRESS_CHUNK_SIZE) { - current_size = CONFIG_NRF_COMPRESS_CHUNK_SIZE; - } - - if (last_part && (processed_size + current_size) == (buf_size - DECOMP_BUF_EXTRA_SIZE)) { - arm_thumb_last_packet = true; - } - - rc = arm_thumb_impl->decompress(NULL, - &buf[processed_size + - DECOMP_BUF_EXTRA_SIZE], - current_size, - arm_thumb_last_packet, - &offset_arm_thumb, - &output_arm_thumb, - &output_size_arm_thumb); - - if (rc) { - BOOT_LOG_ERR("Decompression error: %d", rc); - return BOOT_EBADSTATUS; - } - - if (output_size_arm_thumb > (buf_size - filter_writeback_pos)) { - BOOT_LOG_ERR("Filter writeback position exceeds buffer size"); - return BOOT_EBADSTATUS; - } - - memcpy(&buf[filter_writeback_pos], output_arm_thumb, - output_size_arm_thumb); - filter_writeback_pos += output_size_arm_thumb; - processed_size += offset_arm_thumb; - } - *out_size = filter_writeback_pos; - - return 0; -} -#endif /* CONFIG_NRF_COMPRESS_ARM_THUMB */ - -int boot_copy_region_decompress(struct boot_loader_state *state, const struct flash_area *fap_src, - const struct flash_area *fap_dst, uint32_t off_src, - uint32_t off_dst, uint32_t sz, uint8_t *buf, size_t buf_size) -{ - int rc; - uint32_t pos = 0; - uint16_t decomp_buf_size = 0; - uint16_t write_alignment; - uint32_t write_pos = 0; - uint32_t protected_tlv_size = 0; - uint32_t unprotected_tlv_size = 0; - uint32_t tlv_write_size = 0; - uint32_t decompressed_image_size; - struct nrf_compress_implementation *compression_lzma = NULL; - struct nrf_compress_implementation *compression_arm_thumb = NULL; - struct image_header *hdr; - TARGET_STATIC uint8_t decomp_buf[DECOMP_BUF_ALLOC_SIZE] __attribute__((aligned(4))); - TARGET_STATIC struct image_header modified_hdr; - uint16_t decomp_buf_max_size; - -#if defined(CONFIG_NRF_COMPRESS_ARM_THUMB) - uint8_t unaligned_data_length = 0; -#endif - -#ifdef MCUBOOT_ENC_IMAGES - uint32_t comp_size = 0; - uint8_t decryption_block_size = 0; -#endif - - hdr = boot_img_hdr(state, BOOT_SECONDARY_SLOT); - -#ifdef MCUBOOT_ENC_IMAGES - rc = bootutil_get_img_decrypted_comp_size(hdr, fap_src, &comp_size); - - if (rc) { - BOOT_LOG_ERR("Invalid/missing image decrypted compressed size value"); - rc = BOOT_EBADIMAGE; - goto finish; - } - - if (IS_ENCRYPTED(hdr)) { - if (hdr->ih_flags & IMAGE_F_ENCRYPTED_AES128) { - decryption_block_size = DECRYPTION_BLOCK_SIZE_AES128; - } else if (hdr->ih_flags & IMAGE_F_ENCRYPTED_AES256) { - decryption_block_size = DECRYPTION_BLOCK_SIZE_AES256; - } - } -#endif - - /* Setup decompression system */ -#if CONFIG_NRF_COMPRESS_LZMA_VERSION_LZMA1 - if (!(hdr->ih_flags & IMAGE_F_COMPRESSED_LZMA1)) { -#elif CONFIG_NRF_COMPRESS_LZMA_VERSION_LZMA2 - if (!(hdr->ih_flags & IMAGE_F_COMPRESSED_LZMA2)) { -#endif - /* Compressed image does not use the correct compression type which is supported by this - * build - */ - BOOT_LOG_ERR("Invalid image compression flags: no supported compression found"); - rc = BOOT_EBADIMAGE; - goto finish; - } - - compression_lzma = nrf_compress_implementation_find(NRF_COMPRESS_TYPE_LZMA); - compression_arm_thumb = nrf_compress_implementation_find(NRF_COMPRESS_TYPE_ARM_THUMB); - - if (!is_compression_object_valid(compression_lzma) || - !is_compression_object_valid(compression_arm_thumb)) { - /* Compression library missing or missing required function pointer */ - BOOT_LOG_ERR("Decompression library fatal error"); - rc = BOOT_EBADSTATUS; - goto finish; - } - - rc = compression_lzma->init(NULL); - rc = compression_arm_thumb->init(NULL); - - if (rc) { - BOOT_LOG_ERR("Decompression library fatal error"); - rc = BOOT_EBADSTATUS; - goto finish; - } - - write_alignment = flash_area_align(fap_dst); - - decomp_buf_max_size = DECOMP_BUF_SIZE - (DECOMP_BUF_SIZE % write_alignment); - - memcpy(&modified_hdr, hdr, sizeof(modified_hdr)); - - rc = bootutil_get_img_decomp_size(hdr, fap_src, &decompressed_image_size); - - if (rc) { - BOOT_LOG_ERR("Unable to determine decompressed size of compressed image"); - rc = BOOT_EBADIMAGE; - goto finish; - } - - modified_hdr.ih_flags &= ~COMPRESSIONFLAGS; - modified_hdr.ih_img_size = decompressed_image_size; - - /* Calculate protected TLV size for target image once items are removed */ - rc = boot_size_protected_tlvs(hdr, fap_src, &protected_tlv_size); - - if (rc) { - BOOT_LOG_ERR("Unable to determine protected TLV size of compressed image"); - rc = BOOT_EBADIMAGE; - goto finish; - } - - modified_hdr.ih_protect_tlv_size = protected_tlv_size; - - rc = boot_size_unprotected_tlvs(hdr, fap_src, &unprotected_tlv_size); - - if (rc) { - BOOT_LOG_ERR("Unable to determine unprotected TLV size of compressed image"); - rc = BOOT_EBADIMAGE; - goto finish; - } - - /* Write out the image header first, this should be a multiple of the write size */ - rc = flash_area_write(fap_dst, off_dst, &modified_hdr, sizeof(modified_hdr)); - - if (rc != 0) { - BOOT_LOG_ERR("Flash write failed at offset: 0x%x, size: 0x%x, area: %d, rc: %d", - off_dst, sizeof(modified_hdr), fap_dst->fa_id, rc); - rc = BOOT_EFLASH; - goto finish; - } - - /* Read in, decompress and write out data */ -#ifdef MCUBOOT_ENC_IMAGES - while (pos < comp_size) { - uint32_t copy_size = comp_size - pos; -#else - while (pos < hdr->ih_img_size) { - uint32_t copy_size = hdr->ih_img_size - pos; -#endif - uint32_t tmp_off = 0; - - if (copy_size > buf_size) { - copy_size = buf_size; - } - - rc = flash_area_read(fap_src, off_src + hdr->ih_hdr_size + pos, buf, copy_size); - - if (rc != 0) { - BOOT_LOG_ERR("Flash read failed at offset: 0x%x, size: 0x%x, area: %d, rc: %d", - (off_src + hdr->ih_hdr_size + pos), copy_size, fap_src->fa_id, rc); - rc = BOOT_EFLASH; - goto finish; - } - -#ifdef MCUBOOT_ENC_IMAGES - if (IS_ENCRYPTED(hdr)) { - uint8_t dummy_bytes = 0; - - if ((copy_size % decryption_block_size)) { - dummy_bytes = decryption_block_size - (copy_size % decryption_block_size); - memset(&buf[copy_size], 0x00, dummy_bytes); - } - - boot_enc_decrypt(BOOT_CURR_ENC(state), 1, pos, (copy_size + dummy_bytes), (pos & 0xf), buf); - } -#endif - - /* Decompress data in chunks, writing it back with a larger write offset of the primary - * slot than read size of the secondary slot - */ - while (tmp_off < copy_size) { - uint32_t offset = 0; - uint32_t output_size = 0; - uint32_t chunk_size; - uint32_t compression_buffer_pos = 0; - uint8_t *output = NULL; - bool last_packet = false; - - chunk_size = compression_lzma->decompress_bytes_needed(NULL); - - if (chunk_size > (copy_size - tmp_off)) { - chunk_size = (copy_size - tmp_off); - } - -#ifdef MCUBOOT_ENC_IMAGES - if ((pos + tmp_off + chunk_size) >= comp_size) { -#else - if ((pos + tmp_off + chunk_size) >= hdr->ih_img_size) { -#endif - last_packet = true; - } - - rc = compression_lzma->decompress(NULL, &buf[tmp_off], chunk_size, last_packet, - &offset, &output, &output_size); - - if (rc) { - BOOT_LOG_ERR("Decompression error: %d", rc); - rc = BOOT_EBADSTATUS; - goto finish; - } - - /* Copy data to secondary buffer for writing out */ - while (output_size > 0) { - uint32_t data_size = (decomp_buf_max_size - decomp_buf_size); - - if (data_size > output_size) { - data_size = output_size; - } - -#if defined(CONFIG_NRF_COMPRESS_ARM_THUMB) - if (hdr->ih_flags & IMAGE_F_COMPRESSED_ARM_THUMB_FLT) { - memcpy(&decomp_buf[decomp_buf_size + DECOMP_BUF_EXTRA_SIZE], - &output[compression_buffer_pos], data_size); - } else -#endif - { - memcpy(&decomp_buf[decomp_buf_size], &output[compression_buffer_pos], - data_size); - } - - compression_buffer_pos += data_size; - - decomp_buf_size += data_size; - output_size -= data_size; - - /* Write data out from secondary buffer when it is full */ - if (decomp_buf_size == decomp_buf_max_size) { -#if defined(CONFIG_NRF_COMPRESS_ARM_THUMB) - if (hdr->ih_flags & IMAGE_F_COMPRESSED_ARM_THUMB_FLT) { - - uint32_t filter_output_size; - - /* Run this through the ARM thumb filter */ - rc = boot_arm_thumb_filter(compression_arm_thumb, - &decomp_buf[unaligned_data_length], - decomp_buf_size - unaligned_data_length + DECOMP_BUF_EXTRA_SIZE, - &filter_output_size, - last_packet && output_size == 0); - - if (rc) { - goto finish; - } - - decomp_buf_size = filter_output_size + unaligned_data_length; - unaligned_data_length = decomp_buf_size % write_alignment; - - rc = flash_area_write(fap_dst, - (off_dst + hdr->ih_hdr_size + write_pos), - decomp_buf, - (decomp_buf_size - unaligned_data_length)); - - if (rc != 0) { - BOOT_LOG_ERR( - "Flash write failed at offset: 0x%x, size: 0x%x, area: %d, rc: %d", - (off_dst + hdr->ih_hdr_size + write_pos), - (decomp_buf_size - unaligned_data_length), - fap_dst->fa_id, rc); - rc = BOOT_EFLASH; - goto finish; - } - - memmove(decomp_buf, - &decomp_buf[decomp_buf_size - unaligned_data_length], - unaligned_data_length); - write_pos += decomp_buf_size - unaligned_data_length; - decomp_buf_size = unaligned_data_length; - } else -#endif - { - rc = flash_area_write(fap_dst, (off_dst + hdr->ih_hdr_size + write_pos), - decomp_buf, decomp_buf_max_size); - - if (rc != 0) { - BOOT_LOG_ERR( - "Flash write failed at offset: 0x%x, size: 0x%x, area: %d, rc: %d", - (off_dst + hdr->ih_hdr_size + write_pos), decomp_buf_max_size, - fap_dst->fa_id, rc); - rc = BOOT_EFLASH; - goto finish; - } - - write_pos += decomp_buf_max_size; - decomp_buf_size = 0; - } - } - } - - tmp_off += offset; - } - - pos += copy_size; - } - -#if defined(CONFIG_NRF_COMPRESS_ARM_THUMB) - if (hdr->ih_flags & IMAGE_F_COMPRESSED_ARM_THUMB_FLT && decomp_buf_size > 0) { - /* Extra data that has not been written out that needs ARM thumb filter applied */ - - uint32_t filter_output_size; - - rc = boot_arm_thumb_filter(compression_arm_thumb, - &decomp_buf[unaligned_data_length], - decomp_buf_size - unaligned_data_length + DECOMP_BUF_EXTRA_SIZE, - &filter_output_size, - true); - - if (rc) { - goto finish; - } - - decomp_buf_size = filter_output_size + unaligned_data_length; - - if (decomp_buf_size > decomp_buf_max_size) { - /* It can happen if ARM thumb decompression returned +2 bytes and we had near full - * decomp_buf. We still can hold these additional 2 bytes because of - * DECOMP_BUF_EXTRA_SIZE allocated. */ - - rc = flash_area_write(fap_dst, (off_dst + hdr->ih_hdr_size + write_pos), - decomp_buf, decomp_buf_max_size); - - if (rc != 0) { - BOOT_LOG_ERR("Flash write failed at offset: 0x%x, size: 0x%x, area: %d, rc: %d", - (off_dst + hdr->ih_hdr_size + write_pos), decomp_buf_max_size, - fap_dst->fa_id, rc); - rc = BOOT_EFLASH; - goto finish; - } - memmove(decomp_buf, &decomp_buf[decomp_buf_max_size], - (decomp_buf_size - decomp_buf_max_size)); - - decomp_buf_size = decomp_buf_size - decomp_buf_max_size; - write_pos += decomp_buf_max_size; - } - } -#endif - - /* Clean up decompression system */ - (void)compression_lzma->deinit(NULL); - (void)compression_arm_thumb->deinit(NULL); - - if (protected_tlv_size > 0) { - rc = boot_copy_protected_tlvs(hdr, fap_src, fap_dst, (off_dst + hdr->ih_hdr_size + - write_pos), protected_tlv_size, - decomp_buf, decomp_buf_max_size, &decomp_buf_size, - &tlv_write_size); - - if (rc) { - BOOT_LOG_ERR("Protected TLV copy failure: %d", rc); - goto finish; - } - - write_pos += tlv_write_size; - } - - tlv_write_size = 0; - rc = boot_copy_unprotected_tlvs(hdr, fap_src, fap_dst, (off_dst + hdr->ih_hdr_size + - write_pos), unprotected_tlv_size, - decomp_buf, decomp_buf_max_size, &decomp_buf_size, - &tlv_write_size); - - if (rc) { - BOOT_LOG_ERR("Protected TLV copy failure: %d", rc); - goto finish; - } - - write_pos += tlv_write_size; - - /* Check if we have unwritten data buffered up and, if so, write it out */ - if (decomp_buf_size > 0) { - uint32_t write_padding_size = write_alignment - (decomp_buf_size % write_alignment); - - /* Check if additional write padding should be applied to meet the minimum write size */ - if (write_alignment > 1 && write_padding_size) { - uint8_t flash_erased_value; - - flash_erased_value = flash_area_erased_val(fap_dst); - memset(&decomp_buf[decomp_buf_size], flash_erased_value, write_padding_size); - decomp_buf_size += write_padding_size; - } - - rc = flash_area_write(fap_dst, (off_dst + hdr->ih_hdr_size + write_pos), decomp_buf, - decomp_buf_size); - - if (rc != 0) { - BOOT_LOG_ERR("Flash write failed at offset: 0x%x, size: 0x%x, area: %d, rc: %d", - (off_dst + hdr->ih_hdr_size + write_pos), decomp_buf_size, - fap_dst->fa_id, rc); - rc = BOOT_EFLASH; - goto finish; - } - - write_pos += decomp_buf_size; - decomp_buf_size = 0; - } - -finish: - memset(decomp_buf, 0, sizeof(decomp_buf)); - - return rc; -} - -int bootutil_get_img_decomp_size(const struct image_header *hdr, const struct flash_area *fap, - uint32_t *img_decomp_size) -{ - struct image_tlv_iter it; - uint32_t off; - uint16_t len; - int32_t rc; - - if (hdr == NULL || fap == NULL || img_decomp_size == NULL) { - return BOOT_EBADARGS; - } else if (hdr->ih_protect_tlv_size == 0) { - return BOOT_EBADIMAGE; - } - - rc = bootutil_tlv_iter_begin(&it, hdr, fap, IMAGE_TLV_DECOMP_SIZE, true); - - if (rc) { - return rc; - } - - rc = bootutil_tlv_iter_next(&it, &off, &len, NULL); - - if (rc != 0) { - return -1; - } - - if (len != sizeof(*img_decomp_size)) { - BOOT_LOG_ERR("Invalid decompressed image size TLV: %d", len); - return BOOT_EBADIMAGE; - } - - rc = LOAD_IMAGE_DATA(hdr, fap, off, img_decomp_size, len); - - if (rc) { - BOOT_LOG_ERR("Image data load failed at offset: 0x%x, size: 0x%x, area: %d, rc: %d", - off, len, fap->fa_id, rc); - return BOOT_EFLASH; - } - - return 0; -} diff --git a/boot/zephyr/include/compression/decompression.h b/boot/zephyr/include/compression/decompression.h deleted file mode 100644 index 2104c4eb6..000000000 --- a/boot/zephyr/include/compression/decompression.h +++ /dev/null @@ -1,103 +0,0 @@ -/* - * Copyright (c) 2024 Nordic Semiconductor ASA - * - * SPDX-License-Identifier: LicenseRef-Nordic-5-Clause - */ - -#ifndef H_DECOMPRESSION_ -#define H_DECOMPRESSION_ - -#include -#include -#include -#include "bootutil/bootutil.h" -#include "bootutil/bootutil_public.h" -#include "bootutil/image.h" -#include "../src/bootutil_priv.h" - -#ifdef __cplusplus -extern "C" { -#endif - -/** - * Checks if a compressed image header is valid. - * - * @param hdr Image header. - * @param fap Flash area of the slot. - * @param state Bootloader state object. - * - * @return true if valid; false if invalid. - */ -bool boot_is_compressed_header_valid(const struct image_header *hdr, const struct flash_area *fap, - struct boot_loader_state *state); - -/** - * Reads in compressed image data from a slot, decompresses it and writes it out to a destination - * slot, including corresponding image headers and TLVs. - * - * @param state Bootloader state object. - * @param fap_src Flash area of the source slot. - * @param fap_dst Flash area of the destination slot. - * @param off_src Offset of the source slot to read from (should be 0). - * @param off_dst Offset of the destination slot to write to (should be 0). - * @param sz Size of the source slot data. - * @param buf Temporary buffer for reading data from. - * @param buf_size Size of temporary buffer. - * - * @return 0 on success; nonzero on failure. - */ -int boot_copy_region_decompress(struct boot_loader_state *state, const struct flash_area *fap_src, - const struct flash_area *fap_dst, uint32_t off_src, - uint32_t off_dst, uint32_t sz, uint8_t *buf, size_t buf_size); - -/** - * Gets the total data size (excluding headers and TLVs) of a compressed image when it is - * decompressed. - * - * @param hdr Image header. - * @param fap Flash area of the slot. - * @param img_decomp_size Pointer to variable that will be updated with the decompressed image - * size. - * - * @return 0 on success; nonzero on failure. - */ -int bootutil_get_img_decomp_size(const struct image_header *hdr, const struct flash_area *fap, - uint32_t *img_decomp_size); - -/** - * Calculate MCUboot-compatible image hash of compressed image slot. - * - * @param state MCUboot state. - * @param hdr Image header. - * @param fap Flash area of the slot. - * @param tmp_buf Temporary buffer for reading data from. - * @param tmp_buf_sz Size of temporary buffer. - * @param hash_result Pointer to a variable that will be updated with the image hash. - * @param seed Not currently used, set to NULL. - * @param seed_len Not currently used, set to 0. - * - * @return 0 on success; nonzero on failure. - */ -int bootutil_img_hash_decompress(struct boot_loader_state *state, struct image_header *hdr, - const struct flash_area *fap, uint8_t *tmp_buf, - uint32_t tmp_buf_sz, uint8_t *hash_result, - uint8_t *seed, int seed_len); - -/** - * Calculates the size that the compressed image protected TLV section will occupy once the image - * has been decompressed. - * - * @param hdr Image header. - * @param fap Flash area of the slot. - * @param sz Pointer to variable that will be updated with the protected TLV size. - * - * @return 0 on success; nonzero on failure. - */ -int boot_size_protected_tlvs(const struct image_header *hdr, const struct flash_area *fap_src, - uint32_t *sz); - -#ifdef __cplusplus -} -#endif - -#endif /* H_DECOMPRESSION_ */ From f5b35fc5c09a402762c2cc6cfd2cffebb9d658b9 Mon Sep 17 00:00:00 2001 From: Tomasz Chyrowicz Date: Tue, 9 Sep 2025 11:30:42 +0200 Subject: [PATCH 137/420] Revert "[nrf noup] boot: Improve bootloader request handling" This reverts commit 4292905fb054418de6f43c8437ce9833691f6687. Signed-off-by: Tomasz Chyrowicz --- boot/bootutil/src/bootutil_public.c | 17 ++++------------- boot/zephyr/Kconfig | 11 ----------- 2 files changed, 4 insertions(+), 24 deletions(-) diff --git a/boot/bootutil/src/bootutil_public.c b/boot/bootutil/src/bootutil_public.c index 750157e82..7371a9fe9 100644 --- a/boot/bootutil/src/bootutil_public.c +++ b/boot/bootutil/src/bootutil_public.c @@ -510,8 +510,7 @@ boot_write_copy_done(const struct flash_area *fap) #ifdef SEND_BOOT_REQUEST static int -send_boot_request(uint8_t magic, uint8_t image_ok, bool confirm, int image_id, - uint32_t slot_id) +send_boot_request(uint8_t magic, bool confirm, int image_id, uint32_t slot_id) { int rc = BOOT_EBADIMAGE; @@ -519,16 +518,10 @@ send_boot_request(uint8_t magic, uint8_t image_ok, bool confirm, int image_id, if ((magic == BOOT_MAGIC_GOOD) || (magic == BOOT_MAGIC_UNSET)) { if (confirm) { BOOT_LOG_DBG("Confirm image: %d, %d", image_id, slot_id); - if ((image_ok != BOOT_FLAG_SET) || (magic != BOOT_MAGIC_GOOD)) { - rc = boot_request_confirm_slot(image_id, slot_id); - } else { - rc = 0; - } -#ifdef CONFIG_NCS_MCUBOOT_BOOT_REQUEST_TEST_SETS_BOOT_PREFERENCE + rc = boot_request_confirm_slot(image_id, slot_id); } else { BOOT_LOG_DBG("Set image preference: %d, %d", image_id, slot_id); rc = boot_request_set_preferred_slot(image_id, slot_id); -#endif /* CONFIG_NCS_MCUBOOT_BOOT_REQUEST_TEST_SETS_BOOT_PREFERENCE */ } if (rc != 0) { rc = BOOT_EBADIMAGE; @@ -601,8 +594,7 @@ boot_set_next(const struct flash_area *fa, bool active, bool confirm) image_id = flash_area_to_image_slot(fa, &slot_id); #ifdef SEND_BOOT_REQUEST - rc = send_boot_request(slot_state.magic, slot_state.image_ok, confirm, - image_id, slot_id); + rc = send_boot_request(slot_state.magic, confirm, image_id, slot_id); if ((rc != 0) || active) { return rc; } @@ -694,8 +686,7 @@ boot_set_next(const struct flash_area *fa, bool active, bool confirm) #ifdef SEND_BOOT_REQUEST image_id = flash_area_to_image_slot(fa, &slot_id); - rc = send_boot_request(slot_state.magic, slot_state.image_ok, confirm, - image_id, slot_id); + rc = send_boot_request(slot_state.magic, confirm, image_id, slot_id); if ((rc != 0) || active) { return rc; } diff --git a/boot/zephyr/Kconfig b/boot/zephyr/Kconfig index eeb78f300..c1b0de673 100644 --- a/boot/zephyr/Kconfig +++ b/boot/zephyr/Kconfig @@ -1309,15 +1309,4 @@ config NCS_MCUBOOT_IMG_VALIDATE_ATTEMPT_WAIT_MS Time between image validation attempts, in milliseconds. Allows for recovery from transient bit flips or similar situations. -config NCS_MCUBOOT_BOOT_REQUEST_TEST_SETS_BOOT_PREFERENCE - bool "Set boot preference if a slot is marked for test" - help - This option allows to verify boot preference requests through issuing - the image test. - Using this option is not recommended in production systems, because - it will boot any newly transferred image, even if it has a lower - version than the current one. - The rollback protection (using security counters) will still be - effective. - source "Kconfig.zephyr" From d07da211db15acaf0dfc6813c42d2cb3d7fed78a Mon Sep 17 00:00:00 2001 From: Tomasz Chyrowicz Date: Fri, 29 Aug 2025 17:40:22 +0200 Subject: [PATCH 138/420] Revert "[nrf noup] bootloader: Add bootloader requests" This reverts commit e1f2ab3806ce7ebc7ef34b3fc04272e747590745. Signed-off-by: Tomasz Chyrowicz --- boot/bootutil/include/bootutil/boot_request.h | 105 ------ boot/bootutil/src/bootutil_public.c | 84 +---- boot/bootutil/zephyr/CMakeLists.txt | 5 - .../zephyr/src/boot_request_retention.c | 346 ------------------ boot/zephyr/Kconfig | 4 - boot/zephyr/Kconfig.firmware_loader | 6 - boot/zephyr/Kconfig.serial_recovery | 6 - boot/zephyr/firmware_loader.c | 9 - boot/zephyr/main.c | 53 --- 9 files changed, 5 insertions(+), 613 deletions(-) delete mode 100644 boot/bootutil/include/bootutil/boot_request.h delete mode 100644 boot/bootutil/zephyr/src/boot_request_retention.c diff --git a/boot/bootutil/include/bootutil/boot_request.h b/boot/bootutil/include/bootutil/boot_request.h deleted file mode 100644 index b1e8f891e..000000000 --- a/boot/bootutil/include/bootutil/boot_request.h +++ /dev/null @@ -1,105 +0,0 @@ -/* - * SPDX-License-Identifier: Apache-2.0 - * - * Copyright (c) 2025 Nordic Semiconductor ASA - */ - -#ifndef __BOOT_REQUEST_H__ -#define __BOOT_REQUEST_H__ - -#ifdef __cplusplus -extern "C" { -#endif - -#include -#include - -/** Special value, indicating that there is no preferred slot. */ -#define BOOT_REQUEST_NO_PREFERRED_SLOT UINT32_MAX - -/** - * @brief Request a bootloader to confirm the specified slot of an image. - * - * @param[in] image Image number. - * @param[in] slot Slot number. - * - * @return 0 if requested, negative error code otherwise. - */ -int boot_request_confirm_slot(uint8_t image, uint32_t slot); - -/** - * @brief Request a bootloader to boot the specified slot of an image. - * - * @param[in] image Image number. - * @param[in] slot Slot number. - * - * @return 0 if requested, negative error code otherwise. - */ -int boot_request_set_preferred_slot(uint8_t image, uint32_t slot); - -/** - * @brief Request a bootloader to boot recovery image. - * - * @return 0 if requested, negative error code otherwise. - */ -int boot_request_enter_recovery(void); - -/** - * @brief Request a bootloader to boot firmware loader image. - * - * @return 0 if requested, negative error code otherwise. - */ -int boot_request_enter_firmware_loader(void); - -/** - * @brief Check if there is a request to confirm the specified slot of an image. - * - * @param[in] image Image number. - * @param[in] slot Slot number. - * - * @return true if requested, false otherwise. - */ -bool boot_request_check_confirmed_slot(uint8_t image, uint32_t slot); - -/** - * @brief Find if there is a request to boot certain slot of the specified image. - * - * @param[in] image Image number. - * - * @return slot number if requested, BOOT_REQUEST_NO_PREFERRED_SLOT otherwise. - */ -uint32_t boot_request_get_preferred_slot(uint8_t image); - -/** - * @brief Check if there is a request to boot recovery image. - * - * @return true if requested, false otherwise. - */ -bool boot_request_detect_recovery(void); - -/** - * @brief Check if there is a request to boot firmware loader image. - * - * @return true if requested, false otherwise. - */ -bool boot_request_detect_firmware_loader(void); - -/** - * @brief Initialize boot requests module. - * - * @return 0 if successful, negative error code otherwise. - */ -int boot_request_init(void); - -/** - * @brief Clear/drop all requests. - * - * @return 0 if successful, negative error code otherwise. - */ -int boot_request_clear(void); - -#ifdef __cplusplus -} -#endif - -#endif /* __BOOT_REQUEST_H__ */ diff --git a/boot/bootutil/src/bootutil_public.c b/boot/bootutil/src/bootutil_public.c index 7371a9fe9..8860fca41 100644 --- a/boot/bootutil/src/bootutil_public.c +++ b/boot/bootutil/src/bootutil_public.c @@ -51,11 +51,6 @@ #include "bootutil_priv.h" #include "bootutil_misc.h" -#if defined(CONFIG_NRF_MCUBOOT_BOOT_REQUEST) && !defined(CONFIG_MCUBOOT) -#include -#define SEND_BOOT_REQUEST -#endif /* CONFIG_NRF_MCUBOOT_BOOT_REQUEST && !CONFIG_MCUBOOT */ - #ifdef CONFIG_MCUBOOT BOOT_LOG_MODULE_DECLARE(mcuboot); #else @@ -508,47 +503,16 @@ boot_write_copy_done(const struct flash_area *fap) return boot_write_trailer_flag(fap, off, BOOT_FLAG_SET); } -#ifdef SEND_BOOT_REQUEST -static int -send_boot_request(uint8_t magic, bool confirm, int image_id, uint32_t slot_id) -{ - int rc = BOOT_EBADIMAGE; - - /* Handle write-protected active image. */ - if ((magic == BOOT_MAGIC_GOOD) || (magic == BOOT_MAGIC_UNSET)) { - if (confirm) { - BOOT_LOG_DBG("Confirm image: %d, %d", image_id, slot_id); - rc = boot_request_confirm_slot(image_id, slot_id); - } else { - BOOT_LOG_DBG("Set image preference: %d, %d", image_id, slot_id); - rc = boot_request_set_preferred_slot(image_id, slot_id); - } - if (rc != 0) { - rc = BOOT_EBADIMAGE; - } - } - - return rc; -} -#endif /* SEND_BOOT_REQUEST */ +#ifndef MCUBOOT_BOOTUTIL_LIB_FOR_DIRECT_XIP -#if defined(SEND_BOOT_REQUEST) || (!defined(MCUBOOT_BOOTUTIL_LIB_FOR_DIRECT_XIP)) -static int flash_area_to_image_slot(const struct flash_area *fa, uint32_t *slot) +static int flash_area_to_image(const struct flash_area *fa) { - int id = flash_area_get_id(fa); #if BOOT_IMAGE_NUMBER > 1 uint8_t i = 0; + int id = flash_area_get_id(fa); while (i < BOOT_IMAGE_NUMBER) { - if (FLASH_AREA_IMAGE_PRIMARY(i) == id) { - if (slot != NULL) { - *slot = 0; - } - return i; - } else if (FLASH_AREA_IMAGE_SECONDARY(i) == id) { - if (slot != NULL) { - *slot = 1; - } + if (FLASH_AREA_IMAGE_PRIMARY(i) == id || (FLASH_AREA_IMAGE_SECONDARY(i) == id)) { return i; } @@ -556,31 +520,15 @@ static int flash_area_to_image_slot(const struct flash_area *fa, uint32_t *slot) } #else (void)fa; - if (slot != NULL) { - if (FLASH_AREA_IMAGE_PRIMARY(0) == id) { - *slot = 0; - } else if (FLASH_AREA_IMAGE_SECONDARY(0) == id) { - *slot = 1; - } else { - *slot = UINT32_MAX; - } - } #endif return 0; } -#endif /* defined(SEND_BOOT_REQUEST) || (!defined(MCUBOOT_BOOTUTIL_LIB_FOR_DIRECT_XIP)) */ -#ifndef MCUBOOT_BOOTUTIL_LIB_FOR_DIRECT_XIP int boot_set_next(const struct flash_area *fa, bool active, bool confirm) { struct boot_swap_state slot_state; int rc; - int image_id; - uint32_t slot_id; - - BOOT_LOG_DBG("boot_set_next: fa %p active == %d, confirm == %d", - fa, (int)active, (int)confirm); if (active) { confirm = true; @@ -591,15 +539,6 @@ boot_set_next(const struct flash_area *fa, bool active, bool confirm) return rc; } - image_id = flash_area_to_image_slot(fa, &slot_id); - -#ifdef SEND_BOOT_REQUEST - rc = send_boot_request(slot_state.magic, confirm, image_id, slot_id); - if ((rc != 0) || active) { - return rc; - } -#endif - switch (slot_state.magic) { case BOOT_MAGIC_GOOD: /* If non-active then swap already scheduled, else confirm needed.*/ @@ -630,7 +569,7 @@ boot_set_next(const struct flash_area *fa, bool active, bool confirm) } else { swap_type = BOOT_SWAP_TYPE_TEST; } - rc = boot_write_swap_info(fa, swap_type, image_id); + rc = boot_write_swap_info(fa, swap_type, flash_area_to_image(fa)); } } break; @@ -661,10 +600,6 @@ boot_set_next(const struct flash_area *fa, bool active, bool confirm) { struct boot_swap_state slot_state; int rc; -#ifdef SEND_BOOT_REQUEST - int image_id; - uint32_t slot_id; -#endif BOOT_LOG_DBG("boot_set_next: fa %p active == %d, confirm == %d", fa, (int)active, (int)confirm); @@ -683,15 +618,6 @@ boot_set_next(const struct flash_area *fa, bool active, bool confirm) return rc; } -#ifdef SEND_BOOT_REQUEST - image_id = flash_area_to_image_slot(fa, &slot_id); - - rc = send_boot_request(slot_state.magic, confirm, image_id, slot_id); - if ((rc != 0) || active) { - return rc; - } -#endif - switch (slot_state.magic) { case BOOT_MAGIC_UNSET: /* Magic is needed for MCUboot to even consider booting an image */ diff --git a/boot/bootutil/zephyr/CMakeLists.txt b/boot/bootutil/zephyr/CMakeLists.txt index 111cf4f1d..44f78f395 100644 --- a/boot/bootutil/zephyr/CMakeLists.txt +++ b/boot/bootutil/zephyr/CMakeLists.txt @@ -16,11 +16,6 @@ zephyr_library_named(mcuboot_util) zephyr_library_sources( ../src/bootutil_public.c ) -if(CONFIG_NRF_MCUBOOT_BOOT_REQUEST) - zephyr_library_sources_ifdef(CONFIG_NRF_MCUBOOT_BOOT_REQUEST_IMPL_RETENTION - src/boot_request_retention.c - ) -endif() # Sensitivity to the TEST_BOOT_IMAGE_ACCESS_HOOKS define is implemented for # allowing the test-build with the hooks feature enabled. diff --git a/boot/bootutil/zephyr/src/boot_request_retention.c b/boot/bootutil/zephyr/src/boot_request_retention.c deleted file mode 100644 index 023f5af5e..000000000 --- a/boot/bootutil/zephyr/src/boot_request_retention.c +++ /dev/null @@ -1,346 +0,0 @@ -/* - * SPDX-License-Identifier: Apache-2.0 - * - * Copyright (c) 2025 Nordic Semiconductor ASA - */ -#include - -#include "bootutil/bootutil_log.h" -#include - -/** Special value of image number, indicating a request to the bootloader. */ -#define BOOT_REQUEST_IMG_BOOTLOADER 0xFF - -/** Additional memory used by the retention subsystem (2B - prefix, 4B - CRC).*/ -#define BOOT_REQUEST_ENTRY_METADATA_SIZE (2 + 4) - -MCUBOOT_LOG_MODULE_REGISTER(bootloader_request); - -static const struct device *bootloader_request_dev = - DEVICE_DT_GET(DT_CHOSEN(nrf_bootloader_request)); - -enum boot_request_type { - /** Invalid request. */ - BOOT_REQUEST_INVALID = 0, - - /** Request a change in the bootloader boot mode. - * - * @details Use @p boot_request_mode as argument. - * @p BOOT_REQUEST_IMG_BOOTLOADER as image number. - * - * @note Used to trigger recovery through i.e. retention sybsystem. - */ - BOOT_REQUEST_BOOT_MODE = 1, - - /** Select the preferred image to be selected during boot or update. - * - * @details Use @p boot_request_slot_t as argument. - * - * @note Used in the Direct XIP mode. - */ - BOOT_REQUEST_IMG_PREFERENCE = 2, - - /** Request a confirmation of an image. - * - * @details Use @p boot_request_slot_t as argument. - * - * @note Used if the code cannot modify the image trailer directly. - */ - BOOT_REQUEST_IMG_CONFIRM = 3, -}; - -/* Entries inside the boot request shared memory. */ -enum boot_request_entry { - BOOT_REQUEST_ENTRY_BOOT_MODE = 0, - BOOT_REQUEST_ENTRY_IMAGE_0_PREFERENCE = 1, - BOOT_REQUEST_ENTRY_IMAGE_0_CONFIRM = 2, - BOOT_REQUEST_ENTRY_IMAGE_1_PREFERENCE = 3, - BOOT_REQUEST_ENTRY_IMAGE_1_CONFIRM = 4, - BOOT_REQUEST_ENTRY_MAX = 5, -}; - -/* Assert that all requests will fit within the retention area. */ -BUILD_ASSERT((BOOT_REQUEST_ENTRY_METADATA_SIZE + BOOT_REQUEST_ENTRY_MAX * sizeof(uint8_t)) < - DT_REG_SIZE_BY_IDX(DT_CHOSEN(nrf_bootloader_request), 0), - "nrf,bootloader-request area is too small for bootloader request struct"); - -enum boot_request_slot { - /** Unsupported value. */ - BOOT_REQUEST_SLOT_INVALID = 0, - /** Primary slot. */ - BOOT_REQUEST_SLOT_PRIMARY = 1, - /** Secondary slot. */ - BOOT_REQUEST_SLOT_SECONDARY = 2, -}; - -/** Alias type for the image and number. */ -typedef uint8_t boot_request_slot_t; - -enum boot_request_mode { - /** Execute a regular boot logic. */ - BOOT_REQUEST_MODE_REGULAR = 0, - /** Execute the recovery boot logic. */ - BOOT_REQUEST_MODE_RECOVERY = 1, - /** Execute the firmware loader logic. */ - BOOT_REQUEST_MODE_FIRMWARE_LOADER = 2, - /** Unsupported value. */ - BOOT_REQUEST_MODE_INVALID = 0xFF, -}; - -/** Alias type for the image number. */ -typedef uint8_t boot_request_img_t; - -/** - * @brief Find an entry for a given request. - * - * @param[in] type Type of request. - * @param[in] image Image number. Use @p BOOT_REQUEST_IMG_BOOTLOADER for generic requests. - * @param[out] entry Entry to use. - * - * @return 0 on success; nonzero on failure. - */ -static int boot_request_entry_find(enum boot_request_type type, boot_request_img_t image, - size_t *entry) -{ - if (entry == NULL) { - return -EINVAL; - } - - switch (type) { - case BOOT_REQUEST_BOOT_MODE: - *entry = BOOT_REQUEST_ENTRY_BOOT_MODE; - break; - case BOOT_REQUEST_IMG_PREFERENCE: - switch (image) { - case 0: - *entry = BOOT_REQUEST_ENTRY_IMAGE_0_PREFERENCE; - break; - case 1: - *entry = BOOT_REQUEST_ENTRY_IMAGE_1_PREFERENCE; - break; - default: - return -EINVAL; - } - break; - case BOOT_REQUEST_IMG_CONFIRM: - switch (image) { - case 0: - *entry = BOOT_REQUEST_ENTRY_IMAGE_0_CONFIRM; - break; - case 1: - *entry = BOOT_REQUEST_ENTRY_IMAGE_1_CONFIRM; - break; - default: - return -EINVAL; - } - break; - default: - return -EINVAL; - } - - return 0; -} - -int boot_request_init(void) -{ - if (!device_is_ready(bootloader_request_dev)) { - return -EIO; - } - - return 0; -} - -int boot_request_clear(void) -{ - return retention_clear(bootloader_request_dev); -} - -int boot_request_confirm_slot(uint8_t image, uint32_t slot) -{ - uint8_t value = BOOT_REQUEST_SLOT_INVALID; - size_t req_entry; - int ret; - - ret = boot_request_entry_find(BOOT_REQUEST_IMG_CONFIRM, image, &req_entry); - if (ret != 0) { - return ret; - } - - switch (slot) { - case 0: - value = BOOT_REQUEST_SLOT_PRIMARY; - break; - case 1: - value = BOOT_REQUEST_SLOT_SECONDARY; - break; - default: - return -EINVAL; - } - - return retention_write(bootloader_request_dev, req_entry * sizeof(value), (void *)&value, - sizeof(value)); -} - -bool boot_request_check_confirmed_slot(uint8_t image, uint32_t slot) -{ - uint8_t value = BOOT_REQUEST_SLOT_INVALID; - size_t req_entry; - int ret; - - ret = boot_request_entry_find(BOOT_REQUEST_IMG_CONFIRM, image, &req_entry); - if (ret != 0) { - return false; - } - - ret = retention_read(bootloader_request_dev, req_entry * sizeof(value), (void *)&value, - sizeof(value)); - if (ret != 0) { - return false; - } - - switch (value) { - case BOOT_REQUEST_SLOT_PRIMARY: - return (slot == 0); - case BOOT_REQUEST_SLOT_SECONDARY: - return (slot == 1); - default: - break; - } - - return false; -} - -int boot_request_set_preferred_slot(uint8_t image, uint32_t slot) -{ - uint8_t value = BOOT_REQUEST_SLOT_INVALID; - size_t req_entry; - int ret; - - ret = boot_request_entry_find(BOOT_REQUEST_IMG_PREFERENCE, image, &req_entry); - if (ret != 0) { - return ret; - } - - switch (slot) { - case 0: - value = BOOT_REQUEST_SLOT_PRIMARY; - break; - case 1: - value = BOOT_REQUEST_SLOT_SECONDARY; - break; - default: - return -EINVAL; - } - - return retention_write(bootloader_request_dev, req_entry * sizeof(value), (void *)&value, - sizeof(value)); -} - -#ifdef CONFIG_FIND_NEXT_SLOT_HOOKS -uint32_t boot_request_get_preferred_slot(uint8_t image) -{ - uint8_t value = BOOT_REQUEST_SLOT_INVALID; - size_t req_entry; - int ret; - - ret = boot_request_entry_find(BOOT_REQUEST_IMG_PREFERENCE, image, &req_entry); - if (ret != 0) { - return BOOT_REQUEST_NO_PREFERRED_SLOT; - } - - ret = retention_read(bootloader_request_dev, req_entry * sizeof(value), (void *)&value, - sizeof(value)); - if (ret != 0) { - return BOOT_REQUEST_NO_PREFERRED_SLOT; - } - - switch (value) { - case BOOT_REQUEST_SLOT_PRIMARY: - return 0; - case BOOT_REQUEST_SLOT_SECONDARY: - return 1; - default: - break; - } - - return BOOT_REQUEST_NO_PREFERRED_SLOT; -} -#endif /* CONFIG_FIND_NEXT_SLOT_HOOKS */ - -int boot_request_enter_recovery(void) -{ - uint8_t value = BOOT_REQUEST_MODE_RECOVERY; - size_t req_entry; - int ret; - - ret = boot_request_entry_find(BOOT_REQUEST_BOOT_MODE, BOOT_REQUEST_IMG_BOOTLOADER, - &req_entry); - if (ret != 0) { - return ret; - } - - return retention_write(bootloader_request_dev, req_entry * sizeof(value), (void *)&value, - sizeof(value)); -} - -#ifdef CONFIG_NRF_BOOT_SERIAL_BOOT_REQ -bool boot_request_detect_recovery(void) -{ - uint8_t value = BOOT_REQUEST_MODE_INVALID; - size_t req_entry; - int ret; - - ret = boot_request_entry_find(BOOT_REQUEST_BOOT_MODE, BOOT_REQUEST_IMG_BOOTLOADER, - &req_entry); - if (ret != 0) { - return false; - } - - ret = retention_read(bootloader_request_dev, req_entry * sizeof(value), (void *)&value, - sizeof(value)); - if ((ret == 0) && (value == BOOT_REQUEST_MODE_RECOVERY)) { - return true; - } - - return false; -} -#endif /* CONFIG_NRF_BOOT_SERIAL_BOOT_REQ */ - -int boot_request_enter_firmware_loader(void) -{ - uint8_t value = BOOT_REQUEST_MODE_FIRMWARE_LOADER; - size_t req_entry; - int ret; - - ret = boot_request_entry_find(BOOT_REQUEST_BOOT_MODE, BOOT_REQUEST_IMG_BOOTLOADER, - &req_entry); - if (ret != 0) { - return ret; - } - - return retention_write(bootloader_request_dev, req_entry * sizeof(value), (void *)&value, - sizeof(value)); -} - -#ifdef CONFIG_NRF_BOOT_FIRMWARE_LOADER_BOOT_REQ -bool boot_request_detect_firmware_loader(void) -{ - uint8_t value = BOOT_REQUEST_MODE_INVALID; - size_t req_entry; - int ret; - - ret = boot_request_entry_find(BOOT_REQUEST_BOOT_MODE, BOOT_REQUEST_IMG_BOOTLOADER, - &req_entry); - if (ret != 0) { - return false; - } - - ret = retention_read(bootloader_request_dev, req_entry * sizeof(value), (void *)&value, - sizeof(value)); - if ((ret == 0) && (value == BOOT_REQUEST_MODE_FIRMWARE_LOADER)) { - return true; - } - - return false; -} -#endif /* CONFIG_NRF_BOOT_FIRMWARE_LOADER_BOOT_REQ */ diff --git a/boot/zephyr/Kconfig b/boot/zephyr/Kconfig index c1b0de673..50fbd4dc4 100644 --- a/boot/zephyr/Kconfig +++ b/boot/zephyr/Kconfig @@ -1270,10 +1270,6 @@ config USB_DEVICE_PRODUCT config MCUBOOT_BOOTUTIL_LIB_OWN_LOG bool -config NRF_MCUBOOT_BOOT_REQUEST - bool - imply FIND_NEXT_SLOT_HOOKS if BOOT_DIRECT_XIP || BOOT_RAM_LOAD - config MCUBOOT_VERIFY_IMG_ADDRESS bool "Verify reset address of image in secondary slot" depends on UPDATEABLE_IMAGE_NUMBER > 1 diff --git a/boot/zephyr/Kconfig.firmware_loader b/boot/zephyr/Kconfig.firmware_loader index 376dc06f7..036da98eb 100644 --- a/boot/zephyr/Kconfig.firmware_loader +++ b/boot/zephyr/Kconfig.firmware_loader @@ -42,12 +42,6 @@ config BOOT_FIRMWARE_LOADER_PIN_RESET Checks if the module reset was caused by the reset pin and will remain in bootloader firmware loader mode if it was. -config NRF_BOOT_FIRMWARE_LOADER_BOOT_REQ - bool "Check boot mode via bootloader request" - depends on NRF_MCUBOOT_BOOT_REQUEST - help - Allows for entering firmware loader mode by using bootloader rquests. - endmenu endif diff --git a/boot/zephyr/Kconfig.serial_recovery b/boot/zephyr/Kconfig.serial_recovery index b6c71e5e0..5b4ba3e11 100644 --- a/boot/zephyr/Kconfig.serial_recovery +++ b/boot/zephyr/Kconfig.serial_recovery @@ -191,12 +191,6 @@ config BOOT_SERIAL_PIN_RESET Checks if the module reset was caused by the reset pin and will remain in bootloader serial recovery mode if it was. -config NRF_BOOT_SERIAL_BOOT_REQ - bool "Check boot mode via bootloader request subsystem" - depends on NRF_MCUBOOT_BOOT_REQUEST - help - Allows for entering serial recovery mode by using bootloader requests. - endmenu config BOOT_SERIAL_IMG_GRP_HASH diff --git a/boot/zephyr/firmware_loader.c b/boot/zephyr/firmware_loader.c index 834dc6341..1df848634 100644 --- a/boot/zephyr/firmware_loader.c +++ b/boot/zephyr/firmware_loader.c @@ -17,9 +17,6 @@ #include "io/io.h" #include "mcuboot_config/mcuboot_config.h" -#ifdef CONFIG_NRF_MCUBOOT_BOOT_REQUEST -#include -#endif /* CONFIG_NRF_MCUBOOT_BOOT_REQUEST */ BOOT_LOG_MODULE_DECLARE(mcuboot); @@ -186,12 +183,6 @@ boot_go(struct boot_rsp *rsp) } #endif -#ifdef CONFIG_NRF_BOOT_FIRMWARE_LOADER_BOOT_REQ - if (boot_request_detect_firmware_loader()) { - boot_firmware_loader = true; - } -#endif - /* Check if firmware loader button is pressed. TODO: check all entrance methods */ if (boot_firmware_loader == true) { FIH_CALL(validate_image_slot, fih_rc, FLASH_AREA_IMAGE_SECONDARY(0), rsp); diff --git a/boot/zephyr/main.c b/boot/zephyr/main.c index 38640aa97..fa3eeff90 100644 --- a/boot/zephyr/main.c +++ b/boot/zephyr/main.c @@ -46,12 +46,6 @@ #include "bootutil/fault_injection_hardening.h" #include "bootutil/mcuboot_status.h" #include "flash_map_backend/flash_map_backend.h" -#ifdef CONFIG_NRF_MCUBOOT_BOOT_REQUEST -#include - -/** Number of image slots. */ -#define BOOT_REQUEST_NUM_SLOTS 2 -#endif /* CONFIG_NRF_MCUBOOT_BOOT_REQUEST */ /* Check if Espressif target is supported */ #ifdef CONFIG_SOC_FAMILY_ESPRESSIF_ESP32 @@ -549,37 +543,6 @@ static void boot_serial_enter() } #endif -static int boot_prevalidate(void) -{ -#ifdef CONFIG_NRF_MCUBOOT_BOOT_REQUEST - uint8_t image_index; - uint32_t slot; - uint32_t area_id; - const struct flash_area *fap; - int rc = boot_request_init(); - - if (rc != 0) { - return rc; - } - - for (image_index = 0; image_index < BOOT_IMAGE_NUMBER; ++image_index) { - for (slot = 0; slot < BOOT_REQUEST_NUM_SLOTS; slot++) { - if (boot_request_check_confirmed_slot(image_index, slot)) { - BOOT_LOG_DBG("Confirm image: %d slot: %d due to bootloader request.", - image_index, slot); - - area_id = flash_area_id_from_multi_image_slot(image_index, slot); - rc = flash_area_open(area_id, &fap); - if (rc == 0) { - rc = boot_set_next(fap, true, true); - } - } - } - } -#endif - return 0; -} - int main(void) { struct boot_rsp rsp; @@ -611,11 +574,6 @@ int main(void) mcuboot_status_change(MCUBOOT_STATUS_STARTUP); - rc = boot_prevalidate(); - if (rc) { - BOOT_LOG_ERR("Failed to prevalidate the state: %d", rc); - } - #ifdef CONFIG_BOOT_SERIAL_ENTRANCE_GPIO BOOT_LOG_DBG("Checking GPIO for serial recovery"); if (io_detect_pin() && @@ -631,13 +589,6 @@ int main(void) } #endif -#ifdef CONFIG_NRF_BOOT_SERIAL_BOOT_REQ - if (boot_request_detect_recovery()) { - BOOT_LOG_DBG("Staying in serial recovery"); - boot_serial_enter(); - } -#endif - #if defined(CONFIG_BOOT_USB_DFU_GPIO) BOOT_LOG_DBG("Checking GPIO for USB DFU request"); if (io_detect_pin()) { @@ -698,10 +649,6 @@ int main(void) } BOOT_LOG_DBG("Left boot_go with success == %d", FIH_EQ(fih_rc, FIH_SUCCESS) ? 1 : 0); -#ifdef CONFIG_NRF_MCUBOOT_BOOT_REQUEST - (void)boot_request_clear(); -#endif - #ifdef CONFIG_BOOT_SERIAL_BOOT_MODE if (io_detect_boot_mode()) { /* Boot mode to stay in bootloader, clear status and enter serial From a652982f31f82a76646d20bf60dcaf7c84240262 Mon Sep 17 00:00:00 2001 From: Tomasz Chyrowicz Date: Thu, 31 Jul 2025 13:38:11 +0200 Subject: [PATCH 139/420] [nrf fromtree] boot: Add VID and CID checks Add a possibility to express vendor ID and image class ID inside image's TLVs. Signed-off-by: Tomasz Chyrowicz (cherry picked from commit 94ad4d445c34896c0e4367655e3275338fd533c3) --- boot/bootutil/include/bootutil/image.h | 2 + boot/bootutil/include/bootutil/mcuboot_uuid.h | 63 ++++++++++++++ boot/bootutil/src/image_validate.c | 85 ++++++++++++++++++- boot/zephyr/Kconfig | 12 +++ .../include/mcuboot_config/mcuboot_config.h | 8 ++ boot/zephyr/main.c | 12 +++ docs/design.md | 64 ++++++++++---- 7 files changed, 229 insertions(+), 17 deletions(-) create mode 100644 boot/bootutil/include/bootutil/mcuboot_uuid.h diff --git a/boot/bootutil/include/bootutil/image.h b/boot/bootutil/include/bootutil/image.h index 52fa6d1bb..5b01a5aae 100644 --- a/boot/bootutil/include/bootutil/image.h +++ b/boot/bootutil/include/bootutil/image.h @@ -132,6 +132,8 @@ extern "C" { * signature */ #define IMAGE_TLV_COMP_DEC_SIZE 0x73 /* Compressed decrypted image size */ +#define IMAGE_TLV_UUID_VID 0x74 /* Vendor unique identifier */ +#define IMAGE_TLV_UUID_CID 0x75 /* Device class unique identifier */ /* * vendor reserved TLVs at xxA0-xxFF, * where xx denotes the upper byte diff --git a/boot/bootutil/include/bootutil/mcuboot_uuid.h b/boot/bootutil/include/bootutil/mcuboot_uuid.h new file mode 100644 index 000000000..433d1d2fe --- /dev/null +++ b/boot/bootutil/include/bootutil/mcuboot_uuid.h @@ -0,0 +1,63 @@ +/* + * Copyright (c) 2025 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifndef __MCUBOOT_UUID_H__ +#define __MCUBOOT_UUID_H__ + +/** + * @file mcuboot_uuid.h + * + * @note A vendor ID as well as class ID values may be statically generated + * using CMake, based on the vendor domain name as well as product name. + * It is advised to use vendor ID as an input while generating device + * class ID to avoid collisions between UUIDs from two different vendors. + */ + +#include +#include "bootutil/fault_injection_hardening.h" + +#ifdef __cplusplus +extern "C" { +#endif + + +/** The 128-bit UUID, used for identifying vendors as well as image classes. */ +struct image_uuid { + uint8_t raw[16]; +}; + +/** + * @brief Initialises the UUID module. + * + * @return FIH_SUCCESS on success + */ +fih_ret boot_uuid_init(void); + +/** + * @brief Check if the specified vendor UUID is allowed for a given image. + * + * @param[in] image_id Index of the image (from 0). + * @param[in] uuid_vid The reference to the image's vendor ID value. + * + * @return FIH_SUCCESS on success. + */ +fih_ret boot_uuid_vid_match(uint32_t image_id, const struct image_uuid *uuid_vid); + +/** + * @brief Check if the specified image class UUID is allowed for a given image. + * + * @param[in] image_id Index of the image (from 0). + * @param[in] uuid_cid The reference to the image's class ID value. + * + * @return FIH_SUCCESS on success + */ +fih_ret boot_uuid_cid_match(uint32_t image_id, const struct image_uuid *uuid_cid); + +#ifdef __cplusplus +} +#endif + +#endif /* __MCUBOOT_UUID_H__ */ diff --git a/boot/bootutil/src/image_validate.c b/boot/bootutil/src/image_validate.c index ac7ad2a04..5a5366e59 100644 --- a/boot/bootutil/src/image_validate.c +++ b/boot/bootutil/src/image_validate.c @@ -44,6 +44,9 @@ #include "bootutil/bootutil_log.h" BOOT_LOG_MODULE_DECLARE(mcuboot); +#if defined(MCUBOOT_UUID_VID) || defined(MCUBOOT_UUID_CID) +#include "bootutil/mcuboot_uuid.h" +#endif /* MCUBOOT_UUID_VID || MCUBOOT_UUID_CID */ #ifdef MCUBOOT_ENC_IMAGES #include "bootutil/enc_key.h" @@ -507,7 +510,8 @@ bootutil_img_validate(struct boot_loader_state *state, #endif ) { -#if (defined(EXPECTED_KEY_TLV) && defined(MCUBOOT_HW_KEY)) || defined(MCUBOOT_HW_ROLLBACK_PROT) +#if (defined(EXPECTED_KEY_TLV) && defined(MCUBOOT_HW_KEY)) || defined(MCUBOOT_HW_ROLLBACK_PROT) \ + || defined(MCUBOOT_UUID_VID) || defined(MCUBOOT_UUID_CID) int image_index = (state == NULL ? 0 : BOOT_CURR_IMG(state)); #endif uint32_t off; @@ -553,6 +557,14 @@ bootutil_img_validate(struct boot_loader_state *state, goto out; } #endif +#ifdef MCUBOOT_UUID_VID + struct image_uuid img_uuid_vid = {0x00}; + FIH_DECLARE(uuid_vid_valid, FIH_FAILURE); +#endif +#ifdef MCUBOOT_UUID_CID + struct image_uuid img_uuid_cid = {0x00}; + FIH_DECLARE(uuid_cid_valid, FIH_FAILURE); +#endif BOOT_LOG_DBG("bootutil_img_validate: flash area %p", fap); @@ -793,6 +805,64 @@ bootutil_img_validate(struct boot_loader_state *state, break; } #endif /* MCUBOOT_HW_ROLLBACK_PROT */ +#ifdef MCUBOOT_UUID_VID + case IMAGE_TLV_UUID_VID: + { + /* + * Verify the image's vendor ID length. + * This must always be present. + */ + if (len != sizeof(img_uuid_vid)) { + /* Vendor UUID is not valid. */ + rc = -1; + goto out; + } + + rc = LOAD_IMAGE_DATA(hdr, fap, off, img_uuid_vid.raw, len); + if (rc) { + goto out; + } + + FIH_CALL(boot_uuid_vid_match, fih_rc, image_index, &img_uuid_vid); + if (FIH_NOT_EQ(fih_rc, FIH_SUCCESS)) { + FIH_SET(uuid_vid_valid, FIH_FAILURE); + goto out; + } + + /* The image's vendor identifier has been successfully verified. */ + uuid_vid_valid = fih_rc; + break; + } +#endif +#ifdef MCUBOOT_UUID_CID + case IMAGE_TLV_UUID_CID: + { + /* + * Verify the image's class ID length. + * This must always be present. + */ + if (len != sizeof(img_uuid_cid)) { + /* Image class UUID is not valid. */ + rc = -1; + goto out; + } + + rc = LOAD_IMAGE_DATA(hdr, fap, off, img_uuid_cid.raw, len); + if (rc) { + goto out; + } + + FIH_CALL(boot_uuid_cid_match, fih_rc, image_index, &img_uuid_cid); + if (FIH_NOT_EQ(fih_rc, FIH_SUCCESS)) { + FIH_SET(uuid_cid_valid, FIH_FAILURE); + goto out; + } + + /* The image's class identifier has been successfully verified. */ + uuid_cid_valid = fih_rc; + break; + } +#endif } } @@ -821,6 +891,19 @@ bootutil_img_validate(struct boot_loader_state *state, skip_security_counter_check: #endif +#ifdef MCUBOOT_UUID_VID + if (FIH_NOT_EQ(uuid_vid_valid, FIH_SUCCESS)) { + rc = -1; + goto out; + } +#endif +#ifdef MCUBOOT_UUID_CID + if (FIH_NOT_EQ(uuid_cid_valid, FIH_SUCCESS)) { + rc = -1; + goto out; + } +#endif + out: if (rc) { FIH_SET(fih_rc, FIH_FAILURE); diff --git a/boot/zephyr/Kconfig b/boot/zephyr/Kconfig index 50fbd4dc4..4dd080ab3 100644 --- a/boot/zephyr/Kconfig +++ b/boot/zephyr/Kconfig @@ -1056,6 +1056,18 @@ config MCUBOOT_HW_DOWNGRADE_PREVENTION_COUNTER_LIMITED endchoice +config MCUBOOT_UUID_VID + bool "Expect vendor unique identifier in image's TLV" + help + Provide a vendor identification scheme to prevent processing images + generated by a different vendor. + +config MCUBOOT_UUID_CID + bool "Expect image class unique identifier in image's TLV" + help + Provide an image class identification scheme to prevent processing + images for a different CPU or device produced by the same vendor. + config BOOT_WATCHDOG_FEED bool "Feed the watchdog while doing swap" default y if WATCHDOG diff --git a/boot/zephyr/include/mcuboot_config/mcuboot_config.h b/boot/zephyr/include/mcuboot_config/mcuboot_config.h index d565a6aaf..eb64c12eb 100644 --- a/boot/zephyr/include/mcuboot_config/mcuboot_config.h +++ b/boot/zephyr/include/mcuboot_config/mcuboot_config.h @@ -217,6 +217,14 @@ #define MCUBOOT_HW_ROLLBACK_PROT_COUNTER_LIMITED #endif +#ifdef CONFIG_MCUBOOT_UUID_VID +#define MCUBOOT_UUID_VID +#endif + +#ifdef CONFIG_MCUBOOT_UUID_CID +#define MCUBOOT_UUID_CID +#endif + #ifdef CONFIG_MEASURED_BOOT #define MCUBOOT_MEASURED_BOOT #endif diff --git a/boot/zephyr/main.c b/boot/zephyr/main.c index fa3eeff90..995e2bf60 100644 --- a/boot/zephyr/main.c +++ b/boot/zephyr/main.c @@ -47,6 +47,10 @@ #include "bootutil/mcuboot_status.h" #include "flash_map_backend/flash_map_backend.h" +#if defined(CONFIG_MCUBOOT_UUID_VID) || defined(CONFIG_MCUBOOT_UUID_CID) +#include "bootutil/mcuboot_uuid.h" +#endif /* CONFIG_MCUBOOT_UUID_VID || CONFIG_MCUBOOT_UUID_CID */ + /* Check if Espressif target is supported */ #ifdef CONFIG_SOC_FAMILY_ESPRESSIF_ESP32 @@ -574,6 +578,14 @@ int main(void) mcuboot_status_change(MCUBOOT_STATUS_STARTUP); +#if defined(CONFIG_MCUBOOT_UUID_VID) || defined(CONFIG_MCUBOOT_UUID_CID) + FIH_CALL(boot_uuid_init, fih_rc); + if (FIH_NOT_EQ(fih_rc, FIH_SUCCESS)) { + BOOT_LOG_ERR("Unable to initialize UUID module: %d", fih_rc); + FIH_PANIC; + } +#endif /* CONFIG_MCUBOOT_UUID_VID || CONFIG_MCUBOOT_UUID_CID */ + #ifdef CONFIG_BOOT_SERIAL_ENTRANCE_GPIO BOOT_LOG_DBG("Checking GPIO for serial recovery"); if (io_detect_pin() && diff --git a/docs/design.md b/docs/design.md index c080b2b82..139c38b57 100755 --- a/docs/design.md +++ b/docs/design.md @@ -104,22 +104,54 @@ struct image_tlv { /* * Image trailer TLV types. */ -#define IMAGE_TLV_KEYHASH 0x01 /* hash of the public key */ -#define IMAGE_TLV_SHA256 0x10 /* SHA256 of image hdr and body */ -#define IMAGE_TLV_RSA2048_PSS 0x20 /* RSA2048 of hash output */ -#define IMAGE_TLV_ECDSA224 0x21 /* ECDSA of hash output - Not supported anymore */ -#define IMAGE_TLV_ECDSA_SIG 0x22 /* ECDSA of hash output */ -#define IMAGE_TLV_RSA3072_PSS 0x23 /* RSA3072 of hash output */ -#define IMAGE_TLV_ED25519 0x24 /* ED25519 of hash output */ -#define IMAGE_TLV_SIG_PURE 0x25 /* If true then any signature found has been - calculated over image directly. */ -#define IMAGE_TLV_ENC_RSA2048 0x30 /* Key encrypted with RSA-OAEP-2048 */ -#define IMAGE_TLV_ENC_KW 0x31 /* Key encrypted with AES-KW-128 or - 256 */ -#define IMAGE_TLV_ENC_EC256 0x32 /* Key encrypted with ECIES-P256 */ -#define IMAGE_TLV_ENC_X25519 0x33 /* Key encrypted with ECIES-X25519 */ -#define IMAGE_TLV_DEPENDENCY 0x40 /* Image depends on other image */ -#define IMAGE_TLV_SEC_CNT 0x50 /* security counter */ +#define IMAGE_TLV_KEYHASH 0x01 /* hash of the public key */ +#define IMAGE_TLV_PUBKEY 0x02 /* public key */ +#define IMAGE_TLV_SHA256 0x10 /* SHA256 of image hdr and body */ +#define IMAGE_TLV_SHA384 0x11 /* SHA384 of image hdr and body */ +#define IMAGE_TLV_SHA512 0x12 /* SHA512 of image hdr and body */ +#define IMAGE_TLV_RSA2048_PSS 0x20 /* RSA2048 of hash output */ +#define IMAGE_TLV_ECDSA224 0x21 /* ECDSA of hash output - Not supported anymore */ +#define IMAGE_TLV_ECDSA_SIG 0x22 /* ECDSA of hash output */ +#define IMAGE_TLV_RSA3072_PSS 0x23 /* RSA3072 of hash output */ +#define IMAGE_TLV_ED25519 0x24 /* ed25519 of hash output */ +#define IMAGE_TLV_SIG_PURE 0x25 /* Indicator that attached signature has been prepared + * over image rather than its digest. + */ +#define IMAGE_TLV_ENC_RSA2048 0x30 /* Key encrypted with RSA-OAEP-2048 */ +#define IMAGE_TLV_ENC_KW 0x31 /* Key encrypted with AES-KW 128 or 256*/ +#define IMAGE_TLV_ENC_EC256 0x32 /* Key encrypted with ECIES-EC256 */ +#define IMAGE_TLV_ENC_X25519 0x33 /* Key encrypted with ECIES-X25519 */ +#define IMAGE_TLV_ENC_X25519_SHA512 0x34 /* Key exchange using ECIES-X25519 and SHA512 for MAC + * tag and HKDF in key derivation process + */ +#define IMAGE_TLV_DEPENDENCY 0x40 /* Image depends on other image */ +#define IMAGE_TLV_SEC_CNT 0x50 /* security counter */ +#define IMAGE_TLV_BOOT_RECORD 0x60 /* measured boot record */ +/* The following flags relate to compressed images and are for the decompressed image data */ +#define IMAGE_TLV_DECOMP_SIZE 0x70 /* Decompressed image size excluding header/TLVs */ +#define IMAGE_TLV_DECOMP_SHA 0x71 /* + * Decompressed image shaX hash, this field must match + * the format and size of the raw slot (compressed) + * shaX hash + */ +#define IMAGE_TLV_DECOMP_SIGNATURE 0x72 /* + * Decompressed image signature, this field must match + * 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 + * range. Examples: + * 0x00a0 - 0x00ff + * 0x01a0 - 0x01ff + * 0x02a0 - 0x02ff + * ... + * 0xffa0 - 0xfffe + */ +#define IMAGE_TLV_UUID_VID 0x80 /* Vendor unique identifier */ +#define IMAGE_TLV_UUID_CID 0x81 /* Device class unique identifier */ ``` Optional type-length-value records (TLVs) containing image metadata are placed From 1aaabdeed401f3c62edaccd6e48a9f3d7c5b84e4 Mon Sep 17 00:00:00 2001 From: Tomasz Chyrowicz Date: Mon, 28 Jul 2025 15:51:47 +0200 Subject: [PATCH 140/420] [nrf fromtree] imgtool: Add support for VID and CID Allow to specify VID and CID for an image. Signed-off-by: Tomasz Chyrowicz (cherry picked from commit 59d2f7a545e7591cfd090bba55f8f3def0c1be3b) --- scripts/imgtool/image.py | 60 ++++++++++++++++++++++++++++++++++++++-- scripts/imgtool/main.py | 11 ++++++-- 2 files changed, 65 insertions(+), 6 deletions(-) diff --git a/scripts/imgtool/image.py b/scripts/imgtool/image.py index 112d2ef4e..6e6d3ebe9 100755 --- a/scripts/imgtool/image.py +++ b/scripts/imgtool/image.py @@ -30,7 +30,9 @@ import hashlib import array import os.path +import re import struct +import uuid from enum import Enum import click @@ -96,6 +98,8 @@ 'DECOMP_SHA': 0x71, 'DECOMP_SIGNATURE': 0x72, 'COMP_DEC_SIZE' : 0x73, + 'UUID_VID': 0x74, + 'UUID_CID': 0x75, } TLV_SIZE = 4 @@ -253,6 +257,27 @@ def tlv_matches_key_type(tlv_type, key): return False +def parse_uuid(namespace, value): + # Check if UUID is in the RAW format (12345678-1234-5678-1234-567812345678) + uuid_re = r'[0-9A-f]{8}-[0-9A-f]{4}-[0-9A-f]{4}-[0-9A-f]{4}-[0-9A-f]{12}' + if re.match(uuid_re, value): + uuid_bytes = bytes.fromhex(value.replace('-', '')) + + # Check if UUID is in the RAW HEX format (12345678123456781234567812345678) + elif re.match(r'[0-9A-f]{32}', value): + uuid_bytes = bytes.fromhex(value) + + # Check if UUID is in the string format + elif value.isprintable(): + if namespace is not None: + uuid_bytes = uuid.uuid5(namespace, value).bytes + else: + raise ValueError(f"Unknown namespace for UUID: {value}") + else: + raise ValueError(f"Unknown UUID format: {value}") + + return uuid_bytes + class Image: @@ -262,7 +287,7 @@ def __init__(self, version=None, header_size=IMAGE_HEADER_SIZE, overwrite_only=False, endian="little", load_addr=0, rom_fixed=None, erased_val=None, save_enctlv=False, security_counter=None, max_align=None, - non_bootable=False): + non_bootable=False, vid=None, cid=None): if load_addr and rom_fixed: raise click.UsageError("Can not set rom_fixed and load_addr at the same time") @@ -291,6 +316,8 @@ def __init__(self, version=None, header_size=IMAGE_HEADER_SIZE, self.enctlv_len = 0 self.max_align = max(DEFAULT_MAX_ALIGN, align) if max_align is None else int(max_align) self.non_bootable = non_bootable + self.vid = vid + self.cid = cid if self.max_align == DEFAULT_MAX_ALIGN: self.boot_magic = bytes([ @@ -320,7 +347,7 @@ def __repr__(self): return "".format( + payloadlen=0x{:x}, vid={}, cid={}>".format( self.version, self.header_size, self.security_counter, @@ -332,7 +359,9 @@ def __repr__(self): self.overwrite_only, self.endian, self.__class__.__name__, - len(self.payload)) + len(self.payload), + self.vid, + self.cid) def load(self, path): """Load an image from a given file""" @@ -508,6 +537,16 @@ def create(self, key, public_key_format, enckey, dependencies=None, # = 4 + 4 = 8 Bytes protected_tlv_size += TLV_SIZE + 4 + if self.vid is not None: + # Size of the VID TLV: header ('HH') + payload ('16s') + # = 4 + 16 = 20 Bytes + protected_tlv_size += TLV_SIZE + 16 + + if self.cid is not None: + # Size of the CID TLV: header ('HH') + payload ('16s') + # = 4 + 16 = 20 Bytes + protected_tlv_size += TLV_SIZE + 16 + if sw_type is not None: if len(sw_type) > MAX_SW_TYPE_LENGTH: msg = "'{}' is too long ({} characters) for sw_type. Its " \ @@ -611,6 +650,21 @@ def create(self, key, public_key_format, enckey, dependencies=None, if compression_tlvs is not None: for tag, value in compression_tlvs.items(): prot_tlv.add(tag, value) + + if self.vid is not None: + vid = parse_uuid(uuid.NAMESPACE_DNS, self.vid) + payload = struct.pack(e + '16s', vid) + prot_tlv.add('UUID_VID', payload) + + if self.cid is not None: + if self.vid is not None: + namespace = uuid.UUID(bytes=vid) + else: + namespace = None + cid = parse_uuid(namespace, self.cid) + payload = struct.pack(e + '16s', cid) + prot_tlv.add('UUID_CID', payload) + if custom_tlvs is not None: for tag, value in custom_tlvs.items(): prot_tlv.add(tag, value) diff --git a/scripts/imgtool/main.py b/scripts/imgtool/main.py index 7f9a53657..646c9e961 100755 --- a/scripts/imgtool/main.py +++ b/scripts/imgtool/main.py @@ -473,13 +473,17 @@ def convert(self, value, param, ctx): @click.command(help='''Create a signed or unsigned image\n INFILE and OUTFILE are parsed as Intel HEX if the params have .hex extension, otherwise binary format is used''') +@click.option('--vid', default=None, required=False, + help='Unique vendor identifier, format: (|') +@click.option('--cid', default=None, required=False, + help='Unique image class identifier, format: (|)') def sign(key, public_key_format, align, version, pad_sig, header_size, pad_header, slot_size, pad, confirm, max_sectors, overwrite_only, 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, hmac_sha, is_pure, - vector_to_sign, non_bootable): + vector_to_sign, non_bootable, vid, cid): if confirm: # Confirmed but non-padded images don't make much sense, because @@ -492,7 +496,7 @@ def sign(key, public_key_format, align, version, pad_sig, header_size, endian=endian, load_addr=load_addr, rom_fixed=rom_fixed, erased_val=erased_val, save_enctlv=save_enctlv, security_counter=security_counter, max_align=max_align, - non_bootable=non_bootable) + non_bootable=non_bootable, vid=vid, cid=cid) compression_tlvs = {} img.load(infile) key = load_key(key) if key else None @@ -563,7 +567,8 @@ def sign(key, public_key_format, align, version, pad_sig, header_size, overwrite_only=overwrite_only, endian=endian, load_addr=load_addr, rom_fixed=rom_fixed, erased_val=erased_val, save_enctlv=save_enctlv, - security_counter=security_counter, max_align=max_align) + security_counter=security_counter, max_align=max_align, + vid=vid, cid=cid) compression_filters = [ {"id": lzma.FILTER_LZMA2, "preset": comp_default_preset, "dict_size": comp_default_dictsize, "lp": comp_default_lp, From 09ce751132d4a7b48ec110c3f8ea2e6256601731 Mon Sep 17 00:00:00 2001 From: Tomasz Chyrowicz Date: Mon, 28 Jul 2025 12:46:20 +0200 Subject: [PATCH 141/420] [nrf noup] bootloader: Add bootloader requests Add a capability inside the Zephyr bootloader to handle memory-based bootloader requests to: - Boot recovery firmware - Boot firmware loader - Confirm an image - Set the slot preference Ref: NCSDK-34429 Signed-off-by: Tomasz Chyrowicz (cherry picked from commit e1f2ab3806ce7ebc7ef34b3fc04272e747590745) --- boot/bootutil/include/bootutil/boot_request.h | 105 ++++++ boot/bootutil/src/bootutil_public.c | 84 ++++- boot/bootutil/zephyr/CMakeLists.txt | 5 + .../zephyr/src/boot_request_retention.c | 346 ++++++++++++++++++ boot/zephyr/Kconfig | 4 + boot/zephyr/Kconfig.firmware_loader | 6 + boot/zephyr/Kconfig.serial_recovery | 6 + boot/zephyr/firmware_loader.c | 9 + boot/zephyr/main.c | 53 +++ 9 files changed, 613 insertions(+), 5 deletions(-) create mode 100644 boot/bootutil/include/bootutil/boot_request.h create mode 100644 boot/bootutil/zephyr/src/boot_request_retention.c diff --git a/boot/bootutil/include/bootutil/boot_request.h b/boot/bootutil/include/bootutil/boot_request.h new file mode 100644 index 000000000..b1e8f891e --- /dev/null +++ b/boot/bootutil/include/bootutil/boot_request.h @@ -0,0 +1,105 @@ +/* + * SPDX-License-Identifier: Apache-2.0 + * + * Copyright (c) 2025 Nordic Semiconductor ASA + */ + +#ifndef __BOOT_REQUEST_H__ +#define __BOOT_REQUEST_H__ + +#ifdef __cplusplus +extern "C" { +#endif + +#include +#include + +/** Special value, indicating that there is no preferred slot. */ +#define BOOT_REQUEST_NO_PREFERRED_SLOT UINT32_MAX + +/** + * @brief Request a bootloader to confirm the specified slot of an image. + * + * @param[in] image Image number. + * @param[in] slot Slot number. + * + * @return 0 if requested, negative error code otherwise. + */ +int boot_request_confirm_slot(uint8_t image, uint32_t slot); + +/** + * @brief Request a bootloader to boot the specified slot of an image. + * + * @param[in] image Image number. + * @param[in] slot Slot number. + * + * @return 0 if requested, negative error code otherwise. + */ +int boot_request_set_preferred_slot(uint8_t image, uint32_t slot); + +/** + * @brief Request a bootloader to boot recovery image. + * + * @return 0 if requested, negative error code otherwise. + */ +int boot_request_enter_recovery(void); + +/** + * @brief Request a bootloader to boot firmware loader image. + * + * @return 0 if requested, negative error code otherwise. + */ +int boot_request_enter_firmware_loader(void); + +/** + * @brief Check if there is a request to confirm the specified slot of an image. + * + * @param[in] image Image number. + * @param[in] slot Slot number. + * + * @return true if requested, false otherwise. + */ +bool boot_request_check_confirmed_slot(uint8_t image, uint32_t slot); + +/** + * @brief Find if there is a request to boot certain slot of the specified image. + * + * @param[in] image Image number. + * + * @return slot number if requested, BOOT_REQUEST_NO_PREFERRED_SLOT otherwise. + */ +uint32_t boot_request_get_preferred_slot(uint8_t image); + +/** + * @brief Check if there is a request to boot recovery image. + * + * @return true if requested, false otherwise. + */ +bool boot_request_detect_recovery(void); + +/** + * @brief Check if there is a request to boot firmware loader image. + * + * @return true if requested, false otherwise. + */ +bool boot_request_detect_firmware_loader(void); + +/** + * @brief Initialize boot requests module. + * + * @return 0 if successful, negative error code otherwise. + */ +int boot_request_init(void); + +/** + * @brief Clear/drop all requests. + * + * @return 0 if successful, negative error code otherwise. + */ +int boot_request_clear(void); + +#ifdef __cplusplus +} +#endif + +#endif /* __BOOT_REQUEST_H__ */ diff --git a/boot/bootutil/src/bootutil_public.c b/boot/bootutil/src/bootutil_public.c index 8860fca41..7371a9fe9 100644 --- a/boot/bootutil/src/bootutil_public.c +++ b/boot/bootutil/src/bootutil_public.c @@ -51,6 +51,11 @@ #include "bootutil_priv.h" #include "bootutil_misc.h" +#if defined(CONFIG_NRF_MCUBOOT_BOOT_REQUEST) && !defined(CONFIG_MCUBOOT) +#include +#define SEND_BOOT_REQUEST +#endif /* CONFIG_NRF_MCUBOOT_BOOT_REQUEST && !CONFIG_MCUBOOT */ + #ifdef CONFIG_MCUBOOT BOOT_LOG_MODULE_DECLARE(mcuboot); #else @@ -503,16 +508,47 @@ boot_write_copy_done(const struct flash_area *fap) return boot_write_trailer_flag(fap, off, BOOT_FLAG_SET); } -#ifndef MCUBOOT_BOOTUTIL_LIB_FOR_DIRECT_XIP +#ifdef SEND_BOOT_REQUEST +static int +send_boot_request(uint8_t magic, bool confirm, int image_id, uint32_t slot_id) +{ + int rc = BOOT_EBADIMAGE; -static int flash_area_to_image(const struct flash_area *fa) + /* Handle write-protected active image. */ + if ((magic == BOOT_MAGIC_GOOD) || (magic == BOOT_MAGIC_UNSET)) { + if (confirm) { + BOOT_LOG_DBG("Confirm image: %d, %d", image_id, slot_id); + rc = boot_request_confirm_slot(image_id, slot_id); + } else { + BOOT_LOG_DBG("Set image preference: %d, %d", image_id, slot_id); + rc = boot_request_set_preferred_slot(image_id, slot_id); + } + if (rc != 0) { + rc = BOOT_EBADIMAGE; + } + } + + return rc; +} +#endif /* SEND_BOOT_REQUEST */ + +#if defined(SEND_BOOT_REQUEST) || (!defined(MCUBOOT_BOOTUTIL_LIB_FOR_DIRECT_XIP)) +static int flash_area_to_image_slot(const struct flash_area *fa, uint32_t *slot) { + int id = flash_area_get_id(fa); #if BOOT_IMAGE_NUMBER > 1 uint8_t i = 0; - int id = flash_area_get_id(fa); while (i < BOOT_IMAGE_NUMBER) { - if (FLASH_AREA_IMAGE_PRIMARY(i) == id || (FLASH_AREA_IMAGE_SECONDARY(i) == id)) { + if (FLASH_AREA_IMAGE_PRIMARY(i) == id) { + if (slot != NULL) { + *slot = 0; + } + return i; + } else if (FLASH_AREA_IMAGE_SECONDARY(i) == id) { + if (slot != NULL) { + *slot = 1; + } return i; } @@ -520,15 +556,31 @@ static int flash_area_to_image(const struct flash_area *fa) } #else (void)fa; + if (slot != NULL) { + if (FLASH_AREA_IMAGE_PRIMARY(0) == id) { + *slot = 0; + } else if (FLASH_AREA_IMAGE_SECONDARY(0) == id) { + *slot = 1; + } else { + *slot = UINT32_MAX; + } + } #endif return 0; } +#endif /* defined(SEND_BOOT_REQUEST) || (!defined(MCUBOOT_BOOTUTIL_LIB_FOR_DIRECT_XIP)) */ +#ifndef MCUBOOT_BOOTUTIL_LIB_FOR_DIRECT_XIP int boot_set_next(const struct flash_area *fa, bool active, bool confirm) { struct boot_swap_state slot_state; int rc; + int image_id; + uint32_t slot_id; + + BOOT_LOG_DBG("boot_set_next: fa %p active == %d, confirm == %d", + fa, (int)active, (int)confirm); if (active) { confirm = true; @@ -539,6 +591,15 @@ boot_set_next(const struct flash_area *fa, bool active, bool confirm) return rc; } + image_id = flash_area_to_image_slot(fa, &slot_id); + +#ifdef SEND_BOOT_REQUEST + rc = send_boot_request(slot_state.magic, confirm, image_id, slot_id); + if ((rc != 0) || active) { + return rc; + } +#endif + switch (slot_state.magic) { case BOOT_MAGIC_GOOD: /* If non-active then swap already scheduled, else confirm needed.*/ @@ -569,7 +630,7 @@ boot_set_next(const struct flash_area *fa, bool active, bool confirm) } else { swap_type = BOOT_SWAP_TYPE_TEST; } - rc = boot_write_swap_info(fa, swap_type, flash_area_to_image(fa)); + rc = boot_write_swap_info(fa, swap_type, image_id); } } break; @@ -600,6 +661,10 @@ boot_set_next(const struct flash_area *fa, bool active, bool confirm) { struct boot_swap_state slot_state; int rc; +#ifdef SEND_BOOT_REQUEST + int image_id; + uint32_t slot_id; +#endif BOOT_LOG_DBG("boot_set_next: fa %p active == %d, confirm == %d", fa, (int)active, (int)confirm); @@ -618,6 +683,15 @@ boot_set_next(const struct flash_area *fa, bool active, bool confirm) return rc; } +#ifdef SEND_BOOT_REQUEST + image_id = flash_area_to_image_slot(fa, &slot_id); + + rc = send_boot_request(slot_state.magic, confirm, image_id, slot_id); + if ((rc != 0) || active) { + return rc; + } +#endif + switch (slot_state.magic) { case BOOT_MAGIC_UNSET: /* Magic is needed for MCUboot to even consider booting an image */ diff --git a/boot/bootutil/zephyr/CMakeLists.txt b/boot/bootutil/zephyr/CMakeLists.txt index 44f78f395..111cf4f1d 100644 --- a/boot/bootutil/zephyr/CMakeLists.txt +++ b/boot/bootutil/zephyr/CMakeLists.txt @@ -16,6 +16,11 @@ zephyr_library_named(mcuboot_util) zephyr_library_sources( ../src/bootutil_public.c ) +if(CONFIG_NRF_MCUBOOT_BOOT_REQUEST) + zephyr_library_sources_ifdef(CONFIG_NRF_MCUBOOT_BOOT_REQUEST_IMPL_RETENTION + src/boot_request_retention.c + ) +endif() # Sensitivity to the TEST_BOOT_IMAGE_ACCESS_HOOKS define is implemented for # allowing the test-build with the hooks feature enabled. diff --git a/boot/bootutil/zephyr/src/boot_request_retention.c b/boot/bootutil/zephyr/src/boot_request_retention.c new file mode 100644 index 000000000..023f5af5e --- /dev/null +++ b/boot/bootutil/zephyr/src/boot_request_retention.c @@ -0,0 +1,346 @@ +/* + * SPDX-License-Identifier: Apache-2.0 + * + * Copyright (c) 2025 Nordic Semiconductor ASA + */ +#include + +#include "bootutil/bootutil_log.h" +#include + +/** Special value of image number, indicating a request to the bootloader. */ +#define BOOT_REQUEST_IMG_BOOTLOADER 0xFF + +/** Additional memory used by the retention subsystem (2B - prefix, 4B - CRC).*/ +#define BOOT_REQUEST_ENTRY_METADATA_SIZE (2 + 4) + +MCUBOOT_LOG_MODULE_REGISTER(bootloader_request); + +static const struct device *bootloader_request_dev = + DEVICE_DT_GET(DT_CHOSEN(nrf_bootloader_request)); + +enum boot_request_type { + /** Invalid request. */ + BOOT_REQUEST_INVALID = 0, + + /** Request a change in the bootloader boot mode. + * + * @details Use @p boot_request_mode as argument. + * @p BOOT_REQUEST_IMG_BOOTLOADER as image number. + * + * @note Used to trigger recovery through i.e. retention sybsystem. + */ + BOOT_REQUEST_BOOT_MODE = 1, + + /** Select the preferred image to be selected during boot or update. + * + * @details Use @p boot_request_slot_t as argument. + * + * @note Used in the Direct XIP mode. + */ + BOOT_REQUEST_IMG_PREFERENCE = 2, + + /** Request a confirmation of an image. + * + * @details Use @p boot_request_slot_t as argument. + * + * @note Used if the code cannot modify the image trailer directly. + */ + BOOT_REQUEST_IMG_CONFIRM = 3, +}; + +/* Entries inside the boot request shared memory. */ +enum boot_request_entry { + BOOT_REQUEST_ENTRY_BOOT_MODE = 0, + BOOT_REQUEST_ENTRY_IMAGE_0_PREFERENCE = 1, + BOOT_REQUEST_ENTRY_IMAGE_0_CONFIRM = 2, + BOOT_REQUEST_ENTRY_IMAGE_1_PREFERENCE = 3, + BOOT_REQUEST_ENTRY_IMAGE_1_CONFIRM = 4, + BOOT_REQUEST_ENTRY_MAX = 5, +}; + +/* Assert that all requests will fit within the retention area. */ +BUILD_ASSERT((BOOT_REQUEST_ENTRY_METADATA_SIZE + BOOT_REQUEST_ENTRY_MAX * sizeof(uint8_t)) < + DT_REG_SIZE_BY_IDX(DT_CHOSEN(nrf_bootloader_request), 0), + "nrf,bootloader-request area is too small for bootloader request struct"); + +enum boot_request_slot { + /** Unsupported value. */ + BOOT_REQUEST_SLOT_INVALID = 0, + /** Primary slot. */ + BOOT_REQUEST_SLOT_PRIMARY = 1, + /** Secondary slot. */ + BOOT_REQUEST_SLOT_SECONDARY = 2, +}; + +/** Alias type for the image and number. */ +typedef uint8_t boot_request_slot_t; + +enum boot_request_mode { + /** Execute a regular boot logic. */ + BOOT_REQUEST_MODE_REGULAR = 0, + /** Execute the recovery boot logic. */ + BOOT_REQUEST_MODE_RECOVERY = 1, + /** Execute the firmware loader logic. */ + BOOT_REQUEST_MODE_FIRMWARE_LOADER = 2, + /** Unsupported value. */ + BOOT_REQUEST_MODE_INVALID = 0xFF, +}; + +/** Alias type for the image number. */ +typedef uint8_t boot_request_img_t; + +/** + * @brief Find an entry for a given request. + * + * @param[in] type Type of request. + * @param[in] image Image number. Use @p BOOT_REQUEST_IMG_BOOTLOADER for generic requests. + * @param[out] entry Entry to use. + * + * @return 0 on success; nonzero on failure. + */ +static int boot_request_entry_find(enum boot_request_type type, boot_request_img_t image, + size_t *entry) +{ + if (entry == NULL) { + return -EINVAL; + } + + switch (type) { + case BOOT_REQUEST_BOOT_MODE: + *entry = BOOT_REQUEST_ENTRY_BOOT_MODE; + break; + case BOOT_REQUEST_IMG_PREFERENCE: + switch (image) { + case 0: + *entry = BOOT_REQUEST_ENTRY_IMAGE_0_PREFERENCE; + break; + case 1: + *entry = BOOT_REQUEST_ENTRY_IMAGE_1_PREFERENCE; + break; + default: + return -EINVAL; + } + break; + case BOOT_REQUEST_IMG_CONFIRM: + switch (image) { + case 0: + *entry = BOOT_REQUEST_ENTRY_IMAGE_0_CONFIRM; + break; + case 1: + *entry = BOOT_REQUEST_ENTRY_IMAGE_1_CONFIRM; + break; + default: + return -EINVAL; + } + break; + default: + return -EINVAL; + } + + return 0; +} + +int boot_request_init(void) +{ + if (!device_is_ready(bootloader_request_dev)) { + return -EIO; + } + + return 0; +} + +int boot_request_clear(void) +{ + return retention_clear(bootloader_request_dev); +} + +int boot_request_confirm_slot(uint8_t image, uint32_t slot) +{ + uint8_t value = BOOT_REQUEST_SLOT_INVALID; + size_t req_entry; + int ret; + + ret = boot_request_entry_find(BOOT_REQUEST_IMG_CONFIRM, image, &req_entry); + if (ret != 0) { + return ret; + } + + switch (slot) { + case 0: + value = BOOT_REQUEST_SLOT_PRIMARY; + break; + case 1: + value = BOOT_REQUEST_SLOT_SECONDARY; + break; + default: + return -EINVAL; + } + + return retention_write(bootloader_request_dev, req_entry * sizeof(value), (void *)&value, + sizeof(value)); +} + +bool boot_request_check_confirmed_slot(uint8_t image, uint32_t slot) +{ + uint8_t value = BOOT_REQUEST_SLOT_INVALID; + size_t req_entry; + int ret; + + ret = boot_request_entry_find(BOOT_REQUEST_IMG_CONFIRM, image, &req_entry); + if (ret != 0) { + return false; + } + + ret = retention_read(bootloader_request_dev, req_entry * sizeof(value), (void *)&value, + sizeof(value)); + if (ret != 0) { + return false; + } + + switch (value) { + case BOOT_REQUEST_SLOT_PRIMARY: + return (slot == 0); + case BOOT_REQUEST_SLOT_SECONDARY: + return (slot == 1); + default: + break; + } + + return false; +} + +int boot_request_set_preferred_slot(uint8_t image, uint32_t slot) +{ + uint8_t value = BOOT_REQUEST_SLOT_INVALID; + size_t req_entry; + int ret; + + ret = boot_request_entry_find(BOOT_REQUEST_IMG_PREFERENCE, image, &req_entry); + if (ret != 0) { + return ret; + } + + switch (slot) { + case 0: + value = BOOT_REQUEST_SLOT_PRIMARY; + break; + case 1: + value = BOOT_REQUEST_SLOT_SECONDARY; + break; + default: + return -EINVAL; + } + + return retention_write(bootloader_request_dev, req_entry * sizeof(value), (void *)&value, + sizeof(value)); +} + +#ifdef CONFIG_FIND_NEXT_SLOT_HOOKS +uint32_t boot_request_get_preferred_slot(uint8_t image) +{ + uint8_t value = BOOT_REQUEST_SLOT_INVALID; + size_t req_entry; + int ret; + + ret = boot_request_entry_find(BOOT_REQUEST_IMG_PREFERENCE, image, &req_entry); + if (ret != 0) { + return BOOT_REQUEST_NO_PREFERRED_SLOT; + } + + ret = retention_read(bootloader_request_dev, req_entry * sizeof(value), (void *)&value, + sizeof(value)); + if (ret != 0) { + return BOOT_REQUEST_NO_PREFERRED_SLOT; + } + + switch (value) { + case BOOT_REQUEST_SLOT_PRIMARY: + return 0; + case BOOT_REQUEST_SLOT_SECONDARY: + return 1; + default: + break; + } + + return BOOT_REQUEST_NO_PREFERRED_SLOT; +} +#endif /* CONFIG_FIND_NEXT_SLOT_HOOKS */ + +int boot_request_enter_recovery(void) +{ + uint8_t value = BOOT_REQUEST_MODE_RECOVERY; + size_t req_entry; + int ret; + + ret = boot_request_entry_find(BOOT_REQUEST_BOOT_MODE, BOOT_REQUEST_IMG_BOOTLOADER, + &req_entry); + if (ret != 0) { + return ret; + } + + return retention_write(bootloader_request_dev, req_entry * sizeof(value), (void *)&value, + sizeof(value)); +} + +#ifdef CONFIG_NRF_BOOT_SERIAL_BOOT_REQ +bool boot_request_detect_recovery(void) +{ + uint8_t value = BOOT_REQUEST_MODE_INVALID; + size_t req_entry; + int ret; + + ret = boot_request_entry_find(BOOT_REQUEST_BOOT_MODE, BOOT_REQUEST_IMG_BOOTLOADER, + &req_entry); + if (ret != 0) { + return false; + } + + ret = retention_read(bootloader_request_dev, req_entry * sizeof(value), (void *)&value, + sizeof(value)); + if ((ret == 0) && (value == BOOT_REQUEST_MODE_RECOVERY)) { + return true; + } + + return false; +} +#endif /* CONFIG_NRF_BOOT_SERIAL_BOOT_REQ */ + +int boot_request_enter_firmware_loader(void) +{ + uint8_t value = BOOT_REQUEST_MODE_FIRMWARE_LOADER; + size_t req_entry; + int ret; + + ret = boot_request_entry_find(BOOT_REQUEST_BOOT_MODE, BOOT_REQUEST_IMG_BOOTLOADER, + &req_entry); + if (ret != 0) { + return ret; + } + + return retention_write(bootloader_request_dev, req_entry * sizeof(value), (void *)&value, + sizeof(value)); +} + +#ifdef CONFIG_NRF_BOOT_FIRMWARE_LOADER_BOOT_REQ +bool boot_request_detect_firmware_loader(void) +{ + uint8_t value = BOOT_REQUEST_MODE_INVALID; + size_t req_entry; + int ret; + + ret = boot_request_entry_find(BOOT_REQUEST_BOOT_MODE, BOOT_REQUEST_IMG_BOOTLOADER, + &req_entry); + if (ret != 0) { + return false; + } + + ret = retention_read(bootloader_request_dev, req_entry * sizeof(value), (void *)&value, + sizeof(value)); + if ((ret == 0) && (value == BOOT_REQUEST_MODE_FIRMWARE_LOADER)) { + return true; + } + + return false; +} +#endif /* CONFIG_NRF_BOOT_FIRMWARE_LOADER_BOOT_REQ */ diff --git a/boot/zephyr/Kconfig b/boot/zephyr/Kconfig index 4dd080ab3..4b2458cfc 100644 --- a/boot/zephyr/Kconfig +++ b/boot/zephyr/Kconfig @@ -1282,6 +1282,10 @@ config USB_DEVICE_PRODUCT config MCUBOOT_BOOTUTIL_LIB_OWN_LOG bool +config NRF_MCUBOOT_BOOT_REQUEST + bool + imply FIND_NEXT_SLOT_HOOKS if BOOT_DIRECT_XIP || BOOT_RAM_LOAD + config MCUBOOT_VERIFY_IMG_ADDRESS bool "Verify reset address of image in secondary slot" depends on UPDATEABLE_IMAGE_NUMBER > 1 diff --git a/boot/zephyr/Kconfig.firmware_loader b/boot/zephyr/Kconfig.firmware_loader index 036da98eb..376dc06f7 100644 --- a/boot/zephyr/Kconfig.firmware_loader +++ b/boot/zephyr/Kconfig.firmware_loader @@ -42,6 +42,12 @@ config BOOT_FIRMWARE_LOADER_PIN_RESET Checks if the module reset was caused by the reset pin and will remain in bootloader firmware loader mode if it was. +config NRF_BOOT_FIRMWARE_LOADER_BOOT_REQ + bool "Check boot mode via bootloader request" + depends on NRF_MCUBOOT_BOOT_REQUEST + help + Allows for entering firmware loader mode by using bootloader rquests. + endmenu endif diff --git a/boot/zephyr/Kconfig.serial_recovery b/boot/zephyr/Kconfig.serial_recovery index 5b4ba3e11..b6c71e5e0 100644 --- a/boot/zephyr/Kconfig.serial_recovery +++ b/boot/zephyr/Kconfig.serial_recovery @@ -191,6 +191,12 @@ config BOOT_SERIAL_PIN_RESET Checks if the module reset was caused by the reset pin and will remain in bootloader serial recovery mode if it was. +config NRF_BOOT_SERIAL_BOOT_REQ + bool "Check boot mode via bootloader request subsystem" + depends on NRF_MCUBOOT_BOOT_REQUEST + help + Allows for entering serial recovery mode by using bootloader requests. + endmenu config BOOT_SERIAL_IMG_GRP_HASH diff --git a/boot/zephyr/firmware_loader.c b/boot/zephyr/firmware_loader.c index 1df848634..834dc6341 100644 --- a/boot/zephyr/firmware_loader.c +++ b/boot/zephyr/firmware_loader.c @@ -17,6 +17,9 @@ #include "io/io.h" #include "mcuboot_config/mcuboot_config.h" +#ifdef CONFIG_NRF_MCUBOOT_BOOT_REQUEST +#include +#endif /* CONFIG_NRF_MCUBOOT_BOOT_REQUEST */ BOOT_LOG_MODULE_DECLARE(mcuboot); @@ -183,6 +186,12 @@ boot_go(struct boot_rsp *rsp) } #endif +#ifdef CONFIG_NRF_BOOT_FIRMWARE_LOADER_BOOT_REQ + if (boot_request_detect_firmware_loader()) { + boot_firmware_loader = true; + } +#endif + /* Check if firmware loader button is pressed. TODO: check all entrance methods */ if (boot_firmware_loader == true) { FIH_CALL(validate_image_slot, fih_rc, FLASH_AREA_IMAGE_SECONDARY(0), rsp); diff --git a/boot/zephyr/main.c b/boot/zephyr/main.c index 995e2bf60..d8e7117ef 100644 --- a/boot/zephyr/main.c +++ b/boot/zephyr/main.c @@ -46,6 +46,12 @@ #include "bootutil/fault_injection_hardening.h" #include "bootutil/mcuboot_status.h" #include "flash_map_backend/flash_map_backend.h" +#ifdef CONFIG_NRF_MCUBOOT_BOOT_REQUEST +#include + +/** Number of image slots. */ +#define BOOT_REQUEST_NUM_SLOTS 2 +#endif /* CONFIG_NRF_MCUBOOT_BOOT_REQUEST */ #if defined(CONFIG_MCUBOOT_UUID_VID) || defined(CONFIG_MCUBOOT_UUID_CID) #include "bootutil/mcuboot_uuid.h" @@ -547,6 +553,37 @@ static void boot_serial_enter() } #endif +static int boot_prevalidate(void) +{ +#ifdef CONFIG_NRF_MCUBOOT_BOOT_REQUEST + uint8_t image_index; + uint32_t slot; + uint32_t area_id; + const struct flash_area *fap; + int rc = boot_request_init(); + + if (rc != 0) { + return rc; + } + + for (image_index = 0; image_index < BOOT_IMAGE_NUMBER; ++image_index) { + for (slot = 0; slot < BOOT_REQUEST_NUM_SLOTS; slot++) { + if (boot_request_check_confirmed_slot(image_index, slot)) { + BOOT_LOG_DBG("Confirm image: %d slot: %d due to bootloader request.", + image_index, slot); + + area_id = flash_area_id_from_multi_image_slot(image_index, slot); + rc = flash_area_open(area_id, &fap); + if (rc == 0) { + rc = boot_set_next(fap, true, true); + } + } + } + } +#endif + return 0; +} + int main(void) { struct boot_rsp rsp; @@ -586,6 +623,11 @@ int main(void) } #endif /* CONFIG_MCUBOOT_UUID_VID || CONFIG_MCUBOOT_UUID_CID */ + rc = boot_prevalidate(); + if (rc) { + BOOT_LOG_ERR("Failed to prevalidate the state: %d", rc); + } + #ifdef CONFIG_BOOT_SERIAL_ENTRANCE_GPIO BOOT_LOG_DBG("Checking GPIO for serial recovery"); if (io_detect_pin() && @@ -601,6 +643,13 @@ int main(void) } #endif +#ifdef CONFIG_NRF_BOOT_SERIAL_BOOT_REQ + if (boot_request_detect_recovery()) { + BOOT_LOG_DBG("Staying in serial recovery"); + boot_serial_enter(); + } +#endif + #if defined(CONFIG_BOOT_USB_DFU_GPIO) BOOT_LOG_DBG("Checking GPIO for USB DFU request"); if (io_detect_pin()) { @@ -661,6 +710,10 @@ int main(void) } BOOT_LOG_DBG("Left boot_go with success == %d", FIH_EQ(fih_rc, FIH_SUCCESS) ? 1 : 0); +#ifdef CONFIG_NRF_MCUBOOT_BOOT_REQUEST + (void)boot_request_clear(); +#endif + #ifdef CONFIG_BOOT_SERIAL_BOOT_MODE if (io_detect_boot_mode()) { /* Boot mode to stay in bootloader, clear status and enter serial From 0b546656c3792bfe8e980fbde5eacdb27aa7eccd Mon Sep 17 00:00:00 2001 From: Tomasz Chyrowicz Date: Thu, 4 Sep 2025 13:42:12 +0200 Subject: [PATCH 142/420] [nrf noup] boot: Improve bootloader request handling nrf-squash! [nrf noup] bootloader: Add bootloader requests Improve logic that handles sending bootloader requests as a result of issuing the MCUmgr commands. Signed-off-by: Tomasz Chyrowicz (cherry picked from commit 4292905fb054418de6f43c8437ce9833691f6687) --- boot/bootutil/src/bootutil_public.c | 17 +++++++++++++---- boot/zephyr/Kconfig | 11 +++++++++++ 2 files changed, 24 insertions(+), 4 deletions(-) diff --git a/boot/bootutil/src/bootutil_public.c b/boot/bootutil/src/bootutil_public.c index 7371a9fe9..750157e82 100644 --- a/boot/bootutil/src/bootutil_public.c +++ b/boot/bootutil/src/bootutil_public.c @@ -510,7 +510,8 @@ boot_write_copy_done(const struct flash_area *fap) #ifdef SEND_BOOT_REQUEST static int -send_boot_request(uint8_t magic, bool confirm, int image_id, uint32_t slot_id) +send_boot_request(uint8_t magic, uint8_t image_ok, bool confirm, int image_id, + uint32_t slot_id) { int rc = BOOT_EBADIMAGE; @@ -518,10 +519,16 @@ send_boot_request(uint8_t magic, bool confirm, int image_id, uint32_t slot_id) if ((magic == BOOT_MAGIC_GOOD) || (magic == BOOT_MAGIC_UNSET)) { if (confirm) { BOOT_LOG_DBG("Confirm image: %d, %d", image_id, slot_id); - rc = boot_request_confirm_slot(image_id, slot_id); + if ((image_ok != BOOT_FLAG_SET) || (magic != BOOT_MAGIC_GOOD)) { + rc = boot_request_confirm_slot(image_id, slot_id); + } else { + rc = 0; + } +#ifdef CONFIG_NCS_MCUBOOT_BOOT_REQUEST_TEST_SETS_BOOT_PREFERENCE } else { BOOT_LOG_DBG("Set image preference: %d, %d", image_id, slot_id); rc = boot_request_set_preferred_slot(image_id, slot_id); +#endif /* CONFIG_NCS_MCUBOOT_BOOT_REQUEST_TEST_SETS_BOOT_PREFERENCE */ } if (rc != 0) { rc = BOOT_EBADIMAGE; @@ -594,7 +601,8 @@ boot_set_next(const struct flash_area *fa, bool active, bool confirm) image_id = flash_area_to_image_slot(fa, &slot_id); #ifdef SEND_BOOT_REQUEST - rc = send_boot_request(slot_state.magic, confirm, image_id, slot_id); + rc = send_boot_request(slot_state.magic, slot_state.image_ok, confirm, + image_id, slot_id); if ((rc != 0) || active) { return rc; } @@ -686,7 +694,8 @@ boot_set_next(const struct flash_area *fa, bool active, bool confirm) #ifdef SEND_BOOT_REQUEST image_id = flash_area_to_image_slot(fa, &slot_id); - rc = send_boot_request(slot_state.magic, confirm, image_id, slot_id); + rc = send_boot_request(slot_state.magic, slot_state.image_ok, confirm, + image_id, slot_id); if ((rc != 0) || active) { return rc; } diff --git a/boot/zephyr/Kconfig b/boot/zephyr/Kconfig index 4b2458cfc..57eec3eae 100644 --- a/boot/zephyr/Kconfig +++ b/boot/zephyr/Kconfig @@ -1321,4 +1321,15 @@ config NCS_MCUBOOT_IMG_VALIDATE_ATTEMPT_WAIT_MS Time between image validation attempts, in milliseconds. Allows for recovery from transient bit flips or similar situations. +config NCS_MCUBOOT_BOOT_REQUEST_TEST_SETS_BOOT_PREFERENCE + bool "Set boot preference if a slot is marked for test" + help + This option allows to verify boot preference requests through issuing + the image test. + Using this option is not recommended in production systems, because + it will boot any newly transferred image, even if it has a lower + version than the current one. + The rollback protection (using security counters) will still be + effective. + source "Kconfig.zephyr" From ce9d1d6bf1b26663195752ad137a315c1172c6cb Mon Sep 17 00:00:00 2001 From: Jamie McCrae Date: Thu, 22 Aug 2024 14:17:46 +0100 Subject: [PATCH 143/420] [nrf noup] zephyr: Add support for compressed image updates Adds support for LZMA-compressed firmware updates which also supports encrypted images and supports more than 1 updateable image Signed-off-by: Jamie McCrae Signed-off-by: Michal Kozikowski Signed-off-by: Dominik Ermel (cherry picked from commit 27758d7c440e5fbd284bd4e9b75e3e634562a718) --- boot/bootutil/src/bootutil_misc.c | 80 +- boot/bootutil/src/image_validate.c | 223 ++- boot/bootutil/src/loader.c | 27 +- boot/zephyr/CMakeLists.txt | 6 + boot/zephyr/Kconfig | 9 +- boot/zephyr/decompression.c | 1505 +++++++++++++++++ .../include/compression/decompression.h | 103 ++ 7 files changed, 1929 insertions(+), 24 deletions(-) create mode 100644 boot/zephyr/decompression.c create mode 100644 boot/zephyr/include/compression/decompression.h diff --git a/boot/bootutil/src/bootutil_misc.c b/boot/bootutil/src/bootutil_misc.c index a88ad0dad..96be26692 100644 --- a/boot/bootutil/src/bootutil_misc.c +++ b/boot/bootutil/src/bootutil_misc.c @@ -47,6 +47,11 @@ #include "swap_priv.h" #endif +#if defined(MCUBOOT_DECOMPRESS_IMAGES) +#include +#include +#endif + BOOT_LOG_MODULE_DECLARE(mcuboot); /* Currently only used by imgmgr */ @@ -482,35 +487,76 @@ boot_read_image_size(struct boot_loader_state *state, int slot, uint32_t *size) fap = BOOT_IMG_AREA(state, slot); assert(fap != NULL); - off = BOOT_TLV_OFF(boot_img_hdr(state, slot)); +#ifdef MCUBOOT_DECOMPRESS_IMAGES + if (MUST_DECOMPRESS(fap, BOOT_CURR_IMG(state), boot_img_hdr(state, slot))) { + uint32_t tmp_size = 0; - if (flash_area_read(fap, off, &info, sizeof(info))) { - rc = BOOT_EFLASH; - goto done; - } + rc = bootutil_get_img_decomp_size(boot_img_hdr(state, slot), fap, &tmp_size); + + if (rc) { + rc = BOOT_EBADIMAGE; + goto done; + } + + off = boot_img_hdr(state, slot)->ih_hdr_size + tmp_size; + + rc = boot_size_protected_tlvs(boot_img_hdr(state, slot), fap, &tmp_size); - protect_tlv_size = boot_img_hdr(state, slot)->ih_protect_tlv_size; - if (info.it_magic == IMAGE_TLV_PROT_INFO_MAGIC) { - if (protect_tlv_size != info.it_tlv_tot) { + if (rc) { rc = BOOT_EBADIMAGE; goto done; } - if (flash_area_read(fap, off + info.it_tlv_tot, &info, sizeof(info))) { + off += tmp_size; + + if (flash_area_read(fap, (BOOT_TLV_OFF(boot_img_hdr(state, slot)) + + boot_img_hdr(state, slot)->ih_protect_tlv_size), &info, + sizeof(info))) { rc = BOOT_EFLASH; goto done; } - } else if (protect_tlv_size != 0) { - rc = BOOT_EBADIMAGE; - goto done; - } - if (info.it_magic != IMAGE_TLV_INFO_MAGIC) { - rc = BOOT_EBADIMAGE; - goto done; + if (info.it_magic != IMAGE_TLV_INFO_MAGIC) { + rc = BOOT_EBADIMAGE; + goto done; + } + + *size = off + info.it_tlv_tot; + } else { +#else + if (1) { +#endif + off = BOOT_TLV_OFF(boot_img_hdr(state, slot)); + + if (flash_area_read(fap, off, &info, sizeof(info))) { + rc = BOOT_EFLASH; + goto done; + } + + protect_tlv_size = boot_img_hdr(state, slot)->ih_protect_tlv_size; + if (info.it_magic == IMAGE_TLV_PROT_INFO_MAGIC) { + if (protect_tlv_size != info.it_tlv_tot) { + rc = BOOT_EBADIMAGE; + goto done; + } + + if (flash_area_read(fap, off + info.it_tlv_tot, &info, sizeof(info))) { + rc = BOOT_EFLASH; + goto done; + } + } else if (protect_tlv_size != 0) { + rc = BOOT_EBADIMAGE; + goto done; + } + + if (info.it_magic != IMAGE_TLV_INFO_MAGIC) { + rc = BOOT_EBADIMAGE; + goto done; + } + + *size = off + protect_tlv_size + info.it_tlv_tot; } - *size = off + protect_tlv_size + info.it_tlv_tot; rc = 0; done: diff --git a/boot/bootutil/src/image_validate.c b/boot/bootutil/src/image_validate.c index 5a5366e59..e375e97ab 100644 --- a/boot/bootutil/src/image_validate.c +++ b/boot/bootutil/src/image_validate.c @@ -48,6 +48,11 @@ BOOT_LOG_MODULE_DECLARE(mcuboot); #include "bootutil/mcuboot_uuid.h" #endif /* MCUBOOT_UUID_VID || MCUBOOT_UUID_CID */ +#if defined(MCUBOOT_DECOMPRESS_IMAGES) +#include +#include +#endif + #ifdef MCUBOOT_ENC_IMAGES #include "bootutil/enc_key.h" #endif @@ -511,7 +516,7 @@ bootutil_img_validate(struct boot_loader_state *state, ) { #if (defined(EXPECTED_KEY_TLV) && defined(MCUBOOT_HW_KEY)) || defined(MCUBOOT_HW_ROLLBACK_PROT) \ - || defined(MCUBOOT_UUID_VID) || defined(MCUBOOT_UUID_CID) + || defined(MCUBOOT_UUID_VID) || defined(MCUBOOT_UUID_CID) || defined(MCUBOOT_DECOMPRESS_IMAGES) int image_index = (state == NULL ? 0 : BOOT_CURR_IMG(state)); #endif uint32_t off; @@ -567,6 +572,67 @@ bootutil_img_validate(struct boot_loader_state *state, #endif BOOT_LOG_DBG("bootutil_img_validate: flash area %p", fap); +#ifdef MCUBOOT_DECOMPRESS_IMAGES + /* If the image is compressed, the integrity of the image must also be validated */ + if (MUST_DECOMPRESS(fap, image_index, hdr)) { + bool found_decompressed_size = false; + bool found_decompressed_sha = false; + bool found_decompressed_signature = false; + + rc = bootutil_tlv_iter_begin(&it, hdr, fap, IMAGE_TLV_ANY, true); + if (rc) { + goto out; + } + + if (it.tlv_end > bootutil_max_image_size(state, fap)) { + rc = -1; + goto out; + } + + while (true) { + uint16_t expected_size = 0; + bool *found_flag = NULL; + + rc = bootutil_tlv_iter_next(&it, &off, &len, &type); + if (rc < 0) { + goto out; + } else if (rc > 0) { + break; + } + + switch (type) { + case IMAGE_TLV_DECOMP_SIZE: + expected_size = sizeof(size_t); + found_flag = &found_decompressed_size; + break; + case IMAGE_TLV_DECOMP_SHA: + expected_size = IMAGE_HASH_SIZE; + found_flag = &found_decompressed_sha; + break; + case IMAGE_TLV_DECOMP_SIGNATURE: + found_flag = &found_decompressed_signature; + break; + default: + continue; + }; + + if (type == IMAGE_TLV_DECOMP_SIGNATURE && !EXPECTED_SIG_LEN(len)) { + rc = -1; + goto out; + } else if (type != IMAGE_TLV_DECOMP_SIGNATURE && len != expected_size) { + rc = -1; + goto out; + } + + *found_flag = true; + } + + rc = (!found_decompressed_size || !found_decompressed_sha || !found_decompressed_signature); + if (rc) { + goto out; + } + } +#endif #if defined(EXPECTED_HASH_TLV) && !defined(MCUBOOT_SIGN_PURE) #if defined(MCUBOOT_SWAP_USING_OFFSET) && defined(MCUBOOT_SERIAL_RECOVERY) @@ -904,6 +970,161 @@ bootutil_img_validate(struct boot_loader_state *state, } #endif +#ifdef MCUBOOT_DECOMPRESS_IMAGES + /* Only after all previous verifications have passed, perform a dry-run of the decompression + * and ensure the image is valid + */ + if (!rc && MUST_DECOMPRESS(fap, image_index, hdr)) { + image_hash_valid = 0; + FIH_SET(valid_signature, FIH_FAILURE); + + rc = bootutil_img_hash_decompress(state, hdr, fap, tmp_buf, tmp_buf_sz, + hash, seed, seed_len); + if (rc) { + goto out; + } + + rc = bootutil_tlv_iter_begin(&it, hdr, fap, IMAGE_TLV_DECOMP_SHA, true); + if (rc) { + goto out; + } + + if (it.tlv_end > bootutil_max_image_size(state, fap)) { + rc = -1; + goto out; + } + + while (true) { + rc = bootutil_tlv_iter_next(&it, &off, &len, &type); + if (rc < 0) { + goto out; + } else if (rc > 0) { + break; + } + + if (type == IMAGE_TLV_DECOMP_SHA) { + /* Verify the image hash. This must always be present. */ + if (len != sizeof(hash)) { + rc = -1; + goto out; + } + rc = LOAD_IMAGE_DATA(hdr, fap, off, buf, sizeof(hash)); + if (rc) { + goto out; + } + + FIH_CALL(boot_fih_memequal, fih_rc, hash, buf, sizeof(hash)); + if (FIH_NOT_EQ(fih_rc, FIH_SUCCESS)) { + FIH_SET(fih_rc, FIH_FAILURE); + goto out; + } + + image_hash_valid = 1; + } + } + + rc = !image_hash_valid; + if (rc) { + goto out; + } + +#ifdef EXPECTED_SIG_TLV +#ifdef EXPECTED_KEY_TLV + rc = bootutil_tlv_iter_begin(&it, hdr, fap, EXPECTED_KEY_TLV, false); + if (rc) { + goto out; + } + + if (it.tlv_end > bootutil_max_image_size(state, fap)) { + rc = -1; + goto out; + } + + while (true) { + rc = bootutil_tlv_iter_next(&it, &off, &len, &type); + if (rc < 0) { + goto out; + } else if (rc > 0) { + break; + } + + if (type == EXPECTED_KEY_TLV) { + /* + * Determine which key we should be checking. + */ + if (len > KEY_BUF_SIZE) { + rc = -1; + goto out; + } +#ifndef MCUBOOT_HW_KEY + rc = LOAD_IMAGE_DATA(hdr, fap, off, buf, len); + if (rc) { + goto out; + } + key_id = bootutil_find_key(buf, len); +#else + rc = LOAD_IMAGE_DATA(hdr, fap, off, key_buf, len); + if (rc) { + goto out; + } + key_id = bootutil_find_key(image_index, key_buf, len); +#endif /* !MCUBOOT_HW_KEY */ + /* + * The key may not be found, which is acceptable. There + * can be multiple signatures, each preceded by a key. + */ + } + } +#endif /* EXPECTED_KEY_TLV */ + + rc = bootutil_tlv_iter_begin(&it, hdr, fap, IMAGE_TLV_DECOMP_SIGNATURE, true); + if (rc) { + goto out; + } + + if (it.tlv_end > bootutil_max_image_size(state, fap)) { + rc = -1; + goto out; + } + + while (true) { + rc = bootutil_tlv_iter_next(&it, &off, &len, &type); + if (rc < 0) { + goto out; + } else if (rc > 0) { + rc = 0; + break; + } + + if (type == IMAGE_TLV_DECOMP_SIGNATURE) { + /* Ignore this signature if it is out of bounds. */ + if (key_id < 0 || key_id >= bootutil_key_cnt) { + key_id = -1; + continue; + } + + if (!EXPECTED_SIG_LEN(len) || len > sizeof(buf)) { + rc = -1; + goto out; + } + rc = LOAD_IMAGE_DATA(hdr, fap, off, buf, len); + if (rc) { + goto out; + } + + FIH_CALL(bootutil_verify_sig, valid_signature, hash, sizeof(hash), + buf, len, key_id); + key_id = -1; + } + } +#endif /* EXPECTED_SIG_TLV */ + } +#endif + +#ifdef EXPECTED_SIG_TLV + FIH_SET(fih_rc, valid_signature); +#endif + out: if (rc) { FIH_SET(fih_rc, FIH_FAILURE); diff --git a/boot/bootutil/src/loader.c b/boot/bootutil/src/loader.c index 71fc7d535..3e199ad4a 100644 --- a/boot/bootutil/src/loader.c +++ b/boot/bootutil/src/loader.c @@ -50,6 +50,11 @@ #include "bootutil/boot_hooks.h" #include "bootutil/mcuboot_status.h" +#if defined(MCUBOOT_DECOMPRESS_IMAGES) +#include +#include +#endif + #ifdef __ZEPHYR__ #include #if defined(CONFIG_NCS_MCUBOOT_IMG_VALIDATE_ATTEMPT_WAIT_MS) @@ -1043,10 +1048,10 @@ boot_is_header_valid(const struct image_header *hdr, const struct flash_area *fa return false; } #else - if ((hdr->ih_flags & IMAGE_F_COMPRESSED_LZMA1) && - (hdr->ih_flags & IMAGE_F_COMPRESSED_LZMA2)) - { - return false; + if (MUST_DECOMPRESS(fap, BOOT_CURR_IMG(state), hdr)) { + if (!boot_is_compressed_header_valid(hdr, fap, state)) { + return false; + } } #endif @@ -1294,6 +1299,7 @@ boot_validate_slot(struct boot_loader_state *state, int slot, * attempts to validate and boot it. */ } + #if !defined(__BOOTSIM__) BOOT_LOG_ERR("Image in the %s slot is not valid!", (slot == BOOT_PRIMARY_SLOT) ? "primary" : "secondary"); @@ -1950,6 +1956,9 @@ boot_copy_region(struct boot_loader_state *state, #else (void)state; #endif +#if defined(MCUBOOT_DECOMPRESS_IMAGES) && !defined(MCUBOOT_ENC_IMAGES) + struct image_header *hdr; +#endif TARGET_STATIC uint8_t buf[BUF_SZ] __attribute__((aligned(4))); @@ -1975,6 +1984,16 @@ boot_copy_region(struct boot_loader_state *state, } #endif +#ifdef MCUBOOT_DECOMPRESS_IMAGES + hdr = boot_img_hdr(state, BOOT_SECONDARY_SLOT); + + if (MUST_DECOMPRESS(fap_src, BOOT_CURR_IMG(state), hdr)) { + /* Use alternative function for compressed images */ + return boot_copy_region_decompress(state, fap_src, fap_dst, off_src, off_dst, sz, buf, + BUF_SZ); + } +#endif + bytes_copied = 0; while (bytes_copied < sz) { if (sz - bytes_copied > sizeof buf) { diff --git a/boot/zephyr/CMakeLists.txt b/boot/zephyr/CMakeLists.txt index e4b5ff0ad..4d1cd5301 100644 --- a/boot/zephyr/CMakeLists.txt +++ b/boot/zephyr/CMakeLists.txt @@ -334,6 +334,12 @@ if(CONFIG_BOOT_ENCRYPT_EC256 AND NOT CONFIG_BOOT_ECDSA_PSA) ) endif() +if(CONFIG_BOOT_DECOMPRESSION) + zephyr_library_sources( + decompression.c + ) +endif() + if(CONFIG_MCUBOOT_SERIAL) zephyr_sources(${BOOT_DIR}/zephyr/serial_adapter.c) zephyr_sources(${BOOT_DIR}/boot_serial/src/boot_serial.c) diff --git a/boot/zephyr/Kconfig b/boot/zephyr/Kconfig index 57eec3eae..492f1ca16 100644 --- a/boot/zephyr/Kconfig +++ b/boot/zephyr/Kconfig @@ -1157,6 +1157,9 @@ config BOOT_BANNER_STRING config BOOT_DECOMPRESSION_SUPPORT bool + depends on NRF_COMPRESS && NRF_COMPRESS_DECOMPRESSION && (NRF_COMPRESS_LZMA_VERSION_LZMA1 || NRF_COMPRESS_LZMA_VERSION_LZMA2) + depends on !SINGLE_APPLICATION_SLOT && BOOT_UPGRADE_ONLY + default y help Hidden symbol which should be selected if a system provided decompression support. @@ -1164,6 +1167,8 @@ if BOOT_DECOMPRESSION_SUPPORT menuconfig BOOT_DECOMPRESSION bool "Decompression" + select NRF_COMPRESS_CLEANUP + select PM_USE_CONFIG_SRAM_SIZE if SOC_NRF54L15_CPUAPP help If enabled, will include support for compressed images being loaded to the secondary slot which then get decompressed into the primary slot. This mode allows the secondary slot to @@ -1172,9 +1177,9 @@ menuconfig BOOT_DECOMPRESSION if BOOT_DECOMPRESSION config BOOT_DECOMPRESSION_BUFFER_SIZE - int "Write buffer size" + int range 16 16384 - default 4096 + default NRF_COMPRESS_CHUNK_SIZE help The size of a secondary buffer used for writing decompressed data to the storage device. diff --git a/boot/zephyr/decompression.c b/boot/zephyr/decompression.c new file mode 100644 index 000000000..87e3d3763 --- /dev/null +++ b/boot/zephyr/decompression.c @@ -0,0 +1,1505 @@ +/* + * Copyright (c) 2024 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: LicenseRef-Nordic-5-Clause + */ + +#include +#include "compression/decompression.h" +#include "bootutil/crypto/sha.h" +#include "bootutil/bootutil_log.h" + +#if !defined(__BOOTSIM__) +#define TARGET_STATIC static +#else +#define TARGET_STATIC +#endif + +#if defined(MCUBOOT_SIGN_RSA) +#if MCUBOOT_SIGN_RSA_LEN == 2048 +#define EXPECTED_SIG_TLV IMAGE_TLV_RSA2048_PSS +#elif MCUBOOT_SIGN_RSA_LEN == 3072 +#define EXPECTED_SIG_TLV IMAGE_TLV_RSA3072_PSS +#endif +#elif defined(MCUBOOT_SIGN_EC256) || \ + defined(MCUBOOT_SIGN_EC384) || \ + defined(MCUBOOT_SIGN_EC) +#define EXPECTED_SIG_TLV IMAGE_TLV_ECDSA_SIG +#elif defined(MCUBOOT_SIGN_ED25519) +#define EXPECTED_SIG_TLV IMAGE_TLV_ED25519 +#endif + +#define DECOMP_BUF_SIZE CONFIG_BOOT_DECOMPRESSION_BUFFER_SIZE +#if defined(CONFIG_NRF_COMPRESS_ARM_THUMB) +/* Extra buffer space for being able to writeback ARM thumb decompression output, + * which may be of +2 bytes more size than its input. + */ +#define DECOMP_BUF_EXTRA_SIZE 2 +#else +#define DECOMP_BUF_EXTRA_SIZE 0 +#endif +#define DECOMP_BUF_ALLOC_SIZE (DECOMP_BUF_SIZE + DECOMP_BUF_EXTRA_SIZE) + +#define DECRYPTION_BLOCK_SIZE_AES128 16 +#define DECRYPTION_BLOCK_SIZE_AES256 32 + +/* Number of times that consumed data by decompression system can be 0 in a row before aborting */ +#define OFFSET_ZERO_CHECK_TIMES 3 + +BOOT_LOG_MODULE_DECLARE(mcuboot); + +static int boot_sha_protected_tlvs(const struct image_header *hdr, + const struct flash_area *fap_src, uint32_t protected_size, + uint8_t *buf, size_t buf_size, bootutil_sha_context *sha_ctx); + +bool boot_is_compressed_header_valid(const struct image_header *hdr, const struct flash_area *fap, + struct boot_loader_state *state) +{ + /* Image is compressed in secondary slot, need to check if fits into the primary slot */ + bool opened_flash_area = false; + int primary_fa_id; + int rc; + int size_check; + int size; + uint32_t protected_tlvs_size; + uint32_t decompressed_size; + + primary_fa_id = flash_area_id_from_multi_image_slot(BOOT_CURR_IMG(state), BOOT_PRIMARY_SLOT); + + if (primary_fa_id == fap->fa_id) { + BOOT_LOG_ERR("Primary slots cannot be compressed, image: %d", BOOT_CURR_IMG(state)); + return false; + } + + if (BOOT_IMG_AREA(state, BOOT_PRIMARY_SLOT) == NULL) { + opened_flash_area = true; + } + + rc = flash_area_open(primary_fa_id, &BOOT_IMG_AREA(state, BOOT_PRIMARY_SLOT)); + assert(rc == 0); + + size_check = flash_area_get_size(BOOT_IMG_AREA(state, BOOT_PRIMARY_SLOT)); + + if (opened_flash_area) { + (void)flash_area_close(BOOT_IMG_AREA(state, BOOT_PRIMARY_SLOT)); + } + + rc = bootutil_get_img_decomp_size(hdr, fap, &decompressed_size); + + if (rc) { + return false; + } + + if (!boot_u32_safe_add(&size, decompressed_size, hdr->ih_hdr_size)) { + return false; + } + + rc = boot_size_protected_tlvs(hdr, fap, &protected_tlvs_size); + + if (rc) { + return false; + } + + if (!boot_u32_safe_add(&size, size, protected_tlvs_size)) { + return false; + } + + if (size >= size_check) { + BOOT_LOG_ERR("Compressed image too large, decompressed image size: 0x%x, slot size: 0x%x", + size, size_check); + return false; + } + + return true; +} + +static bool is_compression_object_valid(struct nrf_compress_implementation *compression) +{ + if (compression == NULL || compression->init == NULL || compression->deinit == NULL || + compression->decompress_bytes_needed == NULL || compression->decompress == NULL) { + return false; + } + + return true; +} + +#ifdef MCUBOOT_ENC_IMAGES +int bootutil_get_img_decrypted_comp_size(const struct image_header *hdr, + const struct flash_area *fap, uint32_t *img_comp_size) +{ + if (hdr == NULL || fap == NULL || img_comp_size == NULL) { + return BOOT_EBADARGS; + } else if (hdr->ih_protect_tlv_size == 0) { + return BOOT_EBADIMAGE; + } + + if (!IS_ENCRYPTED(hdr)) { + /* Update is not encrypted so use size from header */ + *img_comp_size = hdr->ih_img_size; + } else { + struct image_tlv_iter it; + uint32_t off; + uint16_t len; + int32_t rc; + + rc = bootutil_tlv_iter_begin(&it, hdr, fap, IMAGE_TLV_COMP_DEC_SIZE, true); + + if (rc) { + return rc; + } + + rc = bootutil_tlv_iter_next(&it, &off, &len, NULL); + + if (rc != 0) { + return -1; + } + + if (len != sizeof(*img_comp_size)) { + BOOT_LOG_ERR("Invalid decompressed image size TLV: %d", len); + return BOOT_EBADIMAGE; + } + + rc = LOAD_IMAGE_DATA(hdr, fap, off, img_comp_size, len); + + if (rc) { + BOOT_LOG_ERR("Image data load failed at offset: 0x%x, size: 0x%x, area: %d, rc: %d", + off, len, fap->fa_id, rc); + return BOOT_EFLASH; + } + } + + return 0; +} +#endif + +int bootutil_img_hash_decompress(struct boot_loader_state *state, struct image_header *hdr, + const struct flash_area *fap, uint8_t *tmp_buf, + uint32_t tmp_buf_sz, uint8_t *hash_result, + uint8_t *seed, int seed_len) +{ + int rc; + uint32_t read_pos = 0; + uint32_t write_pos = 0; + uint32_t protected_tlv_size = 0; + uint32_t decompressed_image_size; + uint32_t output_size_total = 0; + struct nrf_compress_implementation *compression_lzma = NULL; + struct nrf_compress_implementation *compression_arm_thumb = NULL; + TARGET_STATIC struct image_header modified_hdr; + bootutil_sha_context sha_ctx; + +#ifdef MCUBOOT_ENC_IMAGES + struct enc_key_data *enc_state; + int image_index; + uint32_t comp_size = 0; + uint8_t decryption_block_size = 0; + + rc = bootutil_get_img_decrypted_comp_size(hdr, fap, &comp_size); + + if (rc) { + BOOT_LOG_ERR("Invalid/missing image decrypted compressed size value"); + rc = BOOT_EBADIMAGE; + goto finish_end; + } + + if (state == NULL) { + enc_state = NULL; + image_index = 0; + } else { + enc_state = BOOT_CURR_ENC(state); + image_index = BOOT_CURR_IMG(state); + } + + /* Encrypted images only exist in the secondary slot */ + if (MUST_DECRYPT(fap, image_index, hdr) && + !boot_enc_valid(enc_state, 1)) { + return -1; + } + + if (MUST_DECRYPT(fap, image_index, hdr)) { + if (hdr->ih_flags & IMAGE_F_ENCRYPTED_AES128) { + decryption_block_size = DECRYPTION_BLOCK_SIZE_AES128; + } else if (hdr->ih_flags & IMAGE_F_ENCRYPTED_AES256) { + decryption_block_size = DECRYPTION_BLOCK_SIZE_AES256; + } else { + LOG_ERR("Unknown decryption block size"); + rc = BOOT_EBADIMAGE; + goto finish_end; + } + } +#endif + + bootutil_sha_init(&sha_ctx); + + /* Setup decompression system */ +#if CONFIG_NRF_COMPRESS_LZMA_VERSION_LZMA1 + if (!(hdr->ih_flags & IMAGE_F_COMPRESSED_LZMA1)) { +#elif CONFIG_NRF_COMPRESS_LZMA_VERSION_LZMA2 + if (!(hdr->ih_flags & IMAGE_F_COMPRESSED_LZMA2)) { +#endif + /* Compressed image does not use the correct compression type which is supported by this + * build + */ + BOOT_LOG_ERR("Invalid image compression flags: no supported compression found"); + rc = BOOT_EBADIMAGE; + goto finish_without_clean; + } + + compression_lzma = nrf_compress_implementation_find(NRF_COMPRESS_TYPE_LZMA); + compression_arm_thumb = nrf_compress_implementation_find(NRF_COMPRESS_TYPE_ARM_THUMB); + + if (!is_compression_object_valid(compression_lzma) || + !is_compression_object_valid(compression_arm_thumb)) { + /* Compression library missing or missing required function pointer */ + BOOT_LOG_ERR("Decompression library fatal error"); + rc = BOOT_EBADSTATUS; + goto finish_without_clean; + } + + rc = compression_lzma->init(NULL); + rc = compression_arm_thumb->init(NULL); + + if (rc) { + BOOT_LOG_ERR("Decompression library fatal error"); + rc = BOOT_EBADSTATUS; + goto finish_without_clean; + } + + /* We need a modified header which has the updated sizes, start with the original header */ + memcpy(&modified_hdr, hdr, sizeof(modified_hdr)); + + /* Extract the decompressed image size from the protected TLV, set it and remove the + * compressed image flags + */ + rc = bootutil_get_img_decomp_size(hdr, fap, &decompressed_image_size); + + if (rc) { + BOOT_LOG_ERR("Unable to determine decompressed size of compressed image"); + rc = BOOT_EBADIMAGE; + goto finish; + } + + modified_hdr.ih_flags &= ~COMPRESSIONFLAGS; + modified_hdr.ih_img_size = decompressed_image_size; + + /* Calculate the protected TLV size, these will not include the decompressed + * sha/size/signature entries + */ + rc = boot_size_protected_tlvs(hdr, fap, &protected_tlv_size); + + if (rc) { + BOOT_LOG_ERR("Unable to determine protected TLV size of compressed image"); + rc = BOOT_EBADIMAGE; + goto finish; + } + + modified_hdr.ih_protect_tlv_size = protected_tlv_size; + bootutil_sha_update(&sha_ctx, &modified_hdr, sizeof(modified_hdr)); + read_pos = sizeof(modified_hdr); + + while (read_pos < modified_hdr.ih_hdr_size) { + uint32_t copy_size = tmp_buf_sz; + + if ((read_pos + copy_size) > modified_hdr.ih_hdr_size) { + copy_size = modified_hdr.ih_hdr_size - read_pos; + } + + rc = flash_area_read(fap, read_pos, tmp_buf, copy_size); + + if (rc != 0) { + BOOT_LOG_ERR("Flash read failed at offset: 0x%x, size: 0x%x, area: %d, rc: %d", + (hdr->ih_hdr_size + read_pos), copy_size, fap->fa_id, rc); + rc = BOOT_EFLASH; + goto finish; + } + + bootutil_sha_update(&sha_ctx, tmp_buf, copy_size); + read_pos += copy_size; + } + + /* Read in compressed data, decompress and add to hash calculation */ + read_pos = 0; + +#ifdef MCUBOOT_ENC_IMAGES + while (read_pos < comp_size) { + uint32_t copy_size = comp_size - read_pos; +#else + while (read_pos < hdr->ih_img_size) { + uint32_t copy_size = hdr->ih_img_size - read_pos; +#endif + uint32_t tmp_off = 0; + uint8_t offset_zero_check = 0; + + if (copy_size > tmp_buf_sz) { + copy_size = tmp_buf_sz; + } + + rc = flash_area_read(fap, (hdr->ih_hdr_size + read_pos), tmp_buf, copy_size); + + if (rc != 0) { + BOOT_LOG_ERR("Flash read failed at offset: 0x%x, size: 0x%x, area: %d, rc: %d", + (hdr->ih_hdr_size + read_pos), copy_size, fap->fa_id, rc); + rc = BOOT_EFLASH; + goto finish; + } + +#ifdef MCUBOOT_ENC_IMAGES + if (MUST_DECRYPT(fap, image_index, hdr)) { + uint8_t dummy_bytes = 0; + + if ((copy_size % decryption_block_size)) { + dummy_bytes = decryption_block_size - (copy_size % decryption_block_size); + memset(&tmp_buf[copy_size], 0x00, dummy_bytes); + } + + boot_enc_decrypt(enc_state, 1, read_pos, (copy_size + dummy_bytes), (read_pos & 0xf), + tmp_buf); + } +#endif + + /* Decompress data in chunks, writing it back with a larger write offset of the primary + * slot than read size of the secondary slot + */ + while (tmp_off < copy_size) { + uint32_t offset = 0; + uint8_t *output = NULL; + uint32_t output_size = 0; + uint32_t chunk_size; + bool last_packet = false; + + chunk_size = compression_lzma->decompress_bytes_needed(NULL); + + if (chunk_size > (copy_size - tmp_off)) { + chunk_size = (copy_size - tmp_off); + } + +#ifdef MCUBOOT_ENC_IMAGES + if ((read_pos + tmp_off + chunk_size) >= comp_size) { +#else + if ((read_pos + tmp_off + chunk_size) >= hdr->ih_img_size) { +#endif + last_packet = true; + } + + rc = compression_lzma->decompress(NULL, &tmp_buf[tmp_off], chunk_size, last_packet, + &offset, &output, &output_size); + + if (rc) { + BOOT_LOG_ERR("Decompression error: %d", rc); + rc = BOOT_EBADSTATUS; + goto finish; + } + + write_pos += output_size; + + if (write_pos > decompressed_image_size) { + BOOT_LOG_ERR("Decompressed image larger than claimed TLV size, at least: %d", + write_pos); + rc = BOOT_EBADIMAGE; + goto finish; + } + + /* Additional dry-run validity checks */ + if (last_packet == true && write_pos == 0) { + /* Last packet and we still have no output, this is a faulty update */ + BOOT_LOG_ERR("All compressed data consumed without any output, image not valid"); + rc = BOOT_EBADIMAGE; + goto finish; + } + + if (offset == 0) { + /* If the decompression system continually consumes 0 bytes, then there is a + * problem with this update image, abort and mark image as bad + */ + if (offset_zero_check >= OFFSET_ZERO_CHECK_TIMES) { + BOOT_LOG_ERR("Decompression system returning no output data, image not valid"); + rc = BOOT_EBADIMAGE; + goto finish; + } + + ++offset_zero_check; + + break; + } else { + offset_zero_check = 0; + } + + /* Copy data to secondary buffer for calculating hash */ + if (output_size > 0) { + if (hdr->ih_flags & IMAGE_F_COMPRESSED_ARM_THUMB_FLT) { + /* Run this through the ARM thumb filter */ + uint32_t offset_arm_thumb = 0; + uint8_t *output_arm_thumb = NULL; + uint32_t processed_size = 0; + uint32_t output_size_arm_thumb = 0; + + while (processed_size < output_size) { + uint32_t current_size = output_size - processed_size; + bool arm_thumb_last_packet = false; + + if (current_size > CONFIG_NRF_COMPRESS_CHUNK_SIZE) { + current_size = CONFIG_NRF_COMPRESS_CHUNK_SIZE; + } + + if (last_packet && (processed_size + current_size) == + output_size) { + arm_thumb_last_packet = true; + } + + rc = compression_arm_thumb->decompress(NULL, &output[processed_size], + current_size, arm_thumb_last_packet, + &offset_arm_thumb, + &output_arm_thumb, + &output_size_arm_thumb); + + if (rc) { + BOOT_LOG_ERR("Decompression error: %d", rc); + rc = BOOT_EBADSTATUS; + goto finish; + } + + bootutil_sha_update(&sha_ctx, output_arm_thumb, output_size_arm_thumb); + output_size_total += output_size_arm_thumb; + processed_size += current_size; + } + } else { + bootutil_sha_update(&sha_ctx, output, output_size); + output_size_total += output_size; + } + } + + tmp_off += offset; + } + + read_pos += copy_size; + } + + if (modified_hdr.ih_img_size != output_size_total) { + BOOT_LOG_ERR("Decompression expected output_size mismatch: %d vs %d", + modified_hdr.ih_img_size, output_size_total); + rc = BOOT_EBADSTATUS; + goto finish; + } + + /* If there are any protected TLVs present, add them after the main decompressed image */ + if (modified_hdr.ih_protect_tlv_size > 0) { + rc = boot_sha_protected_tlvs(hdr, fap, modified_hdr.ih_protect_tlv_size, tmp_buf, + tmp_buf_sz, &sha_ctx); + } + + bootutil_sha_finish(&sha_ctx, hash_result); + +finish: + /* Clean up decompression system */ + (void)compression_lzma->deinit(NULL); + (void)compression_arm_thumb->deinit(NULL); + +finish_without_clean: + bootutil_sha_drop(&sha_ctx); + +#ifdef MCUBOOT_ENC_IMAGES +finish_end: +#endif + return rc; +} + +static int boot_copy_protected_tlvs(const struct image_header *hdr, + const struct flash_area *fap_src, + const struct flash_area *fap_dst, uint32_t off_dst, + uint32_t protected_size, uint8_t *buf, size_t buf_size, + uint16_t *buf_pos, uint32_t *written) +{ + int rc; + uint32_t off; + uint32_t write_pos = 0; + uint16_t len; + uint16_t type; + struct image_tlv_iter it; + struct image_tlv tlv_header; + struct image_tlv_info tlv_info_header = { + .it_magic = IMAGE_TLV_PROT_INFO_MAGIC, + .it_tlv_tot = protected_size, + }; + uint16_t info_size_left = sizeof(tlv_info_header); + + while (info_size_left > 0) { + uint16_t copy_size = buf_size - *buf_pos; + + if (info_size_left > 0 && copy_size > 0) { + uint16_t single_copy_size = copy_size; + uint8_t *tlv_info_header_address = (uint8_t *)&tlv_info_header; + + if (single_copy_size > info_size_left) { + single_copy_size = info_size_left; + } + + memcpy(&buf[*buf_pos], &tlv_info_header_address[sizeof(tlv_info_header) - + info_size_left], single_copy_size); + *buf_pos += single_copy_size; + info_size_left -= single_copy_size; + } + + if (*buf_pos == buf_size) { + rc = flash_area_write(fap_dst, (off_dst + write_pos), buf, *buf_pos); + + if (rc != 0) { + BOOT_LOG_ERR("Flash write failed at offset: 0x%x, size: 0x%x, area: %d, rc: %d", + (off_dst + write_pos), *buf_pos, fap_dst->fa_id, rc); + rc = BOOT_EFLASH; + goto out; + } + + write_pos += *buf_pos; + *buf_pos = 0; + } + } + + rc = bootutil_tlv_iter_begin(&it, hdr, fap_src, IMAGE_TLV_ANY, true); + + if (rc) { + goto out; + } + + while (true) { + rc = bootutil_tlv_iter_next(&it, &off, &len, &type); + + if (rc < 0) { + goto out; + } else if (rc > 0) { + rc = 0; + break; + } + + if (type == IMAGE_TLV_DECOMP_SIZE || type == IMAGE_TLV_DECOMP_SHA || + type == IMAGE_TLV_DECOMP_SIGNATURE || type == IMAGE_TLV_COMP_DEC_SIZE) { + /* Skip these TLVs as they are not needed */ + continue; + } else { + uint16_t header_size_left = sizeof(tlv_header); + uint16_t data_size_left = len; + + tlv_header.it_type = type; + tlv_header.it_len = len; + + while (header_size_left > 0 || data_size_left > 0) { + uint16_t copy_size = buf_size - *buf_pos; + uint8_t *tlv_header_address = (uint8_t *)&tlv_header; + + if (header_size_left > 0 && copy_size > 0) { + uint16_t single_copy_size = copy_size; + + if (single_copy_size > header_size_left) { + single_copy_size = header_size_left; + } + + memcpy(&buf[*buf_pos], &tlv_header_address[sizeof(tlv_header) - + header_size_left], + single_copy_size); + *buf_pos += single_copy_size; + copy_size -= single_copy_size; + header_size_left -= single_copy_size; + } + + if (data_size_left > 0 && copy_size > 0) { + uint16_t single_copy_size = copy_size; + + if (single_copy_size > data_size_left) { + single_copy_size = data_size_left; + } + + rc = LOAD_IMAGE_DATA(hdr, fap_src, (off + (len - data_size_left)), + &buf[*buf_pos], single_copy_size); + + if (rc) { + BOOT_LOG_ERR( + "Image data load failed at offset: 0x%x, size: 0x%x, area: %d, rc: %d", + (off + (len - data_size_left)), single_copy_size, fap_src->fa_id, rc); + goto out; + } + + *buf_pos += single_copy_size; + data_size_left -= single_copy_size; + } + + if (*buf_pos == buf_size) { + rc = flash_area_write(fap_dst, (off_dst + write_pos), buf, *buf_pos); + + if (rc != 0) { + BOOT_LOG_ERR( + "Flash write failed at offset: 0x%x, size: 0x%x, area: %d, rc: %d", + (off_dst + write_pos), *buf_pos, fap_dst->fa_id, rc); + rc = BOOT_EFLASH; + goto out; + } + + write_pos += *buf_pos; + *buf_pos = 0; + } + } + } + } + + *written = write_pos; + +out: + return rc; +} + +static int boot_sha_protected_tlvs(const struct image_header *hdr, + const struct flash_area *fap_src, uint32_t protected_size, + uint8_t *buf, size_t buf_size, bootutil_sha_context *sha_ctx) +{ + int rc; + uint32_t off; + uint16_t len; + uint16_t type; + struct image_tlv_iter it; + struct image_tlv tlv_header; + struct image_tlv_info tlv_info_header = { + .it_magic = IMAGE_TLV_PROT_INFO_MAGIC, + .it_tlv_tot = protected_size, + }; + + bootutil_sha_update(sha_ctx, &tlv_info_header, sizeof(tlv_info_header)); + + rc = bootutil_tlv_iter_begin(&it, hdr, fap_src, IMAGE_TLV_ANY, true); + if (rc) { + goto out; + } + + while (true) { + uint32_t read_off = 0; + + rc = bootutil_tlv_iter_next(&it, &off, &len, &type); + + if (rc < 0) { + goto out; + } else if (rc > 0) { + rc = 0; + break; + } + + if (type == IMAGE_TLV_DECOMP_SIZE || type == IMAGE_TLV_DECOMP_SHA || + type == IMAGE_TLV_DECOMP_SIGNATURE || type == IMAGE_TLV_COMP_DEC_SIZE) { + /* Skip these TLVs as they are not needed */ + continue; + } + + tlv_header.it_type = type; + tlv_header.it_len = len; + + bootutil_sha_update(sha_ctx, &tlv_header, sizeof(tlv_header)); + + while (read_off < len) { + uint32_t copy_size = buf_size; + + if (copy_size > (len - read_off)) { + copy_size = len - read_off; + } + + rc = LOAD_IMAGE_DATA(hdr, fap_src, (off + read_off), buf, copy_size); + + if (rc) { + BOOT_LOG_ERR( + "Image data load failed at offset: 0x%x, size: 0x%x, area: %d, rc: %d", + (off + read_off), copy_size, fap_src->fa_id, rc); + goto out; + } + + bootutil_sha_update(sha_ctx, buf, copy_size); + read_off += copy_size; + } + } + +out: + return rc; +} + +int boot_size_protected_tlvs(const struct image_header *hdr, const struct flash_area *fap, + uint32_t *sz) +{ + int rc = 0; + uint32_t tlv_size; + uint32_t off; + uint16_t len; + uint16_t type; + struct image_tlv_iter it; + + *sz = 0; + tlv_size = hdr->ih_protect_tlv_size; + + rc = bootutil_tlv_iter_begin(&it, hdr, fap, IMAGE_TLV_ANY, true); + + if (rc) { + goto out; + } + + while (true) { + rc = bootutil_tlv_iter_next(&it, &off, &len, &type); + + if (rc < 0) { + goto out; + } else if (rc > 0) { + rc = 0; + break; + } + + if (type == IMAGE_TLV_DECOMP_SIZE || type == IMAGE_TLV_DECOMP_SHA || + type == IMAGE_TLV_DECOMP_SIGNATURE || type == IMAGE_TLV_COMP_DEC_SIZE) { + /* Exclude these TLVs as they will be copied to the unprotected area */ + tlv_size -= len + sizeof(struct image_tlv); + } + } + + if (!rc) { + if (tlv_size == sizeof(struct image_tlv_info)) { + /* If there are no entries then omit protected TLV section entirely */ + tlv_size = 0; + } + + *sz = tlv_size; + } + +out: + return rc; +} + +int boot_size_unprotected_tlvs(const struct image_header *hdr, const struct flash_area *fap, + uint32_t *sz) +{ + int rc = 0; + uint32_t tlv_size; + uint32_t off; + uint16_t len; + uint16_t type; + struct image_tlv_iter it; + + *sz = 0; + tlv_size = sizeof(struct image_tlv_info); + + rc = bootutil_tlv_iter_begin(&it, hdr, fap, IMAGE_TLV_ANY, false); + + if (rc) { + goto out; + } + + while (true) { + rc = bootutil_tlv_iter_next(&it, &off, &len, &type); + + if (rc < 0) { + goto out; + } else if (rc > 0) { + rc = 0; + break; + } else if (bootutil_tlv_iter_is_prot(&it, off) && type != IMAGE_TLV_DECOMP_SHA && + type != IMAGE_TLV_DECOMP_SIGNATURE) { + /* Include size of protected hash and signature as these will be replacing the + * original ones + */ + continue; + } else if (type == EXPECTED_HASH_TLV || type == EXPECTED_SIG_TLV || type == IMAGE_TLV_COMP_DEC_SIZE) { + /* Exclude the original unprotected TLVs for signature and hash, the length of the + * signature of the compressed data might not be the same size as the signaute of the + * decompressed data, as is the case when using ECDSA-P256 + */ + continue; + } + + tlv_size += len + sizeof(struct image_tlv); + } + + if (!rc) { + if (tlv_size == sizeof(struct image_tlv_info)) { + /* If there are no entries in the unprotected TLV section then there is something wrong + * with this image + */ + BOOT_LOG_ERR("No unprotected TLVs in post-decompressed image output, image is invalid"); + rc = BOOT_EBADIMAGE; + goto out; + } + + *sz = tlv_size; + } + +out: + return rc; +} + +static int boot_copy_unprotected_tlvs(const struct image_header *hdr, + const struct flash_area *fap_src, + const struct flash_area *fap_dst, uint32_t off_dst, + uint32_t unprotected_size, uint8_t *buf, size_t buf_size, + uint16_t *buf_pos, uint32_t *written) +{ + int rc; + uint32_t write_pos = 0; + uint32_t off; + uint16_t len; + uint16_t type; + struct image_tlv_iter it; + struct image_tlv_iter it_protected; + struct image_tlv tlv_header; + struct image_tlv_info tlv_info_header = { + .it_magic = IMAGE_TLV_INFO_MAGIC, + .it_tlv_tot = unprotected_size, + }; + uint16_t info_size_left = sizeof(tlv_info_header); + + while (info_size_left > 0) { + uint16_t copy_size = buf_size - *buf_pos; + + if (info_size_left > 0 && copy_size > 0) { + uint16_t single_copy_size = copy_size; + uint8_t *tlv_info_header_address = (uint8_t *)&tlv_info_header; + + if (single_copy_size > info_size_left) { + single_copy_size = info_size_left; + } + + memcpy(&buf[*buf_pos], &tlv_info_header_address[sizeof(tlv_info_header) - + info_size_left], single_copy_size); + *buf_pos += single_copy_size; + info_size_left -= single_copy_size; + } + + if (*buf_pos == buf_size) { + rc = flash_area_write(fap_dst, (off_dst + write_pos), buf, *buf_pos); + + if (rc != 0) { + BOOT_LOG_ERR("Flash write failed at offset: 0x%x, size: 0x%x, area: %d, rc: %d", + (off_dst + write_pos), *buf_pos, fap_dst->fa_id, rc); + rc = BOOT_EFLASH; + goto out; + } + + write_pos += *buf_pos; + *buf_pos = 0; + } + } + + rc = bootutil_tlv_iter_begin(&it, hdr, fap_src, IMAGE_TLV_ANY, false); + if (rc) { + goto out; + } + + while (true) { + uint16_t header_size_left = sizeof(tlv_header); + uint16_t data_size_left; + + rc = bootutil_tlv_iter_next(&it, &off, &len, &type); + if (rc < 0) { + goto out; + } else if (rc > 0) { + rc = 0; + break; + } else if (bootutil_tlv_iter_is_prot(&it, off)) { + /* Skip protected TLVs */ + continue; + } + + /* Change the values of these fields from having the data in the compressed image + * unprotected TLV (which is valid only for the compressed image data) to having the + * fields in the protected TLV section (which is valid for the decompressed image data). + * The compressed data is no longer needed + */ + if (type == EXPECTED_HASH_TLV || type == EXPECTED_SIG_TLV) { + rc = bootutil_tlv_iter_begin(&it_protected, hdr, fap_src, (type == EXPECTED_HASH_TLV ? + IMAGE_TLV_DECOMP_SHA : + IMAGE_TLV_DECOMP_SIGNATURE), + true); + + if (rc) { + goto out; + } + + while (true) { + rc = bootutil_tlv_iter_next(&it_protected, &off, &len, &type); + if (rc < 0) { + goto out; + } else if (rc > 0) { + rc = 0; + break; + } + } + + if (type == IMAGE_TLV_DECOMP_SHA) { + type = EXPECTED_HASH_TLV; + } else { + type = EXPECTED_SIG_TLV; + } + } + + data_size_left = len; + tlv_header.it_type = type; + tlv_header.it_len = len; + + while (header_size_left > 0 || data_size_left > 0) { + uint16_t copy_size = buf_size - *buf_pos; + + if (header_size_left > 0 && copy_size > 0) { + uint16_t single_copy_size = copy_size; + uint8_t *tlv_header_address = (uint8_t *)&tlv_header; + + if (single_copy_size > header_size_left) { + single_copy_size = header_size_left; + } + + memcpy(&buf[*buf_pos], &tlv_header_address[sizeof(tlv_header) - header_size_left], + single_copy_size); + *buf_pos += single_copy_size; + copy_size -= single_copy_size; + header_size_left -= single_copy_size; + } + + if (data_size_left > 0 && copy_size > 0) { + uint16_t single_copy_size = copy_size; + + if (single_copy_size > data_size_left) { + single_copy_size = data_size_left; + } + + rc = LOAD_IMAGE_DATA(hdr, fap_src, (off + len - data_size_left), + &buf[*buf_pos], single_copy_size); + + if (rc) { + BOOT_LOG_ERR( + "Image data load failed at offset: 0x%x, size: 0x%x, area: %d, rc: %d", + (off + (len - data_size_left)), single_copy_size, fap_src->fa_id, rc); + goto out; + } + + *buf_pos += single_copy_size; + data_size_left -= single_copy_size; + } + + if (*buf_pos == buf_size) { + rc = flash_area_write(fap_dst, (off_dst + write_pos), buf, *buf_pos); + + if (rc != 0) { + BOOT_LOG_ERR( + "Flash write failed at offset: 0x%x, size: 0x%x, area: %d, rc: %d", + (off_dst + write_pos), *buf_pos, fap_dst->fa_id, rc); + rc = BOOT_EFLASH; + goto out; + } + + write_pos += *buf_pos; + *buf_pos = 0; + } + } + } + + *written = write_pos; + +out: + return rc; +} + +#if defined(CONFIG_NRF_COMPRESS_ARM_THUMB) +/** + * @brief Helper function for in-place ARM Thumb filtering. + * This function places the decompressed data back into the same buffer + * at the beginning, overwriting the compressed data. WARNING: because + * ARM Thumb filtering can return +-2 more/less bytes than the input, + * the buffer provided needs to have free DECOMP_BUF_EXTRA_SIZE bytes at + * the beginning and provide valid data for filtering after these. + * + * @param[in] arm_thumb_impl Pointer to the ARM Thumb decompression implementation. + * @param[in,out] buf Pointer to the buffer containing the compressed data / filtered data. + * @param[in] buf_size Size of the buffer (including DECOMP_BUF_EXTRA_SIZE bytes at the beginning). + * @param[out] out_size Pointer to a variable where the size of the filtered data will be stored. + * @param[in] last_part Indicates if this is the last part of the data to be filtered. + * + * @return 0 on success, BOOT_EBADSTATUS on error. + */ +static int boot_arm_thumb_filter(struct nrf_compress_implementation * const arm_thumb_impl, + uint8_t *buf, size_t buf_size, size_t *out_size, bool last_part) { + + uint32_t filter_writeback_pos = 0; + uint32_t processed_size = 0; + int rc; + + while (processed_size < (buf_size - DECOMP_BUF_EXTRA_SIZE)) { + uint32_t offset_arm_thumb = 0; + uint32_t output_size_arm_thumb = 0; + uint8_t *output_arm_thumb = NULL; + uint32_t current_size = (buf_size - DECOMP_BUF_EXTRA_SIZE - processed_size); + bool arm_thumb_last_packet = false; + + if (current_size > CONFIG_NRF_COMPRESS_CHUNK_SIZE) { + current_size = CONFIG_NRF_COMPRESS_CHUNK_SIZE; + } + + if (last_part && (processed_size + current_size) == (buf_size - DECOMP_BUF_EXTRA_SIZE)) { + arm_thumb_last_packet = true; + } + + rc = arm_thumb_impl->decompress(NULL, + &buf[processed_size + + DECOMP_BUF_EXTRA_SIZE], + current_size, + arm_thumb_last_packet, + &offset_arm_thumb, + &output_arm_thumb, + &output_size_arm_thumb); + + if (rc) { + BOOT_LOG_ERR("Decompression error: %d", rc); + return BOOT_EBADSTATUS; + } + + if (output_size_arm_thumb > (buf_size - filter_writeback_pos)) { + BOOT_LOG_ERR("Filter writeback position exceeds buffer size"); + return BOOT_EBADSTATUS; + } + + memcpy(&buf[filter_writeback_pos], output_arm_thumb, + output_size_arm_thumb); + filter_writeback_pos += output_size_arm_thumb; + processed_size += offset_arm_thumb; + } + *out_size = filter_writeback_pos; + + return 0; +} +#endif /* CONFIG_NRF_COMPRESS_ARM_THUMB */ + +int boot_copy_region_decompress(struct boot_loader_state *state, const struct flash_area *fap_src, + const struct flash_area *fap_dst, uint32_t off_src, + uint32_t off_dst, uint32_t sz, uint8_t *buf, size_t buf_size) +{ + int rc; + uint32_t pos = 0; + uint16_t decomp_buf_size = 0; + uint16_t write_alignment; + uint32_t write_pos = 0; + uint32_t protected_tlv_size = 0; + uint32_t unprotected_tlv_size = 0; + uint32_t tlv_write_size = 0; + uint32_t decompressed_image_size; + struct nrf_compress_implementation *compression_lzma = NULL; + struct nrf_compress_implementation *compression_arm_thumb = NULL; + struct image_header *hdr; + TARGET_STATIC uint8_t decomp_buf[DECOMP_BUF_ALLOC_SIZE] __attribute__((aligned(4))); + TARGET_STATIC struct image_header modified_hdr; + uint16_t decomp_buf_max_size; + +#if defined(CONFIG_NRF_COMPRESS_ARM_THUMB) + uint8_t unaligned_data_length = 0; +#endif + +#ifdef MCUBOOT_ENC_IMAGES + uint32_t comp_size = 0; + uint8_t decryption_block_size = 0; +#endif + + hdr = boot_img_hdr(state, BOOT_SECONDARY_SLOT); + +#ifdef MCUBOOT_ENC_IMAGES + rc = bootutil_get_img_decrypted_comp_size(hdr, fap_src, &comp_size); + + if (rc) { + BOOT_LOG_ERR("Invalid/missing image decrypted compressed size value"); + rc = BOOT_EBADIMAGE; + goto finish; + } + + if (IS_ENCRYPTED(hdr)) { + if (hdr->ih_flags & IMAGE_F_ENCRYPTED_AES128) { + decryption_block_size = DECRYPTION_BLOCK_SIZE_AES128; + } else if (hdr->ih_flags & IMAGE_F_ENCRYPTED_AES256) { + decryption_block_size = DECRYPTION_BLOCK_SIZE_AES256; + } + } +#endif + + /* Setup decompression system */ +#if CONFIG_NRF_COMPRESS_LZMA_VERSION_LZMA1 + if (!(hdr->ih_flags & IMAGE_F_COMPRESSED_LZMA1)) { +#elif CONFIG_NRF_COMPRESS_LZMA_VERSION_LZMA2 + if (!(hdr->ih_flags & IMAGE_F_COMPRESSED_LZMA2)) { +#endif + /* Compressed image does not use the correct compression type which is supported by this + * build + */ + BOOT_LOG_ERR("Invalid image compression flags: no supported compression found"); + rc = BOOT_EBADIMAGE; + goto finish; + } + + compression_lzma = nrf_compress_implementation_find(NRF_COMPRESS_TYPE_LZMA); + compression_arm_thumb = nrf_compress_implementation_find(NRF_COMPRESS_TYPE_ARM_THUMB); + + if (!is_compression_object_valid(compression_lzma) || + !is_compression_object_valid(compression_arm_thumb)) { + /* Compression library missing or missing required function pointer */ + BOOT_LOG_ERR("Decompression library fatal error"); + rc = BOOT_EBADSTATUS; + goto finish; + } + + rc = compression_lzma->init(NULL); + rc = compression_arm_thumb->init(NULL); + + if (rc) { + BOOT_LOG_ERR("Decompression library fatal error"); + rc = BOOT_EBADSTATUS; + goto finish; + } + + write_alignment = flash_area_align(fap_dst); + + decomp_buf_max_size = DECOMP_BUF_SIZE - (DECOMP_BUF_SIZE % write_alignment); + + memcpy(&modified_hdr, hdr, sizeof(modified_hdr)); + + rc = bootutil_get_img_decomp_size(hdr, fap_src, &decompressed_image_size); + + if (rc) { + BOOT_LOG_ERR("Unable to determine decompressed size of compressed image"); + rc = BOOT_EBADIMAGE; + goto finish; + } + + modified_hdr.ih_flags &= ~COMPRESSIONFLAGS; + modified_hdr.ih_img_size = decompressed_image_size; + + /* Calculate protected TLV size for target image once items are removed */ + rc = boot_size_protected_tlvs(hdr, fap_src, &protected_tlv_size); + + if (rc) { + BOOT_LOG_ERR("Unable to determine protected TLV size of compressed image"); + rc = BOOT_EBADIMAGE; + goto finish; + } + + modified_hdr.ih_protect_tlv_size = protected_tlv_size; + + rc = boot_size_unprotected_tlvs(hdr, fap_src, &unprotected_tlv_size); + + if (rc) { + BOOT_LOG_ERR("Unable to determine unprotected TLV size of compressed image"); + rc = BOOT_EBADIMAGE; + goto finish; + } + + /* Write out the image header first, this should be a multiple of the write size */ + rc = flash_area_write(fap_dst, off_dst, &modified_hdr, sizeof(modified_hdr)); + + if (rc != 0) { + BOOT_LOG_ERR("Flash write failed at offset: 0x%x, size: 0x%x, area: %d, rc: %d", + off_dst, sizeof(modified_hdr), fap_dst->fa_id, rc); + rc = BOOT_EFLASH; + goto finish; + } + + /* Read in, decompress and write out data */ +#ifdef MCUBOOT_ENC_IMAGES + while (pos < comp_size) { + uint32_t copy_size = comp_size - pos; +#else + while (pos < hdr->ih_img_size) { + uint32_t copy_size = hdr->ih_img_size - pos; +#endif + uint32_t tmp_off = 0; + + if (copy_size > buf_size) { + copy_size = buf_size; + } + + rc = flash_area_read(fap_src, off_src + hdr->ih_hdr_size + pos, buf, copy_size); + + if (rc != 0) { + BOOT_LOG_ERR("Flash read failed at offset: 0x%x, size: 0x%x, area: %d, rc: %d", + (off_src + hdr->ih_hdr_size + pos), copy_size, fap_src->fa_id, rc); + rc = BOOT_EFLASH; + goto finish; + } + +#ifdef MCUBOOT_ENC_IMAGES + if (IS_ENCRYPTED(hdr)) { + uint8_t dummy_bytes = 0; + + if ((copy_size % decryption_block_size)) { + dummy_bytes = decryption_block_size - (copy_size % decryption_block_size); + memset(&buf[copy_size], 0x00, dummy_bytes); + } + + boot_enc_decrypt(BOOT_CURR_ENC(state), 1, pos, (copy_size + dummy_bytes), (pos & 0xf), buf); + } +#endif + + /* Decompress data in chunks, writing it back with a larger write offset of the primary + * slot than read size of the secondary slot + */ + while (tmp_off < copy_size) { + uint32_t offset = 0; + uint32_t output_size = 0; + uint32_t chunk_size; + uint32_t compression_buffer_pos = 0; + uint8_t *output = NULL; + bool last_packet = false; + + chunk_size = compression_lzma->decompress_bytes_needed(NULL); + + if (chunk_size > (copy_size - tmp_off)) { + chunk_size = (copy_size - tmp_off); + } + +#ifdef MCUBOOT_ENC_IMAGES + if ((pos + tmp_off + chunk_size) >= comp_size) { +#else + if ((pos + tmp_off + chunk_size) >= hdr->ih_img_size) { +#endif + last_packet = true; + } + + rc = compression_lzma->decompress(NULL, &buf[tmp_off], chunk_size, last_packet, + &offset, &output, &output_size); + + if (rc) { + BOOT_LOG_ERR("Decompression error: %d", rc); + rc = BOOT_EBADSTATUS; + goto finish; + } + + /* Copy data to secondary buffer for writing out */ + while (output_size > 0) { + uint32_t data_size = (decomp_buf_max_size - decomp_buf_size); + + if (data_size > output_size) { + data_size = output_size; + } + +#if defined(CONFIG_NRF_COMPRESS_ARM_THUMB) + if (hdr->ih_flags & IMAGE_F_COMPRESSED_ARM_THUMB_FLT) { + memcpy(&decomp_buf[decomp_buf_size + DECOMP_BUF_EXTRA_SIZE], + &output[compression_buffer_pos], data_size); + } else +#endif + { + memcpy(&decomp_buf[decomp_buf_size], &output[compression_buffer_pos], + data_size); + } + + compression_buffer_pos += data_size; + + decomp_buf_size += data_size; + output_size -= data_size; + + /* Write data out from secondary buffer when it is full */ + if (decomp_buf_size == decomp_buf_max_size) { +#if defined(CONFIG_NRF_COMPRESS_ARM_THUMB) + if (hdr->ih_flags & IMAGE_F_COMPRESSED_ARM_THUMB_FLT) { + + uint32_t filter_output_size; + + /* Run this through the ARM thumb filter */ + rc = boot_arm_thumb_filter(compression_arm_thumb, + &decomp_buf[unaligned_data_length], + decomp_buf_size - unaligned_data_length + DECOMP_BUF_EXTRA_SIZE, + &filter_output_size, + last_packet && output_size == 0); + + if (rc) { + goto finish; + } + + decomp_buf_size = filter_output_size + unaligned_data_length; + unaligned_data_length = decomp_buf_size % write_alignment; + + rc = flash_area_write(fap_dst, + (off_dst + hdr->ih_hdr_size + write_pos), + decomp_buf, + (decomp_buf_size - unaligned_data_length)); + + if (rc != 0) { + BOOT_LOG_ERR( + "Flash write failed at offset: 0x%x, size: 0x%x, area: %d, rc: %d", + (off_dst + hdr->ih_hdr_size + write_pos), + (decomp_buf_size - unaligned_data_length), + fap_dst->fa_id, rc); + rc = BOOT_EFLASH; + goto finish; + } + + memmove(decomp_buf, + &decomp_buf[decomp_buf_size - unaligned_data_length], + unaligned_data_length); + write_pos += decomp_buf_size - unaligned_data_length; + decomp_buf_size = unaligned_data_length; + } else +#endif + { + rc = flash_area_write(fap_dst, (off_dst + hdr->ih_hdr_size + write_pos), + decomp_buf, decomp_buf_max_size); + + if (rc != 0) { + BOOT_LOG_ERR( + "Flash write failed at offset: 0x%x, size: 0x%x, area: %d, rc: %d", + (off_dst + hdr->ih_hdr_size + write_pos), decomp_buf_max_size, + fap_dst->fa_id, rc); + rc = BOOT_EFLASH; + goto finish; + } + + write_pos += decomp_buf_max_size; + decomp_buf_size = 0; + } + } + } + + tmp_off += offset; + } + + pos += copy_size; + } + +#if defined(CONFIG_NRF_COMPRESS_ARM_THUMB) + if (hdr->ih_flags & IMAGE_F_COMPRESSED_ARM_THUMB_FLT && decomp_buf_size > 0) { + /* Extra data that has not been written out that needs ARM thumb filter applied */ + + uint32_t filter_output_size; + + rc = boot_arm_thumb_filter(compression_arm_thumb, + &decomp_buf[unaligned_data_length], + decomp_buf_size - unaligned_data_length + DECOMP_BUF_EXTRA_SIZE, + &filter_output_size, + true); + + if (rc) { + goto finish; + } + + decomp_buf_size = filter_output_size + unaligned_data_length; + + if (decomp_buf_size > decomp_buf_max_size) { + /* It can happen if ARM thumb decompression returned +2 bytes and we had near full + * decomp_buf. We still can hold these additional 2 bytes because of + * DECOMP_BUF_EXTRA_SIZE allocated. */ + + rc = flash_area_write(fap_dst, (off_dst + hdr->ih_hdr_size + write_pos), + decomp_buf, decomp_buf_max_size); + + if (rc != 0) { + BOOT_LOG_ERR("Flash write failed at offset: 0x%x, size: 0x%x, area: %d, rc: %d", + (off_dst + hdr->ih_hdr_size + write_pos), decomp_buf_max_size, + fap_dst->fa_id, rc); + rc = BOOT_EFLASH; + goto finish; + } + memmove(decomp_buf, &decomp_buf[decomp_buf_max_size], + (decomp_buf_size - decomp_buf_max_size)); + + decomp_buf_size = decomp_buf_size - decomp_buf_max_size; + write_pos += decomp_buf_max_size; + } + } +#endif + + /* Clean up decompression system */ + (void)compression_lzma->deinit(NULL); + (void)compression_arm_thumb->deinit(NULL); + + if (protected_tlv_size > 0) { + rc = boot_copy_protected_tlvs(hdr, fap_src, fap_dst, (off_dst + hdr->ih_hdr_size + + write_pos), protected_tlv_size, + decomp_buf, decomp_buf_max_size, &decomp_buf_size, + &tlv_write_size); + + if (rc) { + BOOT_LOG_ERR("Protected TLV copy failure: %d", rc); + goto finish; + } + + write_pos += tlv_write_size; + } + + tlv_write_size = 0; + rc = boot_copy_unprotected_tlvs(hdr, fap_src, fap_dst, (off_dst + hdr->ih_hdr_size + + write_pos), unprotected_tlv_size, + decomp_buf, decomp_buf_max_size, &decomp_buf_size, + &tlv_write_size); + + if (rc) { + BOOT_LOG_ERR("Protected TLV copy failure: %d", rc); + goto finish; + } + + write_pos += tlv_write_size; + + /* Check if we have unwritten data buffered up and, if so, write it out */ + if (decomp_buf_size > 0) { + uint32_t write_padding_size = write_alignment - (decomp_buf_size % write_alignment); + + /* Check if additional write padding should be applied to meet the minimum write size */ + if (write_alignment > 1 && write_padding_size) { + uint8_t flash_erased_value; + + flash_erased_value = flash_area_erased_val(fap_dst); + memset(&decomp_buf[decomp_buf_size], flash_erased_value, write_padding_size); + decomp_buf_size += write_padding_size; + } + + rc = flash_area_write(fap_dst, (off_dst + hdr->ih_hdr_size + write_pos), decomp_buf, + decomp_buf_size); + + if (rc != 0) { + BOOT_LOG_ERR("Flash write failed at offset: 0x%x, size: 0x%x, area: %d, rc: %d", + (off_dst + hdr->ih_hdr_size + write_pos), decomp_buf_size, + fap_dst->fa_id, rc); + rc = BOOT_EFLASH; + goto finish; + } + + write_pos += decomp_buf_size; + decomp_buf_size = 0; + } + +finish: + memset(decomp_buf, 0, sizeof(decomp_buf)); + + return rc; +} + +int bootutil_get_img_decomp_size(const struct image_header *hdr, const struct flash_area *fap, + uint32_t *img_decomp_size) +{ + struct image_tlv_iter it; + uint32_t off; + uint16_t len; + int32_t rc; + + if (hdr == NULL || fap == NULL || img_decomp_size == NULL) { + return BOOT_EBADARGS; + } else if (hdr->ih_protect_tlv_size == 0) { + return BOOT_EBADIMAGE; + } + + rc = bootutil_tlv_iter_begin(&it, hdr, fap, IMAGE_TLV_DECOMP_SIZE, true); + + if (rc) { + return rc; + } + + rc = bootutil_tlv_iter_next(&it, &off, &len, NULL); + + if (rc != 0) { + return -1; + } + + if (len != sizeof(*img_decomp_size)) { + BOOT_LOG_ERR("Invalid decompressed image size TLV: %d", len); + return BOOT_EBADIMAGE; + } + + rc = LOAD_IMAGE_DATA(hdr, fap, off, img_decomp_size, len); + + if (rc) { + BOOT_LOG_ERR("Image data load failed at offset: 0x%x, size: 0x%x, area: %d, rc: %d", + off, len, fap->fa_id, rc); + return BOOT_EFLASH; + } + + return 0; +} diff --git a/boot/zephyr/include/compression/decompression.h b/boot/zephyr/include/compression/decompression.h new file mode 100644 index 000000000..2104c4eb6 --- /dev/null +++ b/boot/zephyr/include/compression/decompression.h @@ -0,0 +1,103 @@ +/* + * Copyright (c) 2024 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: LicenseRef-Nordic-5-Clause + */ + +#ifndef H_DECOMPRESSION_ +#define H_DECOMPRESSION_ + +#include +#include +#include +#include "bootutil/bootutil.h" +#include "bootutil/bootutil_public.h" +#include "bootutil/image.h" +#include "../src/bootutil_priv.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * Checks if a compressed image header is valid. + * + * @param hdr Image header. + * @param fap Flash area of the slot. + * @param state Bootloader state object. + * + * @return true if valid; false if invalid. + */ +bool boot_is_compressed_header_valid(const struct image_header *hdr, const struct flash_area *fap, + struct boot_loader_state *state); + +/** + * Reads in compressed image data from a slot, decompresses it and writes it out to a destination + * slot, including corresponding image headers and TLVs. + * + * @param state Bootloader state object. + * @param fap_src Flash area of the source slot. + * @param fap_dst Flash area of the destination slot. + * @param off_src Offset of the source slot to read from (should be 0). + * @param off_dst Offset of the destination slot to write to (should be 0). + * @param sz Size of the source slot data. + * @param buf Temporary buffer for reading data from. + * @param buf_size Size of temporary buffer. + * + * @return 0 on success; nonzero on failure. + */ +int boot_copy_region_decompress(struct boot_loader_state *state, const struct flash_area *fap_src, + const struct flash_area *fap_dst, uint32_t off_src, + uint32_t off_dst, uint32_t sz, uint8_t *buf, size_t buf_size); + +/** + * Gets the total data size (excluding headers and TLVs) of a compressed image when it is + * decompressed. + * + * @param hdr Image header. + * @param fap Flash area of the slot. + * @param img_decomp_size Pointer to variable that will be updated with the decompressed image + * size. + * + * @return 0 on success; nonzero on failure. + */ +int bootutil_get_img_decomp_size(const struct image_header *hdr, const struct flash_area *fap, + uint32_t *img_decomp_size); + +/** + * Calculate MCUboot-compatible image hash of compressed image slot. + * + * @param state MCUboot state. + * @param hdr Image header. + * @param fap Flash area of the slot. + * @param tmp_buf Temporary buffer for reading data from. + * @param tmp_buf_sz Size of temporary buffer. + * @param hash_result Pointer to a variable that will be updated with the image hash. + * @param seed Not currently used, set to NULL. + * @param seed_len Not currently used, set to 0. + * + * @return 0 on success; nonzero on failure. + */ +int bootutil_img_hash_decompress(struct boot_loader_state *state, struct image_header *hdr, + const struct flash_area *fap, uint8_t *tmp_buf, + uint32_t tmp_buf_sz, uint8_t *hash_result, + uint8_t *seed, int seed_len); + +/** + * Calculates the size that the compressed image protected TLV section will occupy once the image + * has been decompressed. + * + * @param hdr Image header. + * @param fap Flash area of the slot. + * @param sz Pointer to variable that will be updated with the protected TLV size. + * + * @return 0 on success; nonzero on failure. + */ +int boot_size_protected_tlvs(const struct image_header *hdr, const struct flash_area *fap_src, + uint32_t *sz); + +#ifdef __cplusplus +} +#endif + +#endif /* H_DECOMPRESSION_ */ From 8900bdaf1dd401b08748d4141f1196520579f4fd Mon Sep 17 00:00:00 2001 From: Michal Kozikowski Date: Tue, 13 May 2025 13:33:22 +0200 Subject: [PATCH 144/420] [nrf noup] decompression: Align to changes in nrfcompress API This commit aligns to the changes in the nrfcompress API, which now enables the caller to provide the expected size of the decompressed image. ref: NCSDK-32340 Signed-off-by: Michal Kozikowski Signed-off-by: Dominik Ermel (cherry picked from commit 002515b349bd8cd4e190af2807c50e88ef8605fd) --- boot/zephyr/decompression.c | 65 ++++++++++++++++++++++++------------- 1 file changed, 42 insertions(+), 23 deletions(-) diff --git a/boot/zephyr/decompression.c b/boot/zephyr/decompression.c index 87e3d3763..ce4fe0b2b 100644 --- a/boot/zephyr/decompression.c +++ b/boot/zephyr/decompression.c @@ -256,15 +256,6 @@ int bootutil_img_hash_decompress(struct boot_loader_state *state, struct image_h goto finish_without_clean; } - rc = compression_lzma->init(NULL); - rc = compression_arm_thumb->init(NULL); - - if (rc) { - BOOT_LOG_ERR("Decompression library fatal error"); - rc = BOOT_EBADSTATUS; - goto finish_without_clean; - } - /* We need a modified header which has the updated sizes, start with the original header */ memcpy(&modified_hdr, hdr, sizeof(modified_hdr)); @@ -276,12 +267,28 @@ int bootutil_img_hash_decompress(struct boot_loader_state *state, struct image_h if (rc) { BOOT_LOG_ERR("Unable to determine decompressed size of compressed image"); rc = BOOT_EBADIMAGE; - goto finish; + goto finish_without_clean; } modified_hdr.ih_flags &= ~COMPRESSIONFLAGS; modified_hdr.ih_img_size = decompressed_image_size; + rc = compression_lzma->init(NULL, decompressed_image_size); + + if (rc) { + BOOT_LOG_ERR("Decompression library fatal error"); + rc = BOOT_EBADSTATUS; + goto finish_without_clean; + } + + rc = compression_arm_thumb->init(NULL, decompressed_image_size); + + if (rc) { + BOOT_LOG_ERR("Decompression library fatal error"); + rc = BOOT_EBADSTATUS; + goto finish; + } + /* Calculate the protected TLV size, these will not include the decompressed * sha/size/signature entries */ @@ -1101,7 +1108,7 @@ int boot_copy_region_decompress(struct boot_loader_state *state, const struct fl if (rc) { BOOT_LOG_ERR("Invalid/missing image decrypted compressed size value"); rc = BOOT_EBADIMAGE; - goto finish; + goto finish_without_clean; } if (IS_ENCRYPTED(hdr)) { @@ -1124,7 +1131,7 @@ int boot_copy_region_decompress(struct boot_loader_state *state, const struct fl */ BOOT_LOG_ERR("Invalid image compression flags: no supported compression found"); rc = BOOT_EBADIMAGE; - goto finish; + goto finish_without_clean; } compression_lzma = nrf_compress_implementation_find(NRF_COMPRESS_TYPE_LZMA); @@ -1135,16 +1142,7 @@ int boot_copy_region_decompress(struct boot_loader_state *state, const struct fl /* Compression library missing or missing required function pointer */ BOOT_LOG_ERR("Decompression library fatal error"); rc = BOOT_EBADSTATUS; - goto finish; - } - - rc = compression_lzma->init(NULL); - rc = compression_arm_thumb->init(NULL); - - if (rc) { - BOOT_LOG_ERR("Decompression library fatal error"); - rc = BOOT_EBADSTATUS; - goto finish; + goto finish_without_clean; } write_alignment = flash_area_align(fap_dst); @@ -1158,12 +1156,28 @@ int boot_copy_region_decompress(struct boot_loader_state *state, const struct fl if (rc) { BOOT_LOG_ERR("Unable to determine decompressed size of compressed image"); rc = BOOT_EBADIMAGE; - goto finish; + goto finish_without_clean; } modified_hdr.ih_flags &= ~COMPRESSIONFLAGS; modified_hdr.ih_img_size = decompressed_image_size; + rc = compression_lzma->init(NULL, decompressed_image_size); + + if (rc) { + BOOT_LOG_ERR("Decompression library fatal error"); + rc = BOOT_EBADSTATUS; + goto finish_without_clean; + } + + rc = compression_arm_thumb->init(NULL, decompressed_image_size); + + if (rc) { + BOOT_LOG_ERR("Decompression library fatal error"); + rc = BOOT_EBADSTATUS; + goto finish; + } + /* Calculate protected TLV size for target image once items are removed */ rc = boot_size_protected_tlvs(hdr, fap_src, &protected_tlv_size); @@ -1457,6 +1471,11 @@ int boot_copy_region_decompress(struct boot_loader_state *state, const struct fl } finish: + /* Clean up decompression system */ + (void)compression_lzma->deinit(NULL); + (void)compression_arm_thumb->deinit(NULL); + +finish_without_clean: memset(decomp_buf, 0, sizeof(decomp_buf)); return rc; From 4a528baa162b14d44a95892340aa299525ee1b8b Mon Sep 17 00:00:00 2001 From: Jamie McCrae Date: Thu, 7 Nov 2024 10:53:06 +0000 Subject: [PATCH 145/420] [nrf noup] boot: zephyr: Add experimental selection to compression Adds selecting the experimental Kconfig when compession is in use Signed-off-by: Jamie McCrae Signed-off-by: Dominik Ermel (cherry picked from commit 0ae144127f7d9cfca4907e5cec167c8d6643bf28) --- boot/zephyr/Kconfig | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/boot/zephyr/Kconfig b/boot/zephyr/Kconfig index 492f1ca16..0cc72422f 100644 --- a/boot/zephyr/Kconfig +++ b/boot/zephyr/Kconfig @@ -1166,9 +1166,10 @@ config BOOT_DECOMPRESSION_SUPPORT if BOOT_DECOMPRESSION_SUPPORT menuconfig BOOT_DECOMPRESSION - bool "Decompression" + bool "Decompression [EXPERIMENTAL]" select NRF_COMPRESS_CLEANUP select PM_USE_CONFIG_SRAM_SIZE if SOC_NRF54L15_CPUAPP + select EXPERIMENTAL help If enabled, will include support for compressed images being loaded to the secondary slot which then get decompressed into the primary slot. This mode allows the secondary slot to From 6ba9587457e8b2b705528ffe6cc77435ae9df080 Mon Sep 17 00:00:00 2001 From: Dominik Ermel Date: Fri, 20 Sep 2024 16:34:00 +0000 Subject: [PATCH 146/420] [nrf noup] bootutil: Add support for KMU stored ED25519 signature key The commit adds verification of image using keys stored in KMU. Signed-off-by: Dominik Ermel (cherry picked from commit 26192ca1c9986dd9f50b9e5537bfc38fd2953128) --- boot/bootutil/src/ed25519_psa.c | 51 ++++++++++++++++++++++++++++++ boot/bootutil/src/image_ed25519.c | 9 +++++- boot/bootutil/src/image_validate.c | 12 +++++-- boot/zephyr/CMakeLists.txt | 2 +- boot/zephyr/Kconfig | 26 +++++++++++++++ 5 files changed, 96 insertions(+), 4 deletions(-) diff --git a/boot/bootutil/src/ed25519_psa.c b/boot/bootutil/src/ed25519_psa.c index 5b8a4ed7c..cd016158b 100644 --- a/boot/bootutil/src/ed25519_psa.c +++ b/boot/bootutil/src/ed25519_psa.c @@ -12,6 +12,9 @@ #include #include +#if defined(CONFIG_BOOT_SIGNATURE_USING_KMU) +#include +#endif BOOT_LOG_MODULE_REGISTER(ed25519_psa); @@ -19,6 +22,18 @@ BOOT_LOG_MODULE_REGISTER(ed25519_psa); #define EDDSA_KEY_LENGTH 32 #define EDDSA_SIGNAGURE_LENGTH 64 +#if defined(CONFIG_BOOT_SIGNATURE_USING_KMU) +/* List of KMU stored key ids available for MCUboot */ +#define MAKE_PSA_KMU_KEY_ID(id) PSA_KEY_HANDLE_FROM_CRACEN_KMU_SLOT(CRACEN_KMU_KEY_USAGE_SCHEME_RAW, id) +static psa_key_id_t kmu_key_ids[3] = { + MAKE_PSA_KMU_KEY_ID(226), + MAKE_PSA_KMU_KEY_ID(228), + MAKE_PSA_KMU_KEY_ID(230) +}; +#define KMU_KEY_COUNT (sizeof(kmu_key_ids)/sizeof(kmu_key_ids[0])) +#endif + +#if !defined(CONFIG_BOOT_SIGNATURE_USING_KMU) int ED25519_verify(const uint8_t *message, size_t message_len, const uint8_t signature[EDDSA_SIGNAGURE_LENGTH], const uint8_t public_key[EDDSA_KEY_LENGTH]) @@ -71,3 +86,39 @@ int ED25519_verify(const uint8_t *message, size_t message_len, return ret; } +#else +int ED25519_verify(const uint8_t *message, size_t message_len, + const uint8_t signature[EDDSA_SIGNAGURE_LENGTH], + const uint8_t public_key[EDDSA_KEY_LENGTH]) +{ + ARG_UNUSED(public_key); + /* Set to any error */ + psa_status_t status = PSA_ERROR_BAD_STATE; + int ret = 0; /* Fail by default */ + + /* Initialize PSA Crypto */ + status = psa_crypto_init(); + if (status != PSA_SUCCESS) { + BOOT_LOG_ERR("PSA crypto init failed %d", status); + return 0; + } + + status = PSA_ERROR_BAD_STATE; + + for (int i = 0; i < KMU_KEY_COUNT; ++i) { + psa_key_id_t kid = kmu_key_ids[i]; + + status = psa_verify_message(kid, PSA_ALG_PURE_EDDSA, message, + message_len, signature, + EDDSA_SIGNAGURE_LENGTH); + if (status == PSA_SUCCESS) { + ret = 1; + break; + } + + BOOT_LOG_ERR("ED25519 signature verification failed %d", status); + } + + return ret; +} +#endif diff --git a/boot/bootutil/src/image_ed25519.c b/boot/bootutil/src/image_ed25519.c index 4d83bb3d7..1a02811e3 100644 --- a/boot/bootutil/src/image_ed25519.c +++ b/boot/bootutil/src/image_ed25519.c @@ -34,6 +34,7 @@ extern int ED25519_verify(const uint8_t *message, size_t message_len, const uint8_t signature[EDDSA_SIGNATURE_LENGTH], const uint8_t public_key[NUM_ED25519_BYTES]); +#if !defined(CONFIG_BOOT_SIGNATURE_USING_KMU) #if !defined(MCUBOOT_KEY_IMPORT_BYPASS_ASN) /* * Parse the public key used for signing. @@ -76,6 +77,7 @@ bootutil_import_key(uint8_t **cp, uint8_t *end) return 0; } #endif /* !defined(MCUBOOT_KEY_IMPORT_BYPASS_ASN) */ +#endif /* Signature verification base function. * The function takes buffer of specified length and tries to verify @@ -90,8 +92,10 @@ bootutil_verify(uint8_t *buf, uint32_t blen, { int rc; FIH_DECLARE(fih_rc, FIH_FAILURE); - uint8_t *pubkey; + uint8_t *pubkey = NULL; +#if !defined(CONFIG_BOOT_SIGNATURE_USING_KMU) uint8_t *end; +#endif BOOT_LOG_DBG("bootutil_verify: ED25519 key_id %d", (int)key_id); @@ -102,6 +106,7 @@ bootutil_verify(uint8_t *buf, uint32_t blen, goto out; } +#if !defined(CONFIG_BOOT_SIGNATURE_USING_KMU) pubkey = (uint8_t *)bootutil_keys[key_id].key; end = pubkey + *bootutil_keys[key_id].len; @@ -125,6 +130,8 @@ bootutil_verify(uint8_t *buf, uint32_t blen, } pubkey = end - NUM_ED25519_BYTES; +#endif + #endif rc = ED25519_verify(buf, blen, sig, pubkey); diff --git a/boot/bootutil/src/image_validate.c b/boot/bootutil/src/image_validate.c index e375e97ab..a4a39b548 100644 --- a/boot/bootutil/src/image_validate.c +++ b/boot/bootutil/src/image_validate.c @@ -295,6 +295,7 @@ bootutil_img_hash(struct boot_loader_state *state, # define KEY_BUF_SIZE (SIG_BUF_SIZE + 24) #endif /* !MCUBOOT_HW_KEY */ +#if !defined(CONFIG_BOOT_SIGNATURE_USING_KMU) #if !defined(MCUBOOT_HW_KEY) static int bootutil_find_key(uint8_t *keyhash, uint8_t keyhash_len) @@ -363,6 +364,7 @@ bootutil_find_key(uint8_t image_index, uint8_t *key, uint16_t key_len) } #endif /* !MCUBOOT_HW_KEY */ #endif /* !MCUBOOT_BUILTIN_KEY */ +#endif /* !defined(CONFIG_BOOT_SIGNATURE_USING_KMU) */ #endif /* EXPECTED_SIG_TLV */ /** @@ -744,6 +746,7 @@ bootutil_img_validate(struct boot_loader_state *state, break; } #endif /* defined(EXPECTED_HASH_TLV) && !defined(MCUBOOT_SIGN_PURE) */ +#if !defined(CONFIG_BOOT_SIGNATURE_USING_KMU) #ifdef EXPECTED_KEY_TLV case EXPECTED_KEY_TLV: { @@ -775,15 +778,18 @@ bootutil_img_validate(struct boot_loader_state *state, break; } #endif /* EXPECTED_KEY_TLV */ +#endif /* !defined(CONFIG_BOOT_SIGNATURE_USING_KMU) */ #ifdef EXPECTED_SIG_TLV case EXPECTED_SIG_TLV: { BOOT_LOG_DBG("bootutil_img_validate: EXPECTED_SIG_TLV == %d", EXPECTED_SIG_TLV); +#if !defined(CONFIG_BOOT_SIGNATURE_USING_KMU) /* Ignore this signature if it is out of bounds. */ if (key_id < 0 || key_id >= bootutil_key_cnt) { key_id = -1; continue; } +#endif /* !defined(CONFIG_BOOT_SIGNATURE_USING_KMU) */ if (!EXPECTED_SIG_LEN(len) || len > sizeof(buf)) { rc = -1; goto out; @@ -1029,7 +1035,7 @@ bootutil_img_validate(struct boot_loader_state *state, } #ifdef EXPECTED_SIG_TLV -#ifdef EXPECTED_KEY_TLV +#if !defined(CONFIG_BOOT_SIGNATURE_USING_KMU) && defined(EXPECTED_KEY_TLV) rc = bootutil_tlv_iter_begin(&it, hdr, fap, EXPECTED_KEY_TLV, false); if (rc) { goto out; @@ -1075,7 +1081,7 @@ bootutil_img_validate(struct boot_loader_state *state, */ } } -#endif /* EXPECTED_KEY_TLV */ +#endif /* !CONFIG_BOOT_SIGNATURE_USING_KMU && EXPECTED_KEY_TLV */ rc = bootutil_tlv_iter_begin(&it, hdr, fap, IMAGE_TLV_DECOMP_SIGNATURE, true); if (rc) { @@ -1098,10 +1104,12 @@ bootutil_img_validate(struct boot_loader_state *state, if (type == IMAGE_TLV_DECOMP_SIGNATURE) { /* Ignore this signature if it is out of bounds. */ +#if !defined(CONFIG_BOOT_SIGNATURE_USING_KMU) if (key_id < 0 || key_id >= bootutil_key_cnt) { key_id = -1; continue; } +#endif if (!EXPECTED_SIG_LEN(len) || len > sizeof(buf)) { rc = -1; diff --git a/boot/zephyr/CMakeLists.txt b/boot/zephyr/CMakeLists.txt index 4d1cd5301..fddf35927 100644 --- a/boot/zephyr/CMakeLists.txt +++ b/boot/zephyr/CMakeLists.txt @@ -361,7 +361,7 @@ if(CONFIG_MCUBOOT_SERIAL) endif() endif() -if(NOT CONFIG_BOOT_SIGNATURE_KEY_FILE STREQUAL "") +if(NOT CONFIG_BOOT_SIGNATURE_USING_KMU AND NOT CONFIG_BOOT_SIGNATURE_KEY_FILE STREQUAL "") # CONF_FILE points to the KConfig configuration files of the bootloader. foreach (filepath ${CONF_FILE}) file(READ ${filepath} temp_text) diff --git a/boot/zephyr/Kconfig b/boot/zephyr/Kconfig index 0cc72422f..aa364fe8f 100644 --- a/boot/zephyr/Kconfig +++ b/boot/zephyr/Kconfig @@ -384,6 +384,22 @@ endif endchoice +config BOOT_SIGNATURE_USING_KMU + bool "Use KMU stored keys for signature verification" + depends on NRF_SECURITY + depends on CRACEN_LIB_KMU + select PSA_WANT_ALG_GCM + select PSA_WANT_KEY_TYPE_AES + select PSA_WANT_AES_KEY_SIZE_256 + select PSA_WANT_ALG_SP800_108_COUNTER_CMAC + select PSA_WANT_ALG_CMAC + select PSA_WANT_ALG_ECB_NO_PADDING + help + MCUboot will use keys provisioned to the device key management unit for signature + verification instead of compiling in key data from a file. + +if !BOOT_SIGNATURE_USING_KMU + config BOOT_SIGNATURE_KEY_FILE string "PEM key file" default "root-ec-p256.pem" if BOOT_SIGNATURE_TYPE_ECDSA_P256 @@ -401,6 +417,8 @@ config BOOT_SIGNATURE_KEY_FILE with the public key information will be written in a format expected by MCUboot. +endif + config MCUBOOT_CLEANUP_ARM_CORE bool "Perform core cleanup before chain-load the application" depends on CPU_CORTEX_M @@ -437,6 +455,14 @@ config MCUBOOT_INFINITE_LOOP_AFTER_RAM_CLEANUP Verification option that keeps execution in infinite loop after RAM cleanup has been performed. +# Disable MBEDTLS from being selected if NRF_SECURITY is enabled, and use default NRF_SECURITY +# configuration file for MBEDTLS +config MBEDTLS + depends on !NRF_SECURITY + +config NRF_SECURITY + select MBEDTLS_PROMPTLESS + config MBEDTLS_CFG_FILE # It might be awkward to define an Mbed TLS header file when TinyCrypt # is used, but the fact is that Mbed TLS' ASN1 parse module is used From 83d1d959de612b8bc17dae56355b0ccc40cebde6 Mon Sep 17 00:00:00 2001 From: Jamie McCrae Date: Mon, 2 Dec 2024 10:51:41 +0000 Subject: [PATCH 147/420] [nrf noup] boot: bootutil: Allow configuring number of KMU keys Adds a new Kconfig CONFIG_BOOT_SIGNATURE_KMU_SLOTS which allows specifying how many KMU key IDs are supported, the default is set to 1 instead of 3 which was set before NCSDK-30743 Signed-off-by: Jamie McCrae Signed-off-by: Dominik Ermel (cherry picked from commit 373038be7dde47f025974e6591e91d0dad8ab355) --- boot/bootutil/src/ed25519_psa.c | 7 +++++-- boot/zephyr/Kconfig | 12 ++++++++++++ 2 files changed, 17 insertions(+), 2 deletions(-) diff --git a/boot/bootutil/src/ed25519_psa.c b/boot/bootutil/src/ed25519_psa.c index cd016158b..7665e4067 100644 --- a/boot/bootutil/src/ed25519_psa.c +++ b/boot/bootutil/src/ed25519_psa.c @@ -12,6 +12,7 @@ #include #include +#include #if defined(CONFIG_BOOT_SIGNATURE_USING_KMU) #include #endif @@ -30,7 +31,9 @@ static psa_key_id_t kmu_key_ids[3] = { MAKE_PSA_KMU_KEY_ID(228), MAKE_PSA_KMU_KEY_ID(230) }; -#define KMU_KEY_COUNT (sizeof(kmu_key_ids)/sizeof(kmu_key_ids[0])) + +BUILD_ASSERT(CONFIG_BOOT_SIGNATURE_KMU_SLOTS <= ARRAY_SIZE(kmu_key_ids), + "Invalid number of KMU slots, up to 3 are supported on nRF54L15"); #endif #if !defined(CONFIG_BOOT_SIGNATURE_USING_KMU) @@ -105,7 +108,7 @@ int ED25519_verify(const uint8_t *message, size_t message_len, status = PSA_ERROR_BAD_STATE; - for (int i = 0; i < KMU_KEY_COUNT; ++i) { + for (int i = 0; i < CONFIG_BOOT_SIGNATURE_KMU_SLOTS; ++i) { psa_key_id_t kid = kmu_key_ids[i]; status = psa_verify_message(kid, PSA_ALG_PURE_EDDSA, message, diff --git a/boot/zephyr/Kconfig b/boot/zephyr/Kconfig index aa364fe8f..4de39e577 100644 --- a/boot/zephyr/Kconfig +++ b/boot/zephyr/Kconfig @@ -398,6 +398,18 @@ config BOOT_SIGNATURE_USING_KMU MCUboot will use keys provisioned to the device key management unit for signature verification instead of compiling in key data from a file. +if BOOT_SIGNATURE_USING_KMU + +config BOOT_SIGNATURE_KMU_SLOTS + int "KMU key slots" + range 1 3 + default 1 + help + Selects the number of KMU key slots (also known as generations) to use when verifying + an image. + +endif + if !BOOT_SIGNATURE_USING_KMU config BOOT_SIGNATURE_KEY_FILE From 51b0897bc30cf6cf5a33127bdd5501e59d051499 Mon Sep 17 00:00:00 2001 From: Mateusz Michalek Date: Mon, 17 Mar 2025 21:25:41 +0100 Subject: [PATCH 148/420] [nrf noup] bootutil: key revocation Disable previous generation key when update comes with new valid key and application is confirmed. Signed-off-by: Mateusz Michalek Signed-off-by: Dominik Ermel (cherry picked from commit 9dacf6dbff98acc4eb93312393eee8a197064ea2) --- .../include/bootutil/key_revocation.h | 30 ++++++++++++++ boot/bootutil/src/ed25519_psa.c | 41 +++++++++++++++++++ boot/bootutil/src/key_revocation.c | 24 +++++++++++ boot/bootutil/src/loader.c | 16 ++++++++ boot/zephyr/CMakeLists.txt | 6 +++ boot/zephyr/Kconfig | 12 ++++++ 6 files changed, 129 insertions(+) create mode 100644 boot/bootutil/include/bootutil/key_revocation.h create mode 100644 boot/bootutil/src/key_revocation.c diff --git a/boot/bootutil/include/bootutil/key_revocation.h b/boot/bootutil/include/bootutil/key_revocation.h new file mode 100644 index 000000000..d184c9579 --- /dev/null +++ b/boot/bootutil/include/bootutil/key_revocation.h @@ -0,0 +1,30 @@ +/* + * Copyright (c) 2025 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: LicenseRef-Nordic-5-Clause + */ + +#ifndef H_KEY_REVOCATION_ +#define H_KEY_REVOCATION_ + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +#define BOOT_KEY_REVOKE_OK 0 +#define BOOT_KEY_REVOKE_NOT_READY 1 +#define BOOT_KEY_REVOKE_INVALID 2 +#define BOOT_KEY_REVOKE_FAILED 2 + + +void allow_revoke(void); + +int revoke(void); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/boot/bootutil/src/ed25519_psa.c b/boot/bootutil/src/ed25519_psa.c index 7665e4067..6393d996e 100644 --- a/boot/bootutil/src/ed25519_psa.c +++ b/boot/bootutil/src/ed25519_psa.c @@ -32,6 +32,11 @@ static psa_key_id_t kmu_key_ids[3] = { MAKE_PSA_KMU_KEY_ID(230) }; +#if defined(CONFIG_BOOT_KMU_KEYS_REVOCATION) +#include +static psa_key_id_t *validated_with = NULL; +#endif + BUILD_ASSERT(CONFIG_BOOT_SIGNATURE_KMU_SLOTS <= ARRAY_SIZE(kmu_key_ids), "Invalid number of KMU slots, up to 3 are supported on nRF54L15"); #endif @@ -116,6 +121,9 @@ int ED25519_verify(const uint8_t *message, size_t message_len, EDDSA_SIGNAGURE_LENGTH); if (status == PSA_SUCCESS) { ret = 1; +#if defined(CONFIG_BOOT_KMU_KEYS_REVOCATION) + validated_with = kmu_key_ids + i; +#endif break; } @@ -124,4 +132,37 @@ int ED25519_verify(const uint8_t *message, size_t message_len, return ret; } +#if defined(CONFIG_BOOT_KMU_KEYS_REVOCATION) +int exec_revoke(void) +{ + int ret = BOOT_KEY_REVOKE_OK; + psa_status_t status = psa_crypto_init(); + + if (!validated_with) { + ret = BOOT_KEY_REVOKE_INVALID; + goto out; + } + + if (status != PSA_SUCCESS) { + BOOT_LOG_ERR("PSA crypto init failed with error %d", status); + ret = BOOT_KEY_REVOKE_FAILED; + goto out; + } + for (int i = 0; i < CONFIG_BOOT_SIGNATURE_KMU_SLOTS; i++) { + if ((kmu_key_ids + i) == validated_with) { + break; + } + BOOT_LOG_DBG("Invalidating key ID %d", i); + + status = psa_destroy_key(kmu_key_ids[i]); + if (status == PSA_SUCCESS) { + BOOT_LOG_DBG("Success on key ID %d", i); + } else { + BOOT_LOG_ERR("Key invalidation failed with: %d", status); + } + } +out: + return ret; +} +#endif /* CONFIG_BOOT_KMU_KEYS_REVOCATION */ #endif diff --git a/boot/bootutil/src/key_revocation.c b/boot/bootutil/src/key_revocation.c new file mode 100644 index 000000000..0768a3188 --- /dev/null +++ b/boot/bootutil/src/key_revocation.c @@ -0,0 +1,24 @@ +/* + * Copyright (c) 2025 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: LicenseRef-Nordic-5-Clause + */ + +#include + +extern int exec_revoke(void); + +static uint8_t ready_to_revoke; + +void allow_revoke(void) +{ + ready_to_revoke = 1; +} + +int revoke(void) +{ + if (ready_to_revoke) { + return exec_revoke(); + } + return BOOT_KEY_REVOKE_NOT_READY; +} diff --git a/boot/bootutil/src/loader.c b/boot/bootutil/src/loader.c index 3e199ad4a..1a2290769 100644 --- a/boot/bootutil/src/loader.c +++ b/boot/bootutil/src/loader.c @@ -80,6 +80,10 @@ int pcd_version_cmp_net(const struct flash_area *fap, struct image_header *hdr); #include "mcuboot_config/mcuboot_config.h" +#if defined(CONFIG_BOOT_KEYS_REVOCATION) +#include "bootutil/key_revocation.h" +#endif + BOOT_LOG_MODULE_DECLARE(mcuboot); static struct boot_loader_state boot_data; @@ -3110,6 +3114,11 @@ context_boot_go(struct boot_loader_state *state, struct boot_rsp *rsp) } } +#if defined(CONFIG_BOOT_KEYS_REVOCATION) + if (BOOT_SWAP_TYPE(state) == BOOT_SWAP_TYPE_NONE) { + allow_revoke(); + } +#endif /* Iterate over all the images. At this point all required update operations * have finished. By the end of the loop each image in the primary slot will * have been re-validated. @@ -3218,6 +3227,13 @@ context_boot_go(struct boot_loader_state *state, struct boot_rsp *rsp) fill_rsp(state, rsp); fih_rc = FIH_SUCCESS; +#if defined(CONFIG_BOOT_KEYS_REVOCATION) + rc = revoke(); + if (rc != BOOT_KEY_REVOKE_OK && + rc != BOOT_KEY_REVOKE_NOT_READY) { + FIH_SET(fih_rc, FIH_FAILURE); + } +#endif /* CONFIG_BOOT_KEYS_REVOCATION */ out: /* * Since the boot_status struct stores plaintext encryption keys, reset diff --git a/boot/zephyr/CMakeLists.txt b/boot/zephyr/CMakeLists.txt index fddf35927..f9e0e70bc 100644 --- a/boot/zephyr/CMakeLists.txt +++ b/boot/zephyr/CMakeLists.txt @@ -104,6 +104,12 @@ if(DEFINED CONFIG_BOOT_SHARE_BACKEND_RETENTION) ) endif() +if(DEFINED CONFIG_BOOT_KEYS_REVOCATION) + zephyr_library_sources( + ${BOOT_DIR}/bootutil/src/key_revocation.c +) +endif() + # Generic bootutil sources and includes. zephyr_library_include_directories(${BOOT_DIR}/bootutil/include) zephyr_library_sources( diff --git a/boot/zephyr/Kconfig b/boot/zephyr/Kconfig index 4de39e577..73b3bef7b 100644 --- a/boot/zephyr/Kconfig +++ b/boot/zephyr/Kconfig @@ -410,6 +410,18 @@ config BOOT_SIGNATURE_KMU_SLOTS endif +config BOOT_KEYS_REVOCATION + bool "Auto revoke previous gen key" + help + Automatically revoke previous generation key upon new valid key usage. + +config BOOT_KMU_KEYS_REVOCATION + bool + depends on BOOT_KEYS_REVOCATION + default y if BOOT_SIGNATURE_USING_KMU + help + Enabling KMU key revocation backend. + if !BOOT_SIGNATURE_USING_KMU config BOOT_SIGNATURE_KEY_FILE From 7ed49272a2f00e3e0936c333f2a0240e99226963 Mon Sep 17 00:00:00 2001 From: Artur Hadasz Date: Thu, 24 Jul 2025 13:31:00 +0200 Subject: [PATCH 149/420] [nrf noup] Added BOOT_SIGNATURE_USING_ITS for ecdsa configuration This configuration has the purpose of using keys provisioned to the internal trusted storage (ITS). It makes use of the already existing parts of code for MCUBOOT_BUILTIN_KEY Signed-off-by: Artur Hadasz (cherry picked from commit d69621e3032f03ddf462eb3a9d2df5af03955898) --- boot/bootutil/include/bootutil/crypto/ecdsa.h | 50 +++++++++++++++++++ boot/bootutil/src/image_validate.c | 3 +- boot/zephyr/Kconfig | 9 +++- .../include/mcuboot_config/mcuboot_config.h | 4 ++ 4 files changed, 64 insertions(+), 2 deletions(-) diff --git a/boot/bootutil/include/bootutil/crypto/ecdsa.h b/boot/bootutil/include/bootutil/crypto/ecdsa.h index a5d0f8b1b..31d7bec9a 100644 --- a/boot/bootutil/include/bootutil/crypto/ecdsa.h +++ b/boot/bootutil/include/bootutil/crypto/ecdsa.h @@ -473,6 +473,7 @@ static int bootutil_ecdsa_parse_public_key(bootutil_ecdsa_context *ctx, } #endif /* !MCUBOOT_BUILTIN_KEY */ +#if !defined(CONFIG_NRF_BOOT_SIGNATURE_USING_ITS) /* Verify the signature against the provided hash. The signature gets parsed from * the encoding first, then PSA Crypto has a dedicated API for ECDSA verification */ @@ -491,6 +492,55 @@ static inline int bootutil_ecdsa_verify(bootutil_ecdsa_context *ctx, return (int) psa_verify_hash(ctx->key_id, PSA_ALG_ECDSA(ctx->required_algorithm), hash, hlen, reformatted_signature, 2*ctx->curve_byte_count); } +#else /* !CONFIG_NRF_BOOT_SIGNATURE_USING_ITS */ + +static const psa_key_id_t builtin_key_ids[] = { + 0x40022100, + 0x40022101, + 0x40022102, + 0x40022103 +}; + +#define BOOT_SIGNATURE_BUILTIN_KEY_SLOTS ARRAY_SIZE(builtin_key_ids) + +static inline int bootutil_ecdsa_verify(bootutil_ecdsa_context *ctx, + uint8_t *pk, size_t pk_len, + uint8_t *hash, size_t hlen, + uint8_t *sig, size_t slen) +{ + (void)pk; + (void)pk_len; + (void)slen; + psa_status_t status = PSA_ERROR_BAD_STATE; + + /* Initialize PSA Crypto */ + status = psa_crypto_init(); + if (status != PSA_SUCCESS) { + BOOT_LOG_ERR("PSA crypto init failed %d", status); + return 1; + } + + uint8_t reformatted_signature[96] = {0}; /* Enough for P-384 signature sizes */ + parse_signature_from_rfc5480_encoding(sig, ctx->curve_byte_count, reformatted_signature); + + status = PSA_ERROR_BAD_STATE; + + for (int i = 0; i < BOOT_SIGNATURE_BUILTIN_KEY_SLOTS; ++i) { + psa_key_id_t kid = builtin_key_ids[i]; + + status = psa_verify_hash(kid, PSA_ALG_ECDSA(ctx->required_algorithm), + hash, hlen, reformatted_signature, 2*ctx->curve_byte_count); + if (status == PSA_SUCCESS) { + break; + } + BOOT_LOG_ERR("ECDSA signature verification failed %d", status); + } + + return status == PSA_SUCCESS ? 0 : 2; +} + +#endif /* !CONFIG_NRF_BOOT_SIGNATURE_USING_ITS */ + #elif defined(MCUBOOT_USE_MBED_TLS) typedef mbedtls_ecdsa_context bootutil_ecdsa_context; diff --git a/boot/bootutil/src/image_validate.c b/boot/bootutil/src/image_validate.c index a4a39b548..53d5b860b 100644 --- a/boot/bootutil/src/image_validate.c +++ b/boot/bootutil/src/image_validate.c @@ -518,7 +518,8 @@ bootutil_img_validate(struct boot_loader_state *state, ) { #if (defined(EXPECTED_KEY_TLV) && defined(MCUBOOT_HW_KEY)) || defined(MCUBOOT_HW_ROLLBACK_PROT) \ - || defined(MCUBOOT_UUID_VID) || defined(MCUBOOT_UUID_CID) || defined(MCUBOOT_DECOMPRESS_IMAGES) + || defined(MCUBOOT_UUID_VID) || defined(MCUBOOT_UUID_CID) || defined(MCUBOOT_DECOMPRESS_IMAGES) \ + || defined(MCUBOOT_BUILTIN_KEY) int image_index = (state == NULL ? 0 : BOOT_CURR_IMG(state)); #endif uint32_t off; diff --git a/boot/zephyr/Kconfig b/boot/zephyr/Kconfig index 73b3bef7b..965e65da3 100644 --- a/boot/zephyr/Kconfig +++ b/boot/zephyr/Kconfig @@ -422,7 +422,14 @@ config BOOT_KMU_KEYS_REVOCATION help Enabling KMU key revocation backend. -if !BOOT_SIGNATURE_USING_KMU +config NRF_BOOT_SIGNATURE_USING_ITS + bool "Use ITS stored keys for signature verification" + depends on NRF_SECURITY + help + MCUboot will use keys provisioned to the internal trusted storage for signature + verification instead of compiling in key data from a file. + +if !BOOT_SIGNATURE_USING_KMU && !NRF_BOOT_SIGNATURE_USING_ITS config BOOT_SIGNATURE_KEY_FILE string "PEM key file" diff --git a/boot/zephyr/include/mcuboot_config/mcuboot_config.h b/boot/zephyr/include/mcuboot_config/mcuboot_config.h index eb64c12eb..1f2c03759 100644 --- a/boot/zephyr/include/mcuboot_config/mcuboot_config.h +++ b/boot/zephyr/include/mcuboot_config/mcuboot_config.h @@ -68,6 +68,10 @@ #define MCUBOOT_HW_KEY #endif +#ifdef CONFIG_NRF_BOOT_SIGNATURE_USING_ITS +#define MCUBOOT_BUILTIN_KEY +#endif + #ifdef CONFIG_BOOT_VALIDATE_SLOT0 #define MCUBOOT_VALIDATE_PRIMARY_SLOT #endif From a4bae1322e51d086c454aa5a870441ba4c995b80 Mon Sep 17 00:00:00 2001 From: Dominik Ermel Date: Fri, 1 Aug 2025 10:36:12 +0000 Subject: [PATCH 150/420] [nrf noup] boot: Use NCS_ prefix for sdk-nrf specific Kconfigs nrf-squash! [nrf noup] Added BOOT_SIGNATURE_USING_ITS for ecdsa configuration Replace NRF_BOOT_SIGNATURE_USING_ITS with NCS_BOOT_SIGNATURE_USING_ITS prefix. Signed-off-by: Dominik Ermel (cherry picked from commit 4bfb139af4fadbc651ea61e27d21331834ce2307) --- boot/bootutil/include/bootutil/crypto/ecdsa.h | 6 +++--- boot/zephyr/Kconfig | 4 ++-- boot/zephyr/include/mcuboot_config/mcuboot_config.h | 2 +- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/boot/bootutil/include/bootutil/crypto/ecdsa.h b/boot/bootutil/include/bootutil/crypto/ecdsa.h index 31d7bec9a..0e9205c29 100644 --- a/boot/bootutil/include/bootutil/crypto/ecdsa.h +++ b/boot/bootutil/include/bootutil/crypto/ecdsa.h @@ -473,7 +473,7 @@ static int bootutil_ecdsa_parse_public_key(bootutil_ecdsa_context *ctx, } #endif /* !MCUBOOT_BUILTIN_KEY */ -#if !defined(CONFIG_NRF_BOOT_SIGNATURE_USING_ITS) +#if !defined(CONFIG_NCS_BOOT_SIGNATURE_USING_ITS) /* Verify the signature against the provided hash. The signature gets parsed from * the encoding first, then PSA Crypto has a dedicated API for ECDSA verification */ @@ -492,7 +492,7 @@ static inline int bootutil_ecdsa_verify(bootutil_ecdsa_context *ctx, return (int) psa_verify_hash(ctx->key_id, PSA_ALG_ECDSA(ctx->required_algorithm), hash, hlen, reformatted_signature, 2*ctx->curve_byte_count); } -#else /* !CONFIG_NRF_BOOT_SIGNATURE_USING_ITS */ +#else /* !CONFIG_NCS_BOOT_SIGNATURE_USING_ITS */ static const psa_key_id_t builtin_key_ids[] = { 0x40022100, @@ -539,7 +539,7 @@ static inline int bootutil_ecdsa_verify(bootutil_ecdsa_context *ctx, return status == PSA_SUCCESS ? 0 : 2; } -#endif /* !CONFIG_NRF_BOOT_SIGNATURE_USING_ITS */ +#endif /* !CONFIG_NCS_BOOT_SIGNATURE_USING_ITS */ #elif defined(MCUBOOT_USE_MBED_TLS) diff --git a/boot/zephyr/Kconfig b/boot/zephyr/Kconfig index 965e65da3..03fa2d9c2 100644 --- a/boot/zephyr/Kconfig +++ b/boot/zephyr/Kconfig @@ -422,14 +422,14 @@ config BOOT_KMU_KEYS_REVOCATION help Enabling KMU key revocation backend. -config NRF_BOOT_SIGNATURE_USING_ITS +config NCS_BOOT_SIGNATURE_USING_ITS bool "Use ITS stored keys for signature verification" depends on NRF_SECURITY help MCUboot will use keys provisioned to the internal trusted storage for signature verification instead of compiling in key data from a file. -if !BOOT_SIGNATURE_USING_KMU && !NRF_BOOT_SIGNATURE_USING_ITS +if !BOOT_SIGNATURE_USING_KMU && !NCS_BOOT_SIGNATURE_USING_ITS config BOOT_SIGNATURE_KEY_FILE string "PEM key file" diff --git a/boot/zephyr/include/mcuboot_config/mcuboot_config.h b/boot/zephyr/include/mcuboot_config/mcuboot_config.h index 1f2c03759..6c860e01d 100644 --- a/boot/zephyr/include/mcuboot_config/mcuboot_config.h +++ b/boot/zephyr/include/mcuboot_config/mcuboot_config.h @@ -68,7 +68,7 @@ #define MCUBOOT_HW_KEY #endif -#ifdef CONFIG_NRF_BOOT_SIGNATURE_USING_ITS +#ifdef CONFIG_NCS_BOOT_SIGNATURE_USING_ITS #define MCUBOOT_BUILTIN_KEY #endif From 227eb0a50d1b1fa52f853b2cc4ff1e8cca4bbf71 Mon Sep 17 00:00:00 2001 From: Michal Kozikowski Date: Fri, 22 Aug 2025 12:59:08 +0200 Subject: [PATCH 151/420] [nrf noup] Support for ed25519 signature verification using ITS Thic commit introduces support for ed25519 signature verification when CONFIG_NCS_BOOT_SIGNATURE_USING_ITS is set (through PSA API). Signed-off-by: Michal Kozikowski (cherry picked from commit 391f093019ebcf74bf460b1be4120f2816fa9eb9) --- boot/bootutil/src/ed25519_psa.c | 38 ++++++++++++++++++++---------- boot/bootutil/src/image_ed25519.c | 6 +++-- boot/bootutil/src/image_validate.c | 6 ++--- 3 files changed, 32 insertions(+), 18 deletions(-) diff --git a/boot/bootutil/src/ed25519_psa.c b/boot/bootutil/src/ed25519_psa.c index 6393d996e..8460da7c8 100644 --- a/boot/bootutil/src/ed25519_psa.c +++ b/boot/bootutil/src/ed25519_psa.c @@ -26,22 +26,35 @@ BOOT_LOG_MODULE_REGISTER(ed25519_psa); #if defined(CONFIG_BOOT_SIGNATURE_USING_KMU) /* List of KMU stored key ids available for MCUboot */ #define MAKE_PSA_KMU_KEY_ID(id) PSA_KEY_HANDLE_FROM_CRACEN_KMU_SLOT(CRACEN_KMU_KEY_USAGE_SCHEME_RAW, id) -static psa_key_id_t kmu_key_ids[3] = { +static psa_key_id_t key_ids[] = { MAKE_PSA_KMU_KEY_ID(226), MAKE_PSA_KMU_KEY_ID(228), MAKE_PSA_KMU_KEY_ID(230) }; +#define KEY_SLOTS_COUNT CONFIG_BOOT_SIGNATURE_KMU_SLOTS + #if defined(CONFIG_BOOT_KMU_KEYS_REVOCATION) #include static psa_key_id_t *validated_with = NULL; #endif -BUILD_ASSERT(CONFIG_BOOT_SIGNATURE_KMU_SLOTS <= ARRAY_SIZE(kmu_key_ids), +BUILD_ASSERT(CONFIG_BOOT_SIGNATURE_KMU_SLOTS <= ARRAY_SIZE(key_ids), "Invalid number of KMU slots, up to 3 are supported on nRF54L15"); #endif -#if !defined(CONFIG_BOOT_SIGNATURE_USING_KMU) +#if defined(CONFIG_NCS_BOOT_SIGNATURE_USING_ITS) +static const psa_key_id_t key_ids[] = { + 0x40022100, + 0x40022101, + 0x40022102, + 0x40022103 +}; + +#define KEY_SLOTS_COUNT ARRAY_SIZE(key_ids) +#endif + +#if !defined(CONFIG_BOOT_SIGNATURE_USING_KMU) && !defined(CONFIG_NCS_BOOT_SIGNATURE_USING_ITS) int ED25519_verify(const uint8_t *message, size_t message_len, const uint8_t signature[EDDSA_SIGNAGURE_LENGTH], const uint8_t public_key[EDDSA_KEY_LENGTH]) @@ -102,7 +115,6 @@ int ED25519_verify(const uint8_t *message, size_t message_len, ARG_UNUSED(public_key); /* Set to any error */ psa_status_t status = PSA_ERROR_BAD_STATE; - int ret = 0; /* Fail by default */ /* Initialize PSA Crypto */ status = psa_crypto_init(); @@ -113,24 +125,24 @@ int ED25519_verify(const uint8_t *message, size_t message_len, status = PSA_ERROR_BAD_STATE; - for (int i = 0; i < CONFIG_BOOT_SIGNATURE_KMU_SLOTS; ++i) { - psa_key_id_t kid = kmu_key_ids[i]; + for (int i = 0; i < KEY_SLOTS_COUNT; ++i) { + psa_key_id_t kid = key_ids[i]; status = psa_verify_message(kid, PSA_ALG_PURE_EDDSA, message, message_len, signature, EDDSA_SIGNAGURE_LENGTH); if (status == PSA_SUCCESS) { - ret = 1; #if defined(CONFIG_BOOT_KMU_KEYS_REVOCATION) - validated_with = kmu_key_ids + i; + validated_with = key_ids + i; #endif - break; + return 1; } - BOOT_LOG_ERR("ED25519 signature verification failed %d", status); } - return ret; + BOOT_LOG_ERR("ED25519 signature verification failed %d", status); + + return 0; } #if defined(CONFIG_BOOT_KMU_KEYS_REVOCATION) int exec_revoke(void) @@ -149,12 +161,12 @@ int exec_revoke(void) goto out; } for (int i = 0; i < CONFIG_BOOT_SIGNATURE_KMU_SLOTS; i++) { - if ((kmu_key_ids + i) == validated_with) { + if ((key_ids + i) == validated_with) { break; } BOOT_LOG_DBG("Invalidating key ID %d", i); - status = psa_destroy_key(kmu_key_ids[i]); + status = psa_destroy_key(key_ids[i]); if (status == PSA_SUCCESS) { BOOT_LOG_DBG("Success on key ID %d", i); } else { diff --git a/boot/bootutil/src/image_ed25519.c b/boot/bootutil/src/image_ed25519.c index 1a02811e3..177550749 100644 --- a/boot/bootutil/src/image_ed25519.c +++ b/boot/bootutil/src/image_ed25519.c @@ -36,6 +36,7 @@ extern int ED25519_verify(const uint8_t *message, size_t message_len, #if !defined(CONFIG_BOOT_SIGNATURE_USING_KMU) #if !defined(MCUBOOT_KEY_IMPORT_BYPASS_ASN) +#if !defined(CONFIG_NCS_BOOT_SIGNATURE_USING_ITS) /* * Parse the public key used for signing. */ @@ -78,6 +79,7 @@ bootutil_import_key(uint8_t **cp, uint8_t *end) } #endif /* !defined(MCUBOOT_KEY_IMPORT_BYPASS_ASN) */ #endif +#endif /* Signature verification base function. * The function takes buffer of specified length and tries to verify @@ -93,7 +95,7 @@ bootutil_verify(uint8_t *buf, uint32_t blen, int rc; FIH_DECLARE(fih_rc, FIH_FAILURE); uint8_t *pubkey = NULL; -#if !defined(CONFIG_BOOT_SIGNATURE_USING_KMU) +#if !defined(CONFIG_BOOT_SIGNATURE_USING_KMU) && !defined(CONFIG_NCS_BOOT_SIGNATURE_USING_ITS) uint8_t *end; #endif @@ -106,7 +108,7 @@ bootutil_verify(uint8_t *buf, uint32_t blen, goto out; } -#if !defined(CONFIG_BOOT_SIGNATURE_USING_KMU) +#if !defined(CONFIG_BOOT_SIGNATURE_USING_KMU) && !defined(CONFIG_NCS_BOOT_SIGNATURE_USING_ITS) pubkey = (uint8_t *)bootutil_keys[key_id].key; end = pubkey + *bootutil_keys[key_id].len; diff --git a/boot/bootutil/src/image_validate.c b/boot/bootutil/src/image_validate.c index 53d5b860b..cc5c040bb 100644 --- a/boot/bootutil/src/image_validate.c +++ b/boot/bootutil/src/image_validate.c @@ -784,13 +784,13 @@ bootutil_img_validate(struct boot_loader_state *state, case EXPECTED_SIG_TLV: { BOOT_LOG_DBG("bootutil_img_validate: EXPECTED_SIG_TLV == %d", EXPECTED_SIG_TLV); -#if !defined(CONFIG_BOOT_SIGNATURE_USING_KMU) +#if !defined(CONFIG_BOOT_SIGNATURE_USING_KMU) && !defined(CONFIG_NCS_BOOT_SIGNATURE_USING_ITS) /* Ignore this signature if it is out of bounds. */ if (key_id < 0 || key_id >= bootutil_key_cnt) { key_id = -1; continue; } -#endif /* !defined(CONFIG_BOOT_SIGNATURE_USING_KMU) */ +#endif /* !defined(CONFIG_BOOT_SIGNATURE_USING_KMU) && !defined(CONFIG_NCS_BOOT_SIGNATURE_USING_ITS) */ if (!EXPECTED_SIG_LEN(len) || len > sizeof(buf)) { rc = -1; goto out; @@ -1105,7 +1105,7 @@ bootutil_img_validate(struct boot_loader_state *state, if (type == IMAGE_TLV_DECOMP_SIGNATURE) { /* Ignore this signature if it is out of bounds. */ -#if !defined(CONFIG_BOOT_SIGNATURE_USING_KMU) +#if !defined(CONFIG_BOOT_SIGNATURE_USING_KMU) && !defined(CONFIG_NCS_BOOT_SIGNATURE_USING_ITS) if (key_id < 0 || key_id >= bootutil_key_cnt) { key_id = -1; continue; From 25f49810540e2ef2cba43ef8388ea78418f642d0 Mon Sep 17 00:00:00 2001 From: Tomasz Chyrowicz Date: Fri, 5 Sep 2025 15:49:29 +0200 Subject: [PATCH 152/420] [nrf noup] zephyr: Add basic UUID checks implementation Provide an implementation for MCUboot UUID checks that specify a single, common vendor identifier and a unique class identifier for each image. Ref: NCSDK-34175 Signed-off-by: Tomasz Chyrowicz --- boot/zephyr/CMakeLists.txt | 3 ++ boot/zephyr/Kconfig | 2 + boot/zephyr/uuid/CMakeLists.txt | 74 ++++++++++++++++++++++++++ boot/zephyr/uuid/Kconfig | 55 +++++++++++++++++++ boot/zephyr/uuid/Kconfig.uuid.template | 29 ++++++++++ boot/zephyr/uuid/uuid.c | 74 ++++++++++++++++++++++++++ 6 files changed, 237 insertions(+) create mode 100644 boot/zephyr/uuid/CMakeLists.txt create mode 100644 boot/zephyr/uuid/Kconfig create mode 100644 boot/zephyr/uuid/Kconfig.uuid.template create mode 100644 boot/zephyr/uuid/uuid.c diff --git a/boot/zephyr/CMakeLists.txt b/boot/zephyr/CMakeLists.txt index f9e0e70bc..cfc9a243a 100644 --- a/boot/zephyr/CMakeLists.txt +++ b/boot/zephyr/CMakeLists.txt @@ -51,6 +51,9 @@ if(CONFIG_BOOT_USE_NRF_CC310_BL) endif() endif() +# Include the UUID generation code +add_subdirectory(uuid) + zephyr_library_include_directories( include ) diff --git a/boot/zephyr/Kconfig b/boot/zephyr/Kconfig index 03fa2d9c2..a594fdca2 100644 --- a/boot/zephyr/Kconfig +++ b/boot/zephyr/Kconfig @@ -1125,6 +1125,8 @@ config MCUBOOT_UUID_CID Provide an image class identification scheme to prevent processing images for a different CPU or device produced by the same vendor. +rsource "uuid/Kconfig" + config BOOT_WATCHDOG_FEED bool "Feed the watchdog while doing swap" default y if WATCHDOG diff --git a/boot/zephyr/uuid/CMakeLists.txt b/boot/zephyr/uuid/CMakeLists.txt new file mode 100644 index 000000000..2f5dde2fc --- /dev/null +++ b/boot/zephyr/uuid/CMakeLists.txt @@ -0,0 +1,74 @@ +# +# Copyright (c) 2025 Nordic Semiconductor ASA +# +# SPDX-License-Identifier: LicenseRef-Nordic-5-Clause +# + +if(CONFIG_NCS_MCUBOOT_UUID_SINGLE_VID) + if(CONFIG_MCUBOOT_UUID_VID OR CONFIG_MCUBOOT_UUID_CID) + zephyr_library_sources( + uuid.c + ) + endif() + + # Generate VID value and raw value definition + if(CONFIG_MCUBOOT_UUID_VID OR CONFIG_MCUBOOT_UUID_CID) + if("${CONFIG_NCS_MCUBOOT_UUID_VID_VALUE}" STREQUAL "" AND CONFIG_MCUBOOT_UUID_VID) + message(WARNING "VID value not set") + return() + endif() + + string(REGEX MATCHALL "^([0-9A-F][0-9A-F]|\-)+$" match_parts "${CONFIG_NCS_MCUBOOT_UUID_VID_VALUE}") + if("${match_parts}" STREQUAL "${CONFIG_NCS_MCUBOOT_UUID_VID_VALUE}") + set(UUID_VID ${match_parts}) + else() + set(UUID_DNS_NAMESPACE 6ba7b810-9dad-11d1-80b4-00c04fd430c8) + string( + UUID UUID_VID + NAMESPACE ${UUID_DNS_NAMESPACE} + NAME ${CONFIG_NCS_MCUBOOT_UUID_VID_VALUE} + TYPE SHA1 UPPER + ) + endif() + + if(CONFIG_MCUBOOT_UUID_VID) + # Convert UUID into C array. + string(REGEX REPLACE "([0-9A-F][0-9A-F])\-?" "0x\\1, " UUID_VID_RAW "${UUID_VID}") + zephyr_compile_definitions(NCS_MCUBOOT_UUID_VID_VALUE=${UUID_VID_RAW}) + endif() + endif() + + # Generate VID value(s) and raw value definition(s) + if(CONFIG_MCUBOOT_UUID_CID) + set(MCUBOOT_IMAGES_COUNT ${CONFIG_UPDATEABLE_IMAGE_NUMBER}) + foreach(image_id RANGE ${MCUBOOT_IMAGES_COUNT}) + if(CONFIG_NCS_MCUBOOT_UUID_CID_IMAGE_${image_id}) + if("${CONFIG_NCS_MCUBOOT_UUID_CID_IMAGE_${image_id}_VALUE}" STREQUAL "") + message(WARNING "CID value not set for image ${image_id}") + return() + endif() + + # Check if RAW UUID format is used + string(REGEX MATCHALL "^([0-9A-F][0-9A-F]|\-)+$" match_parts "${CONFIG_NCS_MCUBOOT_UUID_CID_IMAGE_${image_id}_VALUE}") + if("${match_parts}" STREQUAL "${CONFIG_NCS_MCUBOOT_UUID_CID_IMAGE_${image_id}_VALUE}") + set(UUID_CID_IMAGE_${image_id} ${match_parts}) + elseif(NOT "${UUID_VID}" STREQUAL "") + # If not - generate UUID based on VID and CID values + string( + UUID UUID_CID_IMAGE_${image_id} + NAMESPACE ${UUID_VID} + NAME ${CONFIG_NCS_MCUBOOT_UUID_CID_IMAGE_${image_id}_VALUE} + TYPE SHA1 UPPER + ) + else() + message(WARNING "VID value not set, cannot generate CID for image ${image_id}") + return() + endif() + + # Convert UUID into C array. + string(REGEX REPLACE "([0-9A-F][0-9A-F])\-?" "0x\\1, " UUID_CID_IMAGE_${image_id}_RAW "${UUID_CID_IMAGE_${image_id}}") + zephyr_compile_definitions(NCS_MCUBOOT_UUID_CID_IMAGE_${image_id}_VALUE=${UUID_CID_IMAGE_${image_id}_RAW}) + endif() + endforeach() + endif() +endif() diff --git a/boot/zephyr/uuid/Kconfig b/boot/zephyr/uuid/Kconfig new file mode 100644 index 000000000..b6e4c66c2 --- /dev/null +++ b/boot/zephyr/uuid/Kconfig @@ -0,0 +1,55 @@ +# +# Copyright (c) 2025 Nordic Semiconductor ASA +# +# SPDX-License-Identifier: LicenseRef-Nordic-5-Clause +# + +if MCUBOOT_UUID_VID || MCUBOOT_UUID_CID + +menu "Vendor and image Class UUIDs" + +choice NCS_MCUBOOT_UUID_IMPLEMENTATION + prompt "UUID checks implementation" + default NCS_MCUBOOT_UUID_SINGLE_VID + +config NCS_MCUBOOT_UUID_SINGLE_VID + bool "Single VID and one CID per image" + help + This implementation allows to specify a single, common Vendor UUID + (VID) for all images and a unique Class UUID (CID) for each image. + +endchoice # NCS_MCUBOOT_UUID_IMPLEMENTATION + +if NCS_MCUBOOT_UUID_SINGLE_VID + +config NCS_MCUBOOT_UUID_VID_VALUE + string "Vendor name" + default "" + help + The vendor unique identifier. + The following formats are supported: + - Domain name (i.e. amce.corp) used to generate RFC 9562 UUID5 + identifier. + - Raw UUID (i.e. 12345678-1234-5678-1234-567812345678) + - Raw HEX UUID (i.e. 12345678123456781234567812345678) + +if MCUBOOT_UUID_CID + +image=0 +rsource "Kconfig.uuid.template" +image=1 +rsource "Kconfig.uuid.template" +image=2 +rsource "Kconfig.uuid.template" +image=3 +rsource "Kconfig.uuid.template" +image=4 +rsource "Kconfig.uuid.template" + +endif # MCUBOOT_UUID_CID + +endif # NCS_MCUBOOT_UUID_SINGLE_VID + +endmenu + +endif # MCUBOOT_UUID_VID || MCUBOOT_UUID_CID diff --git a/boot/zephyr/uuid/Kconfig.uuid.template b/boot/zephyr/uuid/Kconfig.uuid.template new file mode 100644 index 000000000..c916935c7 --- /dev/null +++ b/boot/zephyr/uuid/Kconfig.uuid.template @@ -0,0 +1,29 @@ +# +# Copyright (c) 2025 Nordic Semiconductor ASA +# +# SPDX-License-Identifier: LicenseRef-Nordic-5-Clause +# + +if UPDATEABLE_IMAGE_NUMBER > $(image) + +config NCS_MCUBOOT_UUID_CID_IMAGE_$(image)_VALUE + string "Image class name (image $(image))" + default "" + help + The image class unique identifier. + The following formats are supported: + - Image class name (i.e. nRF5340_door_lock_btperipheral). + This format requires NCS_MCUBOOT_UUID_VID_VALUE to be defined + as the VID UUID is used as the namespace for generating RFC 9562 + UUID5 identifier. + - Raw UUID (i.e. 12345678-1234-5678-1234-567812345678) + - Raw HEX UUID (i.e. 12345678123456781234567812345678) + +config NCS_MCUBOOT_UUID_CID_IMAGE_$(image) + bool + default y + depends on NCS_MCUBOOT_UUID_CID_IMAGE_$(image)_VALUE != "" + help + Helper symbol to simplify the active CId list generation. + +endif # UPDATEABLE_IMAGE_NUMBER > $(image) diff --git a/boot/zephyr/uuid/uuid.c b/boot/zephyr/uuid/uuid.c new file mode 100644 index 000000000..28b73bc1f --- /dev/null +++ b/boot/zephyr/uuid/uuid.c @@ -0,0 +1,74 @@ +/* + * Copyright (c) 2018 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: LicenseRef-Nordic-5-Clause + */ + +#include + +#define IMAGE_ID_COUNT CONFIG_UPDATEABLE_IMAGE_NUMBER +#define CID_INIT(index, label) \ + static const struct image_uuid label = {{ \ + NCS_MCUBOOT_UUID_CID_IMAGE_## index ##_VALUE \ + }} +#define CID_CONFIG(index) UTIL_CAT(CONFIG_NCS_MCUBOOT_UUID_CID_IMAGE_, index) +#define CID_DEFINE(index, prefix) \ + IF_ENABLED(CID_CONFIG(index), (CID_INIT(index, prefix##index))) + +#define CID_CONDITION(index, label) \ + if (image_id == index) { \ + *uuid_cid = &label; \ + FIH_RET(FIH_SUCCESS); \ + } +#define CID_CHECK(index, prefix) \ + IF_ENABLED(CID_CONFIG(index), (CID_CONDITION(index, prefix##index))) + +static fih_ret boot_uuid_compare(const struct image_uuid *uuid1, const struct image_uuid *uuid2) +{ + return fih_ret_encode_zero_equality(memcmp(uuid1->raw, uuid2->raw, + ARRAY_SIZE(uuid1->raw))); +} + +#ifdef CONFIG_MCUBOOT_UUID_CID +LISTIFY(IMAGE_ID_COUNT, CID_DEFINE, (;), uuid_cid_image_); + +static fih_ret boot_uuid_cid_get(uint32_t image_id, const struct image_uuid **uuid_cid) +{ + if (uuid_cid != NULL) { + LISTIFY(IMAGE_ID_COUNT, CID_CHECK, (), uuid_cid_image_) + } + + FIH_RET(FIH_FAILURE); +} +#endif /* CONFIG_MCUBOOT_UUID_CID */ + +fih_ret boot_uuid_init(void) +{ + FIH_RET(FIH_SUCCESS); +} + +#ifdef CONFIG_MCUBOOT_UUID_VID +fih_ret boot_uuid_vid_match(uint32_t image_id, const struct image_uuid *uuid_vid) +{ + const struct image_uuid uuid_vid_c = {{ + NCS_MCUBOOT_UUID_VID_VALUE + }}; + + return boot_uuid_compare(uuid_vid, &uuid_vid_c); +} +#endif /* CONFIG_MCUBOOT_UUID_VID */ + +#ifdef CONFIG_MCUBOOT_UUID_CID +fih_ret boot_uuid_cid_match(uint32_t image_id, const struct image_uuid *uuid_cid) +{ + FIH_DECLARE(ret_code, FIH_FAILURE); + const struct image_uuid *exp_uuid_cid = NULL; + + FIH_CALL(boot_uuid_cid_get, ret_code, image_id, &exp_uuid_cid); + if (FIH_NOT_EQ(ret_code, FIH_SUCCESS) && FIH_NOT_EQ(ret_code, FIH_FAILURE)) { + FIH_RET(FIH_FAILURE); + } + + return boot_uuid_compare(uuid_cid, exp_uuid_cid); +} +#endif /* CONFIG_MCUBOOT_UUID_CID */ From 7b333ffd5ba2d01b731f528f2be89864abbf7ca3 Mon Sep 17 00:00:00 2001 From: Artur Hadasz Date: Tue, 9 Sep 2025 12:42:37 +0200 Subject: [PATCH 153/420] [nrf noup] boot: Fix test failing with bootloader requests nrf-squash! [nrf noup] boot: Improve bootloader request handling Setting "test" for image was failing when using bootloader requests due to an incorrect value being returned from send_boot_request. Signed-off-by: Artur Hadasz --- boot/bootutil/src/bootutil_public.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/boot/bootutil/src/bootutil_public.c b/boot/bootutil/src/bootutil_public.c index 750157e82..93682abdc 100644 --- a/boot/bootutil/src/bootutil_public.c +++ b/boot/bootutil/src/bootutil_public.c @@ -524,10 +524,12 @@ send_boot_request(uint8_t magic, uint8_t image_ok, bool confirm, int image_id, } else { rc = 0; } -#ifdef CONFIG_NCS_MCUBOOT_BOOT_REQUEST_TEST_SETS_BOOT_PREFERENCE } else { +#ifdef CONFIG_NCS_MCUBOOT_BOOT_REQUEST_TEST_SETS_BOOT_PREFERENCE BOOT_LOG_DBG("Set image preference: %d, %d", image_id, slot_id); rc = boot_request_set_preferred_slot(image_id, slot_id); +#else + rc = 0; #endif /* CONFIG_NCS_MCUBOOT_BOOT_REQUEST_TEST_SETS_BOOT_PREFERENCE */ } if (rc != 0) { From 26d9f6eaaf27abfb9ee4a2a062f666a4d87cfad0 Mon Sep 17 00:00:00 2001 From: Artur Hadasz Date: Thu, 11 Sep 2025 13:35:37 +0200 Subject: [PATCH 154/420] [nrf noup] bootloader: Fix logging in bootloader requests module nrf-squash! [nrf noup] bootloader: Add bootloader requests boot_request_retention.c could not be built if logs were disabled. Signed-off-by: Artur Hadasz --- boot/bootutil/zephyr/src/boot_request_retention.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/boot/bootutil/zephyr/src/boot_request_retention.c b/boot/bootutil/zephyr/src/boot_request_retention.c index 023f5af5e..234dfb5cf 100644 --- a/boot/bootutil/zephyr/src/boot_request_retention.c +++ b/boot/bootutil/zephyr/src/boot_request_retention.c @@ -14,7 +14,7 @@ /** Additional memory used by the retention subsystem (2B - prefix, 4B - CRC).*/ #define BOOT_REQUEST_ENTRY_METADATA_SIZE (2 + 4) -MCUBOOT_LOG_MODULE_REGISTER(bootloader_request); +BOOT_LOG_MODULE_REGISTER(bootloader_request); static const struct device *bootloader_request_dev = DEVICE_DT_GET(DT_CHOSEN(nrf_bootloader_request)); From b6b46a782d503cc52b41672e096fb526daaac31c Mon Sep 17 00:00:00 2001 From: Dominik Ermel Date: Thu, 3 Jul 2025 17:50:21 +0000 Subject: [PATCH 155/420] [nrf noup] bootutil: Locking KMU keys Lock KMU keys before passing execution to application. Signed-off-by: Dominik Ermel --- boot/bootutil/src/ed25519_psa.c | 27 +++++++++++++++++++++++++++ boot/zephyr/include/nrf_cleanup.h | 11 +++++++++++ boot/zephyr/main.c | 7 +++++++ 3 files changed, 45 insertions(+) diff --git a/boot/bootutil/src/ed25519_psa.c b/boot/bootutil/src/ed25519_psa.c index 8460da7c8..3df1acbdd 100644 --- a/boot/bootutil/src/ed25519_psa.c +++ b/boot/bootutil/src/ed25519_psa.c @@ -177,4 +177,31 @@ int exec_revoke(void) return ret; } #endif /* CONFIG_BOOT_KMU_KEYS_REVOCATION */ + +void nrf_crypto_keys_housekeeping(void) +{ + psa_status_t status; + + /* We will continue through all keys, even if we have error while + * processing any of it. Only doing BOOT_LOG_DBG, as we do not + * really want to inform on failures to lock. + */ + for (int i = 0; i < CONFIG_BOOT_SIGNATURE_KMU_SLOTS; ++i) { + psa_key_attributes_t attr; + + status = psa_get_key_attributes(key_ids[i], &attr); + BOOT_LOG_DBG("KMU key 0x%x(%d) attr query status == %d", + key_ids[i], i, status); + + if (status == PSA_SUCCESS) { + status = cracen_kmu_block(&attr); + BOOT_LOG_DBG("KMU key lock status == %d", status); + } + + status = psa_purge_key(key_ids[i]); + BOOT_LOG_DBG("KMU key 0x%x(%d) purge status == %d", + key_ids[i], i, status); + } +} + #endif diff --git a/boot/zephyr/include/nrf_cleanup.h b/boot/zephyr/include/nrf_cleanup.h index 9e87e13f5..8cd8fe377 100644 --- a/boot/zephyr/include/nrf_cleanup.h +++ b/boot/zephyr/include/nrf_cleanup.h @@ -21,4 +21,15 @@ void nrf_cleanup_peripheral(void); */ void nrf_cleanup_ns_ram(void); +/** + * Crypto key storage housekeeping. Intended to clean up key objects from + * crypto backend and apply key policies that should take effect after + * MCUboot no longer needs access to keys. + */ +#if defined(CONFIG_BOOT_SIGNATURE_USING_KMU) +extern void nrf_crypto_keys_housekeeping(void); +#else +#define nrf_crypto_keys_housekeeping() do {} while (0) +#endif + #endif diff --git a/boot/zephyr/main.c b/boot/zephyr/main.c index d8e7117ef..3e91b3662 100644 --- a/boot/zephyr/main.c +++ b/boot/zephyr/main.c @@ -780,6 +780,13 @@ int main(void) mcuboot_status_change(MCUBOOT_STATUS_BOOTABLE_IMAGE_FOUND); + /* From this point MCUboot does not need access to crypto keys. + * Clean up backend key objects and apply key access policies that + * will take effect from now through entire boot session and application + * run. + */ + nrf_crypto_keys_housekeeping(); + #if USE_PARTITION_MANAGER && CONFIG_FPROTECT #ifdef PM_S1_ADDRESS From b26db4dc3b8e937b4d9b3fee733f95f1902e7c7f Mon Sep 17 00:00:00 2001 From: Andrzej Puzdrowski Date: Fri, 1 Aug 2025 18:00:14 +0200 Subject: [PATCH 156/420] [nrf noup] boot/zephyr: nRF54h20 resume from S2RAM (hardened) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Application need special support in the bootloader in order to resume for suspend to RAM. MCUboot is immediate actor which redirects execution to the application (application reset vector) when wake-up from S2RAM is detected. Detection is based on HW (NRF_RESETINFO) and hardened using additional check over independent source of truth (variable with magic value). Thanks to above the application is resuming using its routines - instead of mocking that by routines compiled in by the MCUboot. Implementation is able to support only MCUboot modes with a swap. Direct-XIP is not handled as it require a way to run-time recognization of active application slot. Signed-off-by: Karol Lasończyk Signed-off-by: Tomasz Chyrowicz Signed-off-by: Andrzej Puzdrowski --- boot/zephyr/CMakeLists.txt | 4 ++ boot/zephyr/nrf54h20_custom_s2ram.c | 97 +++++++++++++++++++++++++++++ 2 files changed, 101 insertions(+) create mode 100644 boot/zephyr/nrf54h20_custom_s2ram.c diff --git a/boot/zephyr/CMakeLists.txt b/boot/zephyr/CMakeLists.txt index cfc9a243a..ce55effbb 100644 --- a/boot/zephyr/CMakeLists.txt +++ b/boot/zephyr/CMakeLists.txt @@ -491,6 +491,10 @@ zephyr_library_sources( ) endif() +if(CONFIG_SOC_NRF54H20_PM_S2RAM_OVERRIDE) + zephyr_library_sources(${BOOT_DIR}/zephyr/nrf54h20_custom_s2ram.c) +endif() + if(CONFIG_MCUBOOT_BOOT_BANNER) # Replace Zephyr's boot banner with the MCUboot one zephyr_sources(kernel/banner.c) diff --git a/boot/zephyr/nrf54h20_custom_s2ram.c b/boot/zephyr/nrf54h20_custom_s2ram.c new file mode 100644 index 000000000..7b70e22fe --- /dev/null +++ b/boot/zephyr/nrf54h20_custom_s2ram.c @@ -0,0 +1,97 @@ +/* + * Copyright (c) 2025 Nordic Semiconductor ASA + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +#include +#include "pm_s2ram.h" +#include "power.h" + +#include +#include + +#include "bootutil/fault_injection_hardening.h" + +#if DT_NODE_EXISTS(DT_NODELABEL(mcuboot_s2ram)) &&\ + DT_NODE_HAS_COMPAT(DT_NODELABEL(mcuboot_s2ram), zephyr_memory_region) +/* Linker section name is given by `zephyr,memory-region` property of + * `zephyr,memory-region` compatible DT node with nodelabel `mcuboot_s2ram`. + */ +__attribute__((section(DT_PROP(DT_NODELABEL(mcuboot_s2ram), zephyr_memory_region)))) +volatile struct mcuboot_resume_s mcuboot_resume; +#else +#error "mcuboot resume support section not defined in dts" +#endif + +#define FIXED_PARTITION_ADDR(node_label) \ + (DT_REG_ADDR(DT_NODELABEL(node_label)) + \ + COND_CODE_0(DT_FIXED_PARTITION_EXISTS(DT_NODELABEL(node_label)), (0), \ + (DT_REG_ADDR(DT_GPARENT(DT_NODELABEL(node_label)))))) + + +int soc_s2ram_suspend(pm_s2ram_system_off_fn_t system_off) +{ + (void)(system_off); + return -1; +} + +void pm_s2ram_mark_set(void) +{ + /* empty */ +} + +struct arm_vector_table { + uint32_t msp; + uint32_t reset; +}; + +/* This could be read from slot's image_header.ih_hdr_size, but immediate value + * is much faster to reach + */ +#define APP_EXE_START_OFFSET 0x800 /* nRF54H20 */ + +bool pm_s2ram_mark_check_and_clear(void) +{ + uint32_t reset_reason = nrf_resetinfo_resetreas_local_get(NRF_RESETINFO); + + if (reset_reason != NRF_RESETINFO_RESETREAS_LOCAL_UNRETAINED_MASK) { + /* Normal boot */ + return false; + } + + /* S2RAM resume expected, do doublecheck */ + if (mcuboot_resume.magic == MCUBOOT_S2RAM_RESUME_MAGIC) { + /* clear magic to avoid accidental reuse */ + mcuboot_resume.magic = 0; + } else { + /* magic not valid, normal boot */ + goto resume_failed; + } + + /* s2ram boot */ + struct arm_vector_table *vt; + vt = (struct arm_vector_table *) + (FIXED_PARTITION_ADDR(slot0_partition) + APP_EXE_START_OFFSET); + + /* Jump to application */ + __asm__ volatile ( + /* vt->reset -> r0 */ + " mov r0, %0\n" + /* vt->msp -> r1 */ + " mov r1, %1\n" + /* set stack pointer */ + " msr msp, r1\n" + /* jump to reset vector of an app */ + " bx r0\n" + : + : "r" (vt->reset), "r" (vt->msp) + : "r0", "r1", "memory" + ); + +resume_failed: + FIH_PANIC; + + return true; +} From c39029507179e3e1707eb46ca002a0780bb5b5b4 Mon Sep 17 00:00:00 2001 From: Andrzej Puzdrowski Date: Tue, 9 Sep 2025 17:01:37 +0200 Subject: [PATCH 157/420] [nrf noup] boot/zephyr/socs: nrf54h20 prj.conf for S2RAM Added configuration which pre-configures MCUboot so It is able to support operation of resuming the App from S2RAM by the application itself. Signed-off-by: Andrzej Puzdrowski --- boot/zephyr/socs/nrf54h20_cpuapp.conf | 13 +++++++++++++ 1 file changed, 13 insertions(+) create mode 100644 boot/zephyr/socs/nrf54h20_cpuapp.conf diff --git a/boot/zephyr/socs/nrf54h20_cpuapp.conf b/boot/zephyr/socs/nrf54h20_cpuapp.conf new file mode 100644 index 000000000..09ccb19b2 --- /dev/null +++ b/boot/zephyr/socs/nrf54h20_cpuapp.conf @@ -0,0 +1,13 @@ +# Copyright (c) 2025 Nordic Semiconductor ASA +# +# SPDX-License-Identifier: Apache-2.0 +# + +# Configuration which is needed for supporting resume the application execution +# after suspend to RAM (S2RAM) requested by the application. +# MCUboot does not support S2RAM itself, but serves as an immediate actor while waking up +# from suspension. +CONFIG_PM=y +CONFIG_PM_S2RAM=y +CONFIG_PM_S2RAM_CUSTOM_MARKING=y +CONFIG_SOC_NRF54H20_PM_S2RAM_OVERRIDE=y From d0796dc9b79833eb4fccd0af8fc7c969ea8a0de5 Mon Sep 17 00:00:00 2001 From: Kari Hamalainen Date: Tue, 16 Sep 2025 17:22:26 +0300 Subject: [PATCH 158/420] [nrf noup] ci: add reopen for manifest-pr action Previously reopening of PR did not reopen manifest PR. This commit will enable reopening of manifest PR in such case. Signed-off-by: Kari Hamalainen --- .github/workflows/manifest-PR.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/manifest-PR.yml b/.github/workflows/manifest-PR.yml index a871aa381..473301146 100644 --- a/.github/workflows/manifest-PR.yml +++ b/.github/workflows/manifest-PR.yml @@ -1,7 +1,7 @@ name: handle manifest PR on: pull_request_target: - types: [opened, synchronize, closed] + types: [opened, synchronize, closed, reopened] branches: - main From 0e6e9a3af4fc0e566f794b583457d11723c177f8 Mon Sep 17 00:00:00 2001 From: Jukka Rissanen Date: Tue, 23 Sep 2025 13:04:29 +0300 Subject: [PATCH 159/420] Revert "[nrf noup] ci: add reopen for manifest-pr action" This reverts commit d0796dc9b79833eb4fccd0af8fc7c969ea8a0de5. Signed-off-by: Jukka Rissanen --- .github/workflows/manifest-PR.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/manifest-PR.yml b/.github/workflows/manifest-PR.yml index 473301146..a871aa381 100644 --- a/.github/workflows/manifest-PR.yml +++ b/.github/workflows/manifest-PR.yml @@ -1,7 +1,7 @@ name: handle manifest PR on: pull_request_target: - types: [opened, synchronize, closed, reopened] + types: [opened, synchronize, closed] branches: - main From 1c81b6af591ec399bb474578ea0908c0eaffeedd Mon Sep 17 00:00:00 2001 From: Jukka Rissanen Date: Tue, 23 Sep 2025 13:04:29 +0300 Subject: [PATCH 160/420] Revert "[nrf noup] boot/zephyr/socs: nrf54h20 prj.conf for S2RAM" This reverts commit c39029507179e3e1707eb46ca002a0780bb5b5b4. Signed-off-by: Jukka Rissanen --- boot/zephyr/socs/nrf54h20_cpuapp.conf | 13 ------------- 1 file changed, 13 deletions(-) delete mode 100644 boot/zephyr/socs/nrf54h20_cpuapp.conf diff --git a/boot/zephyr/socs/nrf54h20_cpuapp.conf b/boot/zephyr/socs/nrf54h20_cpuapp.conf deleted file mode 100644 index 09ccb19b2..000000000 --- a/boot/zephyr/socs/nrf54h20_cpuapp.conf +++ /dev/null @@ -1,13 +0,0 @@ -# Copyright (c) 2025 Nordic Semiconductor ASA -# -# SPDX-License-Identifier: Apache-2.0 -# - -# Configuration which is needed for supporting resume the application execution -# after suspend to RAM (S2RAM) requested by the application. -# MCUboot does not support S2RAM itself, but serves as an immediate actor while waking up -# from suspension. -CONFIG_PM=y -CONFIG_PM_S2RAM=y -CONFIG_PM_S2RAM_CUSTOM_MARKING=y -CONFIG_SOC_NRF54H20_PM_S2RAM_OVERRIDE=y From fb65971b69c75918910647e7a42c01313f66b3e2 Mon Sep 17 00:00:00 2001 From: Jukka Rissanen Date: Tue, 23 Sep 2025 13:04:29 +0300 Subject: [PATCH 161/420] Revert "[nrf noup] boot/zephyr: nRF54h20 resume from S2RAM (hardened)" This reverts commit b26db4dc3b8e937b4d9b3fee733f95f1902e7c7f. Signed-off-by: Jukka Rissanen --- boot/zephyr/CMakeLists.txt | 4 -- boot/zephyr/nrf54h20_custom_s2ram.c | 97 ----------------------------- 2 files changed, 101 deletions(-) delete mode 100644 boot/zephyr/nrf54h20_custom_s2ram.c diff --git a/boot/zephyr/CMakeLists.txt b/boot/zephyr/CMakeLists.txt index ce55effbb..cfc9a243a 100644 --- a/boot/zephyr/CMakeLists.txt +++ b/boot/zephyr/CMakeLists.txt @@ -491,10 +491,6 @@ zephyr_library_sources( ) endif() -if(CONFIG_SOC_NRF54H20_PM_S2RAM_OVERRIDE) - zephyr_library_sources(${BOOT_DIR}/zephyr/nrf54h20_custom_s2ram.c) -endif() - if(CONFIG_MCUBOOT_BOOT_BANNER) # Replace Zephyr's boot banner with the MCUboot one zephyr_sources(kernel/banner.c) diff --git a/boot/zephyr/nrf54h20_custom_s2ram.c b/boot/zephyr/nrf54h20_custom_s2ram.c deleted file mode 100644 index 7b70e22fe..000000000 --- a/boot/zephyr/nrf54h20_custom_s2ram.c +++ /dev/null @@ -1,97 +0,0 @@ -/* - * Copyright (c) 2025 Nordic Semiconductor ASA - * SPDX-License-Identifier: Apache-2.0 - */ - -#include -#include -#include -#include "pm_s2ram.h" -#include "power.h" - -#include -#include - -#include "bootutil/fault_injection_hardening.h" - -#if DT_NODE_EXISTS(DT_NODELABEL(mcuboot_s2ram)) &&\ - DT_NODE_HAS_COMPAT(DT_NODELABEL(mcuboot_s2ram), zephyr_memory_region) -/* Linker section name is given by `zephyr,memory-region` property of - * `zephyr,memory-region` compatible DT node with nodelabel `mcuboot_s2ram`. - */ -__attribute__((section(DT_PROP(DT_NODELABEL(mcuboot_s2ram), zephyr_memory_region)))) -volatile struct mcuboot_resume_s mcuboot_resume; -#else -#error "mcuboot resume support section not defined in dts" -#endif - -#define FIXED_PARTITION_ADDR(node_label) \ - (DT_REG_ADDR(DT_NODELABEL(node_label)) + \ - COND_CODE_0(DT_FIXED_PARTITION_EXISTS(DT_NODELABEL(node_label)), (0), \ - (DT_REG_ADDR(DT_GPARENT(DT_NODELABEL(node_label)))))) - - -int soc_s2ram_suspend(pm_s2ram_system_off_fn_t system_off) -{ - (void)(system_off); - return -1; -} - -void pm_s2ram_mark_set(void) -{ - /* empty */ -} - -struct arm_vector_table { - uint32_t msp; - uint32_t reset; -}; - -/* This could be read from slot's image_header.ih_hdr_size, but immediate value - * is much faster to reach - */ -#define APP_EXE_START_OFFSET 0x800 /* nRF54H20 */ - -bool pm_s2ram_mark_check_and_clear(void) -{ - uint32_t reset_reason = nrf_resetinfo_resetreas_local_get(NRF_RESETINFO); - - if (reset_reason != NRF_RESETINFO_RESETREAS_LOCAL_UNRETAINED_MASK) { - /* Normal boot */ - return false; - } - - /* S2RAM resume expected, do doublecheck */ - if (mcuboot_resume.magic == MCUBOOT_S2RAM_RESUME_MAGIC) { - /* clear magic to avoid accidental reuse */ - mcuboot_resume.magic = 0; - } else { - /* magic not valid, normal boot */ - goto resume_failed; - } - - /* s2ram boot */ - struct arm_vector_table *vt; - vt = (struct arm_vector_table *) - (FIXED_PARTITION_ADDR(slot0_partition) + APP_EXE_START_OFFSET); - - /* Jump to application */ - __asm__ volatile ( - /* vt->reset -> r0 */ - " mov r0, %0\n" - /* vt->msp -> r1 */ - " mov r1, %1\n" - /* set stack pointer */ - " msr msp, r1\n" - /* jump to reset vector of an app */ - " bx r0\n" - : - : "r" (vt->reset), "r" (vt->msp) - : "r0", "r1", "memory" - ); - -resume_failed: - FIH_PANIC; - - return true; -} From fd41ec748bc1ef9d92dfacf871c9c8f68599fc32 Mon Sep 17 00:00:00 2001 From: Jukka Rissanen Date: Tue, 23 Sep 2025 13:04:29 +0300 Subject: [PATCH 162/420] Revert "[nrf noup] bootutil: Locking KMU keys" This reverts commit b6b46a782d503cc52b41672e096fb526daaac31c. Signed-off-by: Jukka Rissanen --- boot/bootutil/src/ed25519_psa.c | 27 --------------------------- boot/zephyr/include/nrf_cleanup.h | 11 ----------- boot/zephyr/main.c | 7 ------- 3 files changed, 45 deletions(-) diff --git a/boot/bootutil/src/ed25519_psa.c b/boot/bootutil/src/ed25519_psa.c index 3df1acbdd..8460da7c8 100644 --- a/boot/bootutil/src/ed25519_psa.c +++ b/boot/bootutil/src/ed25519_psa.c @@ -177,31 +177,4 @@ int exec_revoke(void) return ret; } #endif /* CONFIG_BOOT_KMU_KEYS_REVOCATION */ - -void nrf_crypto_keys_housekeeping(void) -{ - psa_status_t status; - - /* We will continue through all keys, even if we have error while - * processing any of it. Only doing BOOT_LOG_DBG, as we do not - * really want to inform on failures to lock. - */ - for (int i = 0; i < CONFIG_BOOT_SIGNATURE_KMU_SLOTS; ++i) { - psa_key_attributes_t attr; - - status = psa_get_key_attributes(key_ids[i], &attr); - BOOT_LOG_DBG("KMU key 0x%x(%d) attr query status == %d", - key_ids[i], i, status); - - if (status == PSA_SUCCESS) { - status = cracen_kmu_block(&attr); - BOOT_LOG_DBG("KMU key lock status == %d", status); - } - - status = psa_purge_key(key_ids[i]); - BOOT_LOG_DBG("KMU key 0x%x(%d) purge status == %d", - key_ids[i], i, status); - } -} - #endif diff --git a/boot/zephyr/include/nrf_cleanup.h b/boot/zephyr/include/nrf_cleanup.h index 8cd8fe377..9e87e13f5 100644 --- a/boot/zephyr/include/nrf_cleanup.h +++ b/boot/zephyr/include/nrf_cleanup.h @@ -21,15 +21,4 @@ void nrf_cleanup_peripheral(void); */ void nrf_cleanup_ns_ram(void); -/** - * Crypto key storage housekeeping. Intended to clean up key objects from - * crypto backend and apply key policies that should take effect after - * MCUboot no longer needs access to keys. - */ -#if defined(CONFIG_BOOT_SIGNATURE_USING_KMU) -extern void nrf_crypto_keys_housekeeping(void); -#else -#define nrf_crypto_keys_housekeeping() do {} while (0) -#endif - #endif diff --git a/boot/zephyr/main.c b/boot/zephyr/main.c index 3e91b3662..d8e7117ef 100644 --- a/boot/zephyr/main.c +++ b/boot/zephyr/main.c @@ -780,13 +780,6 @@ int main(void) mcuboot_status_change(MCUBOOT_STATUS_BOOTABLE_IMAGE_FOUND); - /* From this point MCUboot does not need access to crypto keys. - * Clean up backend key objects and apply key access policies that - * will take effect from now through entire boot session and application - * run. - */ - nrf_crypto_keys_housekeeping(); - #if USE_PARTITION_MANAGER && CONFIG_FPROTECT #ifdef PM_S1_ADDRESS From 0faca0f21de7392f7cce14b13661a9d6fc566da0 Mon Sep 17 00:00:00 2001 From: Jukka Rissanen Date: Tue, 23 Sep 2025 13:04:29 +0300 Subject: [PATCH 163/420] Revert "[nrf noup] bootloader: Fix logging in bootloader requests module" This reverts commit 26d9f6eaaf27abfb9ee4a2a062f666a4d87cfad0. Signed-off-by: Jukka Rissanen --- boot/bootutil/zephyr/src/boot_request_retention.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/boot/bootutil/zephyr/src/boot_request_retention.c b/boot/bootutil/zephyr/src/boot_request_retention.c index 234dfb5cf..023f5af5e 100644 --- a/boot/bootutil/zephyr/src/boot_request_retention.c +++ b/boot/bootutil/zephyr/src/boot_request_retention.c @@ -14,7 +14,7 @@ /** Additional memory used by the retention subsystem (2B - prefix, 4B - CRC).*/ #define BOOT_REQUEST_ENTRY_METADATA_SIZE (2 + 4) -BOOT_LOG_MODULE_REGISTER(bootloader_request); +MCUBOOT_LOG_MODULE_REGISTER(bootloader_request); static const struct device *bootloader_request_dev = DEVICE_DT_GET(DT_CHOSEN(nrf_bootloader_request)); From 5201d150f2a0773b799cc340cafff5595bfe54e6 Mon Sep 17 00:00:00 2001 From: Jukka Rissanen Date: Tue, 23 Sep 2025 13:04:29 +0300 Subject: [PATCH 164/420] Revert "[nrf noup] boot: Fix test failing with bootloader requests" This reverts commit 7b333ffd5ba2d01b731f528f2be89864abbf7ca3. Signed-off-by: Jukka Rissanen --- boot/bootutil/src/bootutil_public.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/boot/bootutil/src/bootutil_public.c b/boot/bootutil/src/bootutil_public.c index 93682abdc..750157e82 100644 --- a/boot/bootutil/src/bootutil_public.c +++ b/boot/bootutil/src/bootutil_public.c @@ -524,12 +524,10 @@ send_boot_request(uint8_t magic, uint8_t image_ok, bool confirm, int image_id, } else { rc = 0; } - } else { #ifdef CONFIG_NCS_MCUBOOT_BOOT_REQUEST_TEST_SETS_BOOT_PREFERENCE + } else { BOOT_LOG_DBG("Set image preference: %d, %d", image_id, slot_id); rc = boot_request_set_preferred_slot(image_id, slot_id); -#else - rc = 0; #endif /* CONFIG_NCS_MCUBOOT_BOOT_REQUEST_TEST_SETS_BOOT_PREFERENCE */ } if (rc != 0) { From f95af372bf8effd7af7bd3b1c7c02b8539a6c580 Mon Sep 17 00:00:00 2001 From: Jukka Rissanen Date: Tue, 23 Sep 2025 13:04:29 +0300 Subject: [PATCH 165/420] Revert "[nrf noup] zephyr: Add basic UUID checks implementation" This reverts commit 25f49810540e2ef2cba43ef8388ea78418f642d0. Signed-off-by: Jukka Rissanen --- boot/zephyr/CMakeLists.txt | 3 -- boot/zephyr/Kconfig | 2 - boot/zephyr/uuid/CMakeLists.txt | 74 -------------------------- boot/zephyr/uuid/Kconfig | 55 ------------------- boot/zephyr/uuid/Kconfig.uuid.template | 29 ---------- boot/zephyr/uuid/uuid.c | 74 -------------------------- 6 files changed, 237 deletions(-) delete mode 100644 boot/zephyr/uuid/CMakeLists.txt delete mode 100644 boot/zephyr/uuid/Kconfig delete mode 100644 boot/zephyr/uuid/Kconfig.uuid.template delete mode 100644 boot/zephyr/uuid/uuid.c diff --git a/boot/zephyr/CMakeLists.txt b/boot/zephyr/CMakeLists.txt index cfc9a243a..f9e0e70bc 100644 --- a/boot/zephyr/CMakeLists.txt +++ b/boot/zephyr/CMakeLists.txt @@ -51,9 +51,6 @@ if(CONFIG_BOOT_USE_NRF_CC310_BL) endif() endif() -# Include the UUID generation code -add_subdirectory(uuid) - zephyr_library_include_directories( include ) diff --git a/boot/zephyr/Kconfig b/boot/zephyr/Kconfig index a594fdca2..03fa2d9c2 100644 --- a/boot/zephyr/Kconfig +++ b/boot/zephyr/Kconfig @@ -1125,8 +1125,6 @@ config MCUBOOT_UUID_CID Provide an image class identification scheme to prevent processing images for a different CPU or device produced by the same vendor. -rsource "uuid/Kconfig" - config BOOT_WATCHDOG_FEED bool "Feed the watchdog while doing swap" default y if WATCHDOG diff --git a/boot/zephyr/uuid/CMakeLists.txt b/boot/zephyr/uuid/CMakeLists.txt deleted file mode 100644 index 2f5dde2fc..000000000 --- a/boot/zephyr/uuid/CMakeLists.txt +++ /dev/null @@ -1,74 +0,0 @@ -# -# Copyright (c) 2025 Nordic Semiconductor ASA -# -# SPDX-License-Identifier: LicenseRef-Nordic-5-Clause -# - -if(CONFIG_NCS_MCUBOOT_UUID_SINGLE_VID) - if(CONFIG_MCUBOOT_UUID_VID OR CONFIG_MCUBOOT_UUID_CID) - zephyr_library_sources( - uuid.c - ) - endif() - - # Generate VID value and raw value definition - if(CONFIG_MCUBOOT_UUID_VID OR CONFIG_MCUBOOT_UUID_CID) - if("${CONFIG_NCS_MCUBOOT_UUID_VID_VALUE}" STREQUAL "" AND CONFIG_MCUBOOT_UUID_VID) - message(WARNING "VID value not set") - return() - endif() - - string(REGEX MATCHALL "^([0-9A-F][0-9A-F]|\-)+$" match_parts "${CONFIG_NCS_MCUBOOT_UUID_VID_VALUE}") - if("${match_parts}" STREQUAL "${CONFIG_NCS_MCUBOOT_UUID_VID_VALUE}") - set(UUID_VID ${match_parts}) - else() - set(UUID_DNS_NAMESPACE 6ba7b810-9dad-11d1-80b4-00c04fd430c8) - string( - UUID UUID_VID - NAMESPACE ${UUID_DNS_NAMESPACE} - NAME ${CONFIG_NCS_MCUBOOT_UUID_VID_VALUE} - TYPE SHA1 UPPER - ) - endif() - - if(CONFIG_MCUBOOT_UUID_VID) - # Convert UUID into C array. - string(REGEX REPLACE "([0-9A-F][0-9A-F])\-?" "0x\\1, " UUID_VID_RAW "${UUID_VID}") - zephyr_compile_definitions(NCS_MCUBOOT_UUID_VID_VALUE=${UUID_VID_RAW}) - endif() - endif() - - # Generate VID value(s) and raw value definition(s) - if(CONFIG_MCUBOOT_UUID_CID) - set(MCUBOOT_IMAGES_COUNT ${CONFIG_UPDATEABLE_IMAGE_NUMBER}) - foreach(image_id RANGE ${MCUBOOT_IMAGES_COUNT}) - if(CONFIG_NCS_MCUBOOT_UUID_CID_IMAGE_${image_id}) - if("${CONFIG_NCS_MCUBOOT_UUID_CID_IMAGE_${image_id}_VALUE}" STREQUAL "") - message(WARNING "CID value not set for image ${image_id}") - return() - endif() - - # Check if RAW UUID format is used - string(REGEX MATCHALL "^([0-9A-F][0-9A-F]|\-)+$" match_parts "${CONFIG_NCS_MCUBOOT_UUID_CID_IMAGE_${image_id}_VALUE}") - if("${match_parts}" STREQUAL "${CONFIG_NCS_MCUBOOT_UUID_CID_IMAGE_${image_id}_VALUE}") - set(UUID_CID_IMAGE_${image_id} ${match_parts}) - elseif(NOT "${UUID_VID}" STREQUAL "") - # If not - generate UUID based on VID and CID values - string( - UUID UUID_CID_IMAGE_${image_id} - NAMESPACE ${UUID_VID} - NAME ${CONFIG_NCS_MCUBOOT_UUID_CID_IMAGE_${image_id}_VALUE} - TYPE SHA1 UPPER - ) - else() - message(WARNING "VID value not set, cannot generate CID for image ${image_id}") - return() - endif() - - # Convert UUID into C array. - string(REGEX REPLACE "([0-9A-F][0-9A-F])\-?" "0x\\1, " UUID_CID_IMAGE_${image_id}_RAW "${UUID_CID_IMAGE_${image_id}}") - zephyr_compile_definitions(NCS_MCUBOOT_UUID_CID_IMAGE_${image_id}_VALUE=${UUID_CID_IMAGE_${image_id}_RAW}) - endif() - endforeach() - endif() -endif() diff --git a/boot/zephyr/uuid/Kconfig b/boot/zephyr/uuid/Kconfig deleted file mode 100644 index b6e4c66c2..000000000 --- a/boot/zephyr/uuid/Kconfig +++ /dev/null @@ -1,55 +0,0 @@ -# -# Copyright (c) 2025 Nordic Semiconductor ASA -# -# SPDX-License-Identifier: LicenseRef-Nordic-5-Clause -# - -if MCUBOOT_UUID_VID || MCUBOOT_UUID_CID - -menu "Vendor and image Class UUIDs" - -choice NCS_MCUBOOT_UUID_IMPLEMENTATION - prompt "UUID checks implementation" - default NCS_MCUBOOT_UUID_SINGLE_VID - -config NCS_MCUBOOT_UUID_SINGLE_VID - bool "Single VID and one CID per image" - help - This implementation allows to specify a single, common Vendor UUID - (VID) for all images and a unique Class UUID (CID) for each image. - -endchoice # NCS_MCUBOOT_UUID_IMPLEMENTATION - -if NCS_MCUBOOT_UUID_SINGLE_VID - -config NCS_MCUBOOT_UUID_VID_VALUE - string "Vendor name" - default "" - help - The vendor unique identifier. - The following formats are supported: - - Domain name (i.e. amce.corp) used to generate RFC 9562 UUID5 - identifier. - - Raw UUID (i.e. 12345678-1234-5678-1234-567812345678) - - Raw HEX UUID (i.e. 12345678123456781234567812345678) - -if MCUBOOT_UUID_CID - -image=0 -rsource "Kconfig.uuid.template" -image=1 -rsource "Kconfig.uuid.template" -image=2 -rsource "Kconfig.uuid.template" -image=3 -rsource "Kconfig.uuid.template" -image=4 -rsource "Kconfig.uuid.template" - -endif # MCUBOOT_UUID_CID - -endif # NCS_MCUBOOT_UUID_SINGLE_VID - -endmenu - -endif # MCUBOOT_UUID_VID || MCUBOOT_UUID_CID diff --git a/boot/zephyr/uuid/Kconfig.uuid.template b/boot/zephyr/uuid/Kconfig.uuid.template deleted file mode 100644 index c916935c7..000000000 --- a/boot/zephyr/uuid/Kconfig.uuid.template +++ /dev/null @@ -1,29 +0,0 @@ -# -# Copyright (c) 2025 Nordic Semiconductor ASA -# -# SPDX-License-Identifier: LicenseRef-Nordic-5-Clause -# - -if UPDATEABLE_IMAGE_NUMBER > $(image) - -config NCS_MCUBOOT_UUID_CID_IMAGE_$(image)_VALUE - string "Image class name (image $(image))" - default "" - help - The image class unique identifier. - The following formats are supported: - - Image class name (i.e. nRF5340_door_lock_btperipheral). - This format requires NCS_MCUBOOT_UUID_VID_VALUE to be defined - as the VID UUID is used as the namespace for generating RFC 9562 - UUID5 identifier. - - Raw UUID (i.e. 12345678-1234-5678-1234-567812345678) - - Raw HEX UUID (i.e. 12345678123456781234567812345678) - -config NCS_MCUBOOT_UUID_CID_IMAGE_$(image) - bool - default y - depends on NCS_MCUBOOT_UUID_CID_IMAGE_$(image)_VALUE != "" - help - Helper symbol to simplify the active CId list generation. - -endif # UPDATEABLE_IMAGE_NUMBER > $(image) diff --git a/boot/zephyr/uuid/uuid.c b/boot/zephyr/uuid/uuid.c deleted file mode 100644 index 28b73bc1f..000000000 --- a/boot/zephyr/uuid/uuid.c +++ /dev/null @@ -1,74 +0,0 @@ -/* - * Copyright (c) 2018 Nordic Semiconductor ASA - * - * SPDX-License-Identifier: LicenseRef-Nordic-5-Clause - */ - -#include - -#define IMAGE_ID_COUNT CONFIG_UPDATEABLE_IMAGE_NUMBER -#define CID_INIT(index, label) \ - static const struct image_uuid label = {{ \ - NCS_MCUBOOT_UUID_CID_IMAGE_## index ##_VALUE \ - }} -#define CID_CONFIG(index) UTIL_CAT(CONFIG_NCS_MCUBOOT_UUID_CID_IMAGE_, index) -#define CID_DEFINE(index, prefix) \ - IF_ENABLED(CID_CONFIG(index), (CID_INIT(index, prefix##index))) - -#define CID_CONDITION(index, label) \ - if (image_id == index) { \ - *uuid_cid = &label; \ - FIH_RET(FIH_SUCCESS); \ - } -#define CID_CHECK(index, prefix) \ - IF_ENABLED(CID_CONFIG(index), (CID_CONDITION(index, prefix##index))) - -static fih_ret boot_uuid_compare(const struct image_uuid *uuid1, const struct image_uuid *uuid2) -{ - return fih_ret_encode_zero_equality(memcmp(uuid1->raw, uuid2->raw, - ARRAY_SIZE(uuid1->raw))); -} - -#ifdef CONFIG_MCUBOOT_UUID_CID -LISTIFY(IMAGE_ID_COUNT, CID_DEFINE, (;), uuid_cid_image_); - -static fih_ret boot_uuid_cid_get(uint32_t image_id, const struct image_uuid **uuid_cid) -{ - if (uuid_cid != NULL) { - LISTIFY(IMAGE_ID_COUNT, CID_CHECK, (), uuid_cid_image_) - } - - FIH_RET(FIH_FAILURE); -} -#endif /* CONFIG_MCUBOOT_UUID_CID */ - -fih_ret boot_uuid_init(void) -{ - FIH_RET(FIH_SUCCESS); -} - -#ifdef CONFIG_MCUBOOT_UUID_VID -fih_ret boot_uuid_vid_match(uint32_t image_id, const struct image_uuid *uuid_vid) -{ - const struct image_uuid uuid_vid_c = {{ - NCS_MCUBOOT_UUID_VID_VALUE - }}; - - return boot_uuid_compare(uuid_vid, &uuid_vid_c); -} -#endif /* CONFIG_MCUBOOT_UUID_VID */ - -#ifdef CONFIG_MCUBOOT_UUID_CID -fih_ret boot_uuid_cid_match(uint32_t image_id, const struct image_uuid *uuid_cid) -{ - FIH_DECLARE(ret_code, FIH_FAILURE); - const struct image_uuid *exp_uuid_cid = NULL; - - FIH_CALL(boot_uuid_cid_get, ret_code, image_id, &exp_uuid_cid); - if (FIH_NOT_EQ(ret_code, FIH_SUCCESS) && FIH_NOT_EQ(ret_code, FIH_FAILURE)) { - FIH_RET(FIH_FAILURE); - } - - return boot_uuid_compare(uuid_cid, exp_uuid_cid); -} -#endif /* CONFIG_MCUBOOT_UUID_CID */ From 764548c72f3181a9ddae909fa1c1df7a8dbb8323 Mon Sep 17 00:00:00 2001 From: Jukka Rissanen Date: Tue, 23 Sep 2025 13:04:29 +0300 Subject: [PATCH 166/420] Revert "[nrf noup] Support for ed25519 signature verification using ITS" This reverts commit 227eb0a50d1b1fa52f853b2cc4ff1e8cca4bbf71. Signed-off-by: Jukka Rissanen --- boot/bootutil/src/ed25519_psa.c | 38 ++++++++++-------------------- boot/bootutil/src/image_ed25519.c | 6 ++--- boot/bootutil/src/image_validate.c | 6 ++--- 3 files changed, 18 insertions(+), 32 deletions(-) diff --git a/boot/bootutil/src/ed25519_psa.c b/boot/bootutil/src/ed25519_psa.c index 8460da7c8..6393d996e 100644 --- a/boot/bootutil/src/ed25519_psa.c +++ b/boot/bootutil/src/ed25519_psa.c @@ -26,35 +26,22 @@ BOOT_LOG_MODULE_REGISTER(ed25519_psa); #if defined(CONFIG_BOOT_SIGNATURE_USING_KMU) /* List of KMU stored key ids available for MCUboot */ #define MAKE_PSA_KMU_KEY_ID(id) PSA_KEY_HANDLE_FROM_CRACEN_KMU_SLOT(CRACEN_KMU_KEY_USAGE_SCHEME_RAW, id) -static psa_key_id_t key_ids[] = { +static psa_key_id_t kmu_key_ids[3] = { MAKE_PSA_KMU_KEY_ID(226), MAKE_PSA_KMU_KEY_ID(228), MAKE_PSA_KMU_KEY_ID(230) }; -#define KEY_SLOTS_COUNT CONFIG_BOOT_SIGNATURE_KMU_SLOTS - #if defined(CONFIG_BOOT_KMU_KEYS_REVOCATION) #include static psa_key_id_t *validated_with = NULL; #endif -BUILD_ASSERT(CONFIG_BOOT_SIGNATURE_KMU_SLOTS <= ARRAY_SIZE(key_ids), +BUILD_ASSERT(CONFIG_BOOT_SIGNATURE_KMU_SLOTS <= ARRAY_SIZE(kmu_key_ids), "Invalid number of KMU slots, up to 3 are supported on nRF54L15"); #endif -#if defined(CONFIG_NCS_BOOT_SIGNATURE_USING_ITS) -static const psa_key_id_t key_ids[] = { - 0x40022100, - 0x40022101, - 0x40022102, - 0x40022103 -}; - -#define KEY_SLOTS_COUNT ARRAY_SIZE(key_ids) -#endif - -#if !defined(CONFIG_BOOT_SIGNATURE_USING_KMU) && !defined(CONFIG_NCS_BOOT_SIGNATURE_USING_ITS) +#if !defined(CONFIG_BOOT_SIGNATURE_USING_KMU) int ED25519_verify(const uint8_t *message, size_t message_len, const uint8_t signature[EDDSA_SIGNAGURE_LENGTH], const uint8_t public_key[EDDSA_KEY_LENGTH]) @@ -115,6 +102,7 @@ int ED25519_verify(const uint8_t *message, size_t message_len, ARG_UNUSED(public_key); /* Set to any error */ psa_status_t status = PSA_ERROR_BAD_STATE; + int ret = 0; /* Fail by default */ /* Initialize PSA Crypto */ status = psa_crypto_init(); @@ -125,24 +113,24 @@ int ED25519_verify(const uint8_t *message, size_t message_len, status = PSA_ERROR_BAD_STATE; - for (int i = 0; i < KEY_SLOTS_COUNT; ++i) { - psa_key_id_t kid = key_ids[i]; + for (int i = 0; i < CONFIG_BOOT_SIGNATURE_KMU_SLOTS; ++i) { + psa_key_id_t kid = kmu_key_ids[i]; status = psa_verify_message(kid, PSA_ALG_PURE_EDDSA, message, message_len, signature, EDDSA_SIGNAGURE_LENGTH); if (status == PSA_SUCCESS) { + ret = 1; #if defined(CONFIG_BOOT_KMU_KEYS_REVOCATION) - validated_with = key_ids + i; + validated_with = kmu_key_ids + i; #endif - return 1; + break; } + BOOT_LOG_ERR("ED25519 signature verification failed %d", status); } - BOOT_LOG_ERR("ED25519 signature verification failed %d", status); - - return 0; + return ret; } #if defined(CONFIG_BOOT_KMU_KEYS_REVOCATION) int exec_revoke(void) @@ -161,12 +149,12 @@ int exec_revoke(void) goto out; } for (int i = 0; i < CONFIG_BOOT_SIGNATURE_KMU_SLOTS; i++) { - if ((key_ids + i) == validated_with) { + if ((kmu_key_ids + i) == validated_with) { break; } BOOT_LOG_DBG("Invalidating key ID %d", i); - status = psa_destroy_key(key_ids[i]); + status = psa_destroy_key(kmu_key_ids[i]); if (status == PSA_SUCCESS) { BOOT_LOG_DBG("Success on key ID %d", i); } else { diff --git a/boot/bootutil/src/image_ed25519.c b/boot/bootutil/src/image_ed25519.c index 177550749..1a02811e3 100644 --- a/boot/bootutil/src/image_ed25519.c +++ b/boot/bootutil/src/image_ed25519.c @@ -36,7 +36,6 @@ extern int ED25519_verify(const uint8_t *message, size_t message_len, #if !defined(CONFIG_BOOT_SIGNATURE_USING_KMU) #if !defined(MCUBOOT_KEY_IMPORT_BYPASS_ASN) -#if !defined(CONFIG_NCS_BOOT_SIGNATURE_USING_ITS) /* * Parse the public key used for signing. */ @@ -79,7 +78,6 @@ bootutil_import_key(uint8_t **cp, uint8_t *end) } #endif /* !defined(MCUBOOT_KEY_IMPORT_BYPASS_ASN) */ #endif -#endif /* Signature verification base function. * The function takes buffer of specified length and tries to verify @@ -95,7 +93,7 @@ bootutil_verify(uint8_t *buf, uint32_t blen, int rc; FIH_DECLARE(fih_rc, FIH_FAILURE); uint8_t *pubkey = NULL; -#if !defined(CONFIG_BOOT_SIGNATURE_USING_KMU) && !defined(CONFIG_NCS_BOOT_SIGNATURE_USING_ITS) +#if !defined(CONFIG_BOOT_SIGNATURE_USING_KMU) uint8_t *end; #endif @@ -108,7 +106,7 @@ bootutil_verify(uint8_t *buf, uint32_t blen, goto out; } -#if !defined(CONFIG_BOOT_SIGNATURE_USING_KMU) && !defined(CONFIG_NCS_BOOT_SIGNATURE_USING_ITS) +#if !defined(CONFIG_BOOT_SIGNATURE_USING_KMU) pubkey = (uint8_t *)bootutil_keys[key_id].key; end = pubkey + *bootutil_keys[key_id].len; diff --git a/boot/bootutil/src/image_validate.c b/boot/bootutil/src/image_validate.c index cc5c040bb..53d5b860b 100644 --- a/boot/bootutil/src/image_validate.c +++ b/boot/bootutil/src/image_validate.c @@ -784,13 +784,13 @@ bootutil_img_validate(struct boot_loader_state *state, case EXPECTED_SIG_TLV: { BOOT_LOG_DBG("bootutil_img_validate: EXPECTED_SIG_TLV == %d", EXPECTED_SIG_TLV); -#if !defined(CONFIG_BOOT_SIGNATURE_USING_KMU) && !defined(CONFIG_NCS_BOOT_SIGNATURE_USING_ITS) +#if !defined(CONFIG_BOOT_SIGNATURE_USING_KMU) /* Ignore this signature if it is out of bounds. */ if (key_id < 0 || key_id >= bootutil_key_cnt) { key_id = -1; continue; } -#endif /* !defined(CONFIG_BOOT_SIGNATURE_USING_KMU) && !defined(CONFIG_NCS_BOOT_SIGNATURE_USING_ITS) */ +#endif /* !defined(CONFIG_BOOT_SIGNATURE_USING_KMU) */ if (!EXPECTED_SIG_LEN(len) || len > sizeof(buf)) { rc = -1; goto out; @@ -1105,7 +1105,7 @@ bootutil_img_validate(struct boot_loader_state *state, if (type == IMAGE_TLV_DECOMP_SIGNATURE) { /* Ignore this signature if it is out of bounds. */ -#if !defined(CONFIG_BOOT_SIGNATURE_USING_KMU) && !defined(CONFIG_NCS_BOOT_SIGNATURE_USING_ITS) +#if !defined(CONFIG_BOOT_SIGNATURE_USING_KMU) if (key_id < 0 || key_id >= bootutil_key_cnt) { key_id = -1; continue; From 2bf1876a302227dda5bd895ed9fa8aef7aafb82a Mon Sep 17 00:00:00 2001 From: Jukka Rissanen Date: Tue, 23 Sep 2025 13:04:29 +0300 Subject: [PATCH 167/420] Revert "[nrf noup] boot: Use NCS_ prefix for sdk-nrf specific Kconfigs" This reverts commit a4bae1322e51d086c454aa5a870441ba4c995b80. Signed-off-by: Jukka Rissanen --- boot/bootutil/include/bootutil/crypto/ecdsa.h | 6 +++--- boot/zephyr/Kconfig | 4 ++-- boot/zephyr/include/mcuboot_config/mcuboot_config.h | 2 +- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/boot/bootutil/include/bootutil/crypto/ecdsa.h b/boot/bootutil/include/bootutil/crypto/ecdsa.h index 0e9205c29..31d7bec9a 100644 --- a/boot/bootutil/include/bootutil/crypto/ecdsa.h +++ b/boot/bootutil/include/bootutil/crypto/ecdsa.h @@ -473,7 +473,7 @@ static int bootutil_ecdsa_parse_public_key(bootutil_ecdsa_context *ctx, } #endif /* !MCUBOOT_BUILTIN_KEY */ -#if !defined(CONFIG_NCS_BOOT_SIGNATURE_USING_ITS) +#if !defined(CONFIG_NRF_BOOT_SIGNATURE_USING_ITS) /* Verify the signature against the provided hash. The signature gets parsed from * the encoding first, then PSA Crypto has a dedicated API for ECDSA verification */ @@ -492,7 +492,7 @@ static inline int bootutil_ecdsa_verify(bootutil_ecdsa_context *ctx, return (int) psa_verify_hash(ctx->key_id, PSA_ALG_ECDSA(ctx->required_algorithm), hash, hlen, reformatted_signature, 2*ctx->curve_byte_count); } -#else /* !CONFIG_NCS_BOOT_SIGNATURE_USING_ITS */ +#else /* !CONFIG_NRF_BOOT_SIGNATURE_USING_ITS */ static const psa_key_id_t builtin_key_ids[] = { 0x40022100, @@ -539,7 +539,7 @@ static inline int bootutil_ecdsa_verify(bootutil_ecdsa_context *ctx, return status == PSA_SUCCESS ? 0 : 2; } -#endif /* !CONFIG_NCS_BOOT_SIGNATURE_USING_ITS */ +#endif /* !CONFIG_NRF_BOOT_SIGNATURE_USING_ITS */ #elif defined(MCUBOOT_USE_MBED_TLS) diff --git a/boot/zephyr/Kconfig b/boot/zephyr/Kconfig index 03fa2d9c2..965e65da3 100644 --- a/boot/zephyr/Kconfig +++ b/boot/zephyr/Kconfig @@ -422,14 +422,14 @@ config BOOT_KMU_KEYS_REVOCATION help Enabling KMU key revocation backend. -config NCS_BOOT_SIGNATURE_USING_ITS +config NRF_BOOT_SIGNATURE_USING_ITS bool "Use ITS stored keys for signature verification" depends on NRF_SECURITY help MCUboot will use keys provisioned to the internal trusted storage for signature verification instead of compiling in key data from a file. -if !BOOT_SIGNATURE_USING_KMU && !NCS_BOOT_SIGNATURE_USING_ITS +if !BOOT_SIGNATURE_USING_KMU && !NRF_BOOT_SIGNATURE_USING_ITS config BOOT_SIGNATURE_KEY_FILE string "PEM key file" diff --git a/boot/zephyr/include/mcuboot_config/mcuboot_config.h b/boot/zephyr/include/mcuboot_config/mcuboot_config.h index 6c860e01d..1f2c03759 100644 --- a/boot/zephyr/include/mcuboot_config/mcuboot_config.h +++ b/boot/zephyr/include/mcuboot_config/mcuboot_config.h @@ -68,7 +68,7 @@ #define MCUBOOT_HW_KEY #endif -#ifdef CONFIG_NCS_BOOT_SIGNATURE_USING_ITS +#ifdef CONFIG_NRF_BOOT_SIGNATURE_USING_ITS #define MCUBOOT_BUILTIN_KEY #endif From 80418c191b021f015496ea91f0942d63d9dcf7f2 Mon Sep 17 00:00:00 2001 From: Jukka Rissanen Date: Tue, 23 Sep 2025 13:04:29 +0300 Subject: [PATCH 168/420] Revert "[nrf noup] Added BOOT_SIGNATURE_USING_ITS for ecdsa configuration" This reverts commit 7ed49272a2f00e3e0936c333f2a0240e99226963. Signed-off-by: Jukka Rissanen --- boot/bootutil/include/bootutil/crypto/ecdsa.h | 50 ------------------- boot/bootutil/src/image_validate.c | 3 +- boot/zephyr/Kconfig | 9 +--- .../include/mcuboot_config/mcuboot_config.h | 4 -- 4 files changed, 2 insertions(+), 64 deletions(-) diff --git a/boot/bootutil/include/bootutil/crypto/ecdsa.h b/boot/bootutil/include/bootutil/crypto/ecdsa.h index 31d7bec9a..a5d0f8b1b 100644 --- a/boot/bootutil/include/bootutil/crypto/ecdsa.h +++ b/boot/bootutil/include/bootutil/crypto/ecdsa.h @@ -473,7 +473,6 @@ static int bootutil_ecdsa_parse_public_key(bootutil_ecdsa_context *ctx, } #endif /* !MCUBOOT_BUILTIN_KEY */ -#if !defined(CONFIG_NRF_BOOT_SIGNATURE_USING_ITS) /* Verify the signature against the provided hash. The signature gets parsed from * the encoding first, then PSA Crypto has a dedicated API for ECDSA verification */ @@ -492,55 +491,6 @@ static inline int bootutil_ecdsa_verify(bootutil_ecdsa_context *ctx, return (int) psa_verify_hash(ctx->key_id, PSA_ALG_ECDSA(ctx->required_algorithm), hash, hlen, reformatted_signature, 2*ctx->curve_byte_count); } -#else /* !CONFIG_NRF_BOOT_SIGNATURE_USING_ITS */ - -static const psa_key_id_t builtin_key_ids[] = { - 0x40022100, - 0x40022101, - 0x40022102, - 0x40022103 -}; - -#define BOOT_SIGNATURE_BUILTIN_KEY_SLOTS ARRAY_SIZE(builtin_key_ids) - -static inline int bootutil_ecdsa_verify(bootutil_ecdsa_context *ctx, - uint8_t *pk, size_t pk_len, - uint8_t *hash, size_t hlen, - uint8_t *sig, size_t slen) -{ - (void)pk; - (void)pk_len; - (void)slen; - psa_status_t status = PSA_ERROR_BAD_STATE; - - /* Initialize PSA Crypto */ - status = psa_crypto_init(); - if (status != PSA_SUCCESS) { - BOOT_LOG_ERR("PSA crypto init failed %d", status); - return 1; - } - - uint8_t reformatted_signature[96] = {0}; /* Enough for P-384 signature sizes */ - parse_signature_from_rfc5480_encoding(sig, ctx->curve_byte_count, reformatted_signature); - - status = PSA_ERROR_BAD_STATE; - - for (int i = 0; i < BOOT_SIGNATURE_BUILTIN_KEY_SLOTS; ++i) { - psa_key_id_t kid = builtin_key_ids[i]; - - status = psa_verify_hash(kid, PSA_ALG_ECDSA(ctx->required_algorithm), - hash, hlen, reformatted_signature, 2*ctx->curve_byte_count); - if (status == PSA_SUCCESS) { - break; - } - BOOT_LOG_ERR("ECDSA signature verification failed %d", status); - } - - return status == PSA_SUCCESS ? 0 : 2; -} - -#endif /* !CONFIG_NRF_BOOT_SIGNATURE_USING_ITS */ - #elif defined(MCUBOOT_USE_MBED_TLS) typedef mbedtls_ecdsa_context bootutil_ecdsa_context; diff --git a/boot/bootutil/src/image_validate.c b/boot/bootutil/src/image_validate.c index 53d5b860b..a4a39b548 100644 --- a/boot/bootutil/src/image_validate.c +++ b/boot/bootutil/src/image_validate.c @@ -518,8 +518,7 @@ bootutil_img_validate(struct boot_loader_state *state, ) { #if (defined(EXPECTED_KEY_TLV) && defined(MCUBOOT_HW_KEY)) || defined(MCUBOOT_HW_ROLLBACK_PROT) \ - || defined(MCUBOOT_UUID_VID) || defined(MCUBOOT_UUID_CID) || defined(MCUBOOT_DECOMPRESS_IMAGES) \ - || defined(MCUBOOT_BUILTIN_KEY) + || defined(MCUBOOT_UUID_VID) || defined(MCUBOOT_UUID_CID) || defined(MCUBOOT_DECOMPRESS_IMAGES) int image_index = (state == NULL ? 0 : BOOT_CURR_IMG(state)); #endif uint32_t off; diff --git a/boot/zephyr/Kconfig b/boot/zephyr/Kconfig index 965e65da3..73b3bef7b 100644 --- a/boot/zephyr/Kconfig +++ b/boot/zephyr/Kconfig @@ -422,14 +422,7 @@ config BOOT_KMU_KEYS_REVOCATION help Enabling KMU key revocation backend. -config NRF_BOOT_SIGNATURE_USING_ITS - bool "Use ITS stored keys for signature verification" - depends on NRF_SECURITY - help - MCUboot will use keys provisioned to the internal trusted storage for signature - verification instead of compiling in key data from a file. - -if !BOOT_SIGNATURE_USING_KMU && !NRF_BOOT_SIGNATURE_USING_ITS +if !BOOT_SIGNATURE_USING_KMU config BOOT_SIGNATURE_KEY_FILE string "PEM key file" diff --git a/boot/zephyr/include/mcuboot_config/mcuboot_config.h b/boot/zephyr/include/mcuboot_config/mcuboot_config.h index 1f2c03759..eb64c12eb 100644 --- a/boot/zephyr/include/mcuboot_config/mcuboot_config.h +++ b/boot/zephyr/include/mcuboot_config/mcuboot_config.h @@ -68,10 +68,6 @@ #define MCUBOOT_HW_KEY #endif -#ifdef CONFIG_NRF_BOOT_SIGNATURE_USING_ITS -#define MCUBOOT_BUILTIN_KEY -#endif - #ifdef CONFIG_BOOT_VALIDATE_SLOT0 #define MCUBOOT_VALIDATE_PRIMARY_SLOT #endif From 6fa2579c807a680b23d349c46c3ab964f6dabdeb Mon Sep 17 00:00:00 2001 From: Jukka Rissanen Date: Tue, 23 Sep 2025 13:04:29 +0300 Subject: [PATCH 169/420] Revert "[nrf noup] bootutil: key revocation" This reverts commit 51b0897bc30cf6cf5a33127bdd5501e59d051499. Signed-off-by: Jukka Rissanen --- .../include/bootutil/key_revocation.h | 30 -------------- boot/bootutil/src/ed25519_psa.c | 41 ------------------- boot/bootutil/src/key_revocation.c | 24 ----------- boot/bootutil/src/loader.c | 16 -------- boot/zephyr/CMakeLists.txt | 6 --- boot/zephyr/Kconfig | 12 ------ 6 files changed, 129 deletions(-) delete mode 100644 boot/bootutil/include/bootutil/key_revocation.h delete mode 100644 boot/bootutil/src/key_revocation.c diff --git a/boot/bootutil/include/bootutil/key_revocation.h b/boot/bootutil/include/bootutil/key_revocation.h deleted file mode 100644 index d184c9579..000000000 --- a/boot/bootutil/include/bootutil/key_revocation.h +++ /dev/null @@ -1,30 +0,0 @@ -/* - * Copyright (c) 2025 Nordic Semiconductor ASA - * - * SPDX-License-Identifier: LicenseRef-Nordic-5-Clause - */ - -#ifndef H_KEY_REVOCATION_ -#define H_KEY_REVOCATION_ - -#include - -#ifdef __cplusplus -extern "C" { -#endif - -#define BOOT_KEY_REVOKE_OK 0 -#define BOOT_KEY_REVOKE_NOT_READY 1 -#define BOOT_KEY_REVOKE_INVALID 2 -#define BOOT_KEY_REVOKE_FAILED 2 - - -void allow_revoke(void); - -int revoke(void); - -#ifdef __cplusplus -} -#endif - -#endif diff --git a/boot/bootutil/src/ed25519_psa.c b/boot/bootutil/src/ed25519_psa.c index 6393d996e..7665e4067 100644 --- a/boot/bootutil/src/ed25519_psa.c +++ b/boot/bootutil/src/ed25519_psa.c @@ -32,11 +32,6 @@ static psa_key_id_t kmu_key_ids[3] = { MAKE_PSA_KMU_KEY_ID(230) }; -#if defined(CONFIG_BOOT_KMU_KEYS_REVOCATION) -#include -static psa_key_id_t *validated_with = NULL; -#endif - BUILD_ASSERT(CONFIG_BOOT_SIGNATURE_KMU_SLOTS <= ARRAY_SIZE(kmu_key_ids), "Invalid number of KMU slots, up to 3 are supported on nRF54L15"); #endif @@ -121,9 +116,6 @@ int ED25519_verify(const uint8_t *message, size_t message_len, EDDSA_SIGNAGURE_LENGTH); if (status == PSA_SUCCESS) { ret = 1; -#if defined(CONFIG_BOOT_KMU_KEYS_REVOCATION) - validated_with = kmu_key_ids + i; -#endif break; } @@ -132,37 +124,4 @@ int ED25519_verify(const uint8_t *message, size_t message_len, return ret; } -#if defined(CONFIG_BOOT_KMU_KEYS_REVOCATION) -int exec_revoke(void) -{ - int ret = BOOT_KEY_REVOKE_OK; - psa_status_t status = psa_crypto_init(); - - if (!validated_with) { - ret = BOOT_KEY_REVOKE_INVALID; - goto out; - } - - if (status != PSA_SUCCESS) { - BOOT_LOG_ERR("PSA crypto init failed with error %d", status); - ret = BOOT_KEY_REVOKE_FAILED; - goto out; - } - for (int i = 0; i < CONFIG_BOOT_SIGNATURE_KMU_SLOTS; i++) { - if ((kmu_key_ids + i) == validated_with) { - break; - } - BOOT_LOG_DBG("Invalidating key ID %d", i); - - status = psa_destroy_key(kmu_key_ids[i]); - if (status == PSA_SUCCESS) { - BOOT_LOG_DBG("Success on key ID %d", i); - } else { - BOOT_LOG_ERR("Key invalidation failed with: %d", status); - } - } -out: - return ret; -} -#endif /* CONFIG_BOOT_KMU_KEYS_REVOCATION */ #endif diff --git a/boot/bootutil/src/key_revocation.c b/boot/bootutil/src/key_revocation.c deleted file mode 100644 index 0768a3188..000000000 --- a/boot/bootutil/src/key_revocation.c +++ /dev/null @@ -1,24 +0,0 @@ -/* - * Copyright (c) 2025 Nordic Semiconductor ASA - * - * SPDX-License-Identifier: LicenseRef-Nordic-5-Clause - */ - -#include - -extern int exec_revoke(void); - -static uint8_t ready_to_revoke; - -void allow_revoke(void) -{ - ready_to_revoke = 1; -} - -int revoke(void) -{ - if (ready_to_revoke) { - return exec_revoke(); - } - return BOOT_KEY_REVOKE_NOT_READY; -} diff --git a/boot/bootutil/src/loader.c b/boot/bootutil/src/loader.c index 1a2290769..3e199ad4a 100644 --- a/boot/bootutil/src/loader.c +++ b/boot/bootutil/src/loader.c @@ -80,10 +80,6 @@ int pcd_version_cmp_net(const struct flash_area *fap, struct image_header *hdr); #include "mcuboot_config/mcuboot_config.h" -#if defined(CONFIG_BOOT_KEYS_REVOCATION) -#include "bootutil/key_revocation.h" -#endif - BOOT_LOG_MODULE_DECLARE(mcuboot); static struct boot_loader_state boot_data; @@ -3114,11 +3110,6 @@ context_boot_go(struct boot_loader_state *state, struct boot_rsp *rsp) } } -#if defined(CONFIG_BOOT_KEYS_REVOCATION) - if (BOOT_SWAP_TYPE(state) == BOOT_SWAP_TYPE_NONE) { - allow_revoke(); - } -#endif /* Iterate over all the images. At this point all required update operations * have finished. By the end of the loop each image in the primary slot will * have been re-validated. @@ -3227,13 +3218,6 @@ context_boot_go(struct boot_loader_state *state, struct boot_rsp *rsp) fill_rsp(state, rsp); fih_rc = FIH_SUCCESS; -#if defined(CONFIG_BOOT_KEYS_REVOCATION) - rc = revoke(); - if (rc != BOOT_KEY_REVOKE_OK && - rc != BOOT_KEY_REVOKE_NOT_READY) { - FIH_SET(fih_rc, FIH_FAILURE); - } -#endif /* CONFIG_BOOT_KEYS_REVOCATION */ out: /* * Since the boot_status struct stores plaintext encryption keys, reset diff --git a/boot/zephyr/CMakeLists.txt b/boot/zephyr/CMakeLists.txt index f9e0e70bc..fddf35927 100644 --- a/boot/zephyr/CMakeLists.txt +++ b/boot/zephyr/CMakeLists.txt @@ -104,12 +104,6 @@ if(DEFINED CONFIG_BOOT_SHARE_BACKEND_RETENTION) ) endif() -if(DEFINED CONFIG_BOOT_KEYS_REVOCATION) - zephyr_library_sources( - ${BOOT_DIR}/bootutil/src/key_revocation.c -) -endif() - # Generic bootutil sources and includes. zephyr_library_include_directories(${BOOT_DIR}/bootutil/include) zephyr_library_sources( diff --git a/boot/zephyr/Kconfig b/boot/zephyr/Kconfig index 73b3bef7b..4de39e577 100644 --- a/boot/zephyr/Kconfig +++ b/boot/zephyr/Kconfig @@ -410,18 +410,6 @@ config BOOT_SIGNATURE_KMU_SLOTS endif -config BOOT_KEYS_REVOCATION - bool "Auto revoke previous gen key" - help - Automatically revoke previous generation key upon new valid key usage. - -config BOOT_KMU_KEYS_REVOCATION - bool - depends on BOOT_KEYS_REVOCATION - default y if BOOT_SIGNATURE_USING_KMU - help - Enabling KMU key revocation backend. - if !BOOT_SIGNATURE_USING_KMU config BOOT_SIGNATURE_KEY_FILE From e48158b8ab719a98e481780ab2f75c914af6ca84 Mon Sep 17 00:00:00 2001 From: Jukka Rissanen Date: Tue, 23 Sep 2025 13:04:29 +0300 Subject: [PATCH 170/420] Revert "[nrf noup] boot: bootutil: Allow configuring number of KMU keys" This reverts commit 83d1d959de612b8bc17dae56355b0ccc40cebde6. Signed-off-by: Jukka Rissanen --- boot/bootutil/src/ed25519_psa.c | 7 ++----- boot/zephyr/Kconfig | 12 ------------ 2 files changed, 2 insertions(+), 17 deletions(-) diff --git a/boot/bootutil/src/ed25519_psa.c b/boot/bootutil/src/ed25519_psa.c index 7665e4067..cd016158b 100644 --- a/boot/bootutil/src/ed25519_psa.c +++ b/boot/bootutil/src/ed25519_psa.c @@ -12,7 +12,6 @@ #include #include -#include #if defined(CONFIG_BOOT_SIGNATURE_USING_KMU) #include #endif @@ -31,9 +30,7 @@ static psa_key_id_t kmu_key_ids[3] = { MAKE_PSA_KMU_KEY_ID(228), MAKE_PSA_KMU_KEY_ID(230) }; - -BUILD_ASSERT(CONFIG_BOOT_SIGNATURE_KMU_SLOTS <= ARRAY_SIZE(kmu_key_ids), - "Invalid number of KMU slots, up to 3 are supported on nRF54L15"); +#define KMU_KEY_COUNT (sizeof(kmu_key_ids)/sizeof(kmu_key_ids[0])) #endif #if !defined(CONFIG_BOOT_SIGNATURE_USING_KMU) @@ -108,7 +105,7 @@ int ED25519_verify(const uint8_t *message, size_t message_len, status = PSA_ERROR_BAD_STATE; - for (int i = 0; i < CONFIG_BOOT_SIGNATURE_KMU_SLOTS; ++i) { + for (int i = 0; i < KMU_KEY_COUNT; ++i) { psa_key_id_t kid = kmu_key_ids[i]; status = psa_verify_message(kid, PSA_ALG_PURE_EDDSA, message, diff --git a/boot/zephyr/Kconfig b/boot/zephyr/Kconfig index 4de39e577..aa364fe8f 100644 --- a/boot/zephyr/Kconfig +++ b/boot/zephyr/Kconfig @@ -398,18 +398,6 @@ config BOOT_SIGNATURE_USING_KMU MCUboot will use keys provisioned to the device key management unit for signature verification instead of compiling in key data from a file. -if BOOT_SIGNATURE_USING_KMU - -config BOOT_SIGNATURE_KMU_SLOTS - int "KMU key slots" - range 1 3 - default 1 - help - Selects the number of KMU key slots (also known as generations) to use when verifying - an image. - -endif - if !BOOT_SIGNATURE_USING_KMU config BOOT_SIGNATURE_KEY_FILE From b0a623a386c91aa36d19800388a86e29c7156265 Mon Sep 17 00:00:00 2001 From: Jukka Rissanen Date: Tue, 23 Sep 2025 13:04:29 +0300 Subject: [PATCH 171/420] Revert "[nrf noup] bootutil: Add support for KMU stored ED25519 signature key" This reverts commit 6ba9587457e8b2b705528ffe6cc77435ae9df080. Signed-off-by: Jukka Rissanen --- boot/bootutil/src/ed25519_psa.c | 51 ------------------------------ boot/bootutil/src/image_ed25519.c | 9 +----- boot/bootutil/src/image_validate.c | 12 ++----- boot/zephyr/CMakeLists.txt | 2 +- boot/zephyr/Kconfig | 26 --------------- 5 files changed, 4 insertions(+), 96 deletions(-) diff --git a/boot/bootutil/src/ed25519_psa.c b/boot/bootutil/src/ed25519_psa.c index cd016158b..5b8a4ed7c 100644 --- a/boot/bootutil/src/ed25519_psa.c +++ b/boot/bootutil/src/ed25519_psa.c @@ -12,9 +12,6 @@ #include #include -#if defined(CONFIG_BOOT_SIGNATURE_USING_KMU) -#include -#endif BOOT_LOG_MODULE_REGISTER(ed25519_psa); @@ -22,18 +19,6 @@ BOOT_LOG_MODULE_REGISTER(ed25519_psa); #define EDDSA_KEY_LENGTH 32 #define EDDSA_SIGNAGURE_LENGTH 64 -#if defined(CONFIG_BOOT_SIGNATURE_USING_KMU) -/* List of KMU stored key ids available for MCUboot */ -#define MAKE_PSA_KMU_KEY_ID(id) PSA_KEY_HANDLE_FROM_CRACEN_KMU_SLOT(CRACEN_KMU_KEY_USAGE_SCHEME_RAW, id) -static psa_key_id_t kmu_key_ids[3] = { - MAKE_PSA_KMU_KEY_ID(226), - MAKE_PSA_KMU_KEY_ID(228), - MAKE_PSA_KMU_KEY_ID(230) -}; -#define KMU_KEY_COUNT (sizeof(kmu_key_ids)/sizeof(kmu_key_ids[0])) -#endif - -#if !defined(CONFIG_BOOT_SIGNATURE_USING_KMU) int ED25519_verify(const uint8_t *message, size_t message_len, const uint8_t signature[EDDSA_SIGNAGURE_LENGTH], const uint8_t public_key[EDDSA_KEY_LENGTH]) @@ -86,39 +71,3 @@ int ED25519_verify(const uint8_t *message, size_t message_len, return ret; } -#else -int ED25519_verify(const uint8_t *message, size_t message_len, - const uint8_t signature[EDDSA_SIGNAGURE_LENGTH], - const uint8_t public_key[EDDSA_KEY_LENGTH]) -{ - ARG_UNUSED(public_key); - /* Set to any error */ - psa_status_t status = PSA_ERROR_BAD_STATE; - int ret = 0; /* Fail by default */ - - /* Initialize PSA Crypto */ - status = psa_crypto_init(); - if (status != PSA_SUCCESS) { - BOOT_LOG_ERR("PSA crypto init failed %d", status); - return 0; - } - - status = PSA_ERROR_BAD_STATE; - - for (int i = 0; i < KMU_KEY_COUNT; ++i) { - psa_key_id_t kid = kmu_key_ids[i]; - - status = psa_verify_message(kid, PSA_ALG_PURE_EDDSA, message, - message_len, signature, - EDDSA_SIGNAGURE_LENGTH); - if (status == PSA_SUCCESS) { - ret = 1; - break; - } - - BOOT_LOG_ERR("ED25519 signature verification failed %d", status); - } - - return ret; -} -#endif diff --git a/boot/bootutil/src/image_ed25519.c b/boot/bootutil/src/image_ed25519.c index 1a02811e3..4d83bb3d7 100644 --- a/boot/bootutil/src/image_ed25519.c +++ b/boot/bootutil/src/image_ed25519.c @@ -34,7 +34,6 @@ extern int ED25519_verify(const uint8_t *message, size_t message_len, const uint8_t signature[EDDSA_SIGNATURE_LENGTH], const uint8_t public_key[NUM_ED25519_BYTES]); -#if !defined(CONFIG_BOOT_SIGNATURE_USING_KMU) #if !defined(MCUBOOT_KEY_IMPORT_BYPASS_ASN) /* * Parse the public key used for signing. @@ -77,7 +76,6 @@ bootutil_import_key(uint8_t **cp, uint8_t *end) return 0; } #endif /* !defined(MCUBOOT_KEY_IMPORT_BYPASS_ASN) */ -#endif /* Signature verification base function. * The function takes buffer of specified length and tries to verify @@ -92,10 +90,8 @@ bootutil_verify(uint8_t *buf, uint32_t blen, { int rc; FIH_DECLARE(fih_rc, FIH_FAILURE); - uint8_t *pubkey = NULL; -#if !defined(CONFIG_BOOT_SIGNATURE_USING_KMU) + uint8_t *pubkey; uint8_t *end; -#endif BOOT_LOG_DBG("bootutil_verify: ED25519 key_id %d", (int)key_id); @@ -106,7 +102,6 @@ bootutil_verify(uint8_t *buf, uint32_t blen, goto out; } -#if !defined(CONFIG_BOOT_SIGNATURE_USING_KMU) pubkey = (uint8_t *)bootutil_keys[key_id].key; end = pubkey + *bootutil_keys[key_id].len; @@ -130,8 +125,6 @@ bootutil_verify(uint8_t *buf, uint32_t blen, } pubkey = end - NUM_ED25519_BYTES; -#endif - #endif rc = ED25519_verify(buf, blen, sig, pubkey); diff --git a/boot/bootutil/src/image_validate.c b/boot/bootutil/src/image_validate.c index a4a39b548..e375e97ab 100644 --- a/boot/bootutil/src/image_validate.c +++ b/boot/bootutil/src/image_validate.c @@ -295,7 +295,6 @@ bootutil_img_hash(struct boot_loader_state *state, # define KEY_BUF_SIZE (SIG_BUF_SIZE + 24) #endif /* !MCUBOOT_HW_KEY */ -#if !defined(CONFIG_BOOT_SIGNATURE_USING_KMU) #if !defined(MCUBOOT_HW_KEY) static int bootutil_find_key(uint8_t *keyhash, uint8_t keyhash_len) @@ -364,7 +363,6 @@ bootutil_find_key(uint8_t image_index, uint8_t *key, uint16_t key_len) } #endif /* !MCUBOOT_HW_KEY */ #endif /* !MCUBOOT_BUILTIN_KEY */ -#endif /* !defined(CONFIG_BOOT_SIGNATURE_USING_KMU) */ #endif /* EXPECTED_SIG_TLV */ /** @@ -746,7 +744,6 @@ bootutil_img_validate(struct boot_loader_state *state, break; } #endif /* defined(EXPECTED_HASH_TLV) && !defined(MCUBOOT_SIGN_PURE) */ -#if !defined(CONFIG_BOOT_SIGNATURE_USING_KMU) #ifdef EXPECTED_KEY_TLV case EXPECTED_KEY_TLV: { @@ -778,18 +775,15 @@ bootutil_img_validate(struct boot_loader_state *state, break; } #endif /* EXPECTED_KEY_TLV */ -#endif /* !defined(CONFIG_BOOT_SIGNATURE_USING_KMU) */ #ifdef EXPECTED_SIG_TLV case EXPECTED_SIG_TLV: { BOOT_LOG_DBG("bootutil_img_validate: EXPECTED_SIG_TLV == %d", EXPECTED_SIG_TLV); -#if !defined(CONFIG_BOOT_SIGNATURE_USING_KMU) /* Ignore this signature if it is out of bounds. */ if (key_id < 0 || key_id >= bootutil_key_cnt) { key_id = -1; continue; } -#endif /* !defined(CONFIG_BOOT_SIGNATURE_USING_KMU) */ if (!EXPECTED_SIG_LEN(len) || len > sizeof(buf)) { rc = -1; goto out; @@ -1035,7 +1029,7 @@ bootutil_img_validate(struct boot_loader_state *state, } #ifdef EXPECTED_SIG_TLV -#if !defined(CONFIG_BOOT_SIGNATURE_USING_KMU) && defined(EXPECTED_KEY_TLV) +#ifdef EXPECTED_KEY_TLV rc = bootutil_tlv_iter_begin(&it, hdr, fap, EXPECTED_KEY_TLV, false); if (rc) { goto out; @@ -1081,7 +1075,7 @@ bootutil_img_validate(struct boot_loader_state *state, */ } } -#endif /* !CONFIG_BOOT_SIGNATURE_USING_KMU && EXPECTED_KEY_TLV */ +#endif /* EXPECTED_KEY_TLV */ rc = bootutil_tlv_iter_begin(&it, hdr, fap, IMAGE_TLV_DECOMP_SIGNATURE, true); if (rc) { @@ -1104,12 +1098,10 @@ bootutil_img_validate(struct boot_loader_state *state, if (type == IMAGE_TLV_DECOMP_SIGNATURE) { /* Ignore this signature if it is out of bounds. */ -#if !defined(CONFIG_BOOT_SIGNATURE_USING_KMU) if (key_id < 0 || key_id >= bootutil_key_cnt) { key_id = -1; continue; } -#endif if (!EXPECTED_SIG_LEN(len) || len > sizeof(buf)) { rc = -1; diff --git a/boot/zephyr/CMakeLists.txt b/boot/zephyr/CMakeLists.txt index fddf35927..4d1cd5301 100644 --- a/boot/zephyr/CMakeLists.txt +++ b/boot/zephyr/CMakeLists.txt @@ -361,7 +361,7 @@ if(CONFIG_MCUBOOT_SERIAL) endif() endif() -if(NOT CONFIG_BOOT_SIGNATURE_USING_KMU AND NOT CONFIG_BOOT_SIGNATURE_KEY_FILE STREQUAL "") +if(NOT CONFIG_BOOT_SIGNATURE_KEY_FILE STREQUAL "") # CONF_FILE points to the KConfig configuration files of the bootloader. foreach (filepath ${CONF_FILE}) file(READ ${filepath} temp_text) diff --git a/boot/zephyr/Kconfig b/boot/zephyr/Kconfig index aa364fe8f..0cc72422f 100644 --- a/boot/zephyr/Kconfig +++ b/boot/zephyr/Kconfig @@ -384,22 +384,6 @@ endif endchoice -config BOOT_SIGNATURE_USING_KMU - bool "Use KMU stored keys for signature verification" - depends on NRF_SECURITY - depends on CRACEN_LIB_KMU - select PSA_WANT_ALG_GCM - select PSA_WANT_KEY_TYPE_AES - select PSA_WANT_AES_KEY_SIZE_256 - select PSA_WANT_ALG_SP800_108_COUNTER_CMAC - select PSA_WANT_ALG_CMAC - select PSA_WANT_ALG_ECB_NO_PADDING - help - MCUboot will use keys provisioned to the device key management unit for signature - verification instead of compiling in key data from a file. - -if !BOOT_SIGNATURE_USING_KMU - config BOOT_SIGNATURE_KEY_FILE string "PEM key file" default "root-ec-p256.pem" if BOOT_SIGNATURE_TYPE_ECDSA_P256 @@ -417,8 +401,6 @@ config BOOT_SIGNATURE_KEY_FILE with the public key information will be written in a format expected by MCUboot. -endif - config MCUBOOT_CLEANUP_ARM_CORE bool "Perform core cleanup before chain-load the application" depends on CPU_CORTEX_M @@ -455,14 +437,6 @@ config MCUBOOT_INFINITE_LOOP_AFTER_RAM_CLEANUP Verification option that keeps execution in infinite loop after RAM cleanup has been performed. -# Disable MBEDTLS from being selected if NRF_SECURITY is enabled, and use default NRF_SECURITY -# configuration file for MBEDTLS -config MBEDTLS - depends on !NRF_SECURITY - -config NRF_SECURITY - select MBEDTLS_PROMPTLESS - config MBEDTLS_CFG_FILE # It might be awkward to define an Mbed TLS header file when TinyCrypt # is used, but the fact is that Mbed TLS' ASN1 parse module is used From 00203c7f5d07a771f90ce57eea71c8202fd88150 Mon Sep 17 00:00:00 2001 From: Jukka Rissanen Date: Tue, 23 Sep 2025 13:04:29 +0300 Subject: [PATCH 172/420] Revert "[nrf noup] boot: zephyr: Add experimental selection to compression" This reverts commit 4a528baa162b14d44a95892340aa299525ee1b8b. Signed-off-by: Jukka Rissanen --- boot/zephyr/Kconfig | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/boot/zephyr/Kconfig b/boot/zephyr/Kconfig index 0cc72422f..492f1ca16 100644 --- a/boot/zephyr/Kconfig +++ b/boot/zephyr/Kconfig @@ -1166,10 +1166,9 @@ config BOOT_DECOMPRESSION_SUPPORT if BOOT_DECOMPRESSION_SUPPORT menuconfig BOOT_DECOMPRESSION - bool "Decompression [EXPERIMENTAL]" + bool "Decompression" select NRF_COMPRESS_CLEANUP select PM_USE_CONFIG_SRAM_SIZE if SOC_NRF54L15_CPUAPP - select EXPERIMENTAL help If enabled, will include support for compressed images being loaded to the secondary slot which then get decompressed into the primary slot. This mode allows the secondary slot to From f96a0f4204134755d5f5bfe76db8fada701082c3 Mon Sep 17 00:00:00 2001 From: Jukka Rissanen Date: Tue, 23 Sep 2025 13:04:29 +0300 Subject: [PATCH 173/420] Revert "[nrf noup] decompression: Align to changes in nrfcompress API" This reverts commit 8900bdaf1dd401b08748d4141f1196520579f4fd. Signed-off-by: Jukka Rissanen --- boot/zephyr/decompression.c | 65 +++++++++++++------------------------ 1 file changed, 23 insertions(+), 42 deletions(-) diff --git a/boot/zephyr/decompression.c b/boot/zephyr/decompression.c index ce4fe0b2b..87e3d3763 100644 --- a/boot/zephyr/decompression.c +++ b/boot/zephyr/decompression.c @@ -256,6 +256,15 @@ int bootutil_img_hash_decompress(struct boot_loader_state *state, struct image_h goto finish_without_clean; } + rc = compression_lzma->init(NULL); + rc = compression_arm_thumb->init(NULL); + + if (rc) { + BOOT_LOG_ERR("Decompression library fatal error"); + rc = BOOT_EBADSTATUS; + goto finish_without_clean; + } + /* We need a modified header which has the updated sizes, start with the original header */ memcpy(&modified_hdr, hdr, sizeof(modified_hdr)); @@ -267,28 +276,12 @@ int bootutil_img_hash_decompress(struct boot_loader_state *state, struct image_h if (rc) { BOOT_LOG_ERR("Unable to determine decompressed size of compressed image"); rc = BOOT_EBADIMAGE; - goto finish_without_clean; + goto finish; } modified_hdr.ih_flags &= ~COMPRESSIONFLAGS; modified_hdr.ih_img_size = decompressed_image_size; - rc = compression_lzma->init(NULL, decompressed_image_size); - - if (rc) { - BOOT_LOG_ERR("Decompression library fatal error"); - rc = BOOT_EBADSTATUS; - goto finish_without_clean; - } - - rc = compression_arm_thumb->init(NULL, decompressed_image_size); - - if (rc) { - BOOT_LOG_ERR("Decompression library fatal error"); - rc = BOOT_EBADSTATUS; - goto finish; - } - /* Calculate the protected TLV size, these will not include the decompressed * sha/size/signature entries */ @@ -1108,7 +1101,7 @@ int boot_copy_region_decompress(struct boot_loader_state *state, const struct fl if (rc) { BOOT_LOG_ERR("Invalid/missing image decrypted compressed size value"); rc = BOOT_EBADIMAGE; - goto finish_without_clean; + goto finish; } if (IS_ENCRYPTED(hdr)) { @@ -1131,7 +1124,7 @@ int boot_copy_region_decompress(struct boot_loader_state *state, const struct fl */ BOOT_LOG_ERR("Invalid image compression flags: no supported compression found"); rc = BOOT_EBADIMAGE; - goto finish_without_clean; + goto finish; } compression_lzma = nrf_compress_implementation_find(NRF_COMPRESS_TYPE_LZMA); @@ -1142,7 +1135,16 @@ int boot_copy_region_decompress(struct boot_loader_state *state, const struct fl /* Compression library missing or missing required function pointer */ BOOT_LOG_ERR("Decompression library fatal error"); rc = BOOT_EBADSTATUS; - goto finish_without_clean; + goto finish; + } + + rc = compression_lzma->init(NULL); + rc = compression_arm_thumb->init(NULL); + + if (rc) { + BOOT_LOG_ERR("Decompression library fatal error"); + rc = BOOT_EBADSTATUS; + goto finish; } write_alignment = flash_area_align(fap_dst); @@ -1156,28 +1158,12 @@ int boot_copy_region_decompress(struct boot_loader_state *state, const struct fl if (rc) { BOOT_LOG_ERR("Unable to determine decompressed size of compressed image"); rc = BOOT_EBADIMAGE; - goto finish_without_clean; + goto finish; } modified_hdr.ih_flags &= ~COMPRESSIONFLAGS; modified_hdr.ih_img_size = decompressed_image_size; - rc = compression_lzma->init(NULL, decompressed_image_size); - - if (rc) { - BOOT_LOG_ERR("Decompression library fatal error"); - rc = BOOT_EBADSTATUS; - goto finish_without_clean; - } - - rc = compression_arm_thumb->init(NULL, decompressed_image_size); - - if (rc) { - BOOT_LOG_ERR("Decompression library fatal error"); - rc = BOOT_EBADSTATUS; - goto finish; - } - /* Calculate protected TLV size for target image once items are removed */ rc = boot_size_protected_tlvs(hdr, fap_src, &protected_tlv_size); @@ -1471,11 +1457,6 @@ int boot_copy_region_decompress(struct boot_loader_state *state, const struct fl } finish: - /* Clean up decompression system */ - (void)compression_lzma->deinit(NULL); - (void)compression_arm_thumb->deinit(NULL); - -finish_without_clean: memset(decomp_buf, 0, sizeof(decomp_buf)); return rc; From 6722cfcba296f6e874f9538c5d7fbea910d1e74b Mon Sep 17 00:00:00 2001 From: Jukka Rissanen Date: Tue, 23 Sep 2025 13:04:29 +0300 Subject: [PATCH 174/420] Revert "[nrf noup] zephyr: Add support for compressed image updates" This reverts commit ce9d1d6bf1b26663195752ad137a315c1172c6cb. Signed-off-by: Jukka Rissanen --- boot/bootutil/src/bootutil_misc.c | 80 +- boot/bootutil/src/image_validate.c | 223 +-- boot/bootutil/src/loader.c | 27 +- boot/zephyr/CMakeLists.txt | 6 - boot/zephyr/Kconfig | 9 +- boot/zephyr/decompression.c | 1505 ----------------- .../include/compression/decompression.h | 103 -- 7 files changed, 24 insertions(+), 1929 deletions(-) delete mode 100644 boot/zephyr/decompression.c delete mode 100644 boot/zephyr/include/compression/decompression.h diff --git a/boot/bootutil/src/bootutil_misc.c b/boot/bootutil/src/bootutil_misc.c index 96be26692..a88ad0dad 100644 --- a/boot/bootutil/src/bootutil_misc.c +++ b/boot/bootutil/src/bootutil_misc.c @@ -47,11 +47,6 @@ #include "swap_priv.h" #endif -#if defined(MCUBOOT_DECOMPRESS_IMAGES) -#include -#include -#endif - BOOT_LOG_MODULE_DECLARE(mcuboot); /* Currently only used by imgmgr */ @@ -487,76 +482,35 @@ boot_read_image_size(struct boot_loader_state *state, int slot, uint32_t *size) fap = BOOT_IMG_AREA(state, slot); assert(fap != NULL); -#ifdef MCUBOOT_DECOMPRESS_IMAGES - if (MUST_DECOMPRESS(fap, BOOT_CURR_IMG(state), boot_img_hdr(state, slot))) { - uint32_t tmp_size = 0; - - rc = bootutil_get_img_decomp_size(boot_img_hdr(state, slot), fap, &tmp_size); - - if (rc) { - rc = BOOT_EBADIMAGE; - goto done; - } - - off = boot_img_hdr(state, slot)->ih_hdr_size + tmp_size; - - rc = boot_size_protected_tlvs(boot_img_hdr(state, slot), fap, &tmp_size); + off = BOOT_TLV_OFF(boot_img_hdr(state, slot)); - if (rc) { - rc = BOOT_EBADIMAGE; - goto done; - } - - off += tmp_size; - - if (flash_area_read(fap, (BOOT_TLV_OFF(boot_img_hdr(state, slot)) + - boot_img_hdr(state, slot)->ih_protect_tlv_size), &info, - sizeof(info))) { - rc = BOOT_EFLASH; - goto done; - } + if (flash_area_read(fap, off, &info, sizeof(info))) { + rc = BOOT_EFLASH; + goto done; + } - if (info.it_magic != IMAGE_TLV_INFO_MAGIC) { + protect_tlv_size = boot_img_hdr(state, slot)->ih_protect_tlv_size; + if (info.it_magic == IMAGE_TLV_PROT_INFO_MAGIC) { + if (protect_tlv_size != info.it_tlv_tot) { rc = BOOT_EBADIMAGE; goto done; } - *size = off + info.it_tlv_tot; - } else { -#else - if (1) { -#endif - off = BOOT_TLV_OFF(boot_img_hdr(state, slot)); - - if (flash_area_read(fap, off, &info, sizeof(info))) { + if (flash_area_read(fap, off + info.it_tlv_tot, &info, sizeof(info))) { rc = BOOT_EFLASH; goto done; } + } else if (protect_tlv_size != 0) { + rc = BOOT_EBADIMAGE; + goto done; + } - protect_tlv_size = boot_img_hdr(state, slot)->ih_protect_tlv_size; - if (info.it_magic == IMAGE_TLV_PROT_INFO_MAGIC) { - if (protect_tlv_size != info.it_tlv_tot) { - rc = BOOT_EBADIMAGE; - goto done; - } - - if (flash_area_read(fap, off + info.it_tlv_tot, &info, sizeof(info))) { - rc = BOOT_EFLASH; - goto done; - } - } else if (protect_tlv_size != 0) { - rc = BOOT_EBADIMAGE; - goto done; - } - - if (info.it_magic != IMAGE_TLV_INFO_MAGIC) { - rc = BOOT_EBADIMAGE; - goto done; - } - - *size = off + protect_tlv_size + info.it_tlv_tot; + if (info.it_magic != IMAGE_TLV_INFO_MAGIC) { + rc = BOOT_EBADIMAGE; + goto done; } + *size = off + protect_tlv_size + info.it_tlv_tot; rc = 0; done: diff --git a/boot/bootutil/src/image_validate.c b/boot/bootutil/src/image_validate.c index e375e97ab..5a5366e59 100644 --- a/boot/bootutil/src/image_validate.c +++ b/boot/bootutil/src/image_validate.c @@ -48,11 +48,6 @@ BOOT_LOG_MODULE_DECLARE(mcuboot); #include "bootutil/mcuboot_uuid.h" #endif /* MCUBOOT_UUID_VID || MCUBOOT_UUID_CID */ -#if defined(MCUBOOT_DECOMPRESS_IMAGES) -#include -#include -#endif - #ifdef MCUBOOT_ENC_IMAGES #include "bootutil/enc_key.h" #endif @@ -516,7 +511,7 @@ bootutil_img_validate(struct boot_loader_state *state, ) { #if (defined(EXPECTED_KEY_TLV) && defined(MCUBOOT_HW_KEY)) || defined(MCUBOOT_HW_ROLLBACK_PROT) \ - || defined(MCUBOOT_UUID_VID) || defined(MCUBOOT_UUID_CID) || defined(MCUBOOT_DECOMPRESS_IMAGES) + || defined(MCUBOOT_UUID_VID) || defined(MCUBOOT_UUID_CID) int image_index = (state == NULL ? 0 : BOOT_CURR_IMG(state)); #endif uint32_t off; @@ -572,67 +567,6 @@ bootutil_img_validate(struct boot_loader_state *state, #endif BOOT_LOG_DBG("bootutil_img_validate: flash area %p", fap); -#ifdef MCUBOOT_DECOMPRESS_IMAGES - /* If the image is compressed, the integrity of the image must also be validated */ - if (MUST_DECOMPRESS(fap, image_index, hdr)) { - bool found_decompressed_size = false; - bool found_decompressed_sha = false; - bool found_decompressed_signature = false; - - rc = bootutil_tlv_iter_begin(&it, hdr, fap, IMAGE_TLV_ANY, true); - if (rc) { - goto out; - } - - if (it.tlv_end > bootutil_max_image_size(state, fap)) { - rc = -1; - goto out; - } - - while (true) { - uint16_t expected_size = 0; - bool *found_flag = NULL; - - rc = bootutil_tlv_iter_next(&it, &off, &len, &type); - if (rc < 0) { - goto out; - } else if (rc > 0) { - break; - } - - switch (type) { - case IMAGE_TLV_DECOMP_SIZE: - expected_size = sizeof(size_t); - found_flag = &found_decompressed_size; - break; - case IMAGE_TLV_DECOMP_SHA: - expected_size = IMAGE_HASH_SIZE; - found_flag = &found_decompressed_sha; - break; - case IMAGE_TLV_DECOMP_SIGNATURE: - found_flag = &found_decompressed_signature; - break; - default: - continue; - }; - - if (type == IMAGE_TLV_DECOMP_SIGNATURE && !EXPECTED_SIG_LEN(len)) { - rc = -1; - goto out; - } else if (type != IMAGE_TLV_DECOMP_SIGNATURE && len != expected_size) { - rc = -1; - goto out; - } - - *found_flag = true; - } - - rc = (!found_decompressed_size || !found_decompressed_sha || !found_decompressed_signature); - if (rc) { - goto out; - } - } -#endif #if defined(EXPECTED_HASH_TLV) && !defined(MCUBOOT_SIGN_PURE) #if defined(MCUBOOT_SWAP_USING_OFFSET) && defined(MCUBOOT_SERIAL_RECOVERY) @@ -970,161 +904,6 @@ bootutil_img_validate(struct boot_loader_state *state, } #endif -#ifdef MCUBOOT_DECOMPRESS_IMAGES - /* Only after all previous verifications have passed, perform a dry-run of the decompression - * and ensure the image is valid - */ - if (!rc && MUST_DECOMPRESS(fap, image_index, hdr)) { - image_hash_valid = 0; - FIH_SET(valid_signature, FIH_FAILURE); - - rc = bootutil_img_hash_decompress(state, hdr, fap, tmp_buf, tmp_buf_sz, - hash, seed, seed_len); - if (rc) { - goto out; - } - - rc = bootutil_tlv_iter_begin(&it, hdr, fap, IMAGE_TLV_DECOMP_SHA, true); - if (rc) { - goto out; - } - - if (it.tlv_end > bootutil_max_image_size(state, fap)) { - rc = -1; - goto out; - } - - while (true) { - rc = bootutil_tlv_iter_next(&it, &off, &len, &type); - if (rc < 0) { - goto out; - } else if (rc > 0) { - break; - } - - if (type == IMAGE_TLV_DECOMP_SHA) { - /* Verify the image hash. This must always be present. */ - if (len != sizeof(hash)) { - rc = -1; - goto out; - } - rc = LOAD_IMAGE_DATA(hdr, fap, off, buf, sizeof(hash)); - if (rc) { - goto out; - } - - FIH_CALL(boot_fih_memequal, fih_rc, hash, buf, sizeof(hash)); - if (FIH_NOT_EQ(fih_rc, FIH_SUCCESS)) { - FIH_SET(fih_rc, FIH_FAILURE); - goto out; - } - - image_hash_valid = 1; - } - } - - rc = !image_hash_valid; - if (rc) { - goto out; - } - -#ifdef EXPECTED_SIG_TLV -#ifdef EXPECTED_KEY_TLV - rc = bootutil_tlv_iter_begin(&it, hdr, fap, EXPECTED_KEY_TLV, false); - if (rc) { - goto out; - } - - if (it.tlv_end > bootutil_max_image_size(state, fap)) { - rc = -1; - goto out; - } - - while (true) { - rc = bootutil_tlv_iter_next(&it, &off, &len, &type); - if (rc < 0) { - goto out; - } else if (rc > 0) { - break; - } - - if (type == EXPECTED_KEY_TLV) { - /* - * Determine which key we should be checking. - */ - if (len > KEY_BUF_SIZE) { - rc = -1; - goto out; - } -#ifndef MCUBOOT_HW_KEY - rc = LOAD_IMAGE_DATA(hdr, fap, off, buf, len); - if (rc) { - goto out; - } - key_id = bootutil_find_key(buf, len); -#else - rc = LOAD_IMAGE_DATA(hdr, fap, off, key_buf, len); - if (rc) { - goto out; - } - key_id = bootutil_find_key(image_index, key_buf, len); -#endif /* !MCUBOOT_HW_KEY */ - /* - * The key may not be found, which is acceptable. There - * can be multiple signatures, each preceded by a key. - */ - } - } -#endif /* EXPECTED_KEY_TLV */ - - rc = bootutil_tlv_iter_begin(&it, hdr, fap, IMAGE_TLV_DECOMP_SIGNATURE, true); - if (rc) { - goto out; - } - - if (it.tlv_end > bootutil_max_image_size(state, fap)) { - rc = -1; - goto out; - } - - while (true) { - rc = bootutil_tlv_iter_next(&it, &off, &len, &type); - if (rc < 0) { - goto out; - } else if (rc > 0) { - rc = 0; - break; - } - - if (type == IMAGE_TLV_DECOMP_SIGNATURE) { - /* Ignore this signature if it is out of bounds. */ - if (key_id < 0 || key_id >= bootutil_key_cnt) { - key_id = -1; - continue; - } - - if (!EXPECTED_SIG_LEN(len) || len > sizeof(buf)) { - rc = -1; - goto out; - } - rc = LOAD_IMAGE_DATA(hdr, fap, off, buf, len); - if (rc) { - goto out; - } - - FIH_CALL(bootutil_verify_sig, valid_signature, hash, sizeof(hash), - buf, len, key_id); - key_id = -1; - } - } -#endif /* EXPECTED_SIG_TLV */ - } -#endif - -#ifdef EXPECTED_SIG_TLV - FIH_SET(fih_rc, valid_signature); -#endif - out: if (rc) { FIH_SET(fih_rc, FIH_FAILURE); diff --git a/boot/bootutil/src/loader.c b/boot/bootutil/src/loader.c index 3e199ad4a..71fc7d535 100644 --- a/boot/bootutil/src/loader.c +++ b/boot/bootutil/src/loader.c @@ -50,11 +50,6 @@ #include "bootutil/boot_hooks.h" #include "bootutil/mcuboot_status.h" -#if defined(MCUBOOT_DECOMPRESS_IMAGES) -#include -#include -#endif - #ifdef __ZEPHYR__ #include #if defined(CONFIG_NCS_MCUBOOT_IMG_VALIDATE_ATTEMPT_WAIT_MS) @@ -1048,10 +1043,10 @@ boot_is_header_valid(const struct image_header *hdr, const struct flash_area *fa return false; } #else - if (MUST_DECOMPRESS(fap, BOOT_CURR_IMG(state), hdr)) { - if (!boot_is_compressed_header_valid(hdr, fap, state)) { - return false; - } + if ((hdr->ih_flags & IMAGE_F_COMPRESSED_LZMA1) && + (hdr->ih_flags & IMAGE_F_COMPRESSED_LZMA2)) + { + return false; } #endif @@ -1299,7 +1294,6 @@ boot_validate_slot(struct boot_loader_state *state, int slot, * attempts to validate and boot it. */ } - #if !defined(__BOOTSIM__) BOOT_LOG_ERR("Image in the %s slot is not valid!", (slot == BOOT_PRIMARY_SLOT) ? "primary" : "secondary"); @@ -1956,9 +1950,6 @@ boot_copy_region(struct boot_loader_state *state, #else (void)state; #endif -#if defined(MCUBOOT_DECOMPRESS_IMAGES) && !defined(MCUBOOT_ENC_IMAGES) - struct image_header *hdr; -#endif TARGET_STATIC uint8_t buf[BUF_SZ] __attribute__((aligned(4))); @@ -1984,16 +1975,6 @@ boot_copy_region(struct boot_loader_state *state, } #endif -#ifdef MCUBOOT_DECOMPRESS_IMAGES - hdr = boot_img_hdr(state, BOOT_SECONDARY_SLOT); - - if (MUST_DECOMPRESS(fap_src, BOOT_CURR_IMG(state), hdr)) { - /* Use alternative function for compressed images */ - return boot_copy_region_decompress(state, fap_src, fap_dst, off_src, off_dst, sz, buf, - BUF_SZ); - } -#endif - bytes_copied = 0; while (bytes_copied < sz) { if (sz - bytes_copied > sizeof buf) { diff --git a/boot/zephyr/CMakeLists.txt b/boot/zephyr/CMakeLists.txt index 4d1cd5301..e4b5ff0ad 100644 --- a/boot/zephyr/CMakeLists.txt +++ b/boot/zephyr/CMakeLists.txt @@ -334,12 +334,6 @@ if(CONFIG_BOOT_ENCRYPT_EC256 AND NOT CONFIG_BOOT_ECDSA_PSA) ) endif() -if(CONFIG_BOOT_DECOMPRESSION) - zephyr_library_sources( - decompression.c - ) -endif() - if(CONFIG_MCUBOOT_SERIAL) zephyr_sources(${BOOT_DIR}/zephyr/serial_adapter.c) zephyr_sources(${BOOT_DIR}/boot_serial/src/boot_serial.c) diff --git a/boot/zephyr/Kconfig b/boot/zephyr/Kconfig index 492f1ca16..57eec3eae 100644 --- a/boot/zephyr/Kconfig +++ b/boot/zephyr/Kconfig @@ -1157,9 +1157,6 @@ config BOOT_BANNER_STRING config BOOT_DECOMPRESSION_SUPPORT bool - depends on NRF_COMPRESS && NRF_COMPRESS_DECOMPRESSION && (NRF_COMPRESS_LZMA_VERSION_LZMA1 || NRF_COMPRESS_LZMA_VERSION_LZMA2) - depends on !SINGLE_APPLICATION_SLOT && BOOT_UPGRADE_ONLY - default y help Hidden symbol which should be selected if a system provided decompression support. @@ -1167,8 +1164,6 @@ if BOOT_DECOMPRESSION_SUPPORT menuconfig BOOT_DECOMPRESSION bool "Decompression" - select NRF_COMPRESS_CLEANUP - select PM_USE_CONFIG_SRAM_SIZE if SOC_NRF54L15_CPUAPP help If enabled, will include support for compressed images being loaded to the secondary slot which then get decompressed into the primary slot. This mode allows the secondary slot to @@ -1177,9 +1172,9 @@ menuconfig BOOT_DECOMPRESSION if BOOT_DECOMPRESSION config BOOT_DECOMPRESSION_BUFFER_SIZE - int + int "Write buffer size" range 16 16384 - default NRF_COMPRESS_CHUNK_SIZE + default 4096 help The size of a secondary buffer used for writing decompressed data to the storage device. diff --git a/boot/zephyr/decompression.c b/boot/zephyr/decompression.c deleted file mode 100644 index 87e3d3763..000000000 --- a/boot/zephyr/decompression.c +++ /dev/null @@ -1,1505 +0,0 @@ -/* - * Copyright (c) 2024 Nordic Semiconductor ASA - * - * SPDX-License-Identifier: LicenseRef-Nordic-5-Clause - */ - -#include -#include "compression/decompression.h" -#include "bootutil/crypto/sha.h" -#include "bootutil/bootutil_log.h" - -#if !defined(__BOOTSIM__) -#define TARGET_STATIC static -#else -#define TARGET_STATIC -#endif - -#if defined(MCUBOOT_SIGN_RSA) -#if MCUBOOT_SIGN_RSA_LEN == 2048 -#define EXPECTED_SIG_TLV IMAGE_TLV_RSA2048_PSS -#elif MCUBOOT_SIGN_RSA_LEN == 3072 -#define EXPECTED_SIG_TLV IMAGE_TLV_RSA3072_PSS -#endif -#elif defined(MCUBOOT_SIGN_EC256) || \ - defined(MCUBOOT_SIGN_EC384) || \ - defined(MCUBOOT_SIGN_EC) -#define EXPECTED_SIG_TLV IMAGE_TLV_ECDSA_SIG -#elif defined(MCUBOOT_SIGN_ED25519) -#define EXPECTED_SIG_TLV IMAGE_TLV_ED25519 -#endif - -#define DECOMP_BUF_SIZE CONFIG_BOOT_DECOMPRESSION_BUFFER_SIZE -#if defined(CONFIG_NRF_COMPRESS_ARM_THUMB) -/* Extra buffer space for being able to writeback ARM thumb decompression output, - * which may be of +2 bytes more size than its input. - */ -#define DECOMP_BUF_EXTRA_SIZE 2 -#else -#define DECOMP_BUF_EXTRA_SIZE 0 -#endif -#define DECOMP_BUF_ALLOC_SIZE (DECOMP_BUF_SIZE + DECOMP_BUF_EXTRA_SIZE) - -#define DECRYPTION_BLOCK_SIZE_AES128 16 -#define DECRYPTION_BLOCK_SIZE_AES256 32 - -/* Number of times that consumed data by decompression system can be 0 in a row before aborting */ -#define OFFSET_ZERO_CHECK_TIMES 3 - -BOOT_LOG_MODULE_DECLARE(mcuboot); - -static int boot_sha_protected_tlvs(const struct image_header *hdr, - const struct flash_area *fap_src, uint32_t protected_size, - uint8_t *buf, size_t buf_size, bootutil_sha_context *sha_ctx); - -bool boot_is_compressed_header_valid(const struct image_header *hdr, const struct flash_area *fap, - struct boot_loader_state *state) -{ - /* Image is compressed in secondary slot, need to check if fits into the primary slot */ - bool opened_flash_area = false; - int primary_fa_id; - int rc; - int size_check; - int size; - uint32_t protected_tlvs_size; - uint32_t decompressed_size; - - primary_fa_id = flash_area_id_from_multi_image_slot(BOOT_CURR_IMG(state), BOOT_PRIMARY_SLOT); - - if (primary_fa_id == fap->fa_id) { - BOOT_LOG_ERR("Primary slots cannot be compressed, image: %d", BOOT_CURR_IMG(state)); - return false; - } - - if (BOOT_IMG_AREA(state, BOOT_PRIMARY_SLOT) == NULL) { - opened_flash_area = true; - } - - rc = flash_area_open(primary_fa_id, &BOOT_IMG_AREA(state, BOOT_PRIMARY_SLOT)); - assert(rc == 0); - - size_check = flash_area_get_size(BOOT_IMG_AREA(state, BOOT_PRIMARY_SLOT)); - - if (opened_flash_area) { - (void)flash_area_close(BOOT_IMG_AREA(state, BOOT_PRIMARY_SLOT)); - } - - rc = bootutil_get_img_decomp_size(hdr, fap, &decompressed_size); - - if (rc) { - return false; - } - - if (!boot_u32_safe_add(&size, decompressed_size, hdr->ih_hdr_size)) { - return false; - } - - rc = boot_size_protected_tlvs(hdr, fap, &protected_tlvs_size); - - if (rc) { - return false; - } - - if (!boot_u32_safe_add(&size, size, protected_tlvs_size)) { - return false; - } - - if (size >= size_check) { - BOOT_LOG_ERR("Compressed image too large, decompressed image size: 0x%x, slot size: 0x%x", - size, size_check); - return false; - } - - return true; -} - -static bool is_compression_object_valid(struct nrf_compress_implementation *compression) -{ - if (compression == NULL || compression->init == NULL || compression->deinit == NULL || - compression->decompress_bytes_needed == NULL || compression->decompress == NULL) { - return false; - } - - return true; -} - -#ifdef MCUBOOT_ENC_IMAGES -int bootutil_get_img_decrypted_comp_size(const struct image_header *hdr, - const struct flash_area *fap, uint32_t *img_comp_size) -{ - if (hdr == NULL || fap == NULL || img_comp_size == NULL) { - return BOOT_EBADARGS; - } else if (hdr->ih_protect_tlv_size == 0) { - return BOOT_EBADIMAGE; - } - - if (!IS_ENCRYPTED(hdr)) { - /* Update is not encrypted so use size from header */ - *img_comp_size = hdr->ih_img_size; - } else { - struct image_tlv_iter it; - uint32_t off; - uint16_t len; - int32_t rc; - - rc = bootutil_tlv_iter_begin(&it, hdr, fap, IMAGE_TLV_COMP_DEC_SIZE, true); - - if (rc) { - return rc; - } - - rc = bootutil_tlv_iter_next(&it, &off, &len, NULL); - - if (rc != 0) { - return -1; - } - - if (len != sizeof(*img_comp_size)) { - BOOT_LOG_ERR("Invalid decompressed image size TLV: %d", len); - return BOOT_EBADIMAGE; - } - - rc = LOAD_IMAGE_DATA(hdr, fap, off, img_comp_size, len); - - if (rc) { - BOOT_LOG_ERR("Image data load failed at offset: 0x%x, size: 0x%x, area: %d, rc: %d", - off, len, fap->fa_id, rc); - return BOOT_EFLASH; - } - } - - return 0; -} -#endif - -int bootutil_img_hash_decompress(struct boot_loader_state *state, struct image_header *hdr, - const struct flash_area *fap, uint8_t *tmp_buf, - uint32_t tmp_buf_sz, uint8_t *hash_result, - uint8_t *seed, int seed_len) -{ - int rc; - uint32_t read_pos = 0; - uint32_t write_pos = 0; - uint32_t protected_tlv_size = 0; - uint32_t decompressed_image_size; - uint32_t output_size_total = 0; - struct nrf_compress_implementation *compression_lzma = NULL; - struct nrf_compress_implementation *compression_arm_thumb = NULL; - TARGET_STATIC struct image_header modified_hdr; - bootutil_sha_context sha_ctx; - -#ifdef MCUBOOT_ENC_IMAGES - struct enc_key_data *enc_state; - int image_index; - uint32_t comp_size = 0; - uint8_t decryption_block_size = 0; - - rc = bootutil_get_img_decrypted_comp_size(hdr, fap, &comp_size); - - if (rc) { - BOOT_LOG_ERR("Invalid/missing image decrypted compressed size value"); - rc = BOOT_EBADIMAGE; - goto finish_end; - } - - if (state == NULL) { - enc_state = NULL; - image_index = 0; - } else { - enc_state = BOOT_CURR_ENC(state); - image_index = BOOT_CURR_IMG(state); - } - - /* Encrypted images only exist in the secondary slot */ - if (MUST_DECRYPT(fap, image_index, hdr) && - !boot_enc_valid(enc_state, 1)) { - return -1; - } - - if (MUST_DECRYPT(fap, image_index, hdr)) { - if (hdr->ih_flags & IMAGE_F_ENCRYPTED_AES128) { - decryption_block_size = DECRYPTION_BLOCK_SIZE_AES128; - } else if (hdr->ih_flags & IMAGE_F_ENCRYPTED_AES256) { - decryption_block_size = DECRYPTION_BLOCK_SIZE_AES256; - } else { - LOG_ERR("Unknown decryption block size"); - rc = BOOT_EBADIMAGE; - goto finish_end; - } - } -#endif - - bootutil_sha_init(&sha_ctx); - - /* Setup decompression system */ -#if CONFIG_NRF_COMPRESS_LZMA_VERSION_LZMA1 - if (!(hdr->ih_flags & IMAGE_F_COMPRESSED_LZMA1)) { -#elif CONFIG_NRF_COMPRESS_LZMA_VERSION_LZMA2 - if (!(hdr->ih_flags & IMAGE_F_COMPRESSED_LZMA2)) { -#endif - /* Compressed image does not use the correct compression type which is supported by this - * build - */ - BOOT_LOG_ERR("Invalid image compression flags: no supported compression found"); - rc = BOOT_EBADIMAGE; - goto finish_without_clean; - } - - compression_lzma = nrf_compress_implementation_find(NRF_COMPRESS_TYPE_LZMA); - compression_arm_thumb = nrf_compress_implementation_find(NRF_COMPRESS_TYPE_ARM_THUMB); - - if (!is_compression_object_valid(compression_lzma) || - !is_compression_object_valid(compression_arm_thumb)) { - /* Compression library missing or missing required function pointer */ - BOOT_LOG_ERR("Decompression library fatal error"); - rc = BOOT_EBADSTATUS; - goto finish_without_clean; - } - - rc = compression_lzma->init(NULL); - rc = compression_arm_thumb->init(NULL); - - if (rc) { - BOOT_LOG_ERR("Decompression library fatal error"); - rc = BOOT_EBADSTATUS; - goto finish_without_clean; - } - - /* We need a modified header which has the updated sizes, start with the original header */ - memcpy(&modified_hdr, hdr, sizeof(modified_hdr)); - - /* Extract the decompressed image size from the protected TLV, set it and remove the - * compressed image flags - */ - rc = bootutil_get_img_decomp_size(hdr, fap, &decompressed_image_size); - - if (rc) { - BOOT_LOG_ERR("Unable to determine decompressed size of compressed image"); - rc = BOOT_EBADIMAGE; - goto finish; - } - - modified_hdr.ih_flags &= ~COMPRESSIONFLAGS; - modified_hdr.ih_img_size = decompressed_image_size; - - /* Calculate the protected TLV size, these will not include the decompressed - * sha/size/signature entries - */ - rc = boot_size_protected_tlvs(hdr, fap, &protected_tlv_size); - - if (rc) { - BOOT_LOG_ERR("Unable to determine protected TLV size of compressed image"); - rc = BOOT_EBADIMAGE; - goto finish; - } - - modified_hdr.ih_protect_tlv_size = protected_tlv_size; - bootutil_sha_update(&sha_ctx, &modified_hdr, sizeof(modified_hdr)); - read_pos = sizeof(modified_hdr); - - while (read_pos < modified_hdr.ih_hdr_size) { - uint32_t copy_size = tmp_buf_sz; - - if ((read_pos + copy_size) > modified_hdr.ih_hdr_size) { - copy_size = modified_hdr.ih_hdr_size - read_pos; - } - - rc = flash_area_read(fap, read_pos, tmp_buf, copy_size); - - if (rc != 0) { - BOOT_LOG_ERR("Flash read failed at offset: 0x%x, size: 0x%x, area: %d, rc: %d", - (hdr->ih_hdr_size + read_pos), copy_size, fap->fa_id, rc); - rc = BOOT_EFLASH; - goto finish; - } - - bootutil_sha_update(&sha_ctx, tmp_buf, copy_size); - read_pos += copy_size; - } - - /* Read in compressed data, decompress and add to hash calculation */ - read_pos = 0; - -#ifdef MCUBOOT_ENC_IMAGES - while (read_pos < comp_size) { - uint32_t copy_size = comp_size - read_pos; -#else - while (read_pos < hdr->ih_img_size) { - uint32_t copy_size = hdr->ih_img_size - read_pos; -#endif - uint32_t tmp_off = 0; - uint8_t offset_zero_check = 0; - - if (copy_size > tmp_buf_sz) { - copy_size = tmp_buf_sz; - } - - rc = flash_area_read(fap, (hdr->ih_hdr_size + read_pos), tmp_buf, copy_size); - - if (rc != 0) { - BOOT_LOG_ERR("Flash read failed at offset: 0x%x, size: 0x%x, area: %d, rc: %d", - (hdr->ih_hdr_size + read_pos), copy_size, fap->fa_id, rc); - rc = BOOT_EFLASH; - goto finish; - } - -#ifdef MCUBOOT_ENC_IMAGES - if (MUST_DECRYPT(fap, image_index, hdr)) { - uint8_t dummy_bytes = 0; - - if ((copy_size % decryption_block_size)) { - dummy_bytes = decryption_block_size - (copy_size % decryption_block_size); - memset(&tmp_buf[copy_size], 0x00, dummy_bytes); - } - - boot_enc_decrypt(enc_state, 1, read_pos, (copy_size + dummy_bytes), (read_pos & 0xf), - tmp_buf); - } -#endif - - /* Decompress data in chunks, writing it back with a larger write offset of the primary - * slot than read size of the secondary slot - */ - while (tmp_off < copy_size) { - uint32_t offset = 0; - uint8_t *output = NULL; - uint32_t output_size = 0; - uint32_t chunk_size; - bool last_packet = false; - - chunk_size = compression_lzma->decompress_bytes_needed(NULL); - - if (chunk_size > (copy_size - tmp_off)) { - chunk_size = (copy_size - tmp_off); - } - -#ifdef MCUBOOT_ENC_IMAGES - if ((read_pos + tmp_off + chunk_size) >= comp_size) { -#else - if ((read_pos + tmp_off + chunk_size) >= hdr->ih_img_size) { -#endif - last_packet = true; - } - - rc = compression_lzma->decompress(NULL, &tmp_buf[tmp_off], chunk_size, last_packet, - &offset, &output, &output_size); - - if (rc) { - BOOT_LOG_ERR("Decompression error: %d", rc); - rc = BOOT_EBADSTATUS; - goto finish; - } - - write_pos += output_size; - - if (write_pos > decompressed_image_size) { - BOOT_LOG_ERR("Decompressed image larger than claimed TLV size, at least: %d", - write_pos); - rc = BOOT_EBADIMAGE; - goto finish; - } - - /* Additional dry-run validity checks */ - if (last_packet == true && write_pos == 0) { - /* Last packet and we still have no output, this is a faulty update */ - BOOT_LOG_ERR("All compressed data consumed without any output, image not valid"); - rc = BOOT_EBADIMAGE; - goto finish; - } - - if (offset == 0) { - /* If the decompression system continually consumes 0 bytes, then there is a - * problem with this update image, abort and mark image as bad - */ - if (offset_zero_check >= OFFSET_ZERO_CHECK_TIMES) { - BOOT_LOG_ERR("Decompression system returning no output data, image not valid"); - rc = BOOT_EBADIMAGE; - goto finish; - } - - ++offset_zero_check; - - break; - } else { - offset_zero_check = 0; - } - - /* Copy data to secondary buffer for calculating hash */ - if (output_size > 0) { - if (hdr->ih_flags & IMAGE_F_COMPRESSED_ARM_THUMB_FLT) { - /* Run this through the ARM thumb filter */ - uint32_t offset_arm_thumb = 0; - uint8_t *output_arm_thumb = NULL; - uint32_t processed_size = 0; - uint32_t output_size_arm_thumb = 0; - - while (processed_size < output_size) { - uint32_t current_size = output_size - processed_size; - bool arm_thumb_last_packet = false; - - if (current_size > CONFIG_NRF_COMPRESS_CHUNK_SIZE) { - current_size = CONFIG_NRF_COMPRESS_CHUNK_SIZE; - } - - if (last_packet && (processed_size + current_size) == - output_size) { - arm_thumb_last_packet = true; - } - - rc = compression_arm_thumb->decompress(NULL, &output[processed_size], - current_size, arm_thumb_last_packet, - &offset_arm_thumb, - &output_arm_thumb, - &output_size_arm_thumb); - - if (rc) { - BOOT_LOG_ERR("Decompression error: %d", rc); - rc = BOOT_EBADSTATUS; - goto finish; - } - - bootutil_sha_update(&sha_ctx, output_arm_thumb, output_size_arm_thumb); - output_size_total += output_size_arm_thumb; - processed_size += current_size; - } - } else { - bootutil_sha_update(&sha_ctx, output, output_size); - output_size_total += output_size; - } - } - - tmp_off += offset; - } - - read_pos += copy_size; - } - - if (modified_hdr.ih_img_size != output_size_total) { - BOOT_LOG_ERR("Decompression expected output_size mismatch: %d vs %d", - modified_hdr.ih_img_size, output_size_total); - rc = BOOT_EBADSTATUS; - goto finish; - } - - /* If there are any protected TLVs present, add them after the main decompressed image */ - if (modified_hdr.ih_protect_tlv_size > 0) { - rc = boot_sha_protected_tlvs(hdr, fap, modified_hdr.ih_protect_tlv_size, tmp_buf, - tmp_buf_sz, &sha_ctx); - } - - bootutil_sha_finish(&sha_ctx, hash_result); - -finish: - /* Clean up decompression system */ - (void)compression_lzma->deinit(NULL); - (void)compression_arm_thumb->deinit(NULL); - -finish_without_clean: - bootutil_sha_drop(&sha_ctx); - -#ifdef MCUBOOT_ENC_IMAGES -finish_end: -#endif - return rc; -} - -static int boot_copy_protected_tlvs(const struct image_header *hdr, - const struct flash_area *fap_src, - const struct flash_area *fap_dst, uint32_t off_dst, - uint32_t protected_size, uint8_t *buf, size_t buf_size, - uint16_t *buf_pos, uint32_t *written) -{ - int rc; - uint32_t off; - uint32_t write_pos = 0; - uint16_t len; - uint16_t type; - struct image_tlv_iter it; - struct image_tlv tlv_header; - struct image_tlv_info tlv_info_header = { - .it_magic = IMAGE_TLV_PROT_INFO_MAGIC, - .it_tlv_tot = protected_size, - }; - uint16_t info_size_left = sizeof(tlv_info_header); - - while (info_size_left > 0) { - uint16_t copy_size = buf_size - *buf_pos; - - if (info_size_left > 0 && copy_size > 0) { - uint16_t single_copy_size = copy_size; - uint8_t *tlv_info_header_address = (uint8_t *)&tlv_info_header; - - if (single_copy_size > info_size_left) { - single_copy_size = info_size_left; - } - - memcpy(&buf[*buf_pos], &tlv_info_header_address[sizeof(tlv_info_header) - - info_size_left], single_copy_size); - *buf_pos += single_copy_size; - info_size_left -= single_copy_size; - } - - if (*buf_pos == buf_size) { - rc = flash_area_write(fap_dst, (off_dst + write_pos), buf, *buf_pos); - - if (rc != 0) { - BOOT_LOG_ERR("Flash write failed at offset: 0x%x, size: 0x%x, area: %d, rc: %d", - (off_dst + write_pos), *buf_pos, fap_dst->fa_id, rc); - rc = BOOT_EFLASH; - goto out; - } - - write_pos += *buf_pos; - *buf_pos = 0; - } - } - - rc = bootutil_tlv_iter_begin(&it, hdr, fap_src, IMAGE_TLV_ANY, true); - - if (rc) { - goto out; - } - - while (true) { - rc = bootutil_tlv_iter_next(&it, &off, &len, &type); - - if (rc < 0) { - goto out; - } else if (rc > 0) { - rc = 0; - break; - } - - if (type == IMAGE_TLV_DECOMP_SIZE || type == IMAGE_TLV_DECOMP_SHA || - type == IMAGE_TLV_DECOMP_SIGNATURE || type == IMAGE_TLV_COMP_DEC_SIZE) { - /* Skip these TLVs as they are not needed */ - continue; - } else { - uint16_t header_size_left = sizeof(tlv_header); - uint16_t data_size_left = len; - - tlv_header.it_type = type; - tlv_header.it_len = len; - - while (header_size_left > 0 || data_size_left > 0) { - uint16_t copy_size = buf_size - *buf_pos; - uint8_t *tlv_header_address = (uint8_t *)&tlv_header; - - if (header_size_left > 0 && copy_size > 0) { - uint16_t single_copy_size = copy_size; - - if (single_copy_size > header_size_left) { - single_copy_size = header_size_left; - } - - memcpy(&buf[*buf_pos], &tlv_header_address[sizeof(tlv_header) - - header_size_left], - single_copy_size); - *buf_pos += single_copy_size; - copy_size -= single_copy_size; - header_size_left -= single_copy_size; - } - - if (data_size_left > 0 && copy_size > 0) { - uint16_t single_copy_size = copy_size; - - if (single_copy_size > data_size_left) { - single_copy_size = data_size_left; - } - - rc = LOAD_IMAGE_DATA(hdr, fap_src, (off + (len - data_size_left)), - &buf[*buf_pos], single_copy_size); - - if (rc) { - BOOT_LOG_ERR( - "Image data load failed at offset: 0x%x, size: 0x%x, area: %d, rc: %d", - (off + (len - data_size_left)), single_copy_size, fap_src->fa_id, rc); - goto out; - } - - *buf_pos += single_copy_size; - data_size_left -= single_copy_size; - } - - if (*buf_pos == buf_size) { - rc = flash_area_write(fap_dst, (off_dst + write_pos), buf, *buf_pos); - - if (rc != 0) { - BOOT_LOG_ERR( - "Flash write failed at offset: 0x%x, size: 0x%x, area: %d, rc: %d", - (off_dst + write_pos), *buf_pos, fap_dst->fa_id, rc); - rc = BOOT_EFLASH; - goto out; - } - - write_pos += *buf_pos; - *buf_pos = 0; - } - } - } - } - - *written = write_pos; - -out: - return rc; -} - -static int boot_sha_protected_tlvs(const struct image_header *hdr, - const struct flash_area *fap_src, uint32_t protected_size, - uint8_t *buf, size_t buf_size, bootutil_sha_context *sha_ctx) -{ - int rc; - uint32_t off; - uint16_t len; - uint16_t type; - struct image_tlv_iter it; - struct image_tlv tlv_header; - struct image_tlv_info tlv_info_header = { - .it_magic = IMAGE_TLV_PROT_INFO_MAGIC, - .it_tlv_tot = protected_size, - }; - - bootutil_sha_update(sha_ctx, &tlv_info_header, sizeof(tlv_info_header)); - - rc = bootutil_tlv_iter_begin(&it, hdr, fap_src, IMAGE_TLV_ANY, true); - if (rc) { - goto out; - } - - while (true) { - uint32_t read_off = 0; - - rc = bootutil_tlv_iter_next(&it, &off, &len, &type); - - if (rc < 0) { - goto out; - } else if (rc > 0) { - rc = 0; - break; - } - - if (type == IMAGE_TLV_DECOMP_SIZE || type == IMAGE_TLV_DECOMP_SHA || - type == IMAGE_TLV_DECOMP_SIGNATURE || type == IMAGE_TLV_COMP_DEC_SIZE) { - /* Skip these TLVs as they are not needed */ - continue; - } - - tlv_header.it_type = type; - tlv_header.it_len = len; - - bootutil_sha_update(sha_ctx, &tlv_header, sizeof(tlv_header)); - - while (read_off < len) { - uint32_t copy_size = buf_size; - - if (copy_size > (len - read_off)) { - copy_size = len - read_off; - } - - rc = LOAD_IMAGE_DATA(hdr, fap_src, (off + read_off), buf, copy_size); - - if (rc) { - BOOT_LOG_ERR( - "Image data load failed at offset: 0x%x, size: 0x%x, area: %d, rc: %d", - (off + read_off), copy_size, fap_src->fa_id, rc); - goto out; - } - - bootutil_sha_update(sha_ctx, buf, copy_size); - read_off += copy_size; - } - } - -out: - return rc; -} - -int boot_size_protected_tlvs(const struct image_header *hdr, const struct flash_area *fap, - uint32_t *sz) -{ - int rc = 0; - uint32_t tlv_size; - uint32_t off; - uint16_t len; - uint16_t type; - struct image_tlv_iter it; - - *sz = 0; - tlv_size = hdr->ih_protect_tlv_size; - - rc = bootutil_tlv_iter_begin(&it, hdr, fap, IMAGE_TLV_ANY, true); - - if (rc) { - goto out; - } - - while (true) { - rc = bootutil_tlv_iter_next(&it, &off, &len, &type); - - if (rc < 0) { - goto out; - } else if (rc > 0) { - rc = 0; - break; - } - - if (type == IMAGE_TLV_DECOMP_SIZE || type == IMAGE_TLV_DECOMP_SHA || - type == IMAGE_TLV_DECOMP_SIGNATURE || type == IMAGE_TLV_COMP_DEC_SIZE) { - /* Exclude these TLVs as they will be copied to the unprotected area */ - tlv_size -= len + sizeof(struct image_tlv); - } - } - - if (!rc) { - if (tlv_size == sizeof(struct image_tlv_info)) { - /* If there are no entries then omit protected TLV section entirely */ - tlv_size = 0; - } - - *sz = tlv_size; - } - -out: - return rc; -} - -int boot_size_unprotected_tlvs(const struct image_header *hdr, const struct flash_area *fap, - uint32_t *sz) -{ - int rc = 0; - uint32_t tlv_size; - uint32_t off; - uint16_t len; - uint16_t type; - struct image_tlv_iter it; - - *sz = 0; - tlv_size = sizeof(struct image_tlv_info); - - rc = bootutil_tlv_iter_begin(&it, hdr, fap, IMAGE_TLV_ANY, false); - - if (rc) { - goto out; - } - - while (true) { - rc = bootutil_tlv_iter_next(&it, &off, &len, &type); - - if (rc < 0) { - goto out; - } else if (rc > 0) { - rc = 0; - break; - } else if (bootutil_tlv_iter_is_prot(&it, off) && type != IMAGE_TLV_DECOMP_SHA && - type != IMAGE_TLV_DECOMP_SIGNATURE) { - /* Include size of protected hash and signature as these will be replacing the - * original ones - */ - continue; - } else if (type == EXPECTED_HASH_TLV || type == EXPECTED_SIG_TLV || type == IMAGE_TLV_COMP_DEC_SIZE) { - /* Exclude the original unprotected TLVs for signature and hash, the length of the - * signature of the compressed data might not be the same size as the signaute of the - * decompressed data, as is the case when using ECDSA-P256 - */ - continue; - } - - tlv_size += len + sizeof(struct image_tlv); - } - - if (!rc) { - if (tlv_size == sizeof(struct image_tlv_info)) { - /* If there are no entries in the unprotected TLV section then there is something wrong - * with this image - */ - BOOT_LOG_ERR("No unprotected TLVs in post-decompressed image output, image is invalid"); - rc = BOOT_EBADIMAGE; - goto out; - } - - *sz = tlv_size; - } - -out: - return rc; -} - -static int boot_copy_unprotected_tlvs(const struct image_header *hdr, - const struct flash_area *fap_src, - const struct flash_area *fap_dst, uint32_t off_dst, - uint32_t unprotected_size, uint8_t *buf, size_t buf_size, - uint16_t *buf_pos, uint32_t *written) -{ - int rc; - uint32_t write_pos = 0; - uint32_t off; - uint16_t len; - uint16_t type; - struct image_tlv_iter it; - struct image_tlv_iter it_protected; - struct image_tlv tlv_header; - struct image_tlv_info tlv_info_header = { - .it_magic = IMAGE_TLV_INFO_MAGIC, - .it_tlv_tot = unprotected_size, - }; - uint16_t info_size_left = sizeof(tlv_info_header); - - while (info_size_left > 0) { - uint16_t copy_size = buf_size - *buf_pos; - - if (info_size_left > 0 && copy_size > 0) { - uint16_t single_copy_size = copy_size; - uint8_t *tlv_info_header_address = (uint8_t *)&tlv_info_header; - - if (single_copy_size > info_size_left) { - single_copy_size = info_size_left; - } - - memcpy(&buf[*buf_pos], &tlv_info_header_address[sizeof(tlv_info_header) - - info_size_left], single_copy_size); - *buf_pos += single_copy_size; - info_size_left -= single_copy_size; - } - - if (*buf_pos == buf_size) { - rc = flash_area_write(fap_dst, (off_dst + write_pos), buf, *buf_pos); - - if (rc != 0) { - BOOT_LOG_ERR("Flash write failed at offset: 0x%x, size: 0x%x, area: %d, rc: %d", - (off_dst + write_pos), *buf_pos, fap_dst->fa_id, rc); - rc = BOOT_EFLASH; - goto out; - } - - write_pos += *buf_pos; - *buf_pos = 0; - } - } - - rc = bootutil_tlv_iter_begin(&it, hdr, fap_src, IMAGE_TLV_ANY, false); - if (rc) { - goto out; - } - - while (true) { - uint16_t header_size_left = sizeof(tlv_header); - uint16_t data_size_left; - - rc = bootutil_tlv_iter_next(&it, &off, &len, &type); - if (rc < 0) { - goto out; - } else if (rc > 0) { - rc = 0; - break; - } else if (bootutil_tlv_iter_is_prot(&it, off)) { - /* Skip protected TLVs */ - continue; - } - - /* Change the values of these fields from having the data in the compressed image - * unprotected TLV (which is valid only for the compressed image data) to having the - * fields in the protected TLV section (which is valid for the decompressed image data). - * The compressed data is no longer needed - */ - if (type == EXPECTED_HASH_TLV || type == EXPECTED_SIG_TLV) { - rc = bootutil_tlv_iter_begin(&it_protected, hdr, fap_src, (type == EXPECTED_HASH_TLV ? - IMAGE_TLV_DECOMP_SHA : - IMAGE_TLV_DECOMP_SIGNATURE), - true); - - if (rc) { - goto out; - } - - while (true) { - rc = bootutil_tlv_iter_next(&it_protected, &off, &len, &type); - if (rc < 0) { - goto out; - } else if (rc > 0) { - rc = 0; - break; - } - } - - if (type == IMAGE_TLV_DECOMP_SHA) { - type = EXPECTED_HASH_TLV; - } else { - type = EXPECTED_SIG_TLV; - } - } - - data_size_left = len; - tlv_header.it_type = type; - tlv_header.it_len = len; - - while (header_size_left > 0 || data_size_left > 0) { - uint16_t copy_size = buf_size - *buf_pos; - - if (header_size_left > 0 && copy_size > 0) { - uint16_t single_copy_size = copy_size; - uint8_t *tlv_header_address = (uint8_t *)&tlv_header; - - if (single_copy_size > header_size_left) { - single_copy_size = header_size_left; - } - - memcpy(&buf[*buf_pos], &tlv_header_address[sizeof(tlv_header) - header_size_left], - single_copy_size); - *buf_pos += single_copy_size; - copy_size -= single_copy_size; - header_size_left -= single_copy_size; - } - - if (data_size_left > 0 && copy_size > 0) { - uint16_t single_copy_size = copy_size; - - if (single_copy_size > data_size_left) { - single_copy_size = data_size_left; - } - - rc = LOAD_IMAGE_DATA(hdr, fap_src, (off + len - data_size_left), - &buf[*buf_pos], single_copy_size); - - if (rc) { - BOOT_LOG_ERR( - "Image data load failed at offset: 0x%x, size: 0x%x, area: %d, rc: %d", - (off + (len - data_size_left)), single_copy_size, fap_src->fa_id, rc); - goto out; - } - - *buf_pos += single_copy_size; - data_size_left -= single_copy_size; - } - - if (*buf_pos == buf_size) { - rc = flash_area_write(fap_dst, (off_dst + write_pos), buf, *buf_pos); - - if (rc != 0) { - BOOT_LOG_ERR( - "Flash write failed at offset: 0x%x, size: 0x%x, area: %d, rc: %d", - (off_dst + write_pos), *buf_pos, fap_dst->fa_id, rc); - rc = BOOT_EFLASH; - goto out; - } - - write_pos += *buf_pos; - *buf_pos = 0; - } - } - } - - *written = write_pos; - -out: - return rc; -} - -#if defined(CONFIG_NRF_COMPRESS_ARM_THUMB) -/** - * @brief Helper function for in-place ARM Thumb filtering. - * This function places the decompressed data back into the same buffer - * at the beginning, overwriting the compressed data. WARNING: because - * ARM Thumb filtering can return +-2 more/less bytes than the input, - * the buffer provided needs to have free DECOMP_BUF_EXTRA_SIZE bytes at - * the beginning and provide valid data for filtering after these. - * - * @param[in] arm_thumb_impl Pointer to the ARM Thumb decompression implementation. - * @param[in,out] buf Pointer to the buffer containing the compressed data / filtered data. - * @param[in] buf_size Size of the buffer (including DECOMP_BUF_EXTRA_SIZE bytes at the beginning). - * @param[out] out_size Pointer to a variable where the size of the filtered data will be stored. - * @param[in] last_part Indicates if this is the last part of the data to be filtered. - * - * @return 0 on success, BOOT_EBADSTATUS on error. - */ -static int boot_arm_thumb_filter(struct nrf_compress_implementation * const arm_thumb_impl, - uint8_t *buf, size_t buf_size, size_t *out_size, bool last_part) { - - uint32_t filter_writeback_pos = 0; - uint32_t processed_size = 0; - int rc; - - while (processed_size < (buf_size - DECOMP_BUF_EXTRA_SIZE)) { - uint32_t offset_arm_thumb = 0; - uint32_t output_size_arm_thumb = 0; - uint8_t *output_arm_thumb = NULL; - uint32_t current_size = (buf_size - DECOMP_BUF_EXTRA_SIZE - processed_size); - bool arm_thumb_last_packet = false; - - if (current_size > CONFIG_NRF_COMPRESS_CHUNK_SIZE) { - current_size = CONFIG_NRF_COMPRESS_CHUNK_SIZE; - } - - if (last_part && (processed_size + current_size) == (buf_size - DECOMP_BUF_EXTRA_SIZE)) { - arm_thumb_last_packet = true; - } - - rc = arm_thumb_impl->decompress(NULL, - &buf[processed_size + - DECOMP_BUF_EXTRA_SIZE], - current_size, - arm_thumb_last_packet, - &offset_arm_thumb, - &output_arm_thumb, - &output_size_arm_thumb); - - if (rc) { - BOOT_LOG_ERR("Decompression error: %d", rc); - return BOOT_EBADSTATUS; - } - - if (output_size_arm_thumb > (buf_size - filter_writeback_pos)) { - BOOT_LOG_ERR("Filter writeback position exceeds buffer size"); - return BOOT_EBADSTATUS; - } - - memcpy(&buf[filter_writeback_pos], output_arm_thumb, - output_size_arm_thumb); - filter_writeback_pos += output_size_arm_thumb; - processed_size += offset_arm_thumb; - } - *out_size = filter_writeback_pos; - - return 0; -} -#endif /* CONFIG_NRF_COMPRESS_ARM_THUMB */ - -int boot_copy_region_decompress(struct boot_loader_state *state, const struct flash_area *fap_src, - const struct flash_area *fap_dst, uint32_t off_src, - uint32_t off_dst, uint32_t sz, uint8_t *buf, size_t buf_size) -{ - int rc; - uint32_t pos = 0; - uint16_t decomp_buf_size = 0; - uint16_t write_alignment; - uint32_t write_pos = 0; - uint32_t protected_tlv_size = 0; - uint32_t unprotected_tlv_size = 0; - uint32_t tlv_write_size = 0; - uint32_t decompressed_image_size; - struct nrf_compress_implementation *compression_lzma = NULL; - struct nrf_compress_implementation *compression_arm_thumb = NULL; - struct image_header *hdr; - TARGET_STATIC uint8_t decomp_buf[DECOMP_BUF_ALLOC_SIZE] __attribute__((aligned(4))); - TARGET_STATIC struct image_header modified_hdr; - uint16_t decomp_buf_max_size; - -#if defined(CONFIG_NRF_COMPRESS_ARM_THUMB) - uint8_t unaligned_data_length = 0; -#endif - -#ifdef MCUBOOT_ENC_IMAGES - uint32_t comp_size = 0; - uint8_t decryption_block_size = 0; -#endif - - hdr = boot_img_hdr(state, BOOT_SECONDARY_SLOT); - -#ifdef MCUBOOT_ENC_IMAGES - rc = bootutil_get_img_decrypted_comp_size(hdr, fap_src, &comp_size); - - if (rc) { - BOOT_LOG_ERR("Invalid/missing image decrypted compressed size value"); - rc = BOOT_EBADIMAGE; - goto finish; - } - - if (IS_ENCRYPTED(hdr)) { - if (hdr->ih_flags & IMAGE_F_ENCRYPTED_AES128) { - decryption_block_size = DECRYPTION_BLOCK_SIZE_AES128; - } else if (hdr->ih_flags & IMAGE_F_ENCRYPTED_AES256) { - decryption_block_size = DECRYPTION_BLOCK_SIZE_AES256; - } - } -#endif - - /* Setup decompression system */ -#if CONFIG_NRF_COMPRESS_LZMA_VERSION_LZMA1 - if (!(hdr->ih_flags & IMAGE_F_COMPRESSED_LZMA1)) { -#elif CONFIG_NRF_COMPRESS_LZMA_VERSION_LZMA2 - if (!(hdr->ih_flags & IMAGE_F_COMPRESSED_LZMA2)) { -#endif - /* Compressed image does not use the correct compression type which is supported by this - * build - */ - BOOT_LOG_ERR("Invalid image compression flags: no supported compression found"); - rc = BOOT_EBADIMAGE; - goto finish; - } - - compression_lzma = nrf_compress_implementation_find(NRF_COMPRESS_TYPE_LZMA); - compression_arm_thumb = nrf_compress_implementation_find(NRF_COMPRESS_TYPE_ARM_THUMB); - - if (!is_compression_object_valid(compression_lzma) || - !is_compression_object_valid(compression_arm_thumb)) { - /* Compression library missing or missing required function pointer */ - BOOT_LOG_ERR("Decompression library fatal error"); - rc = BOOT_EBADSTATUS; - goto finish; - } - - rc = compression_lzma->init(NULL); - rc = compression_arm_thumb->init(NULL); - - if (rc) { - BOOT_LOG_ERR("Decompression library fatal error"); - rc = BOOT_EBADSTATUS; - goto finish; - } - - write_alignment = flash_area_align(fap_dst); - - decomp_buf_max_size = DECOMP_BUF_SIZE - (DECOMP_BUF_SIZE % write_alignment); - - memcpy(&modified_hdr, hdr, sizeof(modified_hdr)); - - rc = bootutil_get_img_decomp_size(hdr, fap_src, &decompressed_image_size); - - if (rc) { - BOOT_LOG_ERR("Unable to determine decompressed size of compressed image"); - rc = BOOT_EBADIMAGE; - goto finish; - } - - modified_hdr.ih_flags &= ~COMPRESSIONFLAGS; - modified_hdr.ih_img_size = decompressed_image_size; - - /* Calculate protected TLV size for target image once items are removed */ - rc = boot_size_protected_tlvs(hdr, fap_src, &protected_tlv_size); - - if (rc) { - BOOT_LOG_ERR("Unable to determine protected TLV size of compressed image"); - rc = BOOT_EBADIMAGE; - goto finish; - } - - modified_hdr.ih_protect_tlv_size = protected_tlv_size; - - rc = boot_size_unprotected_tlvs(hdr, fap_src, &unprotected_tlv_size); - - if (rc) { - BOOT_LOG_ERR("Unable to determine unprotected TLV size of compressed image"); - rc = BOOT_EBADIMAGE; - goto finish; - } - - /* Write out the image header first, this should be a multiple of the write size */ - rc = flash_area_write(fap_dst, off_dst, &modified_hdr, sizeof(modified_hdr)); - - if (rc != 0) { - BOOT_LOG_ERR("Flash write failed at offset: 0x%x, size: 0x%x, area: %d, rc: %d", - off_dst, sizeof(modified_hdr), fap_dst->fa_id, rc); - rc = BOOT_EFLASH; - goto finish; - } - - /* Read in, decompress and write out data */ -#ifdef MCUBOOT_ENC_IMAGES - while (pos < comp_size) { - uint32_t copy_size = comp_size - pos; -#else - while (pos < hdr->ih_img_size) { - uint32_t copy_size = hdr->ih_img_size - pos; -#endif - uint32_t tmp_off = 0; - - if (copy_size > buf_size) { - copy_size = buf_size; - } - - rc = flash_area_read(fap_src, off_src + hdr->ih_hdr_size + pos, buf, copy_size); - - if (rc != 0) { - BOOT_LOG_ERR("Flash read failed at offset: 0x%x, size: 0x%x, area: %d, rc: %d", - (off_src + hdr->ih_hdr_size + pos), copy_size, fap_src->fa_id, rc); - rc = BOOT_EFLASH; - goto finish; - } - -#ifdef MCUBOOT_ENC_IMAGES - if (IS_ENCRYPTED(hdr)) { - uint8_t dummy_bytes = 0; - - if ((copy_size % decryption_block_size)) { - dummy_bytes = decryption_block_size - (copy_size % decryption_block_size); - memset(&buf[copy_size], 0x00, dummy_bytes); - } - - boot_enc_decrypt(BOOT_CURR_ENC(state), 1, pos, (copy_size + dummy_bytes), (pos & 0xf), buf); - } -#endif - - /* Decompress data in chunks, writing it back with a larger write offset of the primary - * slot than read size of the secondary slot - */ - while (tmp_off < copy_size) { - uint32_t offset = 0; - uint32_t output_size = 0; - uint32_t chunk_size; - uint32_t compression_buffer_pos = 0; - uint8_t *output = NULL; - bool last_packet = false; - - chunk_size = compression_lzma->decompress_bytes_needed(NULL); - - if (chunk_size > (copy_size - tmp_off)) { - chunk_size = (copy_size - tmp_off); - } - -#ifdef MCUBOOT_ENC_IMAGES - if ((pos + tmp_off + chunk_size) >= comp_size) { -#else - if ((pos + tmp_off + chunk_size) >= hdr->ih_img_size) { -#endif - last_packet = true; - } - - rc = compression_lzma->decompress(NULL, &buf[tmp_off], chunk_size, last_packet, - &offset, &output, &output_size); - - if (rc) { - BOOT_LOG_ERR("Decompression error: %d", rc); - rc = BOOT_EBADSTATUS; - goto finish; - } - - /* Copy data to secondary buffer for writing out */ - while (output_size > 0) { - uint32_t data_size = (decomp_buf_max_size - decomp_buf_size); - - if (data_size > output_size) { - data_size = output_size; - } - -#if defined(CONFIG_NRF_COMPRESS_ARM_THUMB) - if (hdr->ih_flags & IMAGE_F_COMPRESSED_ARM_THUMB_FLT) { - memcpy(&decomp_buf[decomp_buf_size + DECOMP_BUF_EXTRA_SIZE], - &output[compression_buffer_pos], data_size); - } else -#endif - { - memcpy(&decomp_buf[decomp_buf_size], &output[compression_buffer_pos], - data_size); - } - - compression_buffer_pos += data_size; - - decomp_buf_size += data_size; - output_size -= data_size; - - /* Write data out from secondary buffer when it is full */ - if (decomp_buf_size == decomp_buf_max_size) { -#if defined(CONFIG_NRF_COMPRESS_ARM_THUMB) - if (hdr->ih_flags & IMAGE_F_COMPRESSED_ARM_THUMB_FLT) { - - uint32_t filter_output_size; - - /* Run this through the ARM thumb filter */ - rc = boot_arm_thumb_filter(compression_arm_thumb, - &decomp_buf[unaligned_data_length], - decomp_buf_size - unaligned_data_length + DECOMP_BUF_EXTRA_SIZE, - &filter_output_size, - last_packet && output_size == 0); - - if (rc) { - goto finish; - } - - decomp_buf_size = filter_output_size + unaligned_data_length; - unaligned_data_length = decomp_buf_size % write_alignment; - - rc = flash_area_write(fap_dst, - (off_dst + hdr->ih_hdr_size + write_pos), - decomp_buf, - (decomp_buf_size - unaligned_data_length)); - - if (rc != 0) { - BOOT_LOG_ERR( - "Flash write failed at offset: 0x%x, size: 0x%x, area: %d, rc: %d", - (off_dst + hdr->ih_hdr_size + write_pos), - (decomp_buf_size - unaligned_data_length), - fap_dst->fa_id, rc); - rc = BOOT_EFLASH; - goto finish; - } - - memmove(decomp_buf, - &decomp_buf[decomp_buf_size - unaligned_data_length], - unaligned_data_length); - write_pos += decomp_buf_size - unaligned_data_length; - decomp_buf_size = unaligned_data_length; - } else -#endif - { - rc = flash_area_write(fap_dst, (off_dst + hdr->ih_hdr_size + write_pos), - decomp_buf, decomp_buf_max_size); - - if (rc != 0) { - BOOT_LOG_ERR( - "Flash write failed at offset: 0x%x, size: 0x%x, area: %d, rc: %d", - (off_dst + hdr->ih_hdr_size + write_pos), decomp_buf_max_size, - fap_dst->fa_id, rc); - rc = BOOT_EFLASH; - goto finish; - } - - write_pos += decomp_buf_max_size; - decomp_buf_size = 0; - } - } - } - - tmp_off += offset; - } - - pos += copy_size; - } - -#if defined(CONFIG_NRF_COMPRESS_ARM_THUMB) - if (hdr->ih_flags & IMAGE_F_COMPRESSED_ARM_THUMB_FLT && decomp_buf_size > 0) { - /* Extra data that has not been written out that needs ARM thumb filter applied */ - - uint32_t filter_output_size; - - rc = boot_arm_thumb_filter(compression_arm_thumb, - &decomp_buf[unaligned_data_length], - decomp_buf_size - unaligned_data_length + DECOMP_BUF_EXTRA_SIZE, - &filter_output_size, - true); - - if (rc) { - goto finish; - } - - decomp_buf_size = filter_output_size + unaligned_data_length; - - if (decomp_buf_size > decomp_buf_max_size) { - /* It can happen if ARM thumb decompression returned +2 bytes and we had near full - * decomp_buf. We still can hold these additional 2 bytes because of - * DECOMP_BUF_EXTRA_SIZE allocated. */ - - rc = flash_area_write(fap_dst, (off_dst + hdr->ih_hdr_size + write_pos), - decomp_buf, decomp_buf_max_size); - - if (rc != 0) { - BOOT_LOG_ERR("Flash write failed at offset: 0x%x, size: 0x%x, area: %d, rc: %d", - (off_dst + hdr->ih_hdr_size + write_pos), decomp_buf_max_size, - fap_dst->fa_id, rc); - rc = BOOT_EFLASH; - goto finish; - } - memmove(decomp_buf, &decomp_buf[decomp_buf_max_size], - (decomp_buf_size - decomp_buf_max_size)); - - decomp_buf_size = decomp_buf_size - decomp_buf_max_size; - write_pos += decomp_buf_max_size; - } - } -#endif - - /* Clean up decompression system */ - (void)compression_lzma->deinit(NULL); - (void)compression_arm_thumb->deinit(NULL); - - if (protected_tlv_size > 0) { - rc = boot_copy_protected_tlvs(hdr, fap_src, fap_dst, (off_dst + hdr->ih_hdr_size + - write_pos), protected_tlv_size, - decomp_buf, decomp_buf_max_size, &decomp_buf_size, - &tlv_write_size); - - if (rc) { - BOOT_LOG_ERR("Protected TLV copy failure: %d", rc); - goto finish; - } - - write_pos += tlv_write_size; - } - - tlv_write_size = 0; - rc = boot_copy_unprotected_tlvs(hdr, fap_src, fap_dst, (off_dst + hdr->ih_hdr_size + - write_pos), unprotected_tlv_size, - decomp_buf, decomp_buf_max_size, &decomp_buf_size, - &tlv_write_size); - - if (rc) { - BOOT_LOG_ERR("Protected TLV copy failure: %d", rc); - goto finish; - } - - write_pos += tlv_write_size; - - /* Check if we have unwritten data buffered up and, if so, write it out */ - if (decomp_buf_size > 0) { - uint32_t write_padding_size = write_alignment - (decomp_buf_size % write_alignment); - - /* Check if additional write padding should be applied to meet the minimum write size */ - if (write_alignment > 1 && write_padding_size) { - uint8_t flash_erased_value; - - flash_erased_value = flash_area_erased_val(fap_dst); - memset(&decomp_buf[decomp_buf_size], flash_erased_value, write_padding_size); - decomp_buf_size += write_padding_size; - } - - rc = flash_area_write(fap_dst, (off_dst + hdr->ih_hdr_size + write_pos), decomp_buf, - decomp_buf_size); - - if (rc != 0) { - BOOT_LOG_ERR("Flash write failed at offset: 0x%x, size: 0x%x, area: %d, rc: %d", - (off_dst + hdr->ih_hdr_size + write_pos), decomp_buf_size, - fap_dst->fa_id, rc); - rc = BOOT_EFLASH; - goto finish; - } - - write_pos += decomp_buf_size; - decomp_buf_size = 0; - } - -finish: - memset(decomp_buf, 0, sizeof(decomp_buf)); - - return rc; -} - -int bootutil_get_img_decomp_size(const struct image_header *hdr, const struct flash_area *fap, - uint32_t *img_decomp_size) -{ - struct image_tlv_iter it; - uint32_t off; - uint16_t len; - int32_t rc; - - if (hdr == NULL || fap == NULL || img_decomp_size == NULL) { - return BOOT_EBADARGS; - } else if (hdr->ih_protect_tlv_size == 0) { - return BOOT_EBADIMAGE; - } - - rc = bootutil_tlv_iter_begin(&it, hdr, fap, IMAGE_TLV_DECOMP_SIZE, true); - - if (rc) { - return rc; - } - - rc = bootutil_tlv_iter_next(&it, &off, &len, NULL); - - if (rc != 0) { - return -1; - } - - if (len != sizeof(*img_decomp_size)) { - BOOT_LOG_ERR("Invalid decompressed image size TLV: %d", len); - return BOOT_EBADIMAGE; - } - - rc = LOAD_IMAGE_DATA(hdr, fap, off, img_decomp_size, len); - - if (rc) { - BOOT_LOG_ERR("Image data load failed at offset: 0x%x, size: 0x%x, area: %d, rc: %d", - off, len, fap->fa_id, rc); - return BOOT_EFLASH; - } - - return 0; -} diff --git a/boot/zephyr/include/compression/decompression.h b/boot/zephyr/include/compression/decompression.h deleted file mode 100644 index 2104c4eb6..000000000 --- a/boot/zephyr/include/compression/decompression.h +++ /dev/null @@ -1,103 +0,0 @@ -/* - * Copyright (c) 2024 Nordic Semiconductor ASA - * - * SPDX-License-Identifier: LicenseRef-Nordic-5-Clause - */ - -#ifndef H_DECOMPRESSION_ -#define H_DECOMPRESSION_ - -#include -#include -#include -#include "bootutil/bootutil.h" -#include "bootutil/bootutil_public.h" -#include "bootutil/image.h" -#include "../src/bootutil_priv.h" - -#ifdef __cplusplus -extern "C" { -#endif - -/** - * Checks if a compressed image header is valid. - * - * @param hdr Image header. - * @param fap Flash area of the slot. - * @param state Bootloader state object. - * - * @return true if valid; false if invalid. - */ -bool boot_is_compressed_header_valid(const struct image_header *hdr, const struct flash_area *fap, - struct boot_loader_state *state); - -/** - * Reads in compressed image data from a slot, decompresses it and writes it out to a destination - * slot, including corresponding image headers and TLVs. - * - * @param state Bootloader state object. - * @param fap_src Flash area of the source slot. - * @param fap_dst Flash area of the destination slot. - * @param off_src Offset of the source slot to read from (should be 0). - * @param off_dst Offset of the destination slot to write to (should be 0). - * @param sz Size of the source slot data. - * @param buf Temporary buffer for reading data from. - * @param buf_size Size of temporary buffer. - * - * @return 0 on success; nonzero on failure. - */ -int boot_copy_region_decompress(struct boot_loader_state *state, const struct flash_area *fap_src, - const struct flash_area *fap_dst, uint32_t off_src, - uint32_t off_dst, uint32_t sz, uint8_t *buf, size_t buf_size); - -/** - * Gets the total data size (excluding headers and TLVs) of a compressed image when it is - * decompressed. - * - * @param hdr Image header. - * @param fap Flash area of the slot. - * @param img_decomp_size Pointer to variable that will be updated with the decompressed image - * size. - * - * @return 0 on success; nonzero on failure. - */ -int bootutil_get_img_decomp_size(const struct image_header *hdr, const struct flash_area *fap, - uint32_t *img_decomp_size); - -/** - * Calculate MCUboot-compatible image hash of compressed image slot. - * - * @param state MCUboot state. - * @param hdr Image header. - * @param fap Flash area of the slot. - * @param tmp_buf Temporary buffer for reading data from. - * @param tmp_buf_sz Size of temporary buffer. - * @param hash_result Pointer to a variable that will be updated with the image hash. - * @param seed Not currently used, set to NULL. - * @param seed_len Not currently used, set to 0. - * - * @return 0 on success; nonzero on failure. - */ -int bootutil_img_hash_decompress(struct boot_loader_state *state, struct image_header *hdr, - const struct flash_area *fap, uint8_t *tmp_buf, - uint32_t tmp_buf_sz, uint8_t *hash_result, - uint8_t *seed, int seed_len); - -/** - * Calculates the size that the compressed image protected TLV section will occupy once the image - * has been decompressed. - * - * @param hdr Image header. - * @param fap Flash area of the slot. - * @param sz Pointer to variable that will be updated with the protected TLV size. - * - * @return 0 on success; nonzero on failure. - */ -int boot_size_protected_tlvs(const struct image_header *hdr, const struct flash_area *fap_src, - uint32_t *sz); - -#ifdef __cplusplus -} -#endif - -#endif /* H_DECOMPRESSION_ */ From ad5310a33a6ace0e0f45c7d36fff7b772e45b4ea Mon Sep 17 00:00:00 2001 From: Jukka Rissanen Date: Tue, 23 Sep 2025 13:04:29 +0300 Subject: [PATCH 175/420] Revert "[nrf noup] boot: Improve bootloader request handling" This reverts commit 0b546656c3792bfe8e980fbde5eacdb27aa7eccd. Signed-off-by: Jukka Rissanen --- boot/bootutil/src/bootutil_public.c | 17 ++++------------- boot/zephyr/Kconfig | 11 ----------- 2 files changed, 4 insertions(+), 24 deletions(-) diff --git a/boot/bootutil/src/bootutil_public.c b/boot/bootutil/src/bootutil_public.c index 750157e82..7371a9fe9 100644 --- a/boot/bootutil/src/bootutil_public.c +++ b/boot/bootutil/src/bootutil_public.c @@ -510,8 +510,7 @@ boot_write_copy_done(const struct flash_area *fap) #ifdef SEND_BOOT_REQUEST static int -send_boot_request(uint8_t magic, uint8_t image_ok, bool confirm, int image_id, - uint32_t slot_id) +send_boot_request(uint8_t magic, bool confirm, int image_id, uint32_t slot_id) { int rc = BOOT_EBADIMAGE; @@ -519,16 +518,10 @@ send_boot_request(uint8_t magic, uint8_t image_ok, bool confirm, int image_id, if ((magic == BOOT_MAGIC_GOOD) || (magic == BOOT_MAGIC_UNSET)) { if (confirm) { BOOT_LOG_DBG("Confirm image: %d, %d", image_id, slot_id); - if ((image_ok != BOOT_FLAG_SET) || (magic != BOOT_MAGIC_GOOD)) { - rc = boot_request_confirm_slot(image_id, slot_id); - } else { - rc = 0; - } -#ifdef CONFIG_NCS_MCUBOOT_BOOT_REQUEST_TEST_SETS_BOOT_PREFERENCE + rc = boot_request_confirm_slot(image_id, slot_id); } else { BOOT_LOG_DBG("Set image preference: %d, %d", image_id, slot_id); rc = boot_request_set_preferred_slot(image_id, slot_id); -#endif /* CONFIG_NCS_MCUBOOT_BOOT_REQUEST_TEST_SETS_BOOT_PREFERENCE */ } if (rc != 0) { rc = BOOT_EBADIMAGE; @@ -601,8 +594,7 @@ boot_set_next(const struct flash_area *fa, bool active, bool confirm) image_id = flash_area_to_image_slot(fa, &slot_id); #ifdef SEND_BOOT_REQUEST - rc = send_boot_request(slot_state.magic, slot_state.image_ok, confirm, - image_id, slot_id); + rc = send_boot_request(slot_state.magic, confirm, image_id, slot_id); if ((rc != 0) || active) { return rc; } @@ -694,8 +686,7 @@ boot_set_next(const struct flash_area *fa, bool active, bool confirm) #ifdef SEND_BOOT_REQUEST image_id = flash_area_to_image_slot(fa, &slot_id); - rc = send_boot_request(slot_state.magic, slot_state.image_ok, confirm, - image_id, slot_id); + rc = send_boot_request(slot_state.magic, confirm, image_id, slot_id); if ((rc != 0) || active) { return rc; } diff --git a/boot/zephyr/Kconfig b/boot/zephyr/Kconfig index 57eec3eae..4b2458cfc 100644 --- a/boot/zephyr/Kconfig +++ b/boot/zephyr/Kconfig @@ -1321,15 +1321,4 @@ config NCS_MCUBOOT_IMG_VALIDATE_ATTEMPT_WAIT_MS Time between image validation attempts, in milliseconds. Allows for recovery from transient bit flips or similar situations. -config NCS_MCUBOOT_BOOT_REQUEST_TEST_SETS_BOOT_PREFERENCE - bool "Set boot preference if a slot is marked for test" - help - This option allows to verify boot preference requests through issuing - the image test. - Using this option is not recommended in production systems, because - it will boot any newly transferred image, even if it has a lower - version than the current one. - The rollback protection (using security counters) will still be - effective. - source "Kconfig.zephyr" From bde7f778c32523cec2c5869c764f5ec97ef493ca Mon Sep 17 00:00:00 2001 From: Jukka Rissanen Date: Tue, 23 Sep 2025 13:04:29 +0300 Subject: [PATCH 176/420] Revert "[nrf noup] bootloader: Add bootloader requests" This reverts commit 09ce751132d4a7b48ec110c3f8ea2e6256601731. Signed-off-by: Jukka Rissanen --- boot/bootutil/include/bootutil/boot_request.h | 105 ------ boot/bootutil/src/bootutil_public.c | 84 +---- boot/bootutil/zephyr/CMakeLists.txt | 5 - .../zephyr/src/boot_request_retention.c | 346 ------------------ boot/zephyr/Kconfig | 4 - boot/zephyr/Kconfig.firmware_loader | 6 - boot/zephyr/Kconfig.serial_recovery | 6 - boot/zephyr/firmware_loader.c | 9 - boot/zephyr/main.c | 53 --- 9 files changed, 5 insertions(+), 613 deletions(-) delete mode 100644 boot/bootutil/include/bootutil/boot_request.h delete mode 100644 boot/bootutil/zephyr/src/boot_request_retention.c diff --git a/boot/bootutil/include/bootutil/boot_request.h b/boot/bootutil/include/bootutil/boot_request.h deleted file mode 100644 index b1e8f891e..000000000 --- a/boot/bootutil/include/bootutil/boot_request.h +++ /dev/null @@ -1,105 +0,0 @@ -/* - * SPDX-License-Identifier: Apache-2.0 - * - * Copyright (c) 2025 Nordic Semiconductor ASA - */ - -#ifndef __BOOT_REQUEST_H__ -#define __BOOT_REQUEST_H__ - -#ifdef __cplusplus -extern "C" { -#endif - -#include -#include - -/** Special value, indicating that there is no preferred slot. */ -#define BOOT_REQUEST_NO_PREFERRED_SLOT UINT32_MAX - -/** - * @brief Request a bootloader to confirm the specified slot of an image. - * - * @param[in] image Image number. - * @param[in] slot Slot number. - * - * @return 0 if requested, negative error code otherwise. - */ -int boot_request_confirm_slot(uint8_t image, uint32_t slot); - -/** - * @brief Request a bootloader to boot the specified slot of an image. - * - * @param[in] image Image number. - * @param[in] slot Slot number. - * - * @return 0 if requested, negative error code otherwise. - */ -int boot_request_set_preferred_slot(uint8_t image, uint32_t slot); - -/** - * @brief Request a bootloader to boot recovery image. - * - * @return 0 if requested, negative error code otherwise. - */ -int boot_request_enter_recovery(void); - -/** - * @brief Request a bootloader to boot firmware loader image. - * - * @return 0 if requested, negative error code otherwise. - */ -int boot_request_enter_firmware_loader(void); - -/** - * @brief Check if there is a request to confirm the specified slot of an image. - * - * @param[in] image Image number. - * @param[in] slot Slot number. - * - * @return true if requested, false otherwise. - */ -bool boot_request_check_confirmed_slot(uint8_t image, uint32_t slot); - -/** - * @brief Find if there is a request to boot certain slot of the specified image. - * - * @param[in] image Image number. - * - * @return slot number if requested, BOOT_REQUEST_NO_PREFERRED_SLOT otherwise. - */ -uint32_t boot_request_get_preferred_slot(uint8_t image); - -/** - * @brief Check if there is a request to boot recovery image. - * - * @return true if requested, false otherwise. - */ -bool boot_request_detect_recovery(void); - -/** - * @brief Check if there is a request to boot firmware loader image. - * - * @return true if requested, false otherwise. - */ -bool boot_request_detect_firmware_loader(void); - -/** - * @brief Initialize boot requests module. - * - * @return 0 if successful, negative error code otherwise. - */ -int boot_request_init(void); - -/** - * @brief Clear/drop all requests. - * - * @return 0 if successful, negative error code otherwise. - */ -int boot_request_clear(void); - -#ifdef __cplusplus -} -#endif - -#endif /* __BOOT_REQUEST_H__ */ diff --git a/boot/bootutil/src/bootutil_public.c b/boot/bootutil/src/bootutil_public.c index 7371a9fe9..8860fca41 100644 --- a/boot/bootutil/src/bootutil_public.c +++ b/boot/bootutil/src/bootutil_public.c @@ -51,11 +51,6 @@ #include "bootutil_priv.h" #include "bootutil_misc.h" -#if defined(CONFIG_NRF_MCUBOOT_BOOT_REQUEST) && !defined(CONFIG_MCUBOOT) -#include -#define SEND_BOOT_REQUEST -#endif /* CONFIG_NRF_MCUBOOT_BOOT_REQUEST && !CONFIG_MCUBOOT */ - #ifdef CONFIG_MCUBOOT BOOT_LOG_MODULE_DECLARE(mcuboot); #else @@ -508,47 +503,16 @@ boot_write_copy_done(const struct flash_area *fap) return boot_write_trailer_flag(fap, off, BOOT_FLAG_SET); } -#ifdef SEND_BOOT_REQUEST -static int -send_boot_request(uint8_t magic, bool confirm, int image_id, uint32_t slot_id) -{ - int rc = BOOT_EBADIMAGE; - - /* Handle write-protected active image. */ - if ((magic == BOOT_MAGIC_GOOD) || (magic == BOOT_MAGIC_UNSET)) { - if (confirm) { - BOOT_LOG_DBG("Confirm image: %d, %d", image_id, slot_id); - rc = boot_request_confirm_slot(image_id, slot_id); - } else { - BOOT_LOG_DBG("Set image preference: %d, %d", image_id, slot_id); - rc = boot_request_set_preferred_slot(image_id, slot_id); - } - if (rc != 0) { - rc = BOOT_EBADIMAGE; - } - } - - return rc; -} -#endif /* SEND_BOOT_REQUEST */ +#ifndef MCUBOOT_BOOTUTIL_LIB_FOR_DIRECT_XIP -#if defined(SEND_BOOT_REQUEST) || (!defined(MCUBOOT_BOOTUTIL_LIB_FOR_DIRECT_XIP)) -static int flash_area_to_image_slot(const struct flash_area *fa, uint32_t *slot) +static int flash_area_to_image(const struct flash_area *fa) { - int id = flash_area_get_id(fa); #if BOOT_IMAGE_NUMBER > 1 uint8_t i = 0; + int id = flash_area_get_id(fa); while (i < BOOT_IMAGE_NUMBER) { - if (FLASH_AREA_IMAGE_PRIMARY(i) == id) { - if (slot != NULL) { - *slot = 0; - } - return i; - } else if (FLASH_AREA_IMAGE_SECONDARY(i) == id) { - if (slot != NULL) { - *slot = 1; - } + if (FLASH_AREA_IMAGE_PRIMARY(i) == id || (FLASH_AREA_IMAGE_SECONDARY(i) == id)) { return i; } @@ -556,31 +520,15 @@ static int flash_area_to_image_slot(const struct flash_area *fa, uint32_t *slot) } #else (void)fa; - if (slot != NULL) { - if (FLASH_AREA_IMAGE_PRIMARY(0) == id) { - *slot = 0; - } else if (FLASH_AREA_IMAGE_SECONDARY(0) == id) { - *slot = 1; - } else { - *slot = UINT32_MAX; - } - } #endif return 0; } -#endif /* defined(SEND_BOOT_REQUEST) || (!defined(MCUBOOT_BOOTUTIL_LIB_FOR_DIRECT_XIP)) */ -#ifndef MCUBOOT_BOOTUTIL_LIB_FOR_DIRECT_XIP int boot_set_next(const struct flash_area *fa, bool active, bool confirm) { struct boot_swap_state slot_state; int rc; - int image_id; - uint32_t slot_id; - - BOOT_LOG_DBG("boot_set_next: fa %p active == %d, confirm == %d", - fa, (int)active, (int)confirm); if (active) { confirm = true; @@ -591,15 +539,6 @@ boot_set_next(const struct flash_area *fa, bool active, bool confirm) return rc; } - image_id = flash_area_to_image_slot(fa, &slot_id); - -#ifdef SEND_BOOT_REQUEST - rc = send_boot_request(slot_state.magic, confirm, image_id, slot_id); - if ((rc != 0) || active) { - return rc; - } -#endif - switch (slot_state.magic) { case BOOT_MAGIC_GOOD: /* If non-active then swap already scheduled, else confirm needed.*/ @@ -630,7 +569,7 @@ boot_set_next(const struct flash_area *fa, bool active, bool confirm) } else { swap_type = BOOT_SWAP_TYPE_TEST; } - rc = boot_write_swap_info(fa, swap_type, image_id); + rc = boot_write_swap_info(fa, swap_type, flash_area_to_image(fa)); } } break; @@ -661,10 +600,6 @@ boot_set_next(const struct flash_area *fa, bool active, bool confirm) { struct boot_swap_state slot_state; int rc; -#ifdef SEND_BOOT_REQUEST - int image_id; - uint32_t slot_id; -#endif BOOT_LOG_DBG("boot_set_next: fa %p active == %d, confirm == %d", fa, (int)active, (int)confirm); @@ -683,15 +618,6 @@ boot_set_next(const struct flash_area *fa, bool active, bool confirm) return rc; } -#ifdef SEND_BOOT_REQUEST - image_id = flash_area_to_image_slot(fa, &slot_id); - - rc = send_boot_request(slot_state.magic, confirm, image_id, slot_id); - if ((rc != 0) || active) { - return rc; - } -#endif - switch (slot_state.magic) { case BOOT_MAGIC_UNSET: /* Magic is needed for MCUboot to even consider booting an image */ diff --git a/boot/bootutil/zephyr/CMakeLists.txt b/boot/bootutil/zephyr/CMakeLists.txt index 111cf4f1d..44f78f395 100644 --- a/boot/bootutil/zephyr/CMakeLists.txt +++ b/boot/bootutil/zephyr/CMakeLists.txt @@ -16,11 +16,6 @@ zephyr_library_named(mcuboot_util) zephyr_library_sources( ../src/bootutil_public.c ) -if(CONFIG_NRF_MCUBOOT_BOOT_REQUEST) - zephyr_library_sources_ifdef(CONFIG_NRF_MCUBOOT_BOOT_REQUEST_IMPL_RETENTION - src/boot_request_retention.c - ) -endif() # Sensitivity to the TEST_BOOT_IMAGE_ACCESS_HOOKS define is implemented for # allowing the test-build with the hooks feature enabled. diff --git a/boot/bootutil/zephyr/src/boot_request_retention.c b/boot/bootutil/zephyr/src/boot_request_retention.c deleted file mode 100644 index 023f5af5e..000000000 --- a/boot/bootutil/zephyr/src/boot_request_retention.c +++ /dev/null @@ -1,346 +0,0 @@ -/* - * SPDX-License-Identifier: Apache-2.0 - * - * Copyright (c) 2025 Nordic Semiconductor ASA - */ -#include - -#include "bootutil/bootutil_log.h" -#include - -/** Special value of image number, indicating a request to the bootloader. */ -#define BOOT_REQUEST_IMG_BOOTLOADER 0xFF - -/** Additional memory used by the retention subsystem (2B - prefix, 4B - CRC).*/ -#define BOOT_REQUEST_ENTRY_METADATA_SIZE (2 + 4) - -MCUBOOT_LOG_MODULE_REGISTER(bootloader_request); - -static const struct device *bootloader_request_dev = - DEVICE_DT_GET(DT_CHOSEN(nrf_bootloader_request)); - -enum boot_request_type { - /** Invalid request. */ - BOOT_REQUEST_INVALID = 0, - - /** Request a change in the bootloader boot mode. - * - * @details Use @p boot_request_mode as argument. - * @p BOOT_REQUEST_IMG_BOOTLOADER as image number. - * - * @note Used to trigger recovery through i.e. retention sybsystem. - */ - BOOT_REQUEST_BOOT_MODE = 1, - - /** Select the preferred image to be selected during boot or update. - * - * @details Use @p boot_request_slot_t as argument. - * - * @note Used in the Direct XIP mode. - */ - BOOT_REQUEST_IMG_PREFERENCE = 2, - - /** Request a confirmation of an image. - * - * @details Use @p boot_request_slot_t as argument. - * - * @note Used if the code cannot modify the image trailer directly. - */ - BOOT_REQUEST_IMG_CONFIRM = 3, -}; - -/* Entries inside the boot request shared memory. */ -enum boot_request_entry { - BOOT_REQUEST_ENTRY_BOOT_MODE = 0, - BOOT_REQUEST_ENTRY_IMAGE_0_PREFERENCE = 1, - BOOT_REQUEST_ENTRY_IMAGE_0_CONFIRM = 2, - BOOT_REQUEST_ENTRY_IMAGE_1_PREFERENCE = 3, - BOOT_REQUEST_ENTRY_IMAGE_1_CONFIRM = 4, - BOOT_REQUEST_ENTRY_MAX = 5, -}; - -/* Assert that all requests will fit within the retention area. */ -BUILD_ASSERT((BOOT_REQUEST_ENTRY_METADATA_SIZE + BOOT_REQUEST_ENTRY_MAX * sizeof(uint8_t)) < - DT_REG_SIZE_BY_IDX(DT_CHOSEN(nrf_bootloader_request), 0), - "nrf,bootloader-request area is too small for bootloader request struct"); - -enum boot_request_slot { - /** Unsupported value. */ - BOOT_REQUEST_SLOT_INVALID = 0, - /** Primary slot. */ - BOOT_REQUEST_SLOT_PRIMARY = 1, - /** Secondary slot. */ - BOOT_REQUEST_SLOT_SECONDARY = 2, -}; - -/** Alias type for the image and number. */ -typedef uint8_t boot_request_slot_t; - -enum boot_request_mode { - /** Execute a regular boot logic. */ - BOOT_REQUEST_MODE_REGULAR = 0, - /** Execute the recovery boot logic. */ - BOOT_REQUEST_MODE_RECOVERY = 1, - /** Execute the firmware loader logic. */ - BOOT_REQUEST_MODE_FIRMWARE_LOADER = 2, - /** Unsupported value. */ - BOOT_REQUEST_MODE_INVALID = 0xFF, -}; - -/** Alias type for the image number. */ -typedef uint8_t boot_request_img_t; - -/** - * @brief Find an entry for a given request. - * - * @param[in] type Type of request. - * @param[in] image Image number. Use @p BOOT_REQUEST_IMG_BOOTLOADER for generic requests. - * @param[out] entry Entry to use. - * - * @return 0 on success; nonzero on failure. - */ -static int boot_request_entry_find(enum boot_request_type type, boot_request_img_t image, - size_t *entry) -{ - if (entry == NULL) { - return -EINVAL; - } - - switch (type) { - case BOOT_REQUEST_BOOT_MODE: - *entry = BOOT_REQUEST_ENTRY_BOOT_MODE; - break; - case BOOT_REQUEST_IMG_PREFERENCE: - switch (image) { - case 0: - *entry = BOOT_REQUEST_ENTRY_IMAGE_0_PREFERENCE; - break; - case 1: - *entry = BOOT_REQUEST_ENTRY_IMAGE_1_PREFERENCE; - break; - default: - return -EINVAL; - } - break; - case BOOT_REQUEST_IMG_CONFIRM: - switch (image) { - case 0: - *entry = BOOT_REQUEST_ENTRY_IMAGE_0_CONFIRM; - break; - case 1: - *entry = BOOT_REQUEST_ENTRY_IMAGE_1_CONFIRM; - break; - default: - return -EINVAL; - } - break; - default: - return -EINVAL; - } - - return 0; -} - -int boot_request_init(void) -{ - if (!device_is_ready(bootloader_request_dev)) { - return -EIO; - } - - return 0; -} - -int boot_request_clear(void) -{ - return retention_clear(bootloader_request_dev); -} - -int boot_request_confirm_slot(uint8_t image, uint32_t slot) -{ - uint8_t value = BOOT_REQUEST_SLOT_INVALID; - size_t req_entry; - int ret; - - ret = boot_request_entry_find(BOOT_REQUEST_IMG_CONFIRM, image, &req_entry); - if (ret != 0) { - return ret; - } - - switch (slot) { - case 0: - value = BOOT_REQUEST_SLOT_PRIMARY; - break; - case 1: - value = BOOT_REQUEST_SLOT_SECONDARY; - break; - default: - return -EINVAL; - } - - return retention_write(bootloader_request_dev, req_entry * sizeof(value), (void *)&value, - sizeof(value)); -} - -bool boot_request_check_confirmed_slot(uint8_t image, uint32_t slot) -{ - uint8_t value = BOOT_REQUEST_SLOT_INVALID; - size_t req_entry; - int ret; - - ret = boot_request_entry_find(BOOT_REQUEST_IMG_CONFIRM, image, &req_entry); - if (ret != 0) { - return false; - } - - ret = retention_read(bootloader_request_dev, req_entry * sizeof(value), (void *)&value, - sizeof(value)); - if (ret != 0) { - return false; - } - - switch (value) { - case BOOT_REQUEST_SLOT_PRIMARY: - return (slot == 0); - case BOOT_REQUEST_SLOT_SECONDARY: - return (slot == 1); - default: - break; - } - - return false; -} - -int boot_request_set_preferred_slot(uint8_t image, uint32_t slot) -{ - uint8_t value = BOOT_REQUEST_SLOT_INVALID; - size_t req_entry; - int ret; - - ret = boot_request_entry_find(BOOT_REQUEST_IMG_PREFERENCE, image, &req_entry); - if (ret != 0) { - return ret; - } - - switch (slot) { - case 0: - value = BOOT_REQUEST_SLOT_PRIMARY; - break; - case 1: - value = BOOT_REQUEST_SLOT_SECONDARY; - break; - default: - return -EINVAL; - } - - return retention_write(bootloader_request_dev, req_entry * sizeof(value), (void *)&value, - sizeof(value)); -} - -#ifdef CONFIG_FIND_NEXT_SLOT_HOOKS -uint32_t boot_request_get_preferred_slot(uint8_t image) -{ - uint8_t value = BOOT_REQUEST_SLOT_INVALID; - size_t req_entry; - int ret; - - ret = boot_request_entry_find(BOOT_REQUEST_IMG_PREFERENCE, image, &req_entry); - if (ret != 0) { - return BOOT_REQUEST_NO_PREFERRED_SLOT; - } - - ret = retention_read(bootloader_request_dev, req_entry * sizeof(value), (void *)&value, - sizeof(value)); - if (ret != 0) { - return BOOT_REQUEST_NO_PREFERRED_SLOT; - } - - switch (value) { - case BOOT_REQUEST_SLOT_PRIMARY: - return 0; - case BOOT_REQUEST_SLOT_SECONDARY: - return 1; - default: - break; - } - - return BOOT_REQUEST_NO_PREFERRED_SLOT; -} -#endif /* CONFIG_FIND_NEXT_SLOT_HOOKS */ - -int boot_request_enter_recovery(void) -{ - uint8_t value = BOOT_REQUEST_MODE_RECOVERY; - size_t req_entry; - int ret; - - ret = boot_request_entry_find(BOOT_REQUEST_BOOT_MODE, BOOT_REQUEST_IMG_BOOTLOADER, - &req_entry); - if (ret != 0) { - return ret; - } - - return retention_write(bootloader_request_dev, req_entry * sizeof(value), (void *)&value, - sizeof(value)); -} - -#ifdef CONFIG_NRF_BOOT_SERIAL_BOOT_REQ -bool boot_request_detect_recovery(void) -{ - uint8_t value = BOOT_REQUEST_MODE_INVALID; - size_t req_entry; - int ret; - - ret = boot_request_entry_find(BOOT_REQUEST_BOOT_MODE, BOOT_REQUEST_IMG_BOOTLOADER, - &req_entry); - if (ret != 0) { - return false; - } - - ret = retention_read(bootloader_request_dev, req_entry * sizeof(value), (void *)&value, - sizeof(value)); - if ((ret == 0) && (value == BOOT_REQUEST_MODE_RECOVERY)) { - return true; - } - - return false; -} -#endif /* CONFIG_NRF_BOOT_SERIAL_BOOT_REQ */ - -int boot_request_enter_firmware_loader(void) -{ - uint8_t value = BOOT_REQUEST_MODE_FIRMWARE_LOADER; - size_t req_entry; - int ret; - - ret = boot_request_entry_find(BOOT_REQUEST_BOOT_MODE, BOOT_REQUEST_IMG_BOOTLOADER, - &req_entry); - if (ret != 0) { - return ret; - } - - return retention_write(bootloader_request_dev, req_entry * sizeof(value), (void *)&value, - sizeof(value)); -} - -#ifdef CONFIG_NRF_BOOT_FIRMWARE_LOADER_BOOT_REQ -bool boot_request_detect_firmware_loader(void) -{ - uint8_t value = BOOT_REQUEST_MODE_INVALID; - size_t req_entry; - int ret; - - ret = boot_request_entry_find(BOOT_REQUEST_BOOT_MODE, BOOT_REQUEST_IMG_BOOTLOADER, - &req_entry); - if (ret != 0) { - return false; - } - - ret = retention_read(bootloader_request_dev, req_entry * sizeof(value), (void *)&value, - sizeof(value)); - if ((ret == 0) && (value == BOOT_REQUEST_MODE_FIRMWARE_LOADER)) { - return true; - } - - return false; -} -#endif /* CONFIG_NRF_BOOT_FIRMWARE_LOADER_BOOT_REQ */ diff --git a/boot/zephyr/Kconfig b/boot/zephyr/Kconfig index 4b2458cfc..4dd080ab3 100644 --- a/boot/zephyr/Kconfig +++ b/boot/zephyr/Kconfig @@ -1282,10 +1282,6 @@ config USB_DEVICE_PRODUCT config MCUBOOT_BOOTUTIL_LIB_OWN_LOG bool -config NRF_MCUBOOT_BOOT_REQUEST - bool - imply FIND_NEXT_SLOT_HOOKS if BOOT_DIRECT_XIP || BOOT_RAM_LOAD - config MCUBOOT_VERIFY_IMG_ADDRESS bool "Verify reset address of image in secondary slot" depends on UPDATEABLE_IMAGE_NUMBER > 1 diff --git a/boot/zephyr/Kconfig.firmware_loader b/boot/zephyr/Kconfig.firmware_loader index 376dc06f7..036da98eb 100644 --- a/boot/zephyr/Kconfig.firmware_loader +++ b/boot/zephyr/Kconfig.firmware_loader @@ -42,12 +42,6 @@ config BOOT_FIRMWARE_LOADER_PIN_RESET Checks if the module reset was caused by the reset pin and will remain in bootloader firmware loader mode if it was. -config NRF_BOOT_FIRMWARE_LOADER_BOOT_REQ - bool "Check boot mode via bootloader request" - depends on NRF_MCUBOOT_BOOT_REQUEST - help - Allows for entering firmware loader mode by using bootloader rquests. - endmenu endif diff --git a/boot/zephyr/Kconfig.serial_recovery b/boot/zephyr/Kconfig.serial_recovery index b6c71e5e0..5b4ba3e11 100644 --- a/boot/zephyr/Kconfig.serial_recovery +++ b/boot/zephyr/Kconfig.serial_recovery @@ -191,12 +191,6 @@ config BOOT_SERIAL_PIN_RESET Checks if the module reset was caused by the reset pin and will remain in bootloader serial recovery mode if it was. -config NRF_BOOT_SERIAL_BOOT_REQ - bool "Check boot mode via bootloader request subsystem" - depends on NRF_MCUBOOT_BOOT_REQUEST - help - Allows for entering serial recovery mode by using bootloader requests. - endmenu config BOOT_SERIAL_IMG_GRP_HASH diff --git a/boot/zephyr/firmware_loader.c b/boot/zephyr/firmware_loader.c index 834dc6341..1df848634 100644 --- a/boot/zephyr/firmware_loader.c +++ b/boot/zephyr/firmware_loader.c @@ -17,9 +17,6 @@ #include "io/io.h" #include "mcuboot_config/mcuboot_config.h" -#ifdef CONFIG_NRF_MCUBOOT_BOOT_REQUEST -#include -#endif /* CONFIG_NRF_MCUBOOT_BOOT_REQUEST */ BOOT_LOG_MODULE_DECLARE(mcuboot); @@ -186,12 +183,6 @@ boot_go(struct boot_rsp *rsp) } #endif -#ifdef CONFIG_NRF_BOOT_FIRMWARE_LOADER_BOOT_REQ - if (boot_request_detect_firmware_loader()) { - boot_firmware_loader = true; - } -#endif - /* Check if firmware loader button is pressed. TODO: check all entrance methods */ if (boot_firmware_loader == true) { FIH_CALL(validate_image_slot, fih_rc, FLASH_AREA_IMAGE_SECONDARY(0), rsp); diff --git a/boot/zephyr/main.c b/boot/zephyr/main.c index d8e7117ef..995e2bf60 100644 --- a/boot/zephyr/main.c +++ b/boot/zephyr/main.c @@ -46,12 +46,6 @@ #include "bootutil/fault_injection_hardening.h" #include "bootutil/mcuboot_status.h" #include "flash_map_backend/flash_map_backend.h" -#ifdef CONFIG_NRF_MCUBOOT_BOOT_REQUEST -#include - -/** Number of image slots. */ -#define BOOT_REQUEST_NUM_SLOTS 2 -#endif /* CONFIG_NRF_MCUBOOT_BOOT_REQUEST */ #if defined(CONFIG_MCUBOOT_UUID_VID) || defined(CONFIG_MCUBOOT_UUID_CID) #include "bootutil/mcuboot_uuid.h" @@ -553,37 +547,6 @@ static void boot_serial_enter() } #endif -static int boot_prevalidate(void) -{ -#ifdef CONFIG_NRF_MCUBOOT_BOOT_REQUEST - uint8_t image_index; - uint32_t slot; - uint32_t area_id; - const struct flash_area *fap; - int rc = boot_request_init(); - - if (rc != 0) { - return rc; - } - - for (image_index = 0; image_index < BOOT_IMAGE_NUMBER; ++image_index) { - for (slot = 0; slot < BOOT_REQUEST_NUM_SLOTS; slot++) { - if (boot_request_check_confirmed_slot(image_index, slot)) { - BOOT_LOG_DBG("Confirm image: %d slot: %d due to bootloader request.", - image_index, slot); - - area_id = flash_area_id_from_multi_image_slot(image_index, slot); - rc = flash_area_open(area_id, &fap); - if (rc == 0) { - rc = boot_set_next(fap, true, true); - } - } - } - } -#endif - return 0; -} - int main(void) { struct boot_rsp rsp; @@ -623,11 +586,6 @@ int main(void) } #endif /* CONFIG_MCUBOOT_UUID_VID || CONFIG_MCUBOOT_UUID_CID */ - rc = boot_prevalidate(); - if (rc) { - BOOT_LOG_ERR("Failed to prevalidate the state: %d", rc); - } - #ifdef CONFIG_BOOT_SERIAL_ENTRANCE_GPIO BOOT_LOG_DBG("Checking GPIO for serial recovery"); if (io_detect_pin() && @@ -643,13 +601,6 @@ int main(void) } #endif -#ifdef CONFIG_NRF_BOOT_SERIAL_BOOT_REQ - if (boot_request_detect_recovery()) { - BOOT_LOG_DBG("Staying in serial recovery"); - boot_serial_enter(); - } -#endif - #if defined(CONFIG_BOOT_USB_DFU_GPIO) BOOT_LOG_DBG("Checking GPIO for USB DFU request"); if (io_detect_pin()) { @@ -710,10 +661,6 @@ int main(void) } BOOT_LOG_DBG("Left boot_go with success == %d", FIH_EQ(fih_rc, FIH_SUCCESS) ? 1 : 0); -#ifdef CONFIG_NRF_MCUBOOT_BOOT_REQUEST - (void)boot_request_clear(); -#endif - #ifdef CONFIG_BOOT_SERIAL_BOOT_MODE if (io_detect_boot_mode()) { /* Boot mode to stay in bootloader, clear status and enter serial From 94d83b9c4b28c8998805987e8ad38cbfd0994fa0 Mon Sep 17 00:00:00 2001 From: Jukka Rissanen Date: Tue, 23 Sep 2025 13:04:29 +0300 Subject: [PATCH 177/420] Revert "[nrf fromtree] imgtool: Add support for VID and CID" This reverts commit 1aaabdeed401f3c62edaccd6e48a9f3d7c5b84e4. Signed-off-by: Jukka Rissanen --- scripts/imgtool/image.py | 60 ++-------------------------------------- scripts/imgtool/main.py | 11 ++------ 2 files changed, 6 insertions(+), 65 deletions(-) diff --git a/scripts/imgtool/image.py b/scripts/imgtool/image.py index 6e6d3ebe9..112d2ef4e 100755 --- a/scripts/imgtool/image.py +++ b/scripts/imgtool/image.py @@ -30,9 +30,7 @@ import hashlib import array import os.path -import re import struct -import uuid from enum import Enum import click @@ -98,8 +96,6 @@ 'DECOMP_SHA': 0x71, 'DECOMP_SIGNATURE': 0x72, 'COMP_DEC_SIZE' : 0x73, - 'UUID_VID': 0x74, - 'UUID_CID': 0x75, } TLV_SIZE = 4 @@ -257,27 +253,6 @@ def tlv_matches_key_type(tlv_type, key): return False -def parse_uuid(namespace, value): - # Check if UUID is in the RAW format (12345678-1234-5678-1234-567812345678) - uuid_re = r'[0-9A-f]{8}-[0-9A-f]{4}-[0-9A-f]{4}-[0-9A-f]{4}-[0-9A-f]{12}' - if re.match(uuid_re, value): - uuid_bytes = bytes.fromhex(value.replace('-', '')) - - # Check if UUID is in the RAW HEX format (12345678123456781234567812345678) - elif re.match(r'[0-9A-f]{32}', value): - uuid_bytes = bytes.fromhex(value) - - # Check if UUID is in the string format - elif value.isprintable(): - if namespace is not None: - uuid_bytes = uuid.uuid5(namespace, value).bytes - else: - raise ValueError(f"Unknown namespace for UUID: {value}") - else: - raise ValueError(f"Unknown UUID format: {value}") - - return uuid_bytes - class Image: @@ -287,7 +262,7 @@ def __init__(self, version=None, header_size=IMAGE_HEADER_SIZE, overwrite_only=False, endian="little", load_addr=0, rom_fixed=None, erased_val=None, save_enctlv=False, security_counter=None, max_align=None, - non_bootable=False, vid=None, cid=None): + non_bootable=False): if load_addr and rom_fixed: raise click.UsageError("Can not set rom_fixed and load_addr at the same time") @@ -316,8 +291,6 @@ def __init__(self, version=None, header_size=IMAGE_HEADER_SIZE, self.enctlv_len = 0 self.max_align = max(DEFAULT_MAX_ALIGN, align) if max_align is None else int(max_align) self.non_bootable = non_bootable - self.vid = vid - self.cid = cid if self.max_align == DEFAULT_MAX_ALIGN: self.boot_magic = bytes([ @@ -347,7 +320,7 @@ def __repr__(self): return "".format( + payloadlen=0x{:x}>".format( self.version, self.header_size, self.security_counter, @@ -359,9 +332,7 @@ def __repr__(self): self.overwrite_only, self.endian, self.__class__.__name__, - len(self.payload), - self.vid, - self.cid) + len(self.payload)) def load(self, path): """Load an image from a given file""" @@ -537,16 +508,6 @@ def create(self, key, public_key_format, enckey, dependencies=None, # = 4 + 4 = 8 Bytes protected_tlv_size += TLV_SIZE + 4 - if self.vid is not None: - # Size of the VID TLV: header ('HH') + payload ('16s') - # = 4 + 16 = 20 Bytes - protected_tlv_size += TLV_SIZE + 16 - - if self.cid is not None: - # Size of the CID TLV: header ('HH') + payload ('16s') - # = 4 + 16 = 20 Bytes - protected_tlv_size += TLV_SIZE + 16 - if sw_type is not None: if len(sw_type) > MAX_SW_TYPE_LENGTH: msg = "'{}' is too long ({} characters) for sw_type. Its " \ @@ -650,21 +611,6 @@ def create(self, key, public_key_format, enckey, dependencies=None, if compression_tlvs is not None: for tag, value in compression_tlvs.items(): prot_tlv.add(tag, value) - - if self.vid is not None: - vid = parse_uuid(uuid.NAMESPACE_DNS, self.vid) - payload = struct.pack(e + '16s', vid) - prot_tlv.add('UUID_VID', payload) - - if self.cid is not None: - if self.vid is not None: - namespace = uuid.UUID(bytes=vid) - else: - namespace = None - cid = parse_uuid(namespace, self.cid) - payload = struct.pack(e + '16s', cid) - prot_tlv.add('UUID_CID', payload) - if custom_tlvs is not None: for tag, value in custom_tlvs.items(): prot_tlv.add(tag, value) diff --git a/scripts/imgtool/main.py b/scripts/imgtool/main.py index 646c9e961..7f9a53657 100755 --- a/scripts/imgtool/main.py +++ b/scripts/imgtool/main.py @@ -473,17 +473,13 @@ def convert(self, value, param, ctx): @click.command(help='''Create a signed or unsigned image\n INFILE and OUTFILE are parsed as Intel HEX if the params have .hex extension, otherwise binary format is used''') -@click.option('--vid', default=None, required=False, - help='Unique vendor identifier, format: (|') -@click.option('--cid', default=None, required=False, - help='Unique image class identifier, format: (|)') def sign(key, public_key_format, align, version, pad_sig, header_size, pad_header, slot_size, pad, confirm, max_sectors, overwrite_only, 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, hmac_sha, is_pure, - vector_to_sign, non_bootable, vid, cid): + vector_to_sign, non_bootable): if confirm: # Confirmed but non-padded images don't make much sense, because @@ -496,7 +492,7 @@ def sign(key, public_key_format, align, version, pad_sig, header_size, endian=endian, load_addr=load_addr, rom_fixed=rom_fixed, erased_val=erased_val, save_enctlv=save_enctlv, security_counter=security_counter, max_align=max_align, - non_bootable=non_bootable, vid=vid, cid=cid) + non_bootable=non_bootable) compression_tlvs = {} img.load(infile) key = load_key(key) if key else None @@ -567,8 +563,7 @@ def sign(key, public_key_format, align, version, pad_sig, header_size, overwrite_only=overwrite_only, endian=endian, load_addr=load_addr, rom_fixed=rom_fixed, erased_val=erased_val, save_enctlv=save_enctlv, - security_counter=security_counter, max_align=max_align, - vid=vid, cid=cid) + security_counter=security_counter, max_align=max_align) compression_filters = [ {"id": lzma.FILTER_LZMA2, "preset": comp_default_preset, "dict_size": comp_default_dictsize, "lp": comp_default_lp, From 7c3acc8849ebf868626a0f92e4a6ae504d615dbd Mon Sep 17 00:00:00 2001 From: Jukka Rissanen Date: Tue, 23 Sep 2025 13:04:30 +0300 Subject: [PATCH 178/420] Revert "[nrf fromtree] boot: Add VID and CID checks" This reverts commit a652982f31f82a76646d20bf60dcaf7c84240262. Signed-off-by: Jukka Rissanen --- boot/bootutil/include/bootutil/image.h | 2 - boot/bootutil/include/bootutil/mcuboot_uuid.h | 63 -------------- boot/bootutil/src/image_validate.c | 85 +------------------ boot/zephyr/Kconfig | 12 --- .../include/mcuboot_config/mcuboot_config.h | 8 -- boot/zephyr/main.c | 12 --- docs/design.md | 64 ++++---------- 7 files changed, 17 insertions(+), 229 deletions(-) delete mode 100644 boot/bootutil/include/bootutil/mcuboot_uuid.h diff --git a/boot/bootutil/include/bootutil/image.h b/boot/bootutil/include/bootutil/image.h index 5b01a5aae..52fa6d1bb 100644 --- a/boot/bootutil/include/bootutil/image.h +++ b/boot/bootutil/include/bootutil/image.h @@ -132,8 +132,6 @@ extern "C" { * signature */ #define IMAGE_TLV_COMP_DEC_SIZE 0x73 /* Compressed decrypted image size */ -#define IMAGE_TLV_UUID_VID 0x74 /* Vendor unique identifier */ -#define IMAGE_TLV_UUID_CID 0x75 /* Device class unique identifier */ /* * vendor reserved TLVs at xxA0-xxFF, * where xx denotes the upper byte diff --git a/boot/bootutil/include/bootutil/mcuboot_uuid.h b/boot/bootutil/include/bootutil/mcuboot_uuid.h deleted file mode 100644 index 433d1d2fe..000000000 --- a/boot/bootutil/include/bootutil/mcuboot_uuid.h +++ /dev/null @@ -1,63 +0,0 @@ -/* - * Copyright (c) 2025 Nordic Semiconductor ASA - * - * SPDX-License-Identifier: Apache-2.0 - */ - -#ifndef __MCUBOOT_UUID_H__ -#define __MCUBOOT_UUID_H__ - -/** - * @file mcuboot_uuid.h - * - * @note A vendor ID as well as class ID values may be statically generated - * using CMake, based on the vendor domain name as well as product name. - * It is advised to use vendor ID as an input while generating device - * class ID to avoid collisions between UUIDs from two different vendors. - */ - -#include -#include "bootutil/fault_injection_hardening.h" - -#ifdef __cplusplus -extern "C" { -#endif - - -/** The 128-bit UUID, used for identifying vendors as well as image classes. */ -struct image_uuid { - uint8_t raw[16]; -}; - -/** - * @brief Initialises the UUID module. - * - * @return FIH_SUCCESS on success - */ -fih_ret boot_uuid_init(void); - -/** - * @brief Check if the specified vendor UUID is allowed for a given image. - * - * @param[in] image_id Index of the image (from 0). - * @param[in] uuid_vid The reference to the image's vendor ID value. - * - * @return FIH_SUCCESS on success. - */ -fih_ret boot_uuid_vid_match(uint32_t image_id, const struct image_uuid *uuid_vid); - -/** - * @brief Check if the specified image class UUID is allowed for a given image. - * - * @param[in] image_id Index of the image (from 0). - * @param[in] uuid_cid The reference to the image's class ID value. - * - * @return FIH_SUCCESS on success - */ -fih_ret boot_uuid_cid_match(uint32_t image_id, const struct image_uuid *uuid_cid); - -#ifdef __cplusplus -} -#endif - -#endif /* __MCUBOOT_UUID_H__ */ diff --git a/boot/bootutil/src/image_validate.c b/boot/bootutil/src/image_validate.c index 5a5366e59..ac7ad2a04 100644 --- a/boot/bootutil/src/image_validate.c +++ b/boot/bootutil/src/image_validate.c @@ -44,9 +44,6 @@ #include "bootutil/bootutil_log.h" BOOT_LOG_MODULE_DECLARE(mcuboot); -#if defined(MCUBOOT_UUID_VID) || defined(MCUBOOT_UUID_CID) -#include "bootutil/mcuboot_uuid.h" -#endif /* MCUBOOT_UUID_VID || MCUBOOT_UUID_CID */ #ifdef MCUBOOT_ENC_IMAGES #include "bootutil/enc_key.h" @@ -510,8 +507,7 @@ bootutil_img_validate(struct boot_loader_state *state, #endif ) { -#if (defined(EXPECTED_KEY_TLV) && defined(MCUBOOT_HW_KEY)) || defined(MCUBOOT_HW_ROLLBACK_PROT) \ - || defined(MCUBOOT_UUID_VID) || defined(MCUBOOT_UUID_CID) +#if (defined(EXPECTED_KEY_TLV) && defined(MCUBOOT_HW_KEY)) || defined(MCUBOOT_HW_ROLLBACK_PROT) int image_index = (state == NULL ? 0 : BOOT_CURR_IMG(state)); #endif uint32_t off; @@ -557,14 +553,6 @@ bootutil_img_validate(struct boot_loader_state *state, goto out; } #endif -#ifdef MCUBOOT_UUID_VID - struct image_uuid img_uuid_vid = {0x00}; - FIH_DECLARE(uuid_vid_valid, FIH_FAILURE); -#endif -#ifdef MCUBOOT_UUID_CID - struct image_uuid img_uuid_cid = {0x00}; - FIH_DECLARE(uuid_cid_valid, FIH_FAILURE); -#endif BOOT_LOG_DBG("bootutil_img_validate: flash area %p", fap); @@ -805,64 +793,6 @@ bootutil_img_validate(struct boot_loader_state *state, break; } #endif /* MCUBOOT_HW_ROLLBACK_PROT */ -#ifdef MCUBOOT_UUID_VID - case IMAGE_TLV_UUID_VID: - { - /* - * Verify the image's vendor ID length. - * This must always be present. - */ - if (len != sizeof(img_uuid_vid)) { - /* Vendor UUID is not valid. */ - rc = -1; - goto out; - } - - rc = LOAD_IMAGE_DATA(hdr, fap, off, img_uuid_vid.raw, len); - if (rc) { - goto out; - } - - FIH_CALL(boot_uuid_vid_match, fih_rc, image_index, &img_uuid_vid); - if (FIH_NOT_EQ(fih_rc, FIH_SUCCESS)) { - FIH_SET(uuid_vid_valid, FIH_FAILURE); - goto out; - } - - /* The image's vendor identifier has been successfully verified. */ - uuid_vid_valid = fih_rc; - break; - } -#endif -#ifdef MCUBOOT_UUID_CID - case IMAGE_TLV_UUID_CID: - { - /* - * Verify the image's class ID length. - * This must always be present. - */ - if (len != sizeof(img_uuid_cid)) { - /* Image class UUID is not valid. */ - rc = -1; - goto out; - } - - rc = LOAD_IMAGE_DATA(hdr, fap, off, img_uuid_cid.raw, len); - if (rc) { - goto out; - } - - FIH_CALL(boot_uuid_cid_match, fih_rc, image_index, &img_uuid_cid); - if (FIH_NOT_EQ(fih_rc, FIH_SUCCESS)) { - FIH_SET(uuid_cid_valid, FIH_FAILURE); - goto out; - } - - /* The image's class identifier has been successfully verified. */ - uuid_cid_valid = fih_rc; - break; - } -#endif } } @@ -891,19 +821,6 @@ bootutil_img_validate(struct boot_loader_state *state, skip_security_counter_check: #endif -#ifdef MCUBOOT_UUID_VID - if (FIH_NOT_EQ(uuid_vid_valid, FIH_SUCCESS)) { - rc = -1; - goto out; - } -#endif -#ifdef MCUBOOT_UUID_CID - if (FIH_NOT_EQ(uuid_cid_valid, FIH_SUCCESS)) { - rc = -1; - goto out; - } -#endif - out: if (rc) { FIH_SET(fih_rc, FIH_FAILURE); diff --git a/boot/zephyr/Kconfig b/boot/zephyr/Kconfig index 4dd080ab3..50fbd4dc4 100644 --- a/boot/zephyr/Kconfig +++ b/boot/zephyr/Kconfig @@ -1056,18 +1056,6 @@ config MCUBOOT_HW_DOWNGRADE_PREVENTION_COUNTER_LIMITED endchoice -config MCUBOOT_UUID_VID - bool "Expect vendor unique identifier in image's TLV" - help - Provide a vendor identification scheme to prevent processing images - generated by a different vendor. - -config MCUBOOT_UUID_CID - bool "Expect image class unique identifier in image's TLV" - help - Provide an image class identification scheme to prevent processing - images for a different CPU or device produced by the same vendor. - config BOOT_WATCHDOG_FEED bool "Feed the watchdog while doing swap" default y if WATCHDOG diff --git a/boot/zephyr/include/mcuboot_config/mcuboot_config.h b/boot/zephyr/include/mcuboot_config/mcuboot_config.h index eb64c12eb..d565a6aaf 100644 --- a/boot/zephyr/include/mcuboot_config/mcuboot_config.h +++ b/boot/zephyr/include/mcuboot_config/mcuboot_config.h @@ -217,14 +217,6 @@ #define MCUBOOT_HW_ROLLBACK_PROT_COUNTER_LIMITED #endif -#ifdef CONFIG_MCUBOOT_UUID_VID -#define MCUBOOT_UUID_VID -#endif - -#ifdef CONFIG_MCUBOOT_UUID_CID -#define MCUBOOT_UUID_CID -#endif - #ifdef CONFIG_MEASURED_BOOT #define MCUBOOT_MEASURED_BOOT #endif diff --git a/boot/zephyr/main.c b/boot/zephyr/main.c index 995e2bf60..fa3eeff90 100644 --- a/boot/zephyr/main.c +++ b/boot/zephyr/main.c @@ -47,10 +47,6 @@ #include "bootutil/mcuboot_status.h" #include "flash_map_backend/flash_map_backend.h" -#if defined(CONFIG_MCUBOOT_UUID_VID) || defined(CONFIG_MCUBOOT_UUID_CID) -#include "bootutil/mcuboot_uuid.h" -#endif /* CONFIG_MCUBOOT_UUID_VID || CONFIG_MCUBOOT_UUID_CID */ - /* Check if Espressif target is supported */ #ifdef CONFIG_SOC_FAMILY_ESPRESSIF_ESP32 @@ -578,14 +574,6 @@ int main(void) mcuboot_status_change(MCUBOOT_STATUS_STARTUP); -#if defined(CONFIG_MCUBOOT_UUID_VID) || defined(CONFIG_MCUBOOT_UUID_CID) - FIH_CALL(boot_uuid_init, fih_rc); - if (FIH_NOT_EQ(fih_rc, FIH_SUCCESS)) { - BOOT_LOG_ERR("Unable to initialize UUID module: %d", fih_rc); - FIH_PANIC; - } -#endif /* CONFIG_MCUBOOT_UUID_VID || CONFIG_MCUBOOT_UUID_CID */ - #ifdef CONFIG_BOOT_SERIAL_ENTRANCE_GPIO BOOT_LOG_DBG("Checking GPIO for serial recovery"); if (io_detect_pin() && diff --git a/docs/design.md b/docs/design.md index 139c38b57..c080b2b82 100755 --- a/docs/design.md +++ b/docs/design.md @@ -104,54 +104,22 @@ struct image_tlv { /* * Image trailer TLV types. */ -#define IMAGE_TLV_KEYHASH 0x01 /* hash of the public key */ -#define IMAGE_TLV_PUBKEY 0x02 /* public key */ -#define IMAGE_TLV_SHA256 0x10 /* SHA256 of image hdr and body */ -#define IMAGE_TLV_SHA384 0x11 /* SHA384 of image hdr and body */ -#define IMAGE_TLV_SHA512 0x12 /* SHA512 of image hdr and body */ -#define IMAGE_TLV_RSA2048_PSS 0x20 /* RSA2048 of hash output */ -#define IMAGE_TLV_ECDSA224 0x21 /* ECDSA of hash output - Not supported anymore */ -#define IMAGE_TLV_ECDSA_SIG 0x22 /* ECDSA of hash output */ -#define IMAGE_TLV_RSA3072_PSS 0x23 /* RSA3072 of hash output */ -#define IMAGE_TLV_ED25519 0x24 /* ed25519 of hash output */ -#define IMAGE_TLV_SIG_PURE 0x25 /* Indicator that attached signature has been prepared - * over image rather than its digest. - */ -#define IMAGE_TLV_ENC_RSA2048 0x30 /* Key encrypted with RSA-OAEP-2048 */ -#define IMAGE_TLV_ENC_KW 0x31 /* Key encrypted with AES-KW 128 or 256*/ -#define IMAGE_TLV_ENC_EC256 0x32 /* Key encrypted with ECIES-EC256 */ -#define IMAGE_TLV_ENC_X25519 0x33 /* Key encrypted with ECIES-X25519 */ -#define IMAGE_TLV_ENC_X25519_SHA512 0x34 /* Key exchange using ECIES-X25519 and SHA512 for MAC - * tag and HKDF in key derivation process - */ -#define IMAGE_TLV_DEPENDENCY 0x40 /* Image depends on other image */ -#define IMAGE_TLV_SEC_CNT 0x50 /* security counter */ -#define IMAGE_TLV_BOOT_RECORD 0x60 /* measured boot record */ -/* The following flags relate to compressed images and are for the decompressed image data */ -#define IMAGE_TLV_DECOMP_SIZE 0x70 /* Decompressed image size excluding header/TLVs */ -#define IMAGE_TLV_DECOMP_SHA 0x71 /* - * Decompressed image shaX hash, this field must match - * the format and size of the raw slot (compressed) - * shaX hash - */ -#define IMAGE_TLV_DECOMP_SIGNATURE 0x72 /* - * Decompressed image signature, this field must match - * 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 - * range. Examples: - * 0x00a0 - 0x00ff - * 0x01a0 - 0x01ff - * 0x02a0 - 0x02ff - * ... - * 0xffa0 - 0xfffe - */ -#define IMAGE_TLV_UUID_VID 0x80 /* Vendor unique identifier */ -#define IMAGE_TLV_UUID_CID 0x81 /* Device class unique identifier */ +#define IMAGE_TLV_KEYHASH 0x01 /* hash of the public key */ +#define IMAGE_TLV_SHA256 0x10 /* SHA256 of image hdr and body */ +#define IMAGE_TLV_RSA2048_PSS 0x20 /* RSA2048 of hash output */ +#define IMAGE_TLV_ECDSA224 0x21 /* ECDSA of hash output - Not supported anymore */ +#define IMAGE_TLV_ECDSA_SIG 0x22 /* ECDSA of hash output */ +#define IMAGE_TLV_RSA3072_PSS 0x23 /* RSA3072 of hash output */ +#define IMAGE_TLV_ED25519 0x24 /* ED25519 of hash output */ +#define IMAGE_TLV_SIG_PURE 0x25 /* If true then any signature found has been + calculated over image directly. */ +#define IMAGE_TLV_ENC_RSA2048 0x30 /* Key encrypted with RSA-OAEP-2048 */ +#define IMAGE_TLV_ENC_KW 0x31 /* Key encrypted with AES-KW-128 or + 256 */ +#define IMAGE_TLV_ENC_EC256 0x32 /* Key encrypted with ECIES-P256 */ +#define IMAGE_TLV_ENC_X25519 0x33 /* Key encrypted with ECIES-X25519 */ +#define IMAGE_TLV_DEPENDENCY 0x40 /* Image depends on other image */ +#define IMAGE_TLV_SEC_CNT 0x50 /* security counter */ ``` Optional type-length-value records (TLVs) containing image metadata are placed From 62b9990c614a408d6b8200f8f858f1bef7ff95a9 Mon Sep 17 00:00:00 2001 From: Jukka Rissanen Date: Tue, 23 Sep 2025 13:04:30 +0300 Subject: [PATCH 179/420] Revert "[nrf fromtree] boot: Enable Encryption with PSA + ECDSA" This reverts commit 9b605606969bfa12d66f39bd50656dfe9d73dd52. Signed-off-by: Jukka Rissanen --- boot/bootutil/src/encrypted.c | 65 +++++++++++---------- boot/bootutil/src/encrypted_psa.c | 96 ++----------------------------- boot/zephyr/CMakeLists.txt | 9 ++- 3 files changed, 40 insertions(+), 130 deletions(-) diff --git a/boot/bootutil/src/encrypted.c b/boot/bootutil/src/encrypted.c index 9792a9038..cf6f380e2 100644 --- a/boot/bootutil/src/encrypted.c +++ b/boot/bootutil/src/encrypted.c @@ -22,11 +22,11 @@ #include "bootutil/crypto/aes_kw.h" #endif -#if !defined(MCUBOOT_USE_PSA_CRYPTO) #if defined(MCUBOOT_ENCRYPT_EC256) #include "bootutil/crypto/ecdh_p256.h" #endif +#if !defined(MCUBOOT_USE_PSA_CRYPTO) #if defined(MCUBOOT_ENCRYPT_X25519) #include "bootutil/crypto/ecdh_x25519.h" #endif @@ -50,7 +50,7 @@ BOOT_LOG_MODULE_DECLARE(mcuboot); #include "bootutil_priv.h" /* NOUP Fixme: */ -#if !defined(CONFIG_BOOT_ED25519_PSA) && !defined(CONFIG_BOOT_ECDSA_PSA) +#if !defined(CONFIG_BOOT_ED25519_PSA) #if defined(MCUBOOT_ENCRYPT_EC256) || defined(MCUBOOT_ENCRYPT_X25519) #if defined(_compare) static inline int bootutil_constant_time_compare(const uint8_t *a, const uint8_t *b, size_t size) @@ -105,64 +105,65 @@ static const uint8_t ec_secp256r1_oid[] = MBEDTLS_OID_EC_GRP_SECP256R1; * curve keypair. See RFC5208 and RFC5915. */ static int -parse_priv_enckey(uint8_t **p, uint8_t *end, uint8_t *private_key) +parse_ec256_enckey(uint8_t **p, uint8_t *end, uint8_t *private_key) { + int rc; size_t len; int version; mbedtls_asn1_buf alg; mbedtls_asn1_buf param; - if (mbedtls_asn1_get_tag(p, end, &len, - MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE) != 0) { + if ((rc = mbedtls_asn1_get_tag(p, end, &len, + MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)) != 0) { return -1; } if (*p + len != end) { - return -1; + return -2; } version = 0; if (mbedtls_asn1_get_int(p, end, &version) || version != 0) { - return -1; + return -3; } - if (mbedtls_asn1_get_alg(p, end, &alg, ¶m) != 0) { - return -1; + if ((rc = mbedtls_asn1_get_alg(p, end, &alg, ¶m)) != 0) { + return -5; } if (alg.ASN1_CONTEXT_MEMBER(len) != sizeof(ec_pubkey_oid) - 1 || memcmp(alg.ASN1_CONTEXT_MEMBER(p), ec_pubkey_oid, sizeof(ec_pubkey_oid) - 1)) { - return -1; + return -6; } if (param.ASN1_CONTEXT_MEMBER(len) != sizeof(ec_secp256r1_oid) - 1 || memcmp(param.ASN1_CONTEXT_MEMBER(p), ec_secp256r1_oid, sizeof(ec_secp256r1_oid) - 1)) { - return -1; + return -7; } - if (mbedtls_asn1_get_tag(p, end, &len, MBEDTLS_ASN1_OCTET_STRING) != 0) { - return -1; + if ((rc = mbedtls_asn1_get_tag(p, end, &len, MBEDTLS_ASN1_OCTET_STRING)) != 0) { + return -8; } /* RFC5915 - ECPrivateKey */ - if (mbedtls_asn1_get_tag(p, end, &len, - MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE) != 0) { - return -1; + if ((rc = mbedtls_asn1_get_tag(p, end, &len, + MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)) != 0) { + return -9; } version = 0; if (mbedtls_asn1_get_int(p, end, &version) || version != 1) { - return -1; + return -10; } /* privateKey */ - if (mbedtls_asn1_get_tag(p, end, &len, MBEDTLS_ASN1_OCTET_STRING) != 0) { - return -1; + if ((rc = mbedtls_asn1_get_tag(p, end, &len, MBEDTLS_ASN1_OCTET_STRING)) != 0) { + return -11; } if (len != NUM_ECC_BYTES) { - return -1; + return -12; } memcpy(private_key, *p, len); @@ -179,7 +180,7 @@ static const uint8_t ec_pubkey_oid[] = MBEDTLS_OID_ISO_IDENTIFIED_ORG \ MBEDTLS_OID_ORG_GOV X25519_OID; static int -parse_priv_enckey(uint8_t **p, uint8_t *end, uint8_t *private_key) +parse_x25519_enckey(uint8_t **p, uint8_t *end, uint8_t *private_key) { size_t len; int version; @@ -192,33 +193,33 @@ parse_priv_enckey(uint8_t **p, uint8_t *end, uint8_t *private_key) } if (*p + len != end) { - return -1; + return -2; } version = 0; if (mbedtls_asn1_get_int(p, end, &version) || version != 0) { - return -1; + return -3; } if (mbedtls_asn1_get_alg(p, end, &alg, ¶m) != 0) { - return -1; + return -4; } if (alg.ASN1_CONTEXT_MEMBER(len) != sizeof(ec_pubkey_oid) - 1 || memcmp(alg.ASN1_CONTEXT_MEMBER(p), ec_pubkey_oid, sizeof(ec_pubkey_oid) - 1)) { - return -1; + return -5; } if (mbedtls_asn1_get_tag(p, end, &len, MBEDTLS_ASN1_OCTET_STRING) != 0) { - return -1; + return -6; } if (mbedtls_asn1_get_tag(p, end, &len, MBEDTLS_ASN1_OCTET_STRING) != 0) { - return -1; + return -7; } if (len != EC_PRIVK_LEN) { - return -1; + return -8; } memcpy(private_key, *p, EC_PRIVK_LEN); @@ -454,9 +455,8 @@ boot_decrypt_key(const uint8_t *buf, uint8_t *enckey) * Load the stored EC256 decryption private key */ - rc = parse_priv_enckey(&cp, cpend, private_key); + rc = parse_ec256_enckey(&cp, cpend, private_key); if (rc) { - BOOT_LOG_ERR("Failed to parse ASN1 private key"); return rc; } @@ -482,9 +482,8 @@ boot_decrypt_key(const uint8_t *buf, uint8_t *enckey) * Load the stored X25519 decryption private key */ - rc = parse_priv_enckey(&cp, cpend, private_key); + rc = parse_x25519_enckey(&cp, cpend, private_key); if (rc) { - BOOT_LOG_ERR("Failed to parse ASN1 private key"); return rc; } @@ -581,7 +580,7 @@ boot_decrypt_key(const uint8_t *buf, uint8_t *enckey) return rc; } -#endif /* CONFIG_BOOT_ED25519_PSA && CONFIG_BOOT_ECDSA_PSA */ +#endif /* CONFIG_BOOT_ED25519_PSA */ /* * Load encryption key. diff --git a/boot/bootutil/src/encrypted_psa.c b/boot/bootutil/src/encrypted_psa.c index 55f7f6f2d..7e53ed4a7 100644 --- a/boot/bootutil/src/encrypted_psa.c +++ b/boot/bootutil/src/encrypted_psa.c @@ -33,18 +33,9 @@ BOOT_LOG_MODULE_DECLARE(mcuboot_psa_enc); #define PSA_HMAC_HKDF_SHA PSA_ALG_SHA_256 #endif -#if defined(MCUBOOT_ENCRYPT_EC256) -#define NUM_ECC_BYTES (256 / 8) -static const uint8_t ec_pubkey_oid[] = MBEDTLS_OID_EC_ALG_UNRESTRICTED; -static const uint8_t ec_secp256r1_oid[] = MBEDTLS_OID_EC_GRP_SECP256R1; -#define ECC_FAMILY PSA_ECC_FAMILY_SECP_R1 -#endif /* defined(MCUBOOT_ENCRYPT_EC256) */ -#if defined(MCUBOOT_ENCRYPT_X25519) #define X25519_OID "\x6e" static const uint8_t ec_pubkey_oid[] = MBEDTLS_OID_ISO_IDENTIFIED_ORG \ MBEDTLS_OID_ORG_GOV X25519_OID; -#define ECC_FAMILY PSA_ECC_FAMILY_MONTGOMERY -#endif /* defined(MCUBOOT_ENCRYPT_X25519) */ /* Partitioning of HKDF derived material, from the exchange derived key */ /* AES key encryption key */ @@ -60,86 +51,9 @@ static const uint8_t ec_pubkey_oid[] = MBEDTLS_OID_ISO_IDENTIFIED_ORG \ /* Total size */ #define HKDF_SIZE (HKDF_AES_KEY_SIZE + HKDF_MAC_FEED_SIZE) -#if defined(MCUBOOT_ENCRYPT_EC256) -/* Fixme: This duplicates code from encrypted.c and depends on mbedtls */ - -/* - * Parses the output of `imgtool keygen`, which produces a PKCS#8 elliptic - * curve keypair. See RFC5208 and RFC5915. - */ -static int -parse_priv_enckey(uint8_t **p, uint8_t *end, uint8_t *private_key) -{ - size_t len; - int version; - mbedtls_asn1_buf alg; - mbedtls_asn1_buf param; - - if (mbedtls_asn1_get_tag(p, end, &len, - MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE) != 0) { - return -1; - } - - if (*p + len != end) { - return -1; - } - - version = 0; - if (mbedtls_asn1_get_int(p, end, &version) || version != 0) { - return -1; - } - - if (mbedtls_asn1_get_alg(p, end, &alg, ¶m) != 0) { - return -1; - } - - if (alg.ASN1_CONTEXT_MEMBER(len) != sizeof(ec_pubkey_oid) - 1 || - memcmp(alg.ASN1_CONTEXT_MEMBER(p), ec_pubkey_oid, sizeof(ec_pubkey_oid) - 1)) { - return -1; - } - if (param.ASN1_CONTEXT_MEMBER(len) != sizeof(ec_secp256r1_oid) - 1 || - memcmp(param.ASN1_CONTEXT_MEMBER(p), ec_secp256r1_oid, sizeof(ec_secp256r1_oid) - 1)) { - return -1; - } - - if (mbedtls_asn1_get_tag(p, end, &len, MBEDTLS_ASN1_OCTET_STRING) != 0) { - return -1; - } - - /* RFC5915 - ECPrivateKey */ - - if (mbedtls_asn1_get_tag(p, end, &len, - MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE) != 0) { - return -1; - } - - version = 0; - if (mbedtls_asn1_get_int(p, end, &version) || version != 1) { - return -1; - } - - /* privateKey */ - - if (mbedtls_asn1_get_tag(p, end, &len, MBEDTLS_ASN1_OCTET_STRING) != 0) { - return -1; - } - - if (len != NUM_ECC_BYTES) { - return -1; - } - - memcpy(private_key, *p, len); - - /* publicKey usually follows but is not parsed here */ - - return 0; -} -#endif /* defined(MCUBOOT_ENCRYPT_EC256) */ - -#if defined(MCUBOOT_ENCRYPT_X25519) /* Fixme: This duplicates code from encrypted.c and depends on mbedtls */ static int -parse_priv_enckey(uint8_t **p, uint8_t *end, uint8_t *private_key) +parse_x25519_enckey(uint8_t **p, uint8_t *end, uint8_t *private_key) { size_t len; int version; @@ -184,7 +98,6 @@ parse_priv_enckey(uint8_t **p, uint8_t *end, uint8_t *private_key) memcpy(private_key, *p, EC_PRIVK_LEN); return 0; } -#endif /* defined(MCUBOOT_ENCRYPT_X25519) */ void bootutil_aes_ctr_init(bootutil_aes_ctr_context *ctx) { @@ -240,15 +153,14 @@ boot_decrypt_key(const uint8_t *buf, uint8_t *enckey) } /* - * * Load the stored decryption private key + * Load the stored X25519 decryption private key */ - rc = parse_priv_enckey(&cp, cpend, private_key); + rc = parse_x25519_enckey(&cp, cpend, private_key); if (rc) { - BOOT_LOG_ERR("Failed to parse ASN1 private key"); return rc; } - psa_set_key_type(&kattr, PSA_KEY_TYPE_ECC_KEY_PAIR(ECC_FAMILY)); + psa_set_key_type(&kattr, PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_MONTGOMERY)); psa_set_key_usage_flags(&kattr, PSA_KEY_USAGE_DERIVE); psa_set_key_algorithm(&kattr, PSA_ALG_ECDH); diff --git a/boot/zephyr/CMakeLists.txt b/boot/zephyr/CMakeLists.txt index e4b5ff0ad..b25ef9e7d 100644 --- a/boot/zephyr/CMakeLists.txt +++ b/boot/zephyr/CMakeLists.txt @@ -117,12 +117,11 @@ zephyr_library_sources( ${BOOT_DIR}/bootutil/src/fault_injection_hardening.c ) -if((CONFIG_BOOT_ENCRYPT_X25519 AND CONFIG_BOOT_ED25519_PSA) - OR (CONFIG_BOOT_ENCRYPT_EC256 AND CONFIG_BOOT_ECDSA_PSA)) +if(DEFINED CONFIG_BOOT_ENCRYPT_X25519 AND DEFINED CONFIG_BOOT_ED25519_PSA) zephyr_library_sources(${BOOT_DIR}/bootutil/src/encrypted_psa.c) endif() -if(CONFIG_MEASURED_BOOT OR CONFIG_BOOT_SHARE_DATA) +if(DEFINED CONFIG_MEASURED_BOOT OR DEFINED CONFIG_BOOT_SHARE_DATA) zephyr_library_sources( ${BOOT_DIR}/bootutil/src/boot_record.c ) @@ -316,7 +315,7 @@ elseif(CONFIG_BOOT_SIGNATURE_TYPE_ED25519 OR CONFIG_BOOT_ENCRYPT_X25519) endif() endif() -if(NOT CONFIG_BOOT_ED25519_PSA AND NOT CONFIG_BOOT_ECDSA_PSA) +if(NOT CONFIG_BOOT_ED25519_PSA) if(CONFIG_BOOT_ENCRYPT_EC256 OR CONFIG_BOOT_ENCRYPT_X25519) zephyr_library_sources( ${TINYCRYPT_DIR}/source/aes_encrypt.c @@ -328,7 +327,7 @@ if(NOT CONFIG_BOOT_ED25519_PSA AND NOT CONFIG_BOOT_ECDSA_PSA) endif() endif() -if(CONFIG_BOOT_ENCRYPT_EC256 AND NOT CONFIG_BOOT_ECDSA_PSA) +if(CONFIG_BOOT_ENCRYPT_EC256) zephyr_library_sources( ${TINYCRYPT_DIR}/source/ecc_dh.c ) From 1b2152427979ea88bc5ab3944c577c586b739b13 Mon Sep 17 00:00:00 2001 From: Jukka Rissanen Date: Tue, 23 Sep 2025 13:04:30 +0300 Subject: [PATCH 180/420] Revert "[nrf fromtree] bootutil: Fix bootutil_aes_ctr_drop memset usage" This reverts commit 5af259f253d5e11a3ab6b99de122b2e8db6fa5c7. Signed-off-by: Jukka Rissanen --- boot/bootutil/include/bootutil/crypto/aes_ctr.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/boot/bootutil/include/bootutil/crypto/aes_ctr.h b/boot/bootutil/include/bootutil/crypto/aes_ctr.h index 88ae87c39..e5416dca0 100644 --- a/boot/bootutil/include/bootutil/crypto/aes_ctr.h +++ b/boot/bootutil/include/bootutil/crypto/aes_ctr.h @@ -58,7 +58,7 @@ void bootutil_aes_ctr_init(bootutil_aes_ctr_context *ctx); static inline void bootutil_aes_ctr_drop(bootutil_aes_ctr_context *ctx) { - memset(ctx, 0, sizeof(*ctx)); + memset(ctx, 0, sizeof(ctx)); } static inline int bootutil_aes_ctr_set_key(bootutil_aes_ctr_context *ctx, const uint8_t *k) From 7adec5c2422f63306619c9e0df7ea18aa9a8b146 Mon Sep 17 00:00:00 2001 From: Jukka Rissanen Date: Tue, 23 Sep 2025 13:04:30 +0300 Subject: [PATCH 181/420] Revert "[nrf fromtree] zephyr: Add support for slot selection boot hook" This reverts commit 301ab3359addfcab53539623d866dd83a8d202bf. Signed-off-by: Jukka Rissanen --- boot/zephyr/Kconfig | 7 ------- boot/zephyr/hooks_sample.c | 5 ----- boot/zephyr/include/mcuboot_config/mcuboot_config.h | 4 ---- 3 files changed, 16 deletions(-) diff --git a/boot/zephyr/Kconfig b/boot/zephyr/Kconfig index 50fbd4dc4..323173b1b 100644 --- a/boot/zephyr/Kconfig +++ b/boot/zephyr/Kconfig @@ -1108,13 +1108,6 @@ config MCUBOOT_ACTION_HOOKS 'mcuboot_status_type_t' is listed in boot/bootutil/include/bootutil/mcuboot_status.h -config FIND_NEXT_SLOT_HOOKS - bool "Enable hooks for finding the next active slot" - help - Allow to provide procedures for override or extend the search policy - for the best slot to boot in the Direct XIP mode. - By default a slot with the highest version is selected. - config BOOT_DISABLE_CACHES bool "Disable I/D caches before chain-loading application" depends on CPU_HAS_ICACHE || CPU_HAS_DCACHE diff --git a/boot/zephyr/hooks_sample.c b/boot/zephyr/hooks_sample.c index fc7bd2fa4..a5a729314 100644 --- a/boot/zephyr/hooks_sample.c +++ b/boot/zephyr/hooks_sample.c @@ -93,8 +93,3 @@ int boot_img_install_stat_hook(int image_index, int slot, int *img_install_stat) { return BOOT_HOOK_REGULAR; } - -int boot_find_next_slot_hook(struct boot_loader_state *state, uint8_t image, uint32_t *active_slot) -{ - return BOOT_HOOK_REGULAR; -} diff --git a/boot/zephyr/include/mcuboot_config/mcuboot_config.h b/boot/zephyr/include/mcuboot_config/mcuboot_config.h index d565a6aaf..b9cb020db 100644 --- a/boot/zephyr/include/mcuboot_config/mcuboot_config.h +++ b/boot/zephyr/include/mcuboot_config/mcuboot_config.h @@ -279,10 +279,6 @@ #define MCUBOOT_FLASH_AREA_HOOKS #endif -#ifdef CONFIG_FIND_NEXT_SLOT_HOOKS -#define MCUBOOT_FIND_NEXT_SLOT_HOOKS -#endif - #ifdef CONFIG_MCUBOOT_VERIFY_IMG_ADDRESS #define MCUBOOT_VERIFY_IMG_ADDRESS #endif From 0ae9b52c0b3b0f99cbf817fd7ef4f8410b19eec0 Mon Sep 17 00:00:00 2001 From: Jukka Rissanen Date: Tue, 23 Sep 2025 13:04:30 +0300 Subject: [PATCH 182/420] Revert "[nrf fromtree] loader: Add boot hook for slot selection" This reverts commit c13c65257af74ef087920082d50b040d5d435669. Signed-off-by: Jukka Rissanen --- boot/bootutil/include/bootutil/boot_hooks.h | 24 --------------------- boot/bootutil/src/loader.c | 14 ++---------- 2 files changed, 2 insertions(+), 36 deletions(-) diff --git a/boot/bootutil/include/bootutil/boot_hooks.h b/boot/bootutil/include/bootutil/boot_hooks.h index f5b10e8c7..ef7a89b28 100644 --- a/boot/bootutil/include/bootutil/boot_hooks.h +++ b/boot/bootutil/include/bootutil/boot_hooks.h @@ -82,18 +82,6 @@ #endif /* MCUBOOT_BOOT_GO_HOOKS */ -#ifdef MCUBOOT_FIND_NEXT_SLOT_HOOKS - -#define BOOT_HOOK_FIND_SLOT_CALL(f, ret_default, ...) \ - DO_HOOK_CALL(f, ret_default, __VA_ARGS__) - -#else - -#define BOOT_HOOK_FIND_SLOT_CALL(f, ret_default, ...) \ - HOOK_CALL_NOP(f, ret_default, __VA_ARGS__) - -#endif /* MCUBOOT_FIND_NEXT_SLOT_HOOKS */ - #ifdef MCUBOOT_FLASH_AREA_HOOKS #define BOOT_HOOK_FLASH_AREA_CALL(f, ret_default, ...) \ @@ -272,16 +260,4 @@ int flash_area_get_device_id_hook(const struct flash_area *fa, #define BOOT_RESET_REQUEST_HOOK_CHECK_FAILED 3 #define BOOT_RESET_REQUEST_HOOK_INTERNAL_ERROR 4 -/** - * Finds the preferred slot containing the image. - * - * @param[in] state Boot loader status information. - * @param[in] image Image, for which the slot should be found. - * @param[out] active_slot Number of the preferred slot. - * - * @return 0 if a slot was requested; - * BOOT_HOOK_REGULAR follow the normal execution path. - */ -int boot_find_next_slot_hook(struct boot_loader_state *state, uint8_t image, uint32_t *active_slot); - #endif /*H_BOOTUTIL_HOOKS*/ diff --git a/boot/bootutil/src/loader.c b/boot/bootutil/src/loader.c index 71fc7d535..026a7302a 100644 --- a/boot/bootutil/src/loader.c +++ b/boot/bootutil/src/loader.c @@ -3570,12 +3570,7 @@ boot_load_and_validate_images(struct boot_loader_state *state) break; } - rc = BOOT_HOOK_FIND_SLOT_CALL(boot_find_next_slot_hook, BOOT_HOOK_REGULAR, - state, BOOT_CURR_IMG(state), &active_slot); - if (rc == BOOT_HOOK_REGULAR) { - active_slot = find_slot_with_highest_version(state); - } - + active_slot = find_slot_with_highest_version(state); if (active_slot == NO_ACTIVE_SLOT) { BOOT_LOG_INF("No slot to load for image %d", BOOT_CURR_IMG(state)); @@ -3622,12 +3617,7 @@ boot_load_and_validate_images(struct boot_loader_state *state) break; } - rc = BOOT_HOOK_FIND_SLOT_CALL(boot_find_next_slot_hook, BOOT_HOOK_REGULAR, - state, BOOT_CURR_IMG(state), &active_slot); - if (rc == BOOT_HOOK_REGULAR) { - active_slot = find_slot_with_highest_version(state); - } - + active_slot = find_slot_with_highest_version(state); if (active_slot == NO_ACTIVE_SLOT) { BOOT_LOG_INF("No slot to load for image %d", BOOT_CURR_IMG(state)); From cc2292ee19c7b16748fba960afa45a35383e01a3 Mon Sep 17 00:00:00 2001 From: Jukka Rissanen Date: Tue, 23 Sep 2025 13:04:30 +0300 Subject: [PATCH 183/420] Revert "[nrf noup] zephyr: boards: nrf54lm20dk_nrf54lm20a_cpuapp.conf" This reverts commit d8a2e457f25f4d8b3924e3da69b54965e1690678. Signed-off-by: Jukka Rissanen --- .../boards/nrf54lm20dk_nrf54lm20a_cpuapp.conf | 13 ------------- .../boards/nrf54lm20pdk_nrf54lm20a_cpuapp.conf | 3 +++ 2 files changed, 3 insertions(+), 13 deletions(-) delete mode 100644 boot/zephyr/boards/nrf54lm20dk_nrf54lm20a_cpuapp.conf diff --git a/boot/zephyr/boards/nrf54lm20dk_nrf54lm20a_cpuapp.conf b/boot/zephyr/boards/nrf54lm20dk_nrf54lm20a_cpuapp.conf deleted file mode 100644 index 816560405..000000000 --- a/boot/zephyr/boards/nrf54lm20dk_nrf54lm20a_cpuapp.conf +++ /dev/null @@ -1,13 +0,0 @@ -# Copyright (c) 2025 Nordic Semiconductor ASA -# -# SPDX-License-Identifier: Apache-2.0 -# -CONFIG_BOOT_MAX_IMG_SECTORS=256 - -# Ensure that the SPI NOR driver is disabled by default -CONFIG_SPI_NOR=n - -# TODO: below are not yet supported and need fixing -CONFIG_FPROTECT=n - -CONFIG_BOOT_WATCHDOG_FEED=n diff --git a/boot/zephyr/boards/nrf54lm20pdk_nrf54lm20a_cpuapp.conf b/boot/zephyr/boards/nrf54lm20pdk_nrf54lm20a_cpuapp.conf index 816560405..4944f7b13 100644 --- a/boot/zephyr/boards/nrf54lm20pdk_nrf54lm20a_cpuapp.conf +++ b/boot/zephyr/boards/nrf54lm20pdk_nrf54lm20a_cpuapp.conf @@ -11,3 +11,6 @@ CONFIG_SPI_NOR=n CONFIG_FPROTECT=n CONFIG_BOOT_WATCHDOG_FEED=n + +CONFIG_PSA_CRYPTO_DRIVER_CRACEN=n +CONFIG_PSA_CRYPTO_DRIVER_OBERON=y From a3003ecde1f19cb8e5d37c59adfb898b2440f03d Mon Sep 17 00:00:00 2001 From: Jukka Rissanen Date: Tue, 23 Sep 2025 13:04:30 +0300 Subject: [PATCH 184/420] Revert "[nrf noup] boot: zephyr: Disable self RWX" This reverts commit 285fd59f4386a0317e476da5484f67b906073296. Signed-off-by: Jukka Rissanen --- boot/zephyr/Kconfig | 7 --- boot/zephyr/main.c | 129 +++++++++++--------------------------------- 2 files changed, 31 insertions(+), 105 deletions(-) diff --git a/boot/zephyr/Kconfig b/boot/zephyr/Kconfig index 323173b1b..df5fb0283 100644 --- a/boot/zephyr/Kconfig +++ b/boot/zephyr/Kconfig @@ -423,13 +423,6 @@ config MCUBOOT_CLEANUP_RAM help Sets contents of memory to 0 before jumping to application. -config NCS_MCUBOOT_DISABLE_SELF_RWX - bool "Disable read and execution on self NVM" - depends on (SOC_NRF54L15_CPUAPP || SOC_NRF54L10_CPUAPP || SOC_NRF54L05_CPUAPP) && !FPROTECT - help - Sets RRAMC's region no.4 protection before jumping to application. - It disables reads writes and execution memory area which holds MCUBOOT. - config MCUBOOT_INFINITE_LOOP_AFTER_RAM_CLEANUP bool "Infinite loop after RAM cleanup" depends on MCUBOOT_CLEANUP_RAM diff --git a/boot/zephyr/main.c b/boot/zephyr/main.c index fa3eeff90..53a393401 100644 --- a/boot/zephyr/main.c +++ b/boot/zephyr/main.c @@ -148,25 +148,6 @@ K_SEM_DEFINE(boot_log_sem, 1, 1); #include #endif -#include -#define CLEANUP_RAM_GAP_START ((int)__ramfunc_region_start) -#define CLEANUP_RAM_GAP_SIZE ((int) (__ramfunc_end - __ramfunc_region_start)) - -#if defined(CONFIG_NCS_MCUBOOT_DISABLE_SELF_RWX) -/* Disabling R_X has to be done while running from RAM for obvious reasons. - * Moreover as a last step before jumping to application it must work even after - * RAM has been cleared, therefore these operations are performed while executing from RAM. - * RAM cleanup ommits portion of the memory where code lives. - */ -#include - -#define RRAMC_REGION_RWX_LSB 0 -#define RRAMC_REGION_RWX_WIDTH 3 -#define RRAMC_REGION_TO_LOCK_ADDR NRF_RRAMC->REGION[4].CONFIG -#define RRAMC_REGION_TO_LOCK_ADDR_H (((uint32_t)(&(RRAMC_REGION_TO_LOCK_ADDR))) >> 16) -#define RRAMC_REGION_TO_LOCK_ADDR_L (((uint32_t)(&(RRAMC_REGION_TO_LOCK_ADDR))) & 0x0000fffful) -#endif /* CONFIG_NCS_MCUBOOT_DISABLE_SELF_RWX */ - BOOT_LOG_MODULE_REGISTER(mcuboot); void os_heap_init(void); @@ -182,84 +163,6 @@ struct arm_vector_table { uint32_t reset; }; -static void __ramfunc jump_in(uint32_t reset) -{ - __asm__ volatile ( - /* reset -> r0 */ - " mov r0, %0\n" -#ifdef CONFIG_MCUBOOT_CLEANUP_RAM - /* Base to write -> r1 */ - " mov r1, %1\n" - /* Size to write -> r2 */ - " mov r2, %2\n" - /* Value to write -> r3 */ - " movw r3, %5\n" - /* gap start */ - " mov r4, %3\n" - /* gap size */ - " mov r5, %4\n" - "clear:\n" - " subs r6, r4, r1\n" - " cbnz r6, skip_gap\n" - " add r1, r5\n" - "skip_gap:\n" - " str r3, [r1]\n" - " add r1, r1, #1\n" - " sub r2, r2, #1\n" - " cbz r2, clear_end\n" - " b clear\n" - "clear_end:\n" - " dsb\n" -#ifdef CONFIG_MCUBOOT_INFINITE_LOOP_AFTER_RAM_CLEANUP - " b clear_end\n" -#endif /* CONFIG_MCUBOOT_INFINITE_LOOP_AFTER_RAM_CLEANUP */ -#endif /* CONFIG_MCUBOOT_CLEANUP_RAM */ - -#ifdef CONFIG_NCS_MCUBOOT_DISABLE_SELF_RWX - ".thumb_func\n" - "region_disable_rwx:\n" - " movw r1, %6\n" - " movt r1, %7\n" - " ldr r2, [r1]\n" - /* Size of the region should be set at this point - * by NSIB's DISABLE_NEXT_W. - * If not, set it according partition size. - */ - " ands r4, r2, %12\n" - " cbnz r4, clear_rwx\n" - " movt r2, %8\n" - "clear_rwx:\n" - " bfc r2, %9, %10\n" - /* Disallow further modifications */ - " orr r2, %11\n" - " str r2, [r1]\n" - " dsb\n" - /* Next assembly line is important for current function */ - - #endif /* CONFIG_NCS_MCUBOOT_DISABLE_SELF_RWX */ - - /* Jump to reset vector of an app */ - " bx r0\n" - : - : "r" (reset), - "r" (CONFIG_SRAM_BASE_ADDRESS), - "i" (CONFIG_SRAM_SIZE * 1024), - "r" (CLEANUP_RAM_GAP_START), - "r" (CLEANUP_RAM_GAP_SIZE), - "i" (0) -#ifdef CONFIG_NCS_MCUBOOT_DISABLE_SELF_RWX - , "i" (RRAMC_REGION_TO_LOCK_ADDR_L), - "i" (RRAMC_REGION_TO_LOCK_ADDR_H), - "i" (CONFIG_PM_PARTITION_SIZE_B0_IMAGE / 1024), - "i" (RRAMC_REGION_RWX_LSB), - "i" (RRAMC_REGION_RWX_WIDTH), - "i" (RRAMC_REGION_CONFIG_LOCK_Msk), - "i" (RRAMC_REGION_CONFIG_SIZE_Msk) -#endif /* CONFIG_NCS_MCUBOOT_DISABLE_SELF_RWX */ - : "r0", "r1", "r2", "r3", "r4", "r5", "r6", "memory" - ); -} - static void do_boot(struct boot_rsp *rsp) { /* vt is static as it shall not land on the stack, @@ -370,7 +273,37 @@ static void do_boot(struct boot_rsp *rsp) __set_CONTROL(0x00); /* application will configures core on its own */ __ISB(); #endif - jump_in(vt->reset); +#if CONFIG_MCUBOOT_CLEANUP_RAM + __asm__ volatile ( + /* vt->reset -> r0 */ + " mov r0, %0\n" + /* base to write -> r1 */ + " mov r1, %1\n" + /* size to write -> r2 */ + " mov r2, %2\n" + /* value to write -> r3 */ + " mov r3, %3\n" + "clear:\n" + " str r3, [r1]\n" + " add r1, r1, #4\n" + " sub r2, r2, #4\n" + " cbz r2, out\n" + " b clear\n" + "out:\n" + " dsb\n" +#if CONFIG_MCUBOOT_INFINITE_LOOP_AFTER_RAM_CLEANUP + " b out\n" +#endif /*CONFIG_MCUBOOT_INFINITE_LOOP_AFTER_RAM_CLEANUP */ + /* jump to reset vector of an app */ + " bx r0\n" + : + : "r" (vt->reset), "i" (CONFIG_SRAM_BASE_ADDRESS), + "i" (CONFIG_SRAM_SIZE * 1024), "i" (0) + : "r0", "r1", "r2", "r3", "memory" + ); +#else + ((void (*)(void))vt->reset)(); +#endif } #elif defined(CONFIG_XTENSA) || defined(CONFIG_RISCV) From 4d9919a43cbc7e3b771bda283b60a6c46f7c1eb3 Mon Sep 17 00:00:00 2001 From: Jukka Rissanen Date: Tue, 23 Sep 2025 13:04:30 +0300 Subject: [PATCH 185/420] Revert "[nrf noup] boot: zephyr: firmware_loader: Allow GPIO usage in BM" This reverts commit ecc13ac1b0336c5ff39fc00075d34b55ab619752. Signed-off-by: Jukka Rissanen --- boot/zephyr/Kconfig.firmware_loader | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/boot/zephyr/Kconfig.firmware_loader b/boot/zephyr/Kconfig.firmware_loader index 036da98eb..1ba223949 100644 --- a/boot/zephyr/Kconfig.firmware_loader +++ b/boot/zephyr/Kconfig.firmware_loader @@ -8,7 +8,7 @@ menu "Firmware loader entrance methods" menuconfig BOOT_FIRMWARE_LOADER_ENTRANCE_GPIO bool "GPIO" - depends on GPIO || NCS_BM + depends on GPIO help Use a GPIO to enter firmware loader mode. From 8953d485700fc0cf4d2ea69585fe7cd748dfc154 Mon Sep 17 00:00:00 2001 From: Jukka Rissanen Date: Tue, 23 Sep 2025 13:04:30 +0300 Subject: [PATCH 186/420] Revert "[nrf noup] boot: zephyr: Add NCS boot banner" This reverts commit c85960801ddb83ca6cc2125bd5342139d3befa2c. Signed-off-by: Jukka Rissanen --- boot/zephyr/prj.conf | 3 --- 1 file changed, 3 deletions(-) diff --git a/boot/zephyr/prj.conf b/boot/zephyr/prj.conf index 766762237..02b27f1c4 100644 --- a/boot/zephyr/prj.conf +++ b/boot/zephyr/prj.conf @@ -36,6 +36,3 @@ CONFIG_CBPRINTF_NANO=y CONFIG_PICOLIBC=y ### Disable malloc arena because we don't need it CONFIG_COMMON_LIBC_MALLOC_ARENA_SIZE=0 - -# NCS boot banner -CONFIG_NCS_APPLICATION_BOOT_BANNER_STRING="MCUboot" From 5fae1047b3a12e822c59c81c3d7a7e66b1fd1d67 Mon Sep 17 00:00:00 2001 From: Jukka Rissanen Date: Tue, 23 Sep 2025 13:04:30 +0300 Subject: [PATCH 187/420] Revert "[nrf noup] boot: zephyr: Delay bm IO button check" This reverts commit 1b1a37fb7abf8b6e5f7d1e05daacd0081ce2844e. Signed-off-by: Jukka Rissanen --- boot/zephyr/io_bm.c | 3 --- 1 file changed, 3 deletions(-) diff --git a/boot/zephyr/io_bm.c b/boot/zephyr/io_bm.c index 788bfab9e..798cf7a3f 100644 --- a/boot/zephyr/io_bm.c +++ b/boot/zephyr/io_bm.c @@ -93,9 +93,6 @@ bool io_detect_pin(void) nrf_gpio_cfg_input(BOARD_PIN_BTN_0, BM_BUTTONS_PIN_PULLUP); - /* Delay 5 us for pull-up to be applied */ - k_busy_wait(5); - pin_active = (bool)nrf_gpio_pin_read(BOARD_PIN_BTN_0); if (!pin_active) { From 1e80b6e41d135908d8316c5850a5f5369d5cdd60 Mon Sep 17 00:00:00 2001 From: Jukka Rissanen Date: Tue, 23 Sep 2025 13:04:30 +0300 Subject: [PATCH 188/420] Revert "[nrf noup] boot: zephyr: remove nonsecure ram cleanup" This reverts commit 3adc1f232221dc8a6d77c378aa0d97fa24c9c0cb. Signed-off-by: Jukka Rissanen --- boot/zephyr/CMakeLists.txt | 2 +- boot/zephyr/main.c | 5 ++++- boot/zephyr/nrf_cleanup.c | 9 +++++++++ 3 files changed, 14 insertions(+), 2 deletions(-) diff --git a/boot/zephyr/CMakeLists.txt b/boot/zephyr/CMakeLists.txt index b25ef9e7d..8023c2198 100644 --- a/boot/zephyr/CMakeLists.txt +++ b/boot/zephyr/CMakeLists.txt @@ -743,7 +743,7 @@ if(SYSBUILD) set(mcuboot_image_upgrade_footer_size ${required_upgrade_size} CACHE INTERNAL "Estimated MCUboot update image trailer size" FORCE) endif() -if(CONFIG_MCUBOOT_NRF_CLEANUP_PERIPHERAL) +if(CONFIG_MCUBOOT_NRF_CLEANUP_PERIPHERAL OR CONFIG_MCUBOOT_CLEANUP_NONSECURE_RAM) zephyr_library_sources( ${BOOT_DIR}/zephyr/nrf_cleanup.c ) diff --git a/boot/zephyr/main.c b/boot/zephyr/main.c index 53a393401..c51616dda 100644 --- a/boot/zephyr/main.c +++ b/boot/zephyr/main.c @@ -144,7 +144,7 @@ K_SEM_DEFINE(boot_log_sem, 1, 1); #include #endif -#if CONFIG_MCUBOOT_NRF_CLEANUP_PERIPHERAL +#if CONFIG_MCUBOOT_NRF_CLEANUP_PERIPHERAL || CONFIG_MCUBOOT_NRF_CLEANUP_NONSECURE_RAM #include #endif @@ -224,6 +224,9 @@ static void do_boot(struct boot_rsp *rsp) #if CONFIG_MCUBOOT_NRF_CLEANUP_PERIPHERAL nrf_cleanup_peripheral(); #endif +#if CONFIG_MCUBOOT_NRF_CLEANUP_NONSECURE_RAM && defined(PM_SRAM_NONSECURE_NAME) + nrf_cleanup_ns_ram(); +#endif #if CONFIG_MCUBOOT_CLEANUP_ARM_CORE cleanup_arm_nvic(); /* cleanup NVIC registers */ diff --git a/boot/zephyr/nrf_cleanup.c b/boot/zephyr/nrf_cleanup.c index 5ddc74a64..e261d1914 100644 --- a/boot/zephyr/nrf_cleanup.c +++ b/boot/zephyr/nrf_cleanup.c @@ -158,3 +158,12 @@ void nrf_cleanup_peripheral(void) nrf_cleanup_clock(); #endif } + +#if USE_PARTITION_MANAGER \ + && defined(CONFIG_ARM_TRUSTZONE_M) \ + && defined(PM_SRAM_NONSECURE_NAME) +void nrf_cleanup_ns_ram(void) +{ + memset((void *) PM_SRAM_NONSECURE_ADDRESS, 0, PM_SRAM_NONSECURE_SIZE); +} +#endif From 89933f462d5d6bcfb0738e82244509a7d427fc01 Mon Sep 17 00:00:00 2001 From: Jukka Rissanen Date: Tue, 23 Sep 2025 13:04:30 +0300 Subject: [PATCH 189/420] Revert "[nrf fromtree] zephyr: Add support for AES256" This reverts commit 3b20ec38019dc0841062ba0622b4d7b6792193e5. Signed-off-by: Jukka Rissanen --- boot/zephyr/Kconfig | 16 ---------------- .../include/mcuboot_config/mcuboot_config.h | 8 -------- 2 files changed, 24 deletions(-) diff --git a/boot/zephyr/Kconfig b/boot/zephyr/Kconfig index df5fb0283..79786a361 100644 --- a/boot/zephyr/Kconfig +++ b/boot/zephyr/Kconfig @@ -667,22 +667,6 @@ config BOOT_ENCRYPT_X25519 help Hidden option selecting x25519 encryption. -if BOOT_ENCRYPT_IMAGE - -choice BOOT_ENCRYPT_ALG - prompt "Algorithm used for image encryption" - default BOOT_ENCRYPT_ALG_AES_128 - -config BOOT_ENCRYPT_ALG_AES_128 - bool "Use AES-128 for image encryption" - -config BOOT_ENCRYPT_ALG_AES_256 - bool "Use AES-256 for image encryption" - -endchoice # BOOT_ENCRYPT_ALG - -endif # BOOT_ENCRYPT_IMAGE - if BOOT_ENCRYPT_X25519 && BOOT_USE_PSA_CRYPTO choice BOOT_HMAC_SHA diff --git a/boot/zephyr/include/mcuboot_config/mcuboot_config.h b/boot/zephyr/include/mcuboot_config/mcuboot_config.h index b9cb020db..9ecb74fd2 100644 --- a/boot/zephyr/include/mcuboot_config/mcuboot_config.h +++ b/boot/zephyr/include/mcuboot_config/mcuboot_config.h @@ -159,14 +159,6 @@ #define MCUBOOT_ENCRYPT_X25519 #endif -#ifdef CONFIG_BOOT_ENCRYPT_ALG_AES_128 -#define MCUBOOT_AES_128 -#endif - -#ifdef CONFIG_BOOT_ENCRYPT_ALG_AES_256 -#define MCUBOOT_AES_256 -#endif - /* Support for HMAC/HKDF using SHA512; this is used in key exchange where * HKDF is used for key expansion and HMAC is used for key verification. */ From e8fa07b2bfb5f005144e0c86912740317769ce5e Mon Sep 17 00:00:00 2001 From: Jukka Rissanen Date: Tue, 23 Sep 2025 13:04:30 +0300 Subject: [PATCH 190/420] Revert "[nrf fromtree] imgtool: Allow for AES256 encryption" This reverts commit 1b102ec6654ac85b44a13b991db368f037f2f0af. Signed-off-by: Jukka Rissanen --- scripts/imgtool/image.py | 15 +++------------ 1 file changed, 3 insertions(+), 12 deletions(-) mode change 100755 => 100644 scripts/imgtool/image.py diff --git a/scripts/imgtool/image.py b/scripts/imgtool/image.py old mode 100755 new mode 100644 index 112d2ef4e..b24e5de8d --- a/scripts/imgtool/image.py +++ b/scripts/imgtool/image.py @@ -443,23 +443,14 @@ def ecies_hkdf(self, enckey, plainkey, hmac_sha_alg): else: newpk = X25519PrivateKey.generate() shared = newpk.exchange(enckey._get_public()) - - # Detect AES key length from plainkey size - key_len = len(plainkey) # 16 for AES-128, 32 for AES-256 - - # Generate derived key with appropriate length (key_len + 32 bytes for HMAC) derived_key = HKDF( - algorithm=hmac_sha_alg, length=key_len + hmac_sha_alg.digest_size, salt=None, + algorithm=hmac_sha_alg, length=16 + hmac_sha_alg.digest_size, salt=None, info=b'MCUBoot_ECIES_v1', backend=default_backend()).derive(shared) - - # Use appropriate key length for AES encryption - encryptor = Cipher(algorithms.AES(derived_key[:key_len]), + encryptor = Cipher(algorithms.AES(derived_key[:16]), modes.CTR(bytes([0] * 16)), backend=default_backend()).encryptor() cipherkey = encryptor.update(plainkey) + encryptor.finalize() - - # Use remaining bytes for HMAC (after the AES key) - mac = hmac.HMAC(derived_key[key_len:], hmac_sha_alg, + mac = hmac.HMAC(derived_key[16:], hmac_sha_alg, backend=default_backend()) mac.update(cipherkey) ciphermac = mac.finalize() From 7d95087eeba6ad4fc36753a2485b3137ace05ec4 Mon Sep 17 00:00:00 2001 From: Jukka Rissanen Date: Tue, 23 Sep 2025 13:04:30 +0300 Subject: [PATCH 191/420] Revert "[nrf fromlist] zephyr: Fix FLASH_DEVICE_ID for nRF54H20 platform" This reverts commit e032eb160eda49185351a35059193b0eece9efa3. Signed-off-by: Jukka Rissanen --- boot/zephyr/flash_map_extended.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/boot/zephyr/flash_map_extended.c b/boot/zephyr/flash_map_extended.c index ac9ceba0b..3b95b1fd7 100644 --- a/boot/zephyr/flash_map_extended.c +++ b/boot/zephyr/flash_map_extended.c @@ -38,7 +38,7 @@ BOOT_LOG_MODULE_DECLARE(mcuboot); #elif (defined(CONFIG_SOC_SERIES_NRF54HX) && DT_HAS_CHOSEN(zephyr_flash)) -#define FLASH_DEVICE_ID SOC_FLASH_0_ID +#define FLASH_DEVICE_ID SPI_FLASH_0_ID #define FLASH_DEVICE_BASE CONFIG_FLASH_BASE_ADDRESS #define FLASH_DEVICE_NODE DT_CHOSEN(zephyr_flash) From c8130462af8d973c60ee32d24e9713f4b9d6e696 Mon Sep 17 00:00:00 2001 From: Jukka Rissanen Date: Tue, 23 Sep 2025 13:04:30 +0300 Subject: [PATCH 192/420] Revert "[nrf fromlist] bootutil: Fix PureEdDSA when flash base is not 0x0" This reverts commit c03a815aa7ed2968ff296e82036980d180919974. Signed-off-by: Jukka Rissanen --- boot/bootutil/src/image_validate.c | 10 +--------- docs/release-notes.d/fix-pure-eddsa-base-address.md | 2 -- 2 files changed, 1 insertion(+), 11 deletions(-) delete mode 100644 docs/release-notes.d/fix-pure-eddsa-base-address.md diff --git a/boot/bootutil/src/image_validate.c b/boot/bootutil/src/image_validate.c index ac7ad2a04..8b0a99def 100644 --- a/boot/bootutil/src/image_validate.c +++ b/boot/bootutil/src/image_validate.c @@ -536,9 +536,6 @@ bootutil_img_validate(struct boot_loader_state *state, #endif int rc = 0; FIH_DECLARE(fih_rc, FIH_FAILURE); -#if defined(MCUBOOT_SIGN_PURE) - uintptr_t base = 0; -#endif #ifdef MCUBOOT_HW_ROLLBACK_PROT fih_int security_cnt = fih_int_encode(INT_MAX); uint32_t img_security_cnt = 0; @@ -718,16 +715,11 @@ bootutil_img_validate(struct boot_loader_state *state, FIH_CALL(bootutil_verify_sig, valid_signature, hash, sizeof(hash), buf, len, key_id); #else - rc = flash_device_base(flash_area_get_device_id(fap), &base); - if (rc != 0) { - goto out; - } - /* Directly check signature on the image, by using the mapping of * a device to memory. The pointer is beginning of image in flash, * so offset of area, the range is header + image + protected tlvs. */ - FIH_CALL(bootutil_verify_img, valid_signature, (void *)(base + flash_area_get_off(fap)), + FIH_CALL(bootutil_verify_img, valid_signature, (void *)flash_area_get_off(fap), hdr->ih_hdr_size + hdr->ih_img_size + hdr->ih_protect_tlv_size, buf, len, key_id); #endif diff --git a/docs/release-notes.d/fix-pure-eddsa-base-address.md b/docs/release-notes.d/fix-pure-eddsa-base-address.md deleted file mode 100644 index 4fe226792..000000000 --- a/docs/release-notes.d/fix-pure-eddsa-base-address.md +++ /dev/null @@ -1,2 +0,0 @@ - - Fixed issue in image_validate when `BOOT_SIGNATURE_TYPE_PURE` is enabled - for platforms with NVM memory that does not start at 0x00. From 0496a6ad0c4a8411603dd6444113b8cbcf8917ac Mon Sep 17 00:00:00 2001 From: Jukka Rissanen Date: Tue, 23 Sep 2025 13:04:30 +0300 Subject: [PATCH 193/420] Revert "[nrf noup] zephyr: hw security counter limited set by default" This reverts commit 0fadab126d9ba51365b3db1cdb6d55ed892c62b4. Signed-off-by: Jukka Rissanen --- boot/zephyr/Kconfig | 1 - 1 file changed, 1 deletion(-) diff --git a/boot/zephyr/Kconfig b/boot/zephyr/Kconfig index 79786a361..f40c383db 100644 --- a/boot/zephyr/Kconfig +++ b/boot/zephyr/Kconfig @@ -1022,7 +1022,6 @@ config MCUBOOT_HW_DOWNGRADE_PREVENTION config MCUBOOT_HW_DOWNGRADE_PREVENTION_COUNTER_LIMITED bool "HW based downgrade prevention counter has limited number of updates" depends on MCUBOOT_HW_DOWNGRADE_PREVENTION - default y if SOC_NRF5340_CPUAPP || SOC_SERIES_NRF91X || SOC_SERIES_NRF54LX help When this option is set, the hardware downgrade prevention counter has limited number of updates. This option will enable checking From f02b1a8cd8bdb565b54d219d45cfc2d81288c3c8 Mon Sep 17 00:00:00 2001 From: Jukka Rissanen Date: Tue, 23 Sep 2025 13:04:30 +0300 Subject: [PATCH 194/420] Revert "[nrf fromtree] bootutil: Fixed security counter overflow detected to late" This reverts commit 4e467978a6a1c2f0703e20fe956e4c34e94da700. Signed-off-by: Jukka Rissanen --- boot/bootutil/include/bootutil/security_cnt.h | 13 ------------- boot/bootutil/src/image_validate.c | 13 ------------- boot/zephyr/Kconfig | 11 ----------- boot/zephyr/include/mcuboot_config/mcuboot_config.h | 4 ---- 4 files changed, 41 deletions(-) diff --git a/boot/bootutil/include/bootutil/security_cnt.h b/boot/bootutil/include/bootutil/security_cnt.h index ff3a7371c..7e1389618 100644 --- a/boot/bootutil/include/bootutil/security_cnt.h +++ b/boot/bootutil/include/bootutil/security_cnt.h @@ -72,19 +72,6 @@ fih_ret boot_nv_security_counter_get(uint32_t image_id, fih_int *security_cnt); int32_t boot_nv_security_counter_update(uint32_t image_id, uint32_t img_security_cnt); -/** - * This function verifies whether the security counter update to a given value is possible. - * The update might not be possible if the maximum amount of security counter updates - * was reached. - * - * @param image_id Index of the image (from 0). - * @param img_security_cnt New security counter value. - * - * @return FIH_SUCCESS if update is possible; FIH_FAILURE otherwise - */ -fih_ret boot_nv_security_counter_is_update_possible(uint32_t image_id, - uint32_t img_security_cnt); - #ifdef __cplusplus } #endif diff --git a/boot/bootutil/src/image_validate.c b/boot/bootutil/src/image_validate.c index 8b0a99def..ade67cc4b 100644 --- a/boot/bootutil/src/image_validate.c +++ b/boot/bootutil/src/image_validate.c @@ -766,19 +766,6 @@ bootutil_img_validate(struct boot_loader_state *state, goto out; } -#ifdef MCUBOOT_HW_ROLLBACK_PROT_COUNTER_LIMITED - if (img_security_cnt > (uint32_t)fih_int_decode(security_cnt)) { - FIH_CALL(boot_nv_security_counter_is_update_possible, fih_rc, image_index, - img_security_cnt); - if (FIH_NOT_EQ(fih_rc, FIH_SUCCESS)) { - FIH_SET(fih_rc, FIH_FAILURE); - BOOT_LOG_ERR("Security counter update is not possible, possibly the maximum " - "number of security updates has been reached."); - goto out; - } - } -#endif - /* The image's security counter has been successfully verified. */ security_counter_valid = fih_rc; skip_security_counter_read: diff --git a/boot/zephyr/Kconfig b/boot/zephyr/Kconfig index f40c383db..c614c9bc5 100644 --- a/boot/zephyr/Kconfig +++ b/boot/zephyr/Kconfig @@ -1019,17 +1019,6 @@ config MCUBOOT_HW_DOWNGRADE_PREVENTION Because of the acceptance of equal values it allows for software downgrade to some extent. -config MCUBOOT_HW_DOWNGRADE_PREVENTION_COUNTER_LIMITED - bool "HW based downgrade prevention counter has limited number of updates" - depends on MCUBOOT_HW_DOWNGRADE_PREVENTION - help - When this option is set, the hardware downgrade prevention counter - has limited number of updates. This option will enable checking - if it is possible to update the counter before performing - the upgrade. If an update package contains a security counter - value as a TLV but it is not possible to update the counter, - the update will be rejected. - endchoice config BOOT_WATCHDOG_FEED diff --git a/boot/zephyr/include/mcuboot_config/mcuboot_config.h b/boot/zephyr/include/mcuboot_config/mcuboot_config.h index 9ecb74fd2..ae9571100 100644 --- a/boot/zephyr/include/mcuboot_config/mcuboot_config.h +++ b/boot/zephyr/include/mcuboot_config/mcuboot_config.h @@ -205,10 +205,6 @@ #define MCUBOOT_HW_ROLLBACK_PROT #endif -#ifdef CONFIG_MCUBOOT_HW_DOWNGRADE_PREVENTION_COUNTER_LIMITED -#define MCUBOOT_HW_ROLLBACK_PROT_COUNTER_LIMITED -#endif - #ifdef CONFIG_MEASURED_BOOT #define MCUBOOT_MEASURED_BOOT #endif From b4adebf4f5c2bb6449119a990724356a4039508b Mon Sep 17 00:00:00 2001 From: Jukka Rissanen Date: Tue, 23 Sep 2025 13:04:30 +0300 Subject: [PATCH 195/420] Revert "[nrf noup] boot: zephyr: Adjust PSA requirements for PSA_CORE_LITE" This reverts commit 6c096b8ed7bfddf044b20dfb512c4c1fd06c2ef6. Signed-off-by: Jukka Rissanen --- boot/zephyr/Kconfig | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/boot/zephyr/Kconfig b/boot/zephyr/Kconfig index c614c9bc5..c97a02734 100644 --- a/boot/zephyr/Kconfig +++ b/boot/zephyr/Kconfig @@ -74,14 +74,14 @@ if BOOT_USE_PSA_CRYPTO config BOOT_PSA_IMG_HASH_ALG_SHA256_DEPENDENCIES bool default y if BOOT_SOMETHING_USES_SHA256 - select PSA_WANT_ALG_SHA_256 + select PSA_WANT_ALG_SHA_256 if !PSA_CORE_LITE help Dependencies for hashing with SHA256 config BOOT_PSA_IMG_HASH_ALG_SHA512_DEPENDENCIES bool default y if BOOT_SOMETHING_USES_SHA512 - select PSA_WANT_ALG_SHA_512 + select PSA_WANT_ALG_SHA_512 if !PSA_CORE_LITE help Dependencies for hashing with SHA512 From 5d5e83b1a7fb02d6389e453b17acd693402a8617 Mon Sep 17 00:00:00 2001 From: Jukka Rissanen Date: Tue, 23 Sep 2025 13:04:30 +0300 Subject: [PATCH 196/420] Revert "[nrf fromtree] bootutil: Fix scratch scrambling" This reverts commit 95d384ac85bb8c81c1102f4b94b90515264058ae. Signed-off-by: Jukka Rissanen --- boot/bootutil/src/swap_scratch.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/boot/bootutil/src/swap_scratch.c b/boot/bootutil/src/swap_scratch.c index 6581b55a6..360dbe88c 100644 --- a/boot/bootutil/src/swap_scratch.c +++ b/boot/bootutil/src/swap_scratch.c @@ -926,7 +926,7 @@ boot_swap_sectors(int idx, uint32_t sz, struct boot_loader_state *state, * happens then the scratch which is partially erased would be wrote back to the * primary slot, causing a corrupt unbootable image */ - rc = boot_scramble_region(fap_scratch, 0, flash_area_get_size(fap_scratch), true); + rc = boot_erase_region(fap_scratch, 0, flash_area_get_size(fap_scratch), true); assert(rc == 0); } } From a9e25438e299c85d549e9fe9c1bdd3879021c5ec Mon Sep 17 00:00:00 2001 From: Jukka Rissanen Date: Tue, 23 Sep 2025 13:04:30 +0300 Subject: [PATCH 197/420] Revert "[nrf fromlist] boot/boot_serial: build-time skip of the erasing of img status page" This reverts commit c72ed153fb924203975c38dfea2853ae612e0a9a. Signed-off-by: Jukka Rissanen --- boot/boot_serial/src/boot_serial.c | 12 ++---------- 1 file changed, 2 insertions(+), 10 deletions(-) diff --git a/boot/boot_serial/src/boot_serial.c b/boot/boot_serial/src/boot_serial.c index fd1871b5e..82e1abddb 100644 --- a/boot/boot_serial/src/boot_serial.c +++ b/boot/boot_serial/src/boot_serial.c @@ -77,12 +77,6 @@ BOOT_LOG_MODULE_DECLARE(mcuboot); -#if !(defined(MCUBOOT_SINGLE_APPLICATION_SLOT) || \ - defined(MCUBOOT_FIRMWARE_LOADER) || \ - defined(MCUBOOT_SINGLE_APPLICATION_SLOT_RAM_LOAD)) -#define BOOT_IMAGE_HAS_STATUS_FIELDS -#endif - #ifndef ARRAY_SIZE #define ARRAY_SIZE ZCBOR_ARRAY_SIZE #endif @@ -920,10 +914,8 @@ bs_upload(char *buf, int len) * erase has stopped to let us know whether erase * is needed to be able to write current chunk. */ -#ifdef BOOT_IMAGE_HAS_STATUS_FIELDS static struct flash_sector status_sector; #endif -#endif /* MCUBOOT_ERASE_PROGRESSIVELY */ #ifdef MCUBOOT_SWAP_USING_OFFSET static uint32_t start_off = 0; #endif @@ -996,7 +988,7 @@ bs_upload(char *buf, int len) #endif curr_off = 0; -#if defined(MCUBOOT_ERASE_PROGRESSIVELY) && defined(BOOT_IMAGE_HAS_STATUS_FIELDS) +#ifdef MCUBOOT_ERASE_PROGRESSIVELY /* Get trailer sector information; this is done early because inability to get * that sector information means that upload will not work anyway. * TODO: This is single occurrence issue, it should get detected during tests @@ -1175,7 +1167,7 @@ bs_upload(char *buf, int len) if (rc == 0) { curr_off += img_chunk_len + rem_bytes; if (curr_off == img_size) { -#if defined(MCUBOOT_ERASE_PROGRESSIVELY) && defined(BOOT_IMAGE_HAS_STATUS_FIELDS) +#ifdef MCUBOOT_ERASE_PROGRESSIVELY /* Assure that sector for image trailer was erased. */ /* Check whether it was erased during previous upload. */ off_t start = flash_sector_get_off(&status_sector); From 57c1a8389cbdfd9e52e7bc081db3bb596c43b086 Mon Sep 17 00:00:00 2001 From: Jukka Rissanen Date: Tue, 23 Sep 2025 13:04:30 +0300 Subject: [PATCH 198/420] Revert "[nrf fromtree] boot: Switch to picolibc" This reverts commit edc1c7053f9acb65344fcda860aeb16a8c14d3ff. Signed-off-by: Jukka Rissanen --- boot/zephyr/prj.conf | 6 ++---- boot/zephyr/socs/esp32_procpu.conf | 3 +-- boot/zephyr/socs/esp32c2.conf | 3 +-- boot/zephyr/socs/esp32c3.conf | 3 +-- boot/zephyr/socs/esp32c6.conf | 3 +-- boot/zephyr/socs/esp32s2.conf | 3 +-- boot/zephyr/socs/esp32s3_procpu.conf | 3 +-- 7 files changed, 8 insertions(+), 16 deletions(-) diff --git a/boot/zephyr/prj.conf b/boot/zephyr/prj.conf index 02b27f1c4..119e07579 100644 --- a/boot/zephyr/prj.conf +++ b/boot/zephyr/prj.conf @@ -32,7 +32,5 @@ CONFIG_LOG_DEFAULT_LEVEL=0 CONFIG_MCUBOOT_LOG_LEVEL_INF=y ### Decrease footprint by ~4 KB in comparison to CBPRINTF_COMPLETE=y CONFIG_CBPRINTF_NANO=y -### Use picolibc to reduce flash usage -CONFIG_PICOLIBC=y -### Disable malloc arena because we don't need it -CONFIG_COMMON_LIBC_MALLOC_ARENA_SIZE=0 +### Use the minimal C library to reduce flash usage +CONFIG_MINIMAL_LIBC=y diff --git a/boot/zephyr/socs/esp32_procpu.conf b/boot/zephyr/socs/esp32_procpu.conf index 7d3368bad..b2b405922 100644 --- a/boot/zephyr/socs/esp32_procpu.conf +++ b/boot/zephyr/socs/esp32_procpu.conf @@ -16,5 +16,4 @@ CONFIG_LOG_DEFAULT_LEVEL=0 CONFIG_DEBUG=n CONFIG_HEAP_MEM_POOL_SIZE=4096 -CONFIG_PICOLIBC=y -CONFIG_COMMON_LIBC_MALLOC_ARENA_SIZE=0 +CONFIG_MINIMAL_LIBC=y diff --git a/boot/zephyr/socs/esp32c2.conf b/boot/zephyr/socs/esp32c2.conf index 8fdaa8852..5b49f163b 100644 --- a/boot/zephyr/socs/esp32c2.conf +++ b/boot/zephyr/socs/esp32c2.conf @@ -17,5 +17,4 @@ CONFIG_DEBUG=n CONFIG_XIP=n CONFIG_HEAP_MEM_POOL_SIZE=4096 -CONFIG_PICOLIBC=y -CONFIG_COMMON_LIBC_MALLOC_ARENA_SIZE=0 +CONFIG_MINIMAL_LIBC=y diff --git a/boot/zephyr/socs/esp32c3.conf b/boot/zephyr/socs/esp32c3.conf index 96b81e797..56298cd4f 100644 --- a/boot/zephyr/socs/esp32c3.conf +++ b/boot/zephyr/socs/esp32c3.conf @@ -17,5 +17,4 @@ CONFIG_DEBUG=n CONFIG_XIP=n CONFIG_HEAP_MEM_POOL_SIZE=4096 -CONFIG_PICOLIBC=y -CONFIG_COMMON_LIBC_MALLOC_ARENA_SIZE=0 +CONFIG_MINIMAL_LIBC=y diff --git a/boot/zephyr/socs/esp32c6.conf b/boot/zephyr/socs/esp32c6.conf index 8fdaa8852..5b49f163b 100644 --- a/boot/zephyr/socs/esp32c6.conf +++ b/boot/zephyr/socs/esp32c6.conf @@ -17,5 +17,4 @@ CONFIG_DEBUG=n CONFIG_XIP=n CONFIG_HEAP_MEM_POOL_SIZE=4096 -CONFIG_PICOLIBC=y -CONFIG_COMMON_LIBC_MALLOC_ARENA_SIZE=0 +CONFIG_MINIMAL_LIBC=y diff --git a/boot/zephyr/socs/esp32s2.conf b/boot/zephyr/socs/esp32s2.conf index 7d3368bad..b2b405922 100644 --- a/boot/zephyr/socs/esp32s2.conf +++ b/boot/zephyr/socs/esp32s2.conf @@ -16,5 +16,4 @@ CONFIG_LOG_DEFAULT_LEVEL=0 CONFIG_DEBUG=n CONFIG_HEAP_MEM_POOL_SIZE=4096 -CONFIG_PICOLIBC=y -CONFIG_COMMON_LIBC_MALLOC_ARENA_SIZE=0 +CONFIG_MINIMAL_LIBC=y diff --git a/boot/zephyr/socs/esp32s3_procpu.conf b/boot/zephyr/socs/esp32s3_procpu.conf index 7d3368bad..b2b405922 100644 --- a/boot/zephyr/socs/esp32s3_procpu.conf +++ b/boot/zephyr/socs/esp32s3_procpu.conf @@ -16,5 +16,4 @@ CONFIG_LOG_DEFAULT_LEVEL=0 CONFIG_DEBUG=n CONFIG_HEAP_MEM_POOL_SIZE=4096 -CONFIG_PICOLIBC=y -CONFIG_COMMON_LIBC_MALLOC_ARENA_SIZE=0 +CONFIG_MINIMAL_LIBC=y From 89df5d723aa8ebd1f03c9189665f2c58ec442989 Mon Sep 17 00:00:00 2001 From: Jukka Rissanen Date: Tue, 23 Sep 2025 13:04:30 +0300 Subject: [PATCH 199/420] Revert "[nrf noup] boot: zephyr: Fix bm IO button check" This reverts commit a184e32064cb04efdd49951088f8b2e802990e7e. Signed-off-by: Jukka Rissanen --- boot/zephyr/io_bm.c | 45 ++++++++++++++++++++++++++++++++++++--------- 1 file changed, 36 insertions(+), 9 deletions(-) diff --git a/boot/zephyr/io_bm.c b/boot/zephyr/io_bm.c index 798cf7a3f..3f65a5d0e 100644 --- a/boot/zephyr/io_bm.c +++ b/boot/zephyr/io_bm.c @@ -89,13 +89,31 @@ void io_led_set(int value) bool io_detect_pin(void) { + int rc; bool pin_active; - nrf_gpio_cfg_input(BOARD_PIN_BTN_0, BM_BUTTONS_PIN_PULLUP); + rc = bm_buttons_init( + &(struct bm_buttons_config){ + .pin_number = BOARD_PIN_BTN_0, + .active_state = BM_BUTTONS_ACTIVE_LOW, + .pull_config = BM_BUTTONS_PIN_PULLUP, + }, + 1, + BM_BUTTONS_DETECTION_DELAY_MIN_US); + if (rc) { + BOOT_LOG_ERR("Failed to initialize buttons: %d", rc); + return false; + } - pin_active = (bool)nrf_gpio_pin_read(BOARD_PIN_BTN_0); + rc = bm_buttons_enable(); + if (rc) { + BOOT_LOG_ERR("Failed to enable button detection: %d", rc); + return false; + } - if (!pin_active) { + pin_active = bm_buttons_is_pressed(BOARD_PIN_BTN_0); + + if (pin_active) { if (BUTTON_0_DETECT_DELAY > 0) { #ifdef CONFIG_MULTITHREADING k_sleep(K_MSEC(50)); @@ -107,15 +125,13 @@ bool io_detect_pin(void) int64_t timestamp = k_uptime_get(); for(;;) { - uint32_t delta; - - pin_active = (bool)nrf_gpio_pin_read(BOARD_PIN_BTN_0); + pin_active = bm_buttons_is_pressed(BOARD_PIN_BTN_0); /* Get delta from when this started */ - delta = k_uptime_get() - timestamp; + uint32_t delta = k_uptime_get() - timestamp; /* If not pressed OR if pressed > debounce period, stop. */ - if (delta >= BUTTON_0_DETECT_DELAY || pin_active) { + if (delta >= BUTTON_0_DETECT_DELAY || !pin_active) { break; } @@ -129,7 +145,18 @@ bool io_detect_pin(void) } } - return (bool)!pin_active; + rc = bm_buttons_disable(); + + if (rc) { + BOOT_LOG_ERR("Failed to disable buttons: %d", rc); + } + + rc = bm_buttons_deinit(); + if (rc) { + BOOT_LOG_ERR("Failed to de-initialize buttons: %d", rc); + } + + return (bool)pin_active; } #endif From bf97481438bddbc133dcc0c130381c75c31134ba Mon Sep 17 00:00:00 2001 From: Jukka Rissanen Date: Tue, 23 Sep 2025 13:04:30 +0300 Subject: [PATCH 200/420] Revert "[nrf fromlist] boot: zephyr: Fix including asn1 when ed25519 is used" This reverts commit bc5eb3f126f655b4dd51ce06952e126a8c54186d. Signed-off-by: Jukka Rissanen --- boot/zephyr/CMakeLists.txt | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/boot/zephyr/CMakeLists.txt b/boot/zephyr/CMakeLists.txt index 8023c2198..d700841ee 100644 --- a/boot/zephyr/CMakeLists.txt +++ b/boot/zephyr/CMakeLists.txt @@ -303,13 +303,8 @@ elseif(CONFIG_BOOT_SIGNATURE_TYPE_ED25519 OR CONFIG_BOOT_ENCRYPT_X25519) ${FIAT_DIR}/src/curve25519.c ) else() - if(MBEDTLS_ASN1_DIR) - zephyr_library_sources( - ${MBEDTLS_ASN1_DIR}/src/asn1parse.c - ) - endif() - zephyr_library_sources( + ${MBEDTLS_ASN1_DIR}/src/asn1parse.c ${BOOT_DIR}/bootutil/src/ed25519_psa.c ) endif() From a612064090137ac216665825bdf9a4e8a4ad24c4 Mon Sep 17 00:00:00 2001 From: Jukka Rissanen Date: Tue, 23 Sep 2025 13:04:30 +0300 Subject: [PATCH 201/420] Revert "[nrf noup] workflows: Add manifest PRs creation" This reverts commit 37486f508fd7bc760732a67eab650d76590ebe86. Signed-off-by: Jukka Rissanen --- .github/workflows/manifest-PR.yml | 17 ----------------- 1 file changed, 17 deletions(-) delete mode 100644 .github/workflows/manifest-PR.yml diff --git a/.github/workflows/manifest-PR.yml b/.github/workflows/manifest-PR.yml deleted file mode 100644 index a871aa381..000000000 --- a/.github/workflows/manifest-PR.yml +++ /dev/null @@ -1,17 +0,0 @@ -name: handle manifest PR -on: - pull_request_target: - types: [opened, synchronize, closed] - branches: - - main - - -jobs: - call-manifest-pr-action: - runs-on: ubuntu-latest - steps: - - name: handle manifest PR - uses: nrfconnect/action-manifest-pr@main - with: - token: ${{ secrets.NCS_GITHUB_TOKEN }} - manifest-pr-title-details: ${{ github.event.pull_request.title }} From 2b45eb8959514558a5ea137f085145fcd380f7fd Mon Sep 17 00:00:00 2001 From: Jukka Rissanen Date: Tue, 23 Sep 2025 13:04:30 +0300 Subject: [PATCH 202/420] Revert "[nrf noup] boot/zephyr/nrf_cleanup: fix index error" This reverts commit 58175b6f71bdae10e1d10896c1c858520ab583ec. Signed-off-by: Jukka Rissanen --- boot/zephyr/nrf_cleanup.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/boot/zephyr/nrf_cleanup.c b/boot/zephyr/nrf_cleanup.c index e261d1914..39dfcbc41 100644 --- a/boot/zephyr/nrf_cleanup.c +++ b/boot/zephyr/nrf_cleanup.c @@ -131,7 +131,7 @@ void nrf_cleanup_peripheral(void) for (int j = 0; j < 4; j++) { if (pin[j] != NRF_UARTE_PSEL_DISCONNECTED) { - nrfy_gpio_cfg_default(pin[j]); + nrfy_gpio_cfg_default(pin[i]); } } #endif From 5abb6651cf45eff97284b0fb6b394f8ad92eae10 Mon Sep 17 00:00:00 2001 From: Jukka Rissanen Date: Tue, 23 Sep 2025 13:04:30 +0300 Subject: [PATCH 203/420] Revert "[nrf noup] boot: Use NCS_ prefix for sdk-nrf specific Kconfigs" This reverts commit 30e7326a49a20df7326d3996bec73cf3802745e2. Signed-off-by: Jukka Rissanen --- boot/bootutil/src/loader.c | 38 +++++++++++++++++++------------------- boot/zephyr/Kconfig | 6 +++--- 2 files changed, 22 insertions(+), 22 deletions(-) diff --git a/boot/bootutil/src/loader.c b/boot/bootutil/src/loader.c index 026a7302a..c13851f73 100644 --- a/boot/bootutil/src/loader.c +++ b/boot/bootutil/src/loader.c @@ -52,9 +52,9 @@ #ifdef __ZEPHYR__ #include -#if defined(CONFIG_NCS_MCUBOOT_IMG_VALIDATE_ATTEMPT_WAIT_MS) +#if defined(CONFIG_NRF_MCUBOOT_IMG_VALIDATE_ATTEMPT_WAIT_MS) #include -#endif /* CONFIG_NCS_MCUBOOT_IMG_VALIDATE_ATTEMPT_WAIT_MS */ +#endif /* CONFIG_NRF_MCUBOOT_IMG_VALIDATE_ATTEMPT_WAIT_MS */ #endif #if defined(CONFIG_SOC_NRF5340_CPUAPP) && defined(PM_CPUNET_B0N_ADDRESS) && defined(CONFIG_PCD_APP) @@ -907,10 +907,10 @@ boot_image_check(struct boot_loader_state *state, struct image_header *hdr, } #endif - for (int i = 1; i <= CONFIG_NCS_MCUBOOT_IMG_VALIDATE_ATTEMPT_COUNT; i++ ) { -#if CONFIG_NCS_MCUBOOT_IMG_VALIDATE_ATTEMPT_COUNT > 1 - BOOT_LOG_DBG("Image validation attempt %d/%d", i, CONFIG_NCS_MCUBOOT_IMG_VALIDATE_ATTEMPT_COUNT); -#endif /* CONFIG_NCS_MCUBOOT_IMG_VALIDATE_ATTEMPT_COUNT > 1 */ + for (int i = 1; i <= CONFIG_NRF_MCUBOOT_IMG_VALIDATE_ATTEMPT_COUNT; i++ ) { +#if CONFIG_NRF_MCUBOOT_IMG_VALIDATE_ATTEMPT_COUNT > 1 + BOOT_LOG_DBG("Image validation attempt %d/%d", i, CONFIG_NRF_MCUBOOT_IMG_VALIDATE_ATTEMPT_COUNT); +#endif /* CONFIG_NRF_MCUBOOT_IMG_VALIDATE_ATTEMPT_COUNT > 1 */ #if defined(MCUBOOT_SWAP_USING_OFFSET) && defined(MCUBOOT_SERIAL_RECOVERY) FIH_CALL(bootutil_img_validate, fih_rc, state, hdr, fap, tmpbuf, BOOT_TMPBUF_SZ, @@ -921,25 +921,25 @@ boot_image_check(struct boot_loader_state *state, struct image_header *hdr, #endif if (FIH_EQ(fih_rc, FIH_SUCCESS)) { -#if CONFIG_NCS_MCUBOOT_IMG_VALIDATE_ATTEMPT_COUNT > 1 - BOOT_LOG_DBG("Image validation attempt %d/%d success", i, CONFIG_NCS_MCUBOOT_IMG_VALIDATE_ATTEMPT_COUNT); -#endif /* CONFIG_NCS_MCUBOOT_IMG_VALIDATE_ATTEMPT_COUNT > 1 */ +#if CONFIG_NRF_MCUBOOT_IMG_VALIDATE_ATTEMPT_COUNT > 1 + BOOT_LOG_DBG("Image validation attempt %d/%d success", i, CONFIG_NRF_MCUBOOT_IMG_VALIDATE_ATTEMPT_COUNT); +#endif /* CONFIG_NRF_MCUBOOT_IMG_VALIDATE_ATTEMPT_COUNT > 1 */ break; } else { -#if CONFIG_NCS_MCUBOOT_IMG_VALIDATE_ATTEMPT_COUNT > 1 +#if CONFIG_NRF_MCUBOOT_IMG_VALIDATE_ATTEMPT_COUNT > 1 BOOT_LOG_WRN("Image validation attempt %d/%d failure: %d", i, - CONFIG_NCS_MCUBOOT_IMG_VALIDATE_ATTEMPT_COUNT, fih_rc); -#endif /* CONFIG_NCS_MCUBOOT_IMG_VALIDATE_ATTEMPT_COUNT > 1 */ + CONFIG_NRF_MCUBOOT_IMG_VALIDATE_ATTEMPT_COUNT, fih_rc); +#endif /* CONFIG_NRF_MCUBOOT_IMG_VALIDATE_ATTEMPT_COUNT > 1 */ - if (i < CONFIG_NCS_MCUBOOT_IMG_VALIDATE_ATTEMPT_COUNT) { -#if defined(CONFIG_NCS_MCUBOOT_IMG_VALIDATE_ATTEMPT_WAIT_MS) -#if CONFIG_NCS_MCUBOOT_IMG_VALIDATE_ATTEMPT_COUNT > 1 + if (i < CONFIG_NRF_MCUBOOT_IMG_VALIDATE_ATTEMPT_COUNT) { +#if defined(CONFIG_NRF_MCUBOOT_IMG_VALIDATE_ATTEMPT_WAIT_MS) +#if CONFIG_NRF_MCUBOOT_IMG_VALIDATE_ATTEMPT_COUNT > 1 BOOT_LOG_DBG("Waiting %d ms before next attempt", - CONFIG_NCS_MCUBOOT_IMG_VALIDATE_ATTEMPT_WAIT_MS); -#endif /* CONFIG_NCS_MCUBOOT_IMG_VALIDATE_ATTEMPT_COUNT > 1 */ - k_busy_wait(CONFIG_NCS_MCUBOOT_IMG_VALIDATE_ATTEMPT_WAIT_MS * 1000); -#endif /* CONFIG_NCS_MCUBOOT_IMG_VALIDATE_ATTEMPT_WAIT_MS */ + CONFIG_NRF_MCUBOOT_IMG_VALIDATE_ATTEMPT_WAIT_MS); +#endif /* CONFIG_NRF_MCUBOOT_IMG_VALIDATE_ATTEMPT_COUNT > 1 */ + k_busy_wait(CONFIG_NRF_MCUBOOT_IMG_VALIDATE_ATTEMPT_WAIT_MS * 1000); +#endif /* CONFIG_NRF_MCUBOOT_IMG_VALIDATE_ATTEMPT_WAIT_MS */ } } } diff --git a/boot/zephyr/Kconfig b/boot/zephyr/Kconfig index c97a02734..d92050b80 100644 --- a/boot/zephyr/Kconfig +++ b/boot/zephyr/Kconfig @@ -1246,7 +1246,7 @@ config MCUBOOT_VERIFY_IMG_ADDRESS also be useful when BOOT_DIRECT_XIP is enabled, to ensure that the image linked at the correct address is loaded. -config NCS_MCUBOOT_IMG_VALIDATE_ATTEMPT_COUNT +config NRF_MCUBOOT_IMG_VALIDATE_ATTEMPT_COUNT int "Number of image validation attempts" default 1 help @@ -1255,9 +1255,9 @@ config NCS_MCUBOOT_IMG_VALIDATE_ATTEMPT_COUNT This can prevent erasing an image when initial validation fails. Wait time is controlled by MCUBOOT_IMG_VALIDATE_ATTEMPT_WAIT_MS. -config NCS_MCUBOOT_IMG_VALIDATE_ATTEMPT_WAIT_MS +config NRF_MCUBOOT_IMG_VALIDATE_ATTEMPT_WAIT_MS int "Time between image validation attempts" - depends on NCS_MCUBOOT_IMG_VALIDATE_ATTEMPT_COUNT > 1 + depends on NRF_MCUBOOT_IMG_VALIDATE_ATTEMPT_COUNT > 1 default 5000 help Time between image validation attempts, in milliseconds. From 205ac07eb913909bb90d5c60fdfddbc76e4d18e1 Mon Sep 17 00:00:00 2001 From: Jukka Rissanen Date: Tue, 23 Sep 2025 13:04:30 +0300 Subject: [PATCH 204/420] Revert "[nrf noup] zephyr: Enforce HMAC-SHA512 for NRF54L with X25519" This reverts commit 8b2d04cba336b40f97b1c5edbef80f4e58fa1a90. Signed-off-by: Jukka Rissanen --- boot/zephyr/Kconfig | 1 - 1 file changed, 1 deletion(-) diff --git a/boot/zephyr/Kconfig b/boot/zephyr/Kconfig index d92050b80..1967107ac 100644 --- a/boot/zephyr/Kconfig +++ b/boot/zephyr/Kconfig @@ -671,7 +671,6 @@ if BOOT_ENCRYPT_X25519 && BOOT_USE_PSA_CRYPTO choice BOOT_HMAC_SHA prompt "SHA used for HMAC and HKDF in encryption key exchange" - default BOOT_HMAC_SHA512 if BOOT_ENCRYPT_X25519 && (SOC_NRF54L15_CPUAPP || SOC_NRF54LM20A_ENGA_CPUAPP) default BOOT_HMAC_SHA256 help HMAC/HKDF sha algorithm may be selected to synchronize sha From 671886ab7677bd0567ee6a26e5cbb0a1ce8c8c2d Mon Sep 17 00:00:00 2001 From: Jukka Rissanen Date: Tue, 23 Sep 2025 13:04:30 +0300 Subject: [PATCH 205/420] Revert "[nrf fromtree] imgtool: Fix x25519 TLV HMAC tag" This reverts commit 2128ae512234af3b8eb0c6ecb6ac3270a69b098b. Signed-off-by: Jukka Rissanen --- scripts/imgtool/image.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/imgtool/image.py b/scripts/imgtool/image.py index b24e5de8d..4e2830370 100644 --- a/scripts/imgtool/image.py +++ b/scripts/imgtool/image.py @@ -444,7 +444,7 @@ def ecies_hkdf(self, enckey, plainkey, hmac_sha_alg): newpk = X25519PrivateKey.generate() shared = newpk.exchange(enckey._get_public()) derived_key = HKDF( - algorithm=hmac_sha_alg, length=16 + hmac_sha_alg.digest_size, salt=None, + algorithm=hmac_sha_alg, length=48, salt=None, info=b'MCUBoot_ECIES_v1', backend=default_backend()).derive(shared) encryptor = Cipher(algorithms.AES(derived_key[:16]), modes.CTR(bytes([0] * 16)), From 2bc25aa21e2346f741633cf72c01fa83b332d8ee Mon Sep 17 00:00:00 2001 From: Jukka Rissanen Date: Tue, 23 Sep 2025 13:04:30 +0300 Subject: [PATCH 206/420] Revert "[nrf fromtree] bootutil: Fix X25519 HMAC-SHA512" This reverts commit 31c8554d59b13f95558e0b91653629f810d69250. Signed-off-by: Jukka Rissanen --- boot/bootutil/src/encrypted_psa.c | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/boot/bootutil/src/encrypted_psa.c b/boot/bootutil/src/encrypted_psa.c index 7e53ed4a7..0cfdc9768 100644 --- a/boot/bootutil/src/encrypted_psa.c +++ b/boot/bootutil/src/encrypted_psa.c @@ -43,11 +43,7 @@ static const uint8_t ec_pubkey_oid[] = MBEDTLS_OID_ISO_IDENTIFIED_ORG \ #define HKDF_AES_KEY_SIZE (BOOT_ENC_KEY_SIZE) /* MAC feed */ #define HKDF_MAC_FEED_INDEX (HKDF_AES_KEY_INDEX + HKDF_AES_KEY_SIZE) -#if !defined(MCUBOOT_HMAC_SHA512) -#define HKDF_MAC_FEED_SIZE (32) -#else -#define HKDF_MAC_FEED_SIZE (64) -#endif +#define HKDF_MAC_FEED_SIZE (32) /* This is SHA independent */ /* Total size */ #define HKDF_SIZE (HKDF_AES_KEY_SIZE + HKDF_MAC_FEED_SIZE) From 9f9c14d6cf94539fc2e426d2551f89f609b2e984 Mon Sep 17 00:00:00 2001 From: Jukka Rissanen Date: Tue, 23 Sep 2025 13:04:30 +0300 Subject: [PATCH 207/420] Revert "[nrf noup] boot: zephyr: Kconfig dependencies for PSA LITE" This reverts commit 2f7059edfa0140851289651fd9b69069a31051e2. Signed-off-by: Jukka Rissanen --- boot/zephyr/Kconfig | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/boot/zephyr/Kconfig b/boot/zephyr/Kconfig index 1967107ac..813c88156 100644 --- a/boot/zephyr/Kconfig +++ b/boot/zephyr/Kconfig @@ -74,14 +74,14 @@ if BOOT_USE_PSA_CRYPTO config BOOT_PSA_IMG_HASH_ALG_SHA256_DEPENDENCIES bool default y if BOOT_SOMETHING_USES_SHA256 - select PSA_WANT_ALG_SHA_256 if !PSA_CORE_LITE + select PSA_WANT_ALG_SHA_256 help Dependencies for hashing with SHA256 config BOOT_PSA_IMG_HASH_ALG_SHA512_DEPENDENCIES bool default y if BOOT_SOMETHING_USES_SHA512 - select PSA_WANT_ALG_SHA_512 if !PSA_CORE_LITE + select PSA_WANT_ALG_SHA_512 help Dependencies for hashing with SHA512 @@ -90,7 +90,7 @@ config BOOT_ED25519_PSA_DEPENDENCIES select PSA_WANT_ALG_PURE_EDDSA select PSA_WANT_ECC_TWISTED_EDWARDS_255 select PSA_WANT_ECC_MONTGOMERY_255 - select PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_IMPORT if !PSA_CORE_LITE + select PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_IMPORT help Dependencies for ed25519 signature @@ -364,9 +364,9 @@ config BOOT_ED25519_PSA select PSA_CRYPTO_C select MBEDTLS_PSA_CRYPTO_C select MBEDTLS_ASN1_PARSE_C if MBEDTLS_BUILTIN - select MBEDTLS_ENABLE_HEAP if !PSA_CORE_LITE - select BOOT_IMG_HASH_ALG_SHA256_ALLOW if !PSA_CORE_LITE - select BOOT_IMG_HASH_ALG_SHA512_ALLOW if !PSA_CORE_LITE + select MBEDTLS_ENABLE_HEAP + select BOOT_IMG_HASH_ALG_SHA256_ALLOW + select BOOT_IMG_HASH_ALG_SHA512_ALLOW select BOOT_ED25519_PSA_DEPENDENCIES select BOOT_X25519_PSA_DEPENDENCIES if BOOT_ENCRYPT_IMAGE From 3c620de5e1413a7a9548b37c51ede43ad7e484dc Mon Sep 17 00:00:00 2001 From: Jukka Rissanen Date: Tue, 23 Sep 2025 13:04:30 +0300 Subject: [PATCH 208/420] Revert "[nrf noup] boot: Add retry for image verification" This reverts commit a9e70e43fa548c86bec946dc06210b8a2ba2b860. Signed-off-by: Jukka Rissanen --- boot/bootutil/src/loader.c | 39 ++++---------------------------------- boot/zephyr/Kconfig | 17 ----------------- 2 files changed, 4 insertions(+), 52 deletions(-) diff --git a/boot/bootutil/src/loader.c b/boot/bootutil/src/loader.c index c13851f73..dd4853874 100644 --- a/boot/bootutil/src/loader.c +++ b/boot/bootutil/src/loader.c @@ -52,9 +52,6 @@ #ifdef __ZEPHYR__ #include -#if defined(CONFIG_NRF_MCUBOOT_IMG_VALIDATE_ATTEMPT_WAIT_MS) -#include -#endif /* CONFIG_NRF_MCUBOOT_IMG_VALIDATE_ATTEMPT_WAIT_MS */ #endif #if defined(CONFIG_SOC_NRF5340_CPUAPP) && defined(PM_CPUNET_B0N_ADDRESS) && defined(CONFIG_PCD_APP) @@ -907,42 +904,14 @@ boot_image_check(struct boot_loader_state *state, struct image_header *hdr, } #endif - for (int i = 1; i <= CONFIG_NRF_MCUBOOT_IMG_VALIDATE_ATTEMPT_COUNT; i++ ) { -#if CONFIG_NRF_MCUBOOT_IMG_VALIDATE_ATTEMPT_COUNT > 1 - BOOT_LOG_DBG("Image validation attempt %d/%d", i, CONFIG_NRF_MCUBOOT_IMG_VALIDATE_ATTEMPT_COUNT); -#endif /* CONFIG_NRF_MCUBOOT_IMG_VALIDATE_ATTEMPT_COUNT > 1 */ - #if defined(MCUBOOT_SWAP_USING_OFFSET) && defined(MCUBOOT_SERIAL_RECOVERY) - FIH_CALL(bootutil_img_validate, fih_rc, state, hdr, fap, tmpbuf, BOOT_TMPBUF_SZ, - NULL, 0, NULL, 0); + FIH_CALL(bootutil_img_validate, fih_rc, state, hdr, fap, tmpbuf, BOOT_TMPBUF_SZ, + NULL, 0, NULL, 0); #else - FIH_CALL(bootutil_img_validate, fih_rc, state, hdr, fap, tmpbuf, BOOT_TMPBUF_SZ, - NULL, 0, NULL); + FIH_CALL(bootutil_img_validate, fih_rc, state, hdr, fap, tmpbuf, BOOT_TMPBUF_SZ, + NULL, 0, NULL); #endif - if (FIH_EQ(fih_rc, FIH_SUCCESS)) { -#if CONFIG_NRF_MCUBOOT_IMG_VALIDATE_ATTEMPT_COUNT > 1 - BOOT_LOG_DBG("Image validation attempt %d/%d success", i, CONFIG_NRF_MCUBOOT_IMG_VALIDATE_ATTEMPT_COUNT); -#endif /* CONFIG_NRF_MCUBOOT_IMG_VALIDATE_ATTEMPT_COUNT > 1 */ - break; - } else { -#if CONFIG_NRF_MCUBOOT_IMG_VALIDATE_ATTEMPT_COUNT > 1 - BOOT_LOG_WRN("Image validation attempt %d/%d failure: %d", - i, - CONFIG_NRF_MCUBOOT_IMG_VALIDATE_ATTEMPT_COUNT, fih_rc); -#endif /* CONFIG_NRF_MCUBOOT_IMG_VALIDATE_ATTEMPT_COUNT > 1 */ - - if (i < CONFIG_NRF_MCUBOOT_IMG_VALIDATE_ATTEMPT_COUNT) { -#if defined(CONFIG_NRF_MCUBOOT_IMG_VALIDATE_ATTEMPT_WAIT_MS) -#if CONFIG_NRF_MCUBOOT_IMG_VALIDATE_ATTEMPT_COUNT > 1 - BOOT_LOG_DBG("Waiting %d ms before next attempt", - CONFIG_NRF_MCUBOOT_IMG_VALIDATE_ATTEMPT_WAIT_MS); -#endif /* CONFIG_NRF_MCUBOOT_IMG_VALIDATE_ATTEMPT_COUNT > 1 */ - k_busy_wait(CONFIG_NRF_MCUBOOT_IMG_VALIDATE_ATTEMPT_WAIT_MS * 1000); -#endif /* CONFIG_NRF_MCUBOOT_IMG_VALIDATE_ATTEMPT_WAIT_MS */ - } - } - } FIH_RET(fih_rc); } diff --git a/boot/zephyr/Kconfig b/boot/zephyr/Kconfig index 813c88156..973192d9f 100644 --- a/boot/zephyr/Kconfig +++ b/boot/zephyr/Kconfig @@ -1245,21 +1245,4 @@ config MCUBOOT_VERIFY_IMG_ADDRESS also be useful when BOOT_DIRECT_XIP is enabled, to ensure that the image linked at the correct address is loaded. -config NRF_MCUBOOT_IMG_VALIDATE_ATTEMPT_COUNT - int "Number of image validation attempts" - default 1 - help - Number of image validation attempts performed before an image is considered invalid. - A wait is done between each attempt to allow for recovery from a temporary disruption. - This can prevent erasing an image when initial validation fails. - Wait time is controlled by MCUBOOT_IMG_VALIDATE_ATTEMPT_WAIT_MS. - -config NRF_MCUBOOT_IMG_VALIDATE_ATTEMPT_WAIT_MS - int "Time between image validation attempts" - depends on NRF_MCUBOOT_IMG_VALIDATE_ATTEMPT_COUNT > 1 - default 5000 - help - Time between image validation attempts, in milliseconds. - Allows for recovery from transient bit flips or similar situations. - source "Kconfig.zephyr" From 57add99eae475ca33e956fae70a4230440f36d0d Mon Sep 17 00:00:00 2001 From: Jukka Rissanen Date: Tue, 23 Sep 2025 13:04:30 +0300 Subject: [PATCH 209/420] Revert "[nrf noup] boot: Provide default configuration for nRF54H20" This reverts commit 068718ae281e70cc5c771d51320f1f8707d8ea59. Signed-off-by: Jukka Rissanen --- boot/zephyr/Kconfig | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/boot/zephyr/Kconfig b/boot/zephyr/Kconfig index 973192d9f..1c71f33eb 100644 --- a/boot/zephyr/Kconfig +++ b/boot/zephyr/Kconfig @@ -185,7 +185,6 @@ config BOOT_IMG_HASH_ALG_SHA512_ALLOW config BOOT_IMG_HASH_DIRECTLY_ON_STORAGE bool "Hash calculation functions access storage through address space" - default y if NRF_SECURITY && SOC_NRF54H20 depends on !BOOT_ENCRYPT_IMAGE help When possible to map storage device, at least for read operations, @@ -243,7 +242,7 @@ config BOOT_SIGNATURE_TYPE_PURE_ALLOW choice BOOT_SIGNATURE_TYPE prompt "Signature type" - default BOOT_SIGNATURE_TYPE_ED25519 if SOC_NRF54L15_CPUAPP || SOC_NRF54H20_CPUAPP + default BOOT_SIGNATURE_TYPE_ED25519 if SOC_NRF54L15_CPUAPP default BOOT_SIGNATURE_TYPE_RSA config BOOT_SIGNATURE_TYPE_NONE From c4624f40f8d6cbf2beb6ab66008a36381c064cd8 Mon Sep 17 00:00:00 2001 From: Jukka Rissanen Date: Tue, 23 Sep 2025 13:04:30 +0300 Subject: [PATCH 210/420] Revert "[nrf noup] boot: zephyr: Add bm firmware loader code" This reverts commit 9200785d3284a15f6a469a86efb79d95b68cce1c. Signed-off-by: Jukka Rissanen --- boot/zephyr/CMakeLists.txt | 19 +-- boot/zephyr/firmware_loader_bm.c | 283 ------------------------------- boot/zephyr/io_bm.c | 198 --------------------- 3 files changed, 4 insertions(+), 496 deletions(-) delete mode 100644 boot/zephyr/firmware_loader_bm.c delete mode 100644 boot/zephyr/io_bm.c diff --git a/boot/zephyr/CMakeLists.txt b/boot/zephyr/CMakeLists.txt index d700841ee..e2c981aae 100644 --- a/boot/zephyr/CMakeLists.txt +++ b/boot/zephyr/CMakeLists.txt @@ -64,17 +64,12 @@ endif() # Zephyr port-specific sources. zephyr_library_sources( main.c + io.c flash_map_extended.c os.c keys.c ) -if(CONFIG_NCS_BM) - zephyr_library_sources(io_bm.c) -else() - zephyr_library_sources(io.c) -endif() - if(DEFINED CONFIG_ENABLE_MGMT_PERUSER) zephyr_library_sources( boot_serial_extensions.c @@ -155,15 +150,9 @@ elseif(CONFIG_SINGLE_APPLICATION_SLOT) ) zephyr_library_include_directories(${BOOT_DIR}/bootutil/src) elseif(CONFIG_BOOT_FIRMWARE_LOADER) - if(CONFIG_NCS_BM) - zephyr_library_sources( - ${BOOT_DIR}/zephyr/firmware_loader_bm.c - ) - else() - zephyr_library_sources( - ${BOOT_DIR}/zephyr/firmware_loader.c - ) - endif() + zephyr_library_sources( + ${BOOT_DIR}/zephyr/firmware_loader.c + ) zephyr_library_include_directories(${BOOT_DIR}/bootutil/src) else() zephyr_library_sources( diff --git a/boot/zephyr/firmware_loader_bm.c b/boot/zephyr/firmware_loader_bm.c deleted file mode 100644 index 14d5c96bd..000000000 --- a/boot/zephyr/firmware_loader_bm.c +++ /dev/null @@ -1,283 +0,0 @@ -/* - * Copyright (c) 2025 Nordic Semiconductor ASA - * - * SPDX-License-Identifier: Apache-2.0 - */ - -#include -#include -#include -#include -#include -#include "bootutil/image.h" -#include "bootutil_priv.h" -#include "bootutil/bootutil_log.h" -#include "bootutil/bootutil_public.h" -#include "bootutil/fault_injection_hardening.h" -#include - -#include "io/io.h" -#include "mcuboot_config/mcuboot_config.h" - -#define IMAGE_TLV_INSTALLER_IMAGE 0xa0 - -BOOT_LOG_MODULE_DECLARE(mcuboot); - -static struct flash_area fa_app_installer = { - .fa_id = 1, - .fa_off = FIXED_PARTITION_OFFSET(slot0_partition), - .fa_size = FIXED_PARTITION_SIZE(slot0_partition), - .fa_dev = DEVICE_DT_GET(DT_CHOSEN(zephyr_flash_controller)), -}; - -static struct image_header hdr_app_installer = { 0 }; - -static struct flash_area fa_softdevice = { - .fa_id = 2, - .fa_dev = DEVICE_DT_GET(DT_CHOSEN(zephyr_flash_controller)), -}; - -static struct image_header hdr_softdevice = { 0 }; - -#ifdef CONFIG_BOOT_FIRMWARE_LOADER -static struct flash_area fa_firmware_loader = { - .fa_id = 3, - .fa_dev = DEVICE_DT_GET(DT_CHOSEN(zephyr_flash_controller)), -}; - -static struct image_header hdr_firmware_loader = { 0 }; -#endif - -/** - * Validate hash of a primary boot image. - * - * @param[in] fa_p flash area pointer - * @param[in] hdr boot image header pointer - * - * @return FIH_SUCCESS on success, error code otherwise - */ -static fih_ret validate_image(const struct flash_area *fap, struct image_header *hdr) -{ - static uint8_t tmpbuf[BOOT_TMPBUF_SZ]; - FIH_DECLARE(fih_rc, FIH_FAILURE); - - FIH_CALL(bootutil_img_validate, fih_rc, NULL, hdr, fap, tmpbuf, BOOT_TMPBUF_SZ, NULL, 0, NULL); - FIH_RET(fih_rc); -} - -/** - * Gather information on image and prepare for booting. Will boot from main - * image if none of the enabled entrance modes for the firmware loader are set, - * otherwise will boot the firmware loader. Note: firmware loader must be a - * valid signed image with the same signing key as the application image. - * - * @param[out] rsp Parameters for booting image, on success - * - * @return FIH_SUCCESS on success; non-zero on failure. - */ -fih_ret -boot_go(struct boot_rsp *rsp) -{ - bool boot_firmware_loader = false; - FIH_DECLARE(fih_rc, FIH_FAILURE); - bool softdevice_area_valid = false; - bool firmware_loader_area_valid = false; - int rc; - bool app_installer_image_valid = false; - bool softdevice_image_valid = false; - bool firmware_loader_image_valid = false; - bool app_installer_is_installer_image = false; - - bm_installs_init(); - - if (bm_installs_is_valid()) { - off_t start_address = 0; - size_t image_size = 0; - - rc = bm_installs_get_image_data(BM_INSTALLS_IMAGE_INDEX_SOFTDEVICE, &start_address, - &image_size); - - if (!rc) { - fa_softdevice.fa_off = start_address; - fa_softdevice.fa_size = image_size; - - if (start_address < fa_app_installer.fa_off) { - /* Invalid start address for SoftDevice */ - goto invalid_softdevice; - } - - fa_app_installer.fa_size = start_address - fa_app_installer.fa_off; - - rc = boot_image_load_header(&fa_softdevice, &hdr_softdevice); - - if (!rc) { - softdevice_area_valid = true; - } - } - -invalid_softdevice: -#ifdef CONFIG_BOOT_FIRMWARE_LOADER - start_address = 0; - image_size = 0; - rc = bm_installs_get_image_data(BM_INSTALLS_IMAGE_INDEX_FIRMWARE_LOADER, &start_address, - &image_size); - - if (!rc) { - fa_firmware_loader.fa_off = start_address; - fa_firmware_loader.fa_size = image_size; - - if (start_address < fa_app_installer.fa_off) { - /* Invalid start address for firmware loader */ - goto invalid_firmware_loader; - } - - fa_app_installer.fa_size = start_address - fa_app_installer.fa_off; - - rc = boot_image_load_header(&fa_firmware_loader, &hdr_softdevice); - - if (!rc) { - firmware_loader_area_valid = true; - } - } -#endif - } - -invalid_firmware_loader: - rc = boot_image_load_header(&fa_app_installer, &hdr_app_installer); - - if (rc) { - BOOT_LOG_ERR("Failed loading application/installer image header: %d", rc); - } else { - FIH_CALL(validate_image, fih_rc, &fa_app_installer, &hdr_app_installer); - - if (FIH_EQ(fih_rc, FIH_SUCCESS)) { - struct image_tlv_iter it; - uint32_t off2; - uint16_t len2; - - app_installer_image_valid = true; - - if (hdr_app_installer.ih_protect_tlv_size > 0) { - rc = bootutil_tlv_iter_begin(&it, &hdr_app_installer, &fa_app_installer, - IMAGE_TLV_INSTALLER_IMAGE, true); - - if (rc == 0) { - rc = bootutil_tlv_iter_next(&it, &off2, &len2, NULL); - - if (rc == 0 && len2 == sizeof(app_installer_is_installer_image)) { - rc = LOAD_IMAGE_DATA(&hdr_app_installer, &fa_app_installer, off2, - &app_installer_is_installer_image, len2); - - if (rc != 0) { - app_installer_is_installer_image = false; - } - } - } - } - } - } - - if (softdevice_area_valid) { - fih_rc = FIH_FAILURE; - rc = boot_image_load_header(&fa_softdevice, &hdr_softdevice); - - if (rc) { - BOOT_LOG_ERR("Failed loading SoftDevice image header: %d", rc); - } else { - FIH_CALL(validate_image, fih_rc, &fa_softdevice, &hdr_softdevice); - - if (FIH_EQ(fih_rc, FIH_SUCCESS)) { - softdevice_image_valid = true; - } - } - } - -#ifdef CONFIG_BOOT_FIRMWARE_LOADER - if (firmware_loader_area_valid) { - fih_rc = FIH_FAILURE; - rc = boot_image_load_header(&fa_firmware_loader, &hdr_firmware_loader); - - if (rc) { - BOOT_LOG_ERR("Failed loading firmware loader image header: %d", rc); - } else { - FIH_CALL(validate_image, fih_rc, &fa_firmware_loader, &hdr_firmware_loader); - - if (FIH_EQ(fih_rc, FIH_SUCCESS)) { - firmware_loader_image_valid = true; - } - } - } -#endif - - BOOT_LOG_DBG("Application/installer partition offset: 0x%lx, size: 0x%x, type: %d", - fa_app_installer.fa_off, fa_app_installer.fa_size, - app_installer_is_installer_image); - BOOT_LOG_DBG("SoftDevice partition offset: 0x%lx, size: 0x%x", fa_softdevice.fa_off, - fa_softdevice.fa_size); -#ifdef CONFIG_BOOT_FIRMWARE_LOADER - BOOT_LOG_DBG("Firmware loader off: 0x%lx, size: 0x%x", fa_firmware_loader.fa_off, - fa_firmware_loader.fa_size); - BOOT_LOG_DBG("SoftDevice area valid: %d, Firmware loader area valid: %d, " - "Application/installer image valid: %d, SoftDevice image valid: %d, " - "Firmware loader image valid: %d", softdevice_area_valid, - firmware_loader_area_valid, app_installer_image_valid, softdevice_image_valid, - firmware_loader_image_valid); -#else - BOOT_LOG_DBG("SoftDevice area valid: %d, Application/installer image valid: %d, " - "SoftDevice image valid: %d", softdevice_area_valid, app_installer_image_valid, - softdevice_image_valid); -#endif - -#ifdef CONFIG_BOOT_FIRMWARE_LOADER_ENTRANCE_GPIO - if (io_detect_pin() && !io_boot_skip_serial_recovery()) { - BOOT_LOG_DBG("GPIO detected for firmware loader mode"); - boot_firmware_loader = true; - } -#endif - -#ifdef CONFIG_BOOT_FIRMWARE_LOADER_PIN_RESET - if (io_detect_pin_reset()) { - BOOT_LOG_DBG("Pin reset detected for firmware loader mode"); - boot_firmware_loader = true; - } -#endif - -#ifdef CONFIG_BOOT_FIRMWARE_LOADER_BOOT_MODE - if (io_detect_boot_mode()) { - BOOT_LOG_DBG("Boot mode detected for firmware loader mode"); - boot_firmware_loader = true; - } -#endif - - if (app_installer_image_valid == true && app_installer_is_installer_image == true) { - /* Installer image is present, this gets priority */ - BOOT_LOG_DBG("Booting installer"); - rsp->br_image_off = flash_area_get_off(&fa_app_installer); - rsp->br_hdr = &hdr_app_installer; - } else if (boot_firmware_loader == true && softdevice_image_valid == true && - firmware_loader_image_valid == true) { - /* Boot firmware loader */ - BOOT_LOG_INF("Booting firmware loader"); - rsp->br_image_off = flash_area_get_off(&fa_firmware_loader); - rsp->br_hdr = &hdr_firmware_loader; - } else if (app_installer_image_valid == true && softdevice_image_valid == true) { - /* Boot main application */ - BOOT_LOG_INF("Booting main application"); - rsp->br_image_off = flash_area_get_off(&fa_app_installer); - rsp->br_hdr = &hdr_app_installer; - } else if (app_installer_image_valid == false && softdevice_image_valid == true && - firmware_loader_image_valid == true) { - /* Boot firmware loader due to missing main image */ - BOOT_LOG_INF("Booting firmware loader due to missing application image"); - rsp->br_image_off = flash_area_get_off(&fa_firmware_loader); - rsp->br_hdr = &hdr_firmware_loader; - } else { - /* Cannot boot in this configuration */ - BOOT_LOG_ERR("Error: no bootable configuration found"); - return -1; - } - - rsp->br_flash_dev_id = flash_area_get_device_id(&fa_app_installer); - - return 0; -} diff --git a/boot/zephyr/io_bm.c b/boot/zephyr/io_bm.c deleted file mode 100644 index 3f65a5d0e..000000000 --- a/boot/zephyr/io_bm.c +++ /dev/null @@ -1,198 +0,0 @@ -/* - * Copyright (c) 2012-2014 Wind River Systems, Inc. - * Copyright (c) 2020 Arm Limited - * Copyright (c) 2021-2025 Nordic Semiconductor ASA - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include -#include -#include -#include -#include -#include -#include -#include - -#include "target.h" -#include "bootutil/bootutil_log.h" - -#include -#include - -#if defined(CONFIG_BOOT_SERIAL_PIN_RESET) || defined(CONFIG_BOOT_FIRMWARE_LOADER_PIN_RESET) -#include -#endif - -#if defined(CONFIG_BOOT_SERIAL_BOOT_MODE) || defined(CONFIG_BOOT_FIRMWARE_LOADER_BOOT_MODE) -#include -#endif - -/* Validate serial recovery configuration */ -#ifdef CONFIG_MCUBOOT_SERIAL -#if !defined(CONFIG_BOOT_SERIAL_ENTRANCE_GPIO) && \ - !defined(CONFIG_BOOT_SERIAL_WAIT_FOR_DFU) && \ - !defined(CONFIG_BOOT_SERIAL_BOOT_MODE) && \ - !defined(CONFIG_BOOT_SERIAL_NO_APPLICATION) && \ - !defined(CONFIG_BOOT_SERIAL_PIN_RESET) -#error "Serial recovery selected without an entrance mode set" -#endif -#endif - -/* Validate firmware loader configuration */ -#ifdef CONFIG_BOOT_FIRMWARE_LOADER -#if !defined(CONFIG_BOOT_FIRMWARE_LOADER_ENTRANCE_GPIO) && \ - !defined(CONFIG_BOOT_FIRMWARE_LOADER_BOOT_MODE) && \ - !defined(CONFIG_BOOT_FIRMWARE_LOADER_NO_APPLICATION) && \ - !defined(CONFIG_BOOT_FIRMWARE_LOADER_PIN_RESET) -#error "Firmware loader selected without an entrance mode set" -#endif -#endif - -BOOT_LOG_MODULE_DECLARE(mcuboot); - -#ifdef CONFIG_MCUBOOT_INDICATION_LED - -void io_led_init(void) -{ - nrf_gpio_cfg_output(BOARD_PIN_LED_0); - nrf_gpio_pin_write(BOARD_PIN_LED_0, BOARD_LED_ACTIVE_STATE); -} - -void io_led_set(int value) -{ - nrf_gpio_pin_write(BOARD_PIN_LED_0, (value == 0 ? !BOARD_LED_ACTIVE_STATE : BOARD_LED_ACTIVE_STATE)); -} -#endif /* CONFIG_MCUBOOT_INDICATION_LED */ - -#if defined(CONFIG_BOOT_SERIAL_ENTRANCE_GPIO) || defined(CONFIG_BOOT_USB_DFU_GPIO) || \ - defined(CONFIG_BOOT_FIRMWARE_LOADER_ENTRANCE_GPIO) - -#if defined(CONFIG_MCUBOOT_SERIAL) -#define BUTTON_0_DETECT_DELAY CONFIG_BOOT_SERIAL_DETECT_DELAY -#elif defined(CONFIG_BOOT_FIRMWARE_LOADER) -#define BUTTON_0_DETECT_DELAY CONFIG_BOOT_FIRMWARE_LOADER_DETECT_DELAY -#else -#define BUTTON_0_DETECT_DELAY CONFIG_BOOT_USB_DFU_DETECT_DELAY -#endif - -bool io_detect_pin(void) -{ - int rc; - bool pin_active; - - rc = bm_buttons_init( - &(struct bm_buttons_config){ - .pin_number = BOARD_PIN_BTN_0, - .active_state = BM_BUTTONS_ACTIVE_LOW, - .pull_config = BM_BUTTONS_PIN_PULLUP, - }, - 1, - BM_BUTTONS_DETECTION_DELAY_MIN_US); - if (rc) { - BOOT_LOG_ERR("Failed to initialize buttons: %d", rc); - return false; - } - - rc = bm_buttons_enable(); - if (rc) { - BOOT_LOG_ERR("Failed to enable button detection: %d", rc); - return false; - } - - pin_active = bm_buttons_is_pressed(BOARD_PIN_BTN_0); - - if (pin_active) { - if (BUTTON_0_DETECT_DELAY > 0) { -#ifdef CONFIG_MULTITHREADING - k_sleep(K_MSEC(50)); -#else - k_busy_wait(50000); -#endif - - /* Get the uptime for debounce purposes. */ - int64_t timestamp = k_uptime_get(); - - for(;;) { - pin_active = bm_buttons_is_pressed(BOARD_PIN_BTN_0); - - /* Get delta from when this started */ - uint32_t delta = k_uptime_get() - timestamp; - - /* If not pressed OR if pressed > debounce period, stop. */ - if (delta >= BUTTON_0_DETECT_DELAY || !pin_active) { - break; - } - - /* Delay 1 ms */ -#ifdef CONFIG_MULTITHREADING - k_sleep(K_MSEC(1)); -#else - k_busy_wait(1000); -#endif - } - } - } - - rc = bm_buttons_disable(); - - if (rc) { - BOOT_LOG_ERR("Failed to disable buttons: %d", rc); - } - - rc = bm_buttons_deinit(); - if (rc) { - BOOT_LOG_ERR("Failed to de-initialize buttons: %d", rc); - } - - return (bool)pin_active; -} -#endif - -#if defined(CONFIG_BOOT_SERIAL_PIN_RESET) || defined(CONFIG_BOOT_FIRMWARE_LOADER_PIN_RESET) -bool io_detect_pin_reset(void) -{ - uint32_t reset_cause; - int rc; - - rc = hwinfo_get_reset_cause(&reset_cause); - - if (rc == 0 && (reset_cause & RESET_PIN)) { - (void)hwinfo_clear_reset_cause(); - return true; - } - - return false; -} -#endif - -#if defined(CONFIG_BOOT_SERIAL_BOOT_MODE) || defined(CONFIG_BOOT_FIRMWARE_LOADER_BOOT_MODE) -bool io_detect_boot_mode(void) -{ - int32_t boot_mode; - - boot_mode = bootmode_check(BOOT_MODE_TYPE_BOOTLOADER); - - if (boot_mode == 1) { - /* Boot mode to stay in bootloader, clear status and enter serial - * recovery mode - */ - bootmode_clear(); - - return true; - } - - return false; -} -#endif From 69df65fba6372c3c187e1672d9b168c62bec640b Mon Sep 17 00:00:00 2001 From: Jukka Rissanen Date: Tue, 23 Sep 2025 13:04:30 +0300 Subject: [PATCH 211/420] Revert "[nrf noup] nrf_cleanup: nRF54h: fix missing peripheral cleanup" This reverts commit b6c992e20c51fd77c1761450aaae118fee3f097d. Signed-off-by: Jukka Rissanen --- boot/zephyr/nrf_cleanup.c | 23 +++-------------------- 1 file changed, 3 insertions(+), 20 deletions(-) diff --git a/boot/zephyr/nrf_cleanup.c b/boot/zephyr/nrf_cleanup.c index 39dfcbc41..f90a46af1 100644 --- a/boot/zephyr/nrf_cleanup.c +++ b/boot/zephyr/nrf_cleanup.c @@ -4,7 +4,7 @@ * SPDX-License-Identifier: LicenseRef-Nordic-5-Clause */ -#if defined(CONFIG_NRFX_CLOCK) +#if !defined(CONFIG_SOC_SERIES_NRF54HX) #include #endif #include @@ -13,9 +13,6 @@ #if defined(NRF_RTC0) || defined(NRF_RTC1) || defined(NRF_RTC2) #include #endif -#if defined(CONFIG_NRF_GRTC_TIMER) - #include -#endif #if defined(NRF_PPI) #include #endif @@ -51,13 +48,6 @@ static inline void nrf_cleanup_rtc(NRF_RTC_Type * rtc_reg) } #endif -#if defined(CONFIG_NRF_GRTC_TIMER) -static inline void nrf_cleanup_grtc(void) -{ - nrfx_grtc_uninit(); -} -#endif - #if defined(NRF_UARTE_CLEANUP) static NRF_UARTE_Type *nrf_uarte_to_clean[] = { #if defined(NRF_UARTE0) @@ -72,13 +62,10 @@ static NRF_UARTE_Type *nrf_uarte_to_clean[] = { #if defined(NRF_UARTE30) NRF_UARTE30, #endif -#if defined(NRF_UARTE136) - NRF_UARTE136, -#endif }; #endif -#if defined(CONFIG_NRFX_CLOCK) +#if !defined(CONFIG_SOC_SERIES_NRF54HX) static void nrf_cleanup_clock(void) { nrf_clock_int_disable(NRF_CLOCK, 0xFFFFFFFF); @@ -97,10 +84,6 @@ void nrf_cleanup_peripheral(void) nrf_cleanup_rtc(NRF_RTC2); #endif -#if defined(CONFIG_NRF_GRTC_TIMER) - nrf_cleanup_grtc(); -#endif - #if defined(NRF_UARTE_CLEANUP) for (int i = 0; i < sizeof(nrf_uarte_to_clean) / sizeof(nrf_uarte_to_clean[0]); ++i) { NRF_UARTE_Type *current = nrf_uarte_to_clean[i]; @@ -154,7 +137,7 @@ void nrf_cleanup_peripheral(void) nrf_dppi_channels_disable_all(NRF_DPPIC); #endif -#if defined(CONFIG_NRFX_CLOCK) +#if !defined(CONFIG_SOC_SERIES_NRF54HX) nrf_cleanup_clock(); #endif } From 8ba196611473352c61cadb18dbdf93440b73d092 Mon Sep 17 00:00:00 2001 From: Jukka Rissanen Date: Tue, 23 Sep 2025 13:04:30 +0300 Subject: [PATCH 212/420] Revert "[nrf noup] boot: zephyr: boards: nrf54lm20pdk" This reverts commit 1aa8af0eae8d67f21cdccd81588f37cebde536c8. Signed-off-by: Jukka Rissanen --- .../boards/nrf54lm20pdk_nrf54lm20a_cpuapp.conf | 16 ---------------- 1 file changed, 16 deletions(-) delete mode 100644 boot/zephyr/boards/nrf54lm20pdk_nrf54lm20a_cpuapp.conf diff --git a/boot/zephyr/boards/nrf54lm20pdk_nrf54lm20a_cpuapp.conf b/boot/zephyr/boards/nrf54lm20pdk_nrf54lm20a_cpuapp.conf deleted file mode 100644 index 4944f7b13..000000000 --- a/boot/zephyr/boards/nrf54lm20pdk_nrf54lm20a_cpuapp.conf +++ /dev/null @@ -1,16 +0,0 @@ -# Copyright (c) 2025 Nordic Semiconductor ASA -# -# SPDX-License-Identifier: Apache-2.0 -# -CONFIG_BOOT_MAX_IMG_SECTORS=256 - -# Ensure that the SPI NOR driver is disabled by default -CONFIG_SPI_NOR=n - -# TODO: below are not yet supported and need fixing -CONFIG_FPROTECT=n - -CONFIG_BOOT_WATCHDOG_FEED=n - -CONFIG_PSA_CRYPTO_DRIVER_CRACEN=n -CONFIG_PSA_CRYPTO_DRIVER_OBERON=y From 7633055af6c9d19f135fa5439e69d3ccfe147a35 Mon Sep 17 00:00:00 2001 From: Jukka Rissanen Date: Tue, 23 Sep 2025 13:04:30 +0300 Subject: [PATCH 213/420] Revert "[nrf noup] nrf_cleanup: nRF54l: disable cleanup on UARTE pins" This reverts commit 5f6e119a726d9f17b3f65139540db838f2286bde. Signed-off-by: Jukka Rissanen --- boot/zephyr/nrf_cleanup.c | 7 ------- 1 file changed, 7 deletions(-) diff --git a/boot/zephyr/nrf_cleanup.c b/boot/zephyr/nrf_cleanup.c index f90a46af1..1252334ca 100644 --- a/boot/zephyr/nrf_cleanup.c +++ b/boot/zephyr/nrf_cleanup.c @@ -97,12 +97,6 @@ void nrf_cleanup_peripheral(void) nrfy_uarte_event_clear(current, NRF_UARTE_EVENT_RXTO); nrfy_uarte_disable(current); -#ifndef CONFIG_SOC_SERIES_NRF54LX - /* Disconnect pins UARTE pins - * causes issues on nRF54l SoCs, - * could be enabled once fix to NCSDK-33039 will be implemented. - */ - uint32_t pin[4]; pin[0] = nrfy_uarte_tx_pin_get(current); @@ -117,7 +111,6 @@ void nrf_cleanup_peripheral(void) nrfy_gpio_cfg_default(pin[i]); } } -#endif #if defined(NRF_DPPIC) /* Clear all SUBSCRIBE configurations. */ From 814a7db4d2ab1d64aea50fecc50780f10b10a9e8 Mon Sep 17 00:00:00 2001 From: Jukka Rissanen Date: Tue, 23 Sep 2025 13:04:30 +0300 Subject: [PATCH 214/420] Revert "[nrf noup] boot/zephyr/Kconfig: fix MBEDTLS_CFG_FILE value" This reverts commit c6e2585f8e382a3bc6f1700d892d3636a3155af5. Signed-off-by: Jukka Rissanen --- boot/zephyr/Kconfig | 1 + 1 file changed, 1 insertion(+) diff --git a/boot/zephyr/Kconfig b/boot/zephyr/Kconfig index 1c71f33eb..5aee4f1eb 100644 --- a/boot/zephyr/Kconfig +++ b/boot/zephyr/Kconfig @@ -434,6 +434,7 @@ config MBEDTLS_CFG_FILE # is used, but the fact is that Mbed TLS' ASN1 parse module is used # also when TinyCrypt is used as crypto backend. default "mcuboot-mbedtls-cfg.h" if BOOT_USE_TINYCRYPT + default "config-tls-generic.h" if NRF_SECURITY && (MBEDTLS_BUILTIN || BOOT_USE_PSA_CRYPTO) default "mcuboot-mbedtls-cfg.h" if BOOT_USE_MBEDTLS && !MBEDTLS_BUILTIN config BOOT_HW_KEY From 74d2d08a9ca7778171a20b69d505d3d059475e19 Mon Sep 17 00:00:00 2001 From: Jukka Rissanen Date: Tue, 23 Sep 2025 13:04:30 +0300 Subject: [PATCH 215/420] Revert "[nrf noup] boot/zephyr/nrf_cleanup: cleanup uarte pins" This reverts commit fac7ac4990fe9f28348bfb3e0e52ac4bf51c757a. Signed-off-by: Jukka Rissanen --- boot/zephyr/nrf_cleanup.c | 16 ---------------- 1 file changed, 16 deletions(-) diff --git a/boot/zephyr/nrf_cleanup.c b/boot/zephyr/nrf_cleanup.c index 1252334ca..72c601db3 100644 --- a/boot/zephyr/nrf_cleanup.c +++ b/boot/zephyr/nrf_cleanup.c @@ -9,7 +9,6 @@ #endif #include #include -#include #if defined(NRF_RTC0) || defined(NRF_RTC1) || defined(NRF_RTC2) #include #endif @@ -97,21 +96,6 @@ void nrf_cleanup_peripheral(void) nrfy_uarte_event_clear(current, NRF_UARTE_EVENT_RXTO); nrfy_uarte_disable(current); - uint32_t pin[4]; - - pin[0] = nrfy_uarte_tx_pin_get(current); - pin[1] = nrfy_uarte_rx_pin_get(current); - pin[2] = nrfy_uarte_rts_pin_get(current); - pin[3] = nrfy_uarte_cts_pin_get(current); - - nrfy_uarte_pins_disconnect(current); - - for (int j = 0; j < 4; j++) { - if (pin[j] != NRF_UARTE_PSEL_DISCONNECTED) { - nrfy_gpio_cfg_default(pin[i]); - } - } - #if defined(NRF_DPPIC) /* Clear all SUBSCRIBE configurations. */ memset((uint8_t *)current + NRF_UARTE_SUBSCRIBE_CONF_OFFS, 0, From 700a74963bc9e3fbc88f9164999ba43b0a034cc2 Mon Sep 17 00:00:00 2001 From: Jukka Rissanen Date: Tue, 23 Sep 2025 13:04:30 +0300 Subject: [PATCH 216/420] Revert "[nrf noup] boot/zephyr: nrf54h20dk cleanup adaptations" This reverts commit 31766fcae89baee588d1ac49802ce5b1fd7b544d. Signed-off-by: Jukka Rissanen --- boot/zephyr/nrf_cleanup.c | 7 ------- 1 file changed, 7 deletions(-) diff --git a/boot/zephyr/nrf_cleanup.c b/boot/zephyr/nrf_cleanup.c index 72c601db3..051705ec9 100644 --- a/boot/zephyr/nrf_cleanup.c +++ b/boot/zephyr/nrf_cleanup.c @@ -4,9 +4,7 @@ * SPDX-License-Identifier: LicenseRef-Nordic-5-Clause */ -#if !defined(CONFIG_SOC_SERIES_NRF54HX) #include -#endif #include #include #if defined(NRF_RTC0) || defined(NRF_RTC1) || defined(NRF_RTC2) @@ -64,12 +62,10 @@ static NRF_UARTE_Type *nrf_uarte_to_clean[] = { }; #endif -#if !defined(CONFIG_SOC_SERIES_NRF54HX) static void nrf_cleanup_clock(void) { nrf_clock_int_disable(NRF_CLOCK, 0xFFFFFFFF); } -#endif void nrf_cleanup_peripheral(void) { @@ -113,10 +109,7 @@ void nrf_cleanup_peripheral(void) #if defined(NRF_DPPIC) nrf_dppi_channels_disable_all(NRF_DPPIC); #endif - -#if !defined(CONFIG_SOC_SERIES_NRF54HX) nrf_cleanup_clock(); -#endif } #if USE_PARTITION_MANAGER \ From b9aa02b31cbced1f646d5e7bd808c9864f4ddf4d Mon Sep 17 00:00:00 2001 From: Jukka Rissanen Date: Tue, 23 Sep 2025 13:04:30 +0300 Subject: [PATCH 217/420] Revert "[nrf noup] boot/zephyr: nrf54h20dk board support" This reverts commit c872f6ab7bd026fe779543f24ede6d2b343202f3. Signed-off-by: Jukka Rissanen --- boot/zephyr/boards/nrf54h20dk_nrf54h20_cpuapp_iron.conf | 3 --- 1 file changed, 3 deletions(-) diff --git a/boot/zephyr/boards/nrf54h20dk_nrf54h20_cpuapp_iron.conf b/boot/zephyr/boards/nrf54h20dk_nrf54h20_cpuapp_iron.conf index 31666d9fe..12c96ff0f 100644 --- a/boot/zephyr/boards/nrf54h20dk_nrf54h20_cpuapp_iron.conf +++ b/boot/zephyr/boards/nrf54h20dk_nrf54h20_cpuapp_iron.conf @@ -6,7 +6,4 @@ # Ensure that the SPI NOR driver is disabled by default CONFIG_SPI_NOR=n -# TODO: below are not yet supported and need fixing -CONFIG_FPROTECT=n - CONFIG_BOOT_WATCHDOG_FEED=n From 366e7de1a00448a9f8ca10efe56b1dd66fc40e9e Mon Sep 17 00:00:00 2001 From: Jukka Rissanen Date: Tue, 23 Sep 2025 13:04:30 +0300 Subject: [PATCH 218/420] Revert "[nrf noup] zephyr: Use mbedTLS specific C functions with RSA" This reverts commit 7f674d9817e30c458a33af49211a34f21bb023da. Signed-off-by: Jukka Rissanen --- boot/zephyr/Kconfig | 2 -- 1 file changed, 2 deletions(-) diff --git a/boot/zephyr/Kconfig b/boot/zephyr/Kconfig index 5aee4f1eb..3d729d663 100644 --- a/boot/zephyr/Kconfig +++ b/boot/zephyr/Kconfig @@ -261,8 +261,6 @@ config BOOT_SIGNATURE_TYPE_RSA select MBEDTLS_PKCS1_V15 if MBEDTLS_BUILTIN select MBEDTLS_PKCS1_V21 if MBEDTLS_BUILTIN select MBEDTLS_KEY_EXCHANGE_RSA_ENABLED if MBEDTLS_BUILTIN - select MBEDTLS_PLATFORM_NO_STD_FUNCTIONS if MBEDTLS_BUILTIN - select MBEDTLS_PLATFORM_SNPRINTF_ALT if MBEDTLS_BUILTIN select BOOT_ENCRYPTION_SUPPORT select BOOT_IMG_HASH_ALG_SHA256_ALLOW select BOOT_AES_MBEDTLS_DEPENDENCIES if MBEDTLS_BUILTIN && BOOT_ENCRYPT_IMAGE From 5688774cc53aefce774eef3bf21c37c00c1cd96f Mon Sep 17 00:00:00 2001 From: Jukka Rissanen Date: Tue, 23 Sep 2025 13:04:30 +0300 Subject: [PATCH 219/420] Revert "[nrf noup] zephyr: Fix path variables" This reverts commit 791dd599386c95e464c6958927fb98a88dd61e3e. Signed-off-by: Jukka Rissanen --- boot/zephyr/CMakeLists.txt | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/boot/zephyr/CMakeLists.txt b/boot/zephyr/CMakeLists.txt index e2c981aae..0bd0fb919 100644 --- a/boot/zephyr/CMakeLists.txt +++ b/boot/zephyr/CMakeLists.txt @@ -35,20 +35,21 @@ if(NOT CONFIG_MBEDTLS_BUILTIN AND NOT CONFIG_BOOT_KEY_IMPORT_BYPASS_ASN) set(MBEDTLS_ASN1_DIR "${MCUBOOT_DIR}/ext/mbedtls-asn1") assert_exists(MBEDTLS_ASN1_DIR) endif() -set(MCUBOOT_NRF_EXT_DIR "${MCUBOOT_DIR}/ext/nrf") +set(NRF_DIR "${MCUBOOT_DIR}/ext/nrf") if(CONFIG_BOOT_USE_NRF_CC310_BL) - if(NOT EXISTS ${ZEPHYR_NRFXLIB_MODULE_DIR}) - message(FATAL_ERROR " +set(NRFXLIB_DIR ${ZEPHYR_BASE}/../nrfxlib) +if(NOT EXISTS ${NRFXLIB_DIR}) + message(FATAL_ERROR " ------------------------------------------------------------------------ - No such file or directory: ${ZEPHYR_NRFXLIB_MODULE_DIR} + No such file or directory: ${NRFXLIB_DIR} The current configuration enables nRF CC310 crypto accelerator hardware with the `CONFIG_BOOT_USE_NRF_CC310_BL` option. Please follow `ext/nrf/README.md` guide to fix your setup or use tinycrypt instead of the HW accelerator. To use the tinycrypt set `CONFIG_BOOT_ECDSA_TINYCRYPT` to y. ------------------------------------------------------------------------") - endif() +endif() endif() zephyr_library_include_directories( @@ -217,8 +218,8 @@ if(CONFIG_BOOT_SIGNATURE_TYPE_ECDSA_P256 OR CONFIG_BOOT_ENCRYPT_EC256) ${TINYCRYPT_DIR}/source/utils.c ) elseif(CONFIG_BOOT_USE_NRF_CC310_BL) - zephyr_library_sources(${MCUBOOT_NRF_EXT_DIR}/cc310_glue.c) - zephyr_library_include_directories(${MCUBOOT_NRF_EXT_DIR}) + zephyr_library_sources(${NRF_DIR}/cc310_glue.c) + zephyr_library_include_directories(${NRF_DIR}) zephyr_link_libraries(nrfxlib_crypto) elseif(CONFIG_BOOT_USE_NRF_EXTERNAL_CRYPTO) zephyr_include_directories(${BL_CRYPTO_DIR}/../include) From 0d27007632340042793039257c0aaa2bd3634035 Mon Sep 17 00:00:00 2001 From: Jukka Rissanen Date: Tue, 23 Sep 2025 13:04:30 +0300 Subject: [PATCH 220/420] Revert "[nrf noup] zephyr: sdk-nrf specific overrides on PSA Kconfigs" This reverts commit f471000c9946cbd678b25ce9b63427550d525450. Signed-off-by: Jukka Rissanen --- boot/bootutil/zephyr/CMakeLists.txt | 2 +- boot/zephyr/Kconfig | 18 +++++++----------- 2 files changed, 8 insertions(+), 12 deletions(-) diff --git a/boot/bootutil/zephyr/CMakeLists.txt b/boot/bootutil/zephyr/CMakeLists.txt index 44f78f395..f6d37441c 100644 --- a/boot/bootutil/zephyr/CMakeLists.txt +++ b/boot/bootutil/zephyr/CMakeLists.txt @@ -40,7 +40,7 @@ if(CONFIG_BOOT_USE_PSA_CRYPTO) ) endif() -if(CONFIG_BOOT_USE_MBEDTLS OR CONFIG_BOOT_USE_PSA_CRYPTO AND NOT CONFIG_NRF_SECURITY) +if(CONFIG_BOOT_USE_MBEDTLS OR CONFIG_BOOT_USE_PSA_CRYPTO) zephyr_link_libraries(mbedTLS) endif() endif() diff --git a/boot/zephyr/Kconfig b/boot/zephyr/Kconfig index 3d729d663..e482d9fab 100644 --- a/boot/zephyr/Kconfig +++ b/boot/zephyr/Kconfig @@ -88,7 +88,8 @@ config BOOT_PSA_IMG_HASH_ALG_SHA512_DEPENDENCIES config BOOT_ED25519_PSA_DEPENDENCIES bool select PSA_WANT_ALG_PURE_EDDSA - select PSA_WANT_ECC_TWISTED_EDWARDS_255 + # Seems that upstream mbedTLS does not have TE + #select PSA_WANT_ECC_TWISTED_EDWARDS_255 select PSA_WANT_ECC_MONTGOMERY_255 select PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_IMPORT help @@ -118,7 +119,7 @@ endif # BOOT_ENCRYPT_IMAGE config BOOT_ECDSA_PSA_DEPENDENCIES bool select PSA_WANT_ALG_ECDSA - select PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_IMPORT if !PSA_CORE_LITE + select PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_IMPORT select PSA_WANT_ECC_SECP_R1_256 help Dependencies for ECDSA signature @@ -247,8 +248,7 @@ choice BOOT_SIGNATURE_TYPE config BOOT_SIGNATURE_TYPE_NONE bool "No signature; use only hash check" - select BOOT_USE_TINYCRYPT if !SOC_SERIES_NRF54LX - select BOOT_USE_PSA_CRYPTO if SOC_SERIES_NRF54LX + select BOOT_USE_TINYCRYPT select BOOT_IMG_HASH_ALG_SHA256_ALLOW config BOOT_SIGNATURE_TYPE_RSA @@ -280,7 +280,6 @@ config BOOT_SIGNATURE_TYPE_ECDSA_P256 if BOOT_SIGNATURE_TYPE_ECDSA_P256 choice BOOT_ECDSA_IMPLEMENTATION prompt "Ecdsa implementation" - default BOOT_ECDSA_PSA if NRF_SECURITY default BOOT_ECDSA_TINYCRYPT config BOOT_ECDSA_TINYCRYPT @@ -297,12 +296,11 @@ config BOOT_ECDSA_CC310 config BOOT_ECDSA_PSA bool "Use psa cryptoo" - depends on NRF_SECURITY select BOOT_USE_PSA_CRYPTO select PSA_CRYPTO_CLIENT select PSA_CRYPTO_C - select BOOT_IMG_HASH_ALG_SHA256_ALLOW if !PSA_CORE_LITE - select BOOT_IMG_HASH_ALG_SHA512_ALLOW if !PSA_CORE_LITE + select BOOT_IMG_HASH_ALG_SHA256_ALLOW + select BOOT_IMG_HASH_ALG_SHA512_ALLOW select BOOT_ECDSA_PSA_DEPENDENCIES endchoice # Ecdsa implementation @@ -334,7 +332,6 @@ config BOOT_SIGNATURE_TYPE_PURE choice BOOT_ED25519_IMPLEMENTATION prompt "Ecdsa implementation" - default BOOT_ED25519_PSA if NRF_SECURITY default BOOT_ED25519_TINYCRYPT config BOOT_ED25519_TINYCRYPT @@ -355,7 +352,7 @@ config BOOT_ED25519_MBEDTLS config BOOT_ED25519_PSA bool "Use PSA crypto" - depends on NRF_SECURITY + select MBEDTLS select BOOT_USE_PSA_CRYPTO select PSA_CRYPTO_CLIENT select PSA_CRYPTO_C @@ -432,7 +429,6 @@ config MBEDTLS_CFG_FILE # is used, but the fact is that Mbed TLS' ASN1 parse module is used # also when TinyCrypt is used as crypto backend. default "mcuboot-mbedtls-cfg.h" if BOOT_USE_TINYCRYPT - default "config-tls-generic.h" if NRF_SECURITY && (MBEDTLS_BUILTIN || BOOT_USE_PSA_CRYPTO) default "mcuboot-mbedtls-cfg.h" if BOOT_USE_MBEDTLS && !MBEDTLS_BUILTIN config BOOT_HW_KEY From 0f917c66603f21da5f5666e702741dd8d192dcf7 Mon Sep 17 00:00:00 2001 From: Jukka Rissanen Date: Tue, 23 Sep 2025 13:04:30 +0300 Subject: [PATCH 221/420] Revert "[nrf noup] partition_manager: Add support for internal flash netcore DFU" This reverts commit 1f1b7be6c9500a53f9e55fe30a6b22898d5d478f. Signed-off-by: Jukka Rissanen --- boot/zephyr/pm.yml | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/boot/zephyr/pm.yml b/boot/zephyr/pm.yml index eec62473c..ab8f6d1c3 100644 --- a/boot/zephyr/pm.yml +++ b/boot/zephyr/pm.yml @@ -78,17 +78,11 @@ mcuboot_pad: mcuboot_primary_1: region: ram_flash size: CONFIG_NRF53_RAM_FLASH_SIZE -#endif /* CONFIG_NRF53_MCUBOOT_PRIMARY_1_RAM_FLASH */ +#endif /* CONFIG_NRF53_MULTI_IMAGE_UPDATE */ #if (CONFIG_NRF53_MULTI_IMAGE_UPDATE) mcuboot_secondary_1: -#if defined(CONFIG_PM_EXTERNAL_FLASH_MCUBOOT_SECONDARY) region: external_flash -#else - placement: - align: {start: CONFIG_FPROTECT_BLOCK_SIZE} - after: mcuboot_secondary -#endif size: CONFIG_NRF53_RAM_FLASH_SIZE #endif /* CONFIG_NRF53_MULTI_IMAGE_UPDATE */ From 6620badf1b370feaa9656e171387ecc4c2a524ee Mon Sep 17 00:00:00 2001 From: Jukka Rissanen Date: Tue, 23 Sep 2025 13:04:30 +0300 Subject: [PATCH 222/420] Revert "[nrf noup] boot: zephyr: boards: Disabled NCS boot banner for thingy 53" This reverts commit fd3ccd378677d6cd27df57dcb774698fa5adbdd9. Signed-off-by: Jukka Rissanen --- boot/zephyr/boards/thingy53_nrf5340_cpuapp.conf | 1 - 1 file changed, 1 deletion(-) diff --git a/boot/zephyr/boards/thingy53_nrf5340_cpuapp.conf b/boot/zephyr/boards/thingy53_nrf5340_cpuapp.conf index bbef18460..d68509786 100644 --- a/boot/zephyr/boards/thingy53_nrf5340_cpuapp.conf +++ b/boot/zephyr/boards/thingy53_nrf5340_cpuapp.conf @@ -47,7 +47,6 @@ CONFIG_USB_CDC_ACM=y CONFIG_CBPRINTF_NANO=y CONFIG_TIMESLICING=n CONFIG_BOOT_BANNER=n -CONFIG_NCS_BOOT_BANNER=n CONFIG_CONSOLE=n CONFIG_CONSOLE_HANDLER=n CONFIG_UART_CONSOLE=n From 33af731c5bab2a1a24c5a961d9ac2e210f831fb0 Mon Sep 17 00:00:00 2001 From: Jukka Rissanen Date: Tue, 23 Sep 2025 13:04:30 +0300 Subject: [PATCH 223/420] Revert "[nrf noup] sysflash: Add missing _FLASH_0_ID definitions" This reverts commit 60dcc0d468fde468f36637a5603204a8ea972b9b. Signed-off-by: Jukka Rissanen --- boot/zephyr/include/sysflash/pm_sysflash.h | 8 -------- 1 file changed, 8 deletions(-) diff --git a/boot/zephyr/include/sysflash/pm_sysflash.h b/boot/zephyr/include/sysflash/pm_sysflash.h index 0cb16292f..42f25182e 100644 --- a/boot/zephyr/include/sysflash/pm_sysflash.h +++ b/boot/zephyr/include/sysflash/pm_sysflash.h @@ -84,12 +84,4 @@ static inline uint32_t __flash_area_ids_for_slot(int img, int slot) #endif /* CONFIG_SINGLE_APPLICATION_SLOT */ -#ifndef SOC_FLASH_0_ID -#define SOC_FLASH_0_ID 0 -#endif - -#ifndef SPI_FLASH_0_ID -#define SPI_FLASH_0_ID 1 -#endif - #endif /* __PM_SYSFLASH_H__ */ From e5e4f193d7f85db6eeedda93b4f2ec0b4f000ff1 Mon Sep 17 00:00:00 2001 From: Jukka Rissanen Date: Tue, 23 Sep 2025 13:04:30 +0300 Subject: [PATCH 224/420] Revert "[nrf noup] boot: Remove child/parent references" This reverts commit 9e2bba9806b33af0d52e1f62774de55a48d2538d. Signed-off-by: Jukka Rissanen --- boot/bootutil/src/swap_priv.h | 2 +- boot/zephyr/pm.yml | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/boot/bootutil/src/swap_priv.h b/boot/bootutil/src/swap_priv.h index 10473a9cc..90e0b3742 100644 --- a/boot/bootutil/src/swap_priv.h +++ b/boot/bootutil/src/swap_priv.h @@ -131,7 +131,7 @@ bool swap_write_block_size_check(struct boot_loader_state *state); int app_max_size(struct boot_loader_state *state); #if defined(PM_S1_ADDRESS) && !defined(MCUBOOT_OVERWRITE_ONLY) && \ -CONFIG_MCUBOOT_MCUBOOT_IMAGE_NUMBER != -1 +(CONFIG_MCUBOOT_MCUBOOT_IMAGE_NUMBER != -1 || defined(LEGACY_CHILD_PARENT_S0_S1_UPDATE_ENABLED)) /** * Performs an NSIB update */ diff --git a/boot/zephyr/pm.yml b/boot/zephyr/pm.yml index ab8f6d1c3..13ffc44aa 100644 --- a/boot/zephyr/pm.yml +++ b/boot/zephyr/pm.yml @@ -4,7 +4,9 @@ mcuboot: size: CONFIG_PM_PARTITION_SIZE_MCUBOOT placement: before: [mcuboot_primary] +#if defined(CONFIG_HIDE_CHILD_PARENT_CONFIG) align: {end: 0x1000} +#endif mcuboot_primary_app: # All images to be placed in MCUboot's slot 0 should be placed in this From bcf90565b7d70a96a006ddc9815449fa75791b22 Mon Sep 17 00:00:00 2001 From: Jukka Rissanen Date: Tue, 23 Sep 2025 13:04:30 +0300 Subject: [PATCH 225/420] Revert "[nrf noup] boot: zephyr: serial_recovery: Add nRF5340 Kconfig override" This reverts commit 2f3b28c09ebc156310732cc991d2c5995e62aed2. Signed-off-by: Jukka Rissanen --- boot/zephyr/Kconfig.serial_recovery | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/boot/zephyr/Kconfig.serial_recovery b/boot/zephyr/Kconfig.serial_recovery index 5b4ba3e11..45d252408 100644 --- a/boot/zephyr/Kconfig.serial_recovery +++ b/boot/zephyr/Kconfig.serial_recovery @@ -46,14 +46,9 @@ config BOOT_SERIAL_CDC_ACM endchoice -DT_COMPAT_SIM_FLASH:= zephyr,sim-flash -DT_SIM_FLASH_PATH := $(dt_nodelabel_path,flash_sim0) - config MCUBOOT_SERIAL_DIRECT_IMAGE_UPLOAD bool "Allow to select image number for DFU" - # Allow this option to be selected in cases where support for direct uploading to nRF5340 - # network core should be supported - depends on !SINGLE_APPLICATION_SLOT || (SINGLE_APPLICATION_SLOT && SOC_NRF5340_CPUAPP && BOOT_IMAGE_ACCESS_HOOK_NRF5340 && FLASH_SIMULATOR && $(dt_compat_enabled,$(DT_COMPAT_SIM_FLASH))) + depends on !SINGLE_APPLICATION_SLOT help With the option enabled, the mcuboot serial recovery will respect the "image" field in mcumgr image update frame From 426d53e0e44307a1221a683963644e29a6a1eca4 Mon Sep 17 00:00:00 2001 From: Jukka Rissanen Date: Tue, 23 Sep 2025 13:04:30 +0300 Subject: [PATCH 226/420] Revert "[nrf noup] boot/zephyr/Kconfig: conditionally disable BOOT_MAX_IMG_SECTORS_AUTO" This reverts commit a4457ac3dd0a734fb7ff2122fef2eadc3dc5b2ad. Signed-off-by: Jukka Rissanen --- boot/zephyr/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/boot/zephyr/Kconfig b/boot/zephyr/Kconfig index e482d9fab..89cda41bd 100644 --- a/boot/zephyr/Kconfig +++ b/boot/zephyr/Kconfig @@ -709,7 +709,7 @@ config BOOT_ENCRYPTION_KEY_FILE config BOOT_MAX_IMG_SECTORS_AUTO bool "Calculate maximum sectors automatically" - default y if !PARTITION_MANAGER_ENABLED + default y help If this option is enabled then the maximum number of supported sectors per image will be calculated automatically from the flash erase sizes and size of each partition for From 614b735ebd20cd5b57486cc373894a05e5b97793 Mon Sep 17 00:00:00 2001 From: Jukka Rissanen Date: Tue, 23 Sep 2025 13:04:30 +0300 Subject: [PATCH 227/420] Revert "[nrf noup] boot/zephyr: add nrf54l15dk ext flash configs" This reverts commit 835b63f3a179634b5c265aa1f39f4834b54bd9cc. Signed-off-by: Jukka Rissanen --- .../nrf54l15dk_nrf54l05_cpuapp.conf} | 2 + .../nrf54l15dk_nrf54l10_cpuapp.conf} | 2 + .../boards/nrf54l15dk_nrf54l15_cpuapp.conf | 16 +++++++ .../nrf54l15dk_nrf54l15_cpuapp_ext_flash.conf | 9 ---- ...f54l15dk_nrf54l15_cpuapp_ext_flash.overlay | 48 ------------------- boot/zephyr/prj.conf | 1 + boot/zephyr/socs/nrf54l15_cpuapp.conf | 14 ------ 7 files changed, 21 insertions(+), 71 deletions(-) rename boot/zephyr/{socs/nrf54l05_cpuapp.conf => boards/nrf54l15dk_nrf54l05_cpuapp.conf} (94%) rename boot/zephyr/{socs/nrf54l10_cpuapp.conf => boards/nrf54l15dk_nrf54l10_cpuapp.conf} (94%) create mode 100644 boot/zephyr/boards/nrf54l15dk_nrf54l15_cpuapp.conf delete mode 100644 boot/zephyr/boards/nrf54l15dk_nrf54l15_cpuapp_ext_flash.conf delete mode 100644 boot/zephyr/boards/nrf54l15dk_nrf54l15_cpuapp_ext_flash.overlay diff --git a/boot/zephyr/socs/nrf54l05_cpuapp.conf b/boot/zephyr/boards/nrf54l15dk_nrf54l05_cpuapp.conf similarity index 94% rename from boot/zephyr/socs/nrf54l05_cpuapp.conf rename to boot/zephyr/boards/nrf54l15dk_nrf54l05_cpuapp.conf index c8fcd32c3..f911aa248 100644 --- a/boot/zephyr/socs/nrf54l05_cpuapp.conf +++ b/boot/zephyr/boards/nrf54l15dk_nrf54l05_cpuapp.conf @@ -7,6 +7,8 @@ CONFIG_BOOT_MAX_IMG_SECTORS=256 # Ensure that the SPI NOR driver is disabled by default CONFIG_SPI_NOR=n +CONFIG_FPROTECT=y + CONFIG_BOOT_WATCHDOG_FEED=n # Ensure the fastest RRAM write operations diff --git a/boot/zephyr/socs/nrf54l10_cpuapp.conf b/boot/zephyr/boards/nrf54l15dk_nrf54l10_cpuapp.conf similarity index 94% rename from boot/zephyr/socs/nrf54l10_cpuapp.conf rename to boot/zephyr/boards/nrf54l15dk_nrf54l10_cpuapp.conf index c8fcd32c3..f911aa248 100644 --- a/boot/zephyr/socs/nrf54l10_cpuapp.conf +++ b/boot/zephyr/boards/nrf54l15dk_nrf54l10_cpuapp.conf @@ -7,6 +7,8 @@ CONFIG_BOOT_MAX_IMG_SECTORS=256 # Ensure that the SPI NOR driver is disabled by default CONFIG_SPI_NOR=n +CONFIG_FPROTECT=y + CONFIG_BOOT_WATCHDOG_FEED=n # Ensure the fastest RRAM write operations diff --git a/boot/zephyr/boards/nrf54l15dk_nrf54l15_cpuapp.conf b/boot/zephyr/boards/nrf54l15dk_nrf54l15_cpuapp.conf new file mode 100644 index 000000000..1dbd7c1ab --- /dev/null +++ b/boot/zephyr/boards/nrf54l15dk_nrf54l15_cpuapp.conf @@ -0,0 +1,16 @@ +# Copyright (c) 2024 Nordic Semiconductor ASA +# +# SPDX-License-Identifier: Apache-2.0 +# +CONFIG_BOOT_MAX_IMG_SECTORS=256 + +# Ensure that the SPI NOR driver is disabled by default +CONFIG_SPI_NOR=n + +# TODO: below are not yet supported and need fixing +CONFIG_FPROTECT=n + +CONFIG_BOOT_WATCHDOG_FEED=n + +# Ensure the fastest RRAM write operations +CONFIG_NRF_RRAM_WRITE_BUFFER_SIZE=32 diff --git a/boot/zephyr/boards/nrf54l15dk_nrf54l15_cpuapp_ext_flash.conf b/boot/zephyr/boards/nrf54l15dk_nrf54l15_cpuapp_ext_flash.conf deleted file mode 100644 index ec944f828..000000000 --- a/boot/zephyr/boards/nrf54l15dk_nrf54l15_cpuapp_ext_flash.conf +++ /dev/null @@ -1,9 +0,0 @@ -CONFIG_SPI=y -CONFIG_SPI_NOR=y -CONFIG_FLASH=y -CONFIG_PM_PARTITION_SIZE_MCUBOOT=0x14000 -CONFIG_MAIN_STACK_SIZE=20480 -CONFIG_BOOT_MAX_IMG_SECTORS=512 -CONFIG_SPI_NOR_FLASH_LAYOUT_PAGE_SIZE=4096 -# Ensure that the qspi driver is disabled by default -CONFIG_NORDIC_QSPI_NOR=n diff --git a/boot/zephyr/boards/nrf54l15dk_nrf54l15_cpuapp_ext_flash.overlay b/boot/zephyr/boards/nrf54l15dk_nrf54l15_cpuapp_ext_flash.overlay deleted file mode 100644 index ba6274221..000000000 --- a/boot/zephyr/boards/nrf54l15dk_nrf54l15_cpuapp_ext_flash.overlay +++ /dev/null @@ -1,48 +0,0 @@ -/ { - chosen { - nordic,pm-ext-flash = &mx25r64; - zephyr,code-partition = &boot_partition; - }; -}; - -/delete-node/ &boot_partition; -/delete-node/ &slot0_partition; -/delete-node/ &slot1_partition; - -/delete-node/ &storage_partition; - -&cpuapp_rram { - reg = < 0x0 DT_SIZE_K(1524) >; - - partitions { - boot_partition: partition@0 { - label = "mcuboot"; - reg = <0x000000000 0x00014000>; - }; - - slot0_partition: partition@14000 { - label = "image-0"; - reg = <0x000014000 0x0015A000>; - }; - - storage_partition: partition@16E000 { - label = "storage"; - reg = < 0x16E000 0x9000 >; - }; - }; -}; - -&mx25r64 { - status = "okay"; - - partitions { - compatible = "fixed-partitions"; - #address-cells = <1>; - #size-cells = <1>; - - slot1_partition: partition@0 { - label = "image-1"; - reg = <0x000000000 0x0015A000>; - }; - }; -}; diff --git a/boot/zephyr/prj.conf b/boot/zephyr/prj.conf index 119e07579..734e319fb 100644 --- a/boot/zephyr/prj.conf +++ b/boot/zephyr/prj.conf @@ -18,6 +18,7 @@ CONFIG_BOOT_BOOTSTRAP=n # CONFIG_TINYCRYPT_SHA256 is not set CONFIG_FLASH=y +CONFIG_FPROTECT=y ### Various Zephyr boards enable features that we don't want. # CONFIG_BT is not set diff --git a/boot/zephyr/socs/nrf54l15_cpuapp.conf b/boot/zephyr/socs/nrf54l15_cpuapp.conf index 645325513..8db9d2d23 100644 --- a/boot/zephyr/socs/nrf54l15_cpuapp.conf +++ b/boot/zephyr/socs/nrf54l15_cpuapp.conf @@ -1,17 +1,3 @@ -# Copyright (c) 2024 Nordic Semiconductor ASA -# -# SPDX-License-Identifier: Apache-2.0 -# -CONFIG_BOOT_MAX_IMG_SECTORS=256 - -# Ensure that the SPI NOR driver is disabled by default -CONFIG_SPI_NOR=n - -CONFIG_BOOT_WATCHDOG_FEED=n - -# Ensure the fastest RRAM write operations -CONFIG_NRF_RRAM_WRITE_BUFFER_SIZE=32 - # Link Time Optimizations CONFIG_ISR_TABLES_LOCAL_DECLARATION=y CONFIG_LTO=y From bea2cbc52c7cd4f8b8be04e05f11519091a235ca Mon Sep 17 00:00:00 2001 From: Jukka Rissanen Date: Tue, 23 Sep 2025 13:04:30 +0300 Subject: [PATCH 228/420] Revert "[nrf noup] workflows: Add a backport workflow" This reverts commit e40684941b5d29b21d9ae4d4afb56841b685f177. Signed-off-by: Jukka Rissanen --- .github/workflows/backport.yml | 31 ------------------------------- 1 file changed, 31 deletions(-) delete mode 100644 .github/workflows/backport.yml diff --git a/.github/workflows/backport.yml b/.github/workflows/backport.yml deleted file mode 100644 index e986738ff..000000000 --- a/.github/workflows/backport.yml +++ /dev/null @@ -1,31 +0,0 @@ -name: Backport -on: - pull_request_target: - types: - - closed - - labeled - branches: - - main - -jobs: - backport: - name: Backport - runs-on: ubuntu-22.04 - # Only react to merged PRs for security reasons. - # See https://docs.github.com/en/actions/using-workflows/events-that-trigger-workflows#pull_request_target. - if: > - github.event.pull_request.merged && - ( - github.event.action == 'closed' || - ( - github.event.action == 'labeled' && - contains(github.event.label.name, 'backport') - ) - ) - steps: - - name: Backport - uses: zephyrproject-rtos/action-backport@v2.0.3-3 - with: - github_token: ${{ secrets.NCS_GITHUB_TOKEN }} - issue_labels: Backport - labels_template: '["Backport"]' From 835ce6db53e5a982305cd9785f9ca409a98e0c2e Mon Sep 17 00:00:00 2001 From: Jukka Rissanen Date: Tue, 23 Sep 2025 13:04:30 +0300 Subject: [PATCH 229/420] Revert "[nrf noup] boards: Thingy:91 X release config" This reverts commit be6d73eca89a94e990f57eac4acd8a6c60858a84. Signed-off-by: Jukka Rissanen --- boot/zephyr/boards/thingy91x_nrf5340_cpuapp.conf | 3 --- boot/zephyr/boards/thingy91x_nrf9151.conf | 7 ++----- boot/zephyr/boards/thingy91x_nrf9151.overlay | 4 ---- 3 files changed, 2 insertions(+), 12 deletions(-) delete mode 100644 boot/zephyr/boards/thingy91x_nrf9151.overlay diff --git a/boot/zephyr/boards/thingy91x_nrf5340_cpuapp.conf b/boot/zephyr/boards/thingy91x_nrf5340_cpuapp.conf index d3e253b65..37c7e95b1 100644 --- a/boot/zephyr/boards/thingy91x_nrf5340_cpuapp.conf +++ b/boot/zephyr/boards/thingy91x_nrf5340_cpuapp.conf @@ -58,6 +58,3 @@ CONFIG_BOOT_SERIAL_IMG_GRP_IMAGE_STATE=y # Skip checks on the secondary image to make it possible to update MCUBoot on S1/S0 CONFIG_MCUBOOT_VERIFY_IMG_ADDRESS=n - -CONFIG_BOOT_SERIAL_NO_APPLICATION=y -CONFIG_FW_INFO_FIRMWARE_VERSION=2 diff --git a/boot/zephyr/boards/thingy91x_nrf9151.conf b/boot/zephyr/boards/thingy91x_nrf9151.conf index 8088686e0..2efe1e170 100644 --- a/boot/zephyr/boards/thingy91x_nrf9151.conf +++ b/boot/zephyr/boards/thingy91x_nrf9151.conf @@ -5,16 +5,13 @@ CONFIG_SPI=y CONFIG_SPI_NOR=y CONFIG_SPI_NOR_FLASH_LAYOUT_PAGE_SIZE=4096 CONFIG_SPI_NOR_SFDP_DEVICETREE=y +CONFIG_MULTITHREADING=y # Disable Zephyr console and use UART for MCUboot serial recovery instead CONFIG_CONSOLE=n CONFIG_CONSOLE_HANDLER=n CONFIG_UART_CONSOLE=n CONFIG_MCUBOOT_SERIAL=y + CONFIG_MCUBOOT_SERIAL_DIRECT_IMAGE_UPLOAD=y CONFIG_BOOT_SERIAL_IMG_GRP_IMAGE_STATE=y - -CONFIG_PM_EXTERNAL_FLASH_MCUBOOT_SECONDARY=y -CONFIG_PM_OVERRIDE_EXTERNAL_DRIVER_CHECK=y - -CONFIG_FW_INFO_FIRMWARE_VERSION=2 diff --git a/boot/zephyr/boards/thingy91x_nrf9151.overlay b/boot/zephyr/boards/thingy91x_nrf9151.overlay deleted file mode 100644 index 7f2818c0d..000000000 --- a/boot/zephyr/boards/thingy91x_nrf9151.overlay +++ /dev/null @@ -1,4 +0,0 @@ -&uart0 { - status = "okay"; - current-speed = < 1000000 >; -}; From 2285d579be3b09eaad05c46dbcc488fa2675eb35 Mon Sep 17 00:00:00 2001 From: Jukka Rissanen Date: Tue, 23 Sep 2025 13:04:30 +0300 Subject: [PATCH 230/420] Revert "[nrf noup] boot: bootutil: loader: Add s0/s1 checking of MCUboot image" This reverts commit d5f373adeb1c296c8d312ca8484f5f73414d7f48. Signed-off-by: Jukka Rissanen --- boot/bootutil/src/loader.c | 45 -------------------------------------- 1 file changed, 45 deletions(-) diff --git a/boot/bootutil/src/loader.c b/boot/bootutil/src/loader.c index dd4853874..a75d1a911 100644 --- a/boot/bootutil/src/loader.c +++ b/boot/bootutil/src/loader.c @@ -101,17 +101,6 @@ static struct sector_buffer_t sector_buffers; #endif #endif -#if CONFIG_MCUBOOT_MCUBOOT_IMAGE_NUMBER != -1 && defined(MCUBOOT_OVERWRITE_ONLY) && \ - defined(MCUBOOT_DOWNGRADE_PREVENTION) -/* s0/s1 package version of the current MCUboot image */ -static const struct image_version mcuboot_s0_s1_image_version = { - .iv_major = CONFIG_MCUBOOT_MCUBOOT_S0_S1_VERSION_MAJOR, - .iv_minor = CONFIG_MCUBOOT_MCUBOOT_S0_S1_VERSION_MINOR, - .iv_revision = CONFIG_MCUBOOT_MCUBOOT_S0_S1_VERSION_REVISION, - .iv_build_num = CONFIG_MCUBOOT_MCUBOOT_S0_S1_VERSION_BUILD_NUMBER, -}; -#endif - #if (BOOT_IMAGE_NUMBER > 1) #define IMAGES_ITER(x) for ((x) = 0; (x) < BOOT_IMAGE_NUMBER; ++(x)) #else @@ -1193,45 +1182,11 @@ boot_validate_slot(struct boot_loader_state *state, int slot, rc = boot_version_cmp( &boot_img_hdr(state, BOOT_SECONDARY_SLOT)->ih_ver, &boot_img_hdr(state, BOOT_PRIMARY_SLOT)->ih_ver); - -#if CONFIG_MCUBOOT_MCUBOOT_IMAGE_NUMBER != -1 - if (rc >= 0 && BOOT_CURR_IMG(state) == CONFIG_MCUBOOT_MCUBOOT_IMAGE_NUMBER) { - /* Also check the new version of MCUboot against that of the current s0/s1 MCUboot - * trailer version to prevent downgrades - */ - int version_check; - - version_check = boot_version_cmp(&boot_img_hdr(state, BOOT_SECONDARY_SLOT)->ih_ver, - &mcuboot_s0_s1_image_version); - - /* Only update rc if the currently running version is newer */ - if (version_check < rc) { - rc = version_check; - } - } -#endif } #else rc = boot_version_cmp( &boot_img_hdr(state, BOOT_SECONDARY_SLOT)->ih_ver, &boot_img_hdr(state, BOOT_PRIMARY_SLOT)->ih_ver); - -#if CONFIG_MCUBOOT_MCUBOOT_IMAGE_NUMBER != -1 - if (rc >= 0 && BOOT_CURR_IMG(state) == CONFIG_MCUBOOT_MCUBOOT_IMAGE_NUMBER) { - /* Also check the new version of MCUboot against that of the current s0/s1 MCUboot - * trailer version to prevent downgrades - */ - int version_check; - - version_check = boot_version_cmp(&boot_img_hdr(state, BOOT_SECONDARY_SLOT)->ih_ver, - &mcuboot_s0_s1_image_version); - - /* Only update rc if the currently running version is newer */ - if (version_check < rc) { - rc = version_check; - } - } -#endif #endif if (rc < 0 && boot_check_header_erased(state, BOOT_PRIMARY_SLOT)) { BOOT_LOG_ERR("insufficient version in secondary slot"); From 41a2f1bfaaf96b210df690b3a3a99a155301b00a Mon Sep 17 00:00:00 2001 From: Jukka Rissanen Date: Tue, 23 Sep 2025 13:04:30 +0300 Subject: [PATCH 231/420] Revert "[nrf noup] treewide: Add support for sysbuild assigned images" This reverts commit 352b2a4a9cdd531cb3a1401f100e7d82e7434958. Signed-off-by: Jukka Rissanen --- boot/bootutil/src/bootutil_misc.c | 12 -- boot/bootutil/src/loader.c | 181 ++++++++------------- boot/bootutil/src/swap_nsib.c | 70 -------- boot/bootutil/src/swap_priv.h | 8 - boot/zephyr/CMakeLists.txt | 6 - boot/zephyr/include/sysflash/pm_sysflash.h | 69 ++++---- 6 files changed, 105 insertions(+), 241 deletions(-) delete mode 100644 boot/bootutil/src/swap_nsib.c diff --git a/boot/bootutil/src/bootutil_misc.c b/boot/bootutil/src/bootutil_misc.c index a88ad0dad..17ed4c616 100644 --- a/boot/bootutil/src/bootutil_misc.c +++ b/boot/bootutil/src/bootutil_misc.c @@ -427,18 +427,6 @@ boot_write_enc_key(const struct flash_area *fap, uint8_t slot, uint32_t bootutil_max_image_size(struct boot_loader_state *state, const struct flash_area *fap) { -#if defined(CONFIG_MCUBOOT_MCUBOOT_IMAGE_NUMBER) && CONFIG_MCUBOOT_MCUBOOT_IMAGE_NUMBER != -1 - if (BOOT_CURR_IMG(state) == CONFIG_MCUBOOT_MCUBOOT_IMAGE_NUMBER) { - /* NSIB is a direct upgrade without any status or trailer, get the full size of the - * primary slot. - */ - const struct flash_area *fap_nsib = BOOT_IMG_AREA(state, 0); - assert(fap_nsib != NULL); - - return flash_area_get_size(fap_nsib); - } -#endif /* CONFIG_MCUBOOT_MCUBOOT_IMAGE_NUMBER != -1 */ - #if defined(MCUBOOT_SINGLE_APPLICATION_SLOT) || \ defined(MCUBOOT_FIRMWARE_LOADER) || \ defined(MCUBOOT_SINGLE_APPLICATION_SLOT_RAM_LOAD) diff --git a/boot/bootutil/src/loader.c b/boot/bootutil/src/loader.c index a75d1a911..dabb562c9 100644 --- a/boot/bootutil/src/loader.c +++ b/boot/bootutil/src/loader.c @@ -160,15 +160,15 @@ boot_read_image_headers(struct boot_loader_state *state, bool require_all, * * Failure to read any headers is a fatal error. */ -#if CONFIG_MCUBOOT_MCUBOOT_IMAGE_NUMBER != -1 +#ifdef PM_S1_ADDRESS /* Patch needed for NCS. The primary slot of the second image * (image 1) will not contain a valid image header until an upgrade * of mcuboot has happened (filling S1 with the new version). */ - if (BOOT_CURR_IMG(state) == CONFIG_MCUBOOT_MCUBOOT_IMAGE_NUMBER && i == 0) { + if (BOOT_CURR_IMG(state) == 1 && i == 0) { continue; } -#endif /* CONFIG_MCUBOOT_MCUBOOT_IMAGE_NUMBER != -1 */ +#endif /* PM_S1_ADDRESS */ if (i > 0 && !require_all) { return 0; } else { @@ -1176,7 +1176,7 @@ boot_validate_slot(struct boot_loader_state *state, int slot, #if defined(CONFIG_SOC_NRF5340_CPUAPP) && defined(CONFIG_NRF53_MULTI_IMAGE_UPDATE) \ && defined(CONFIG_PCD_APP) && defined(CONFIG_PCD_READ_NETCORE_APP_VERSION) - if (BOOT_CURR_IMG(state) == CONFIG_MCUBOOT_NETWORK_CORE_IMAGE_NUMBER) { + if (BOOT_CURR_IMG(state) == 1) { rc = pcd_version_cmp_net(fap, boot_img_hdr(state, BOOT_SECONDARY_SLOT)); } else { rc = boot_version_cmp( @@ -1247,54 +1247,35 @@ boot_validate_slot(struct boot_loader_state *state, int slot, struct image_header *secondary_hdr = boot_img_hdr(state, slot); uint32_t reset_value = 0; uint32_t reset_addr = secondary_hdr->ih_hdr_size + sizeof(reset_value); - uint32_t min_addr, max_addr; - bool check_addresses = false; if (flash_area_read(fap, reset_addr, &reset_value, sizeof(reset_value)) != 0) { fih_rc = FIH_NO_BOOTABLE_IMAGE; goto out; } + uint32_t min_addr, max_addr; + #ifdef PM_CPUNET_APP_ADDRESS /* The primary slot for the network core is emulated in RAM. * Its flash_area hasn't got relevant boundaries. * Therfore need to override its boundaries for the check. */ - if (BOOT_CURR_IMG(state) == CONFIG_MCUBOOT_NETWORK_CORE_IMAGE_NUMBER) { + if (BOOT_CURR_IMG(state) == 1) { min_addr = PM_CPUNET_APP_ADDRESS; max_addr = PM_CPUNET_APP_ADDRESS + PM_CPUNET_APP_SIZE; - check_addresses = true; - } else -#endif -#if CONFIG_MCUBOOT_MCUBOOT_IMAGE_NUMBER != -1 - if (BOOT_CURR_IMG(state) == CONFIG_MCUBOOT_MCUBOOT_IMAGE_NUMBER) { -#if (CONFIG_NCS_IS_VARIANT_IMAGE) +#ifdef PM_S1_ADDRESS + } else if (BOOT_CURR_IMG(state) == 0) { min_addr = PM_S0_ADDRESS; - max_addr = (PM_S0_ADDRESS + PM_S0_SIZE); -#else - min_addr = PM_S1_ADDRESS; - max_addr = (PM_S1_ADDRESS + PM_S1_SIZE); + max_addr = pri_fa->fa_off + pri_fa->fa_size; #endif - check_addresses = true; } else #endif - if (BOOT_CURR_IMG(state) == CONFIG_MCUBOOT_APPLICATION_IMAGE_NUMBER) { -#if CONFIG_MCUBOOT_MCUBOOT_IMAGE_NUMBER != -1 -#if (CONFIG_NCS_IS_VARIANT_IMAGE) - min_addr = MIN(pri_fa->fa_off, PM_S0_ADDRESS); - max_addr = MAX((pri_fa->fa_off + pri_fa->fa_size), (PM_S0_ADDRESS + PM_S0_SIZE)); -#else - min_addr = MIN(pri_fa->fa_off, PM_S1_ADDRESS); - max_addr = MAX((pri_fa->fa_off + pri_fa->fa_size), (PM_S1_ADDRESS + PM_S1_SIZE)); -#endif -#else + { min_addr = pri_fa->fa_off; max_addr = pri_fa->fa_off + pri_fa->fa_size; -#endif - check_addresses = true; } - if (check_addresses == true && (reset_value < min_addr || reset_value > max_addr)) { + if (reset_value < min_addr || reset_value> (max_addr)) { BOOT_LOG_ERR("Reset address of image in secondary slot is not in the primary slot"); BOOT_LOG_ERR("Erasing image from secondary slot"); @@ -1416,54 +1397,36 @@ boot_update_security_counter(struct boot_loader_state *state, int slot, int hdr_ #define SEC_SLOT_TOUCHED 1 #define SEC_SLOT_ASSIGNED 2 -static uint8_t sec_slot_assignment[MCUBOOT_IMAGE_NUMBER] = {0}; - -#if CONFIG_MCUBOOT_MCUBOOT_IMAGE_NUMBER != -1 -static inline void sec_slot_untouch(struct boot_loader_state *state) -{ - sec_slot_assignment[CONFIG_MCUBOOT_APPLICATION_IMAGE_NUMBER] = SEC_SLOT_VIRGIN; - sec_slot_assignment[CONFIG_MCUBOOT_MCUBOOT_IMAGE_NUMBER] = SEC_SLOT_VIRGIN; -} +#if (MCUBOOT_IMAGE_NUMBER == 2) && defined(PM_B0_ADDRESS) && \ + !defined(CONFIG_NRF53_MULTI_IMAGE_UPDATE) +/* This configuration is peculiar - the one physical secondary slot is + * mocking two logical secondary + */ +#define SEC_SLOT_PHYSICAL_CNT 1 #else -static inline void sec_slot_untouch(struct boot_loader_state *state) -{ -} +#define SEC_SLOT_PHYSICAL_CNT MCUBOOT_IMAGE_NUMBER #endif +static uint8_t sec_slot_assignmnet[SEC_SLOT_PHYSICAL_CNT] = {0}; + static inline void sec_slot_touch(struct boot_loader_state *state) { -#if CONFIG_MCUBOOT_MCUBOOT_IMAGE_NUMBER != -1 - if (BOOT_CURR_IMG(state) == CONFIG_MCUBOOT_MCUBOOT_IMAGE_NUMBER) { - if (sec_slot_assignment[CONFIG_MCUBOOT_APPLICATION_IMAGE_NUMBER] == SEC_SLOT_VIRGIN) { - sec_slot_assignment[CONFIG_MCUBOOT_APPLICATION_IMAGE_NUMBER] = SEC_SLOT_TOUCHED; - } - } else if (BOOT_CURR_IMG(state) == CONFIG_MCUBOOT_APPLICATION_IMAGE_NUMBER) { - if (sec_slot_assignment[CONFIG_MCUBOOT_MCUBOOT_IMAGE_NUMBER] == SEC_SLOT_VIRGIN) { - sec_slot_assignment[CONFIG_MCUBOOT_MCUBOOT_IMAGE_NUMBER] = SEC_SLOT_TOUCHED; - } - } -#endif + uint8_t idx = (SEC_SLOT_PHYSICAL_CNT == 1) ? 0 : BOOT_CURR_IMG(state); - if (sec_slot_assignment[BOOT_CURR_IMG(state)] == SEC_SLOT_VIRGIN) { - sec_slot_assignment[BOOT_CURR_IMG(state)] = SEC_SLOT_TOUCHED; + if (SEC_SLOT_VIRGIN == sec_slot_assignmnet[idx]) { + sec_slot_assignmnet[idx] = SEC_SLOT_TOUCHED; } } static inline void sec_slot_mark_assigned(struct boot_loader_state *state) { -#if CONFIG_MCUBOOT_MCUBOOT_IMAGE_NUMBER != -1 - if (BOOT_CURR_IMG(state) == CONFIG_MCUBOOT_MCUBOOT_IMAGE_NUMBER) { - sec_slot_assignment[CONFIG_MCUBOOT_APPLICATION_IMAGE_NUMBER] = SEC_SLOT_ASSIGNED; - } else if (BOOT_CURR_IMG(state) == CONFIG_MCUBOOT_APPLICATION_IMAGE_NUMBER) { - sec_slot_assignment[CONFIG_MCUBOOT_MCUBOOT_IMAGE_NUMBER] = SEC_SLOT_ASSIGNED; - } -#endif + uint8_t idx = (SEC_SLOT_PHYSICAL_CNT == 1) ? 0 : BOOT_CURR_IMG(state); - sec_slot_assignment[BOOT_CURR_IMG(state)] = SEC_SLOT_ASSIGNED; + sec_slot_assignmnet[idx] = SEC_SLOT_ASSIGNED; } /** - * Cleanup up all secondary slot which couldn't be assigned to any primary slot. + * Cleanu up all secondary slot which couldn't be assigned to any primary slot. * * This function erases content of each secondary slot which contains valid * header but couldn't be assigned to any of supported primary images. @@ -1475,8 +1438,8 @@ static void sec_slot_cleanup_if_unusable(void) { uint8_t idx; - for (idx = 0; idx < MCUBOOT_IMAGE_NUMBER; idx++) { - if (SEC_SLOT_TOUCHED == sec_slot_assignment[idx]) { + for (idx = 0; idx < SEC_SLOT_PHYSICAL_CNT; idx++) { + if (SEC_SLOT_TOUCHED == sec_slot_assignmnet[idx]) { const struct flash_area *secondary_fa; int rc; @@ -1485,20 +1448,17 @@ static void sec_slot_cleanup_if_unusable(void) if (!rc) { rc = flash_area_erase(secondary_fa, 0, secondary_fa->fa_size); if (!rc) { - BOOT_LOG_ERR("Cleaned-up secondary slot of image %d", idx); + BOOT_LOG_ERR("Cleaned-up secondary slot of %d. image.", idx); } } if (rc) { - BOOT_LOG_ERR("Failed to clean-up secondary slot of image %d: %d", idx, rc); + BOOT_LOG_ERR("Can not cleanup secondary slot of %d. image.", idx); } } } } #else -static inline void sec_slot_untouch(struct boot_loader_state *state) -{ -} static inline void sec_slot_touch(struct boot_loader_state *state) { } @@ -1530,7 +1490,7 @@ boot_validated_swap_type(struct boot_loader_state *state, owner_nsib[BOOT_CURR_IMG(state)] = false; #endif -#if defined(PM_S1_ADDRESS) || defined(PM_CPUNET_B0N_ADDRESS) +#if defined(PM_S1_ADDRESS) || defined(CONFIG_SOC_NRF5340_CPUAPP) const struct flash_area *secondary_fa = BOOT_IMG_AREA(state, BOOT_SECONDARY_SLOT); struct image_header *hdr = boot_img_hdr(state, BOOT_SECONDARY_SLOT); @@ -1568,31 +1528,31 @@ boot_validated_swap_type(struct boot_loader_state *state, } /* Check start and end of primary slot for current image */ -#if (CONFIG_NCS_IS_VARIANT_IMAGE) - if (reset_addr >= PM_S0_ADDRESS && reset_addr <= (PM_S0_ADDRESS + PM_S0_SIZE)) { -#else - if (reset_addr >= PM_S1_ADDRESS && reset_addr <= (PM_S1_ADDRESS + PM_S1_SIZE)) { -#endif - if (BOOT_CURR_IMG(state) == CONFIG_MCUBOOT_APPLICATION_IMAGE_NUMBER) { - /* This is not the s0/s1 upgrade image but the application image, pretend - * there is no image so the NSIB update can be loaded - */ - return BOOT_SWAP_TYPE_NONE; - } + if (reset_addr < primary_fa->fa_off) { +#if defined(CONFIG_SOC_NRF5340_CPUAPP) && defined(CONFIG_NRF53_MULTI_IMAGE_UPDATE) + const struct flash_area *nsib_fa; - owner_nsib[BOOT_CURR_IMG(state)] = true; -#if (CONFIG_NCS_IS_VARIANT_IMAGE) - } else if (reset_addr >= PM_S1_ADDRESS && reset_addr <= (PM_S1_ADDRESS + PM_S1_SIZE)) { + /* NSIB upgrade slot */ + rc = flash_area_open((uint32_t)_image_1_primary_slot_id, + &nsib_fa); + + if (rc != 0) { + return BOOT_SWAP_TYPE_FAIL; + } + + /* Image is placed before Primary and within the NSIB slot */ + if (reset_addr > nsib_fa->fa_off + && reset_addr < (nsib_fa->fa_off + nsib_fa->fa_size)) { + /* Set primary to be NSIB upgrade slot */ + BOOT_IMG_AREA(state, 0) = nsib_fa; + owner_nsib[BOOT_CURR_IMG(state)] = true; + } #else - } else if (reset_addr >= PM_S0_ADDRESS && reset_addr <= (PM_S0_ADDRESS + PM_S0_SIZE)) { + return BOOT_SWAP_TYPE_NONE; + #endif - /* NSIB upgrade but for the wrong slot, must be erased */ - BOOT_LOG_ERR("Image in slot is for wrong s0/s1 image"); - flash_area_erase(secondary_fa, 0, secondary_fa->fa_size); - sec_slot_untouch(state); - BOOT_LOG_ERR("Cleaned-up secondary slot of image %d", BOOT_CURR_IMG(state)); - return BOOT_SWAP_TYPE_FAIL; - } else if (reset_addr < primary_fa->fa_off || reset_addr > (primary_fa->fa_off + primary_fa->fa_size)) { + + } else if (reset_addr > (primary_fa->fa_off + primary_fa->fa_size)) { /* The image in the secondary slot is not intended for any */ return BOOT_SWAP_TYPE_NONE; } @@ -1605,7 +1565,7 @@ boot_validated_swap_type(struct boot_loader_state *state, sec_slot_mark_assigned(state); } -#endif /* PM_S1_ADDRESS || PM_CPUNET_B0N_ADDRESS */ +#endif /* PM_S1_ADDRESS || CONFIG_SOC_NRF5340_CPUAPP */ swap_type = boot_swap_type_multi(BOOT_CURR_IMG(state)); if (BOOT_IS_UPGRADE(swap_type)) { @@ -2277,22 +2237,7 @@ boot_swap_image(struct boot_loader_state *state, struct boot_status *bs) flash_area_close(fap); } -#if defined(PM_S1_ADDRESS) && CONFIG_MCUBOOT_MCUBOOT_IMAGE_NUMBER != -1 - if (owner_nsib[BOOT_CURR_IMG(state)]) { - if (BOOT_CURR_IMG(state) == CONFIG_MCUBOOT_MCUBOOT_IMAGE_NUMBER) { - /* For NSIB, move the image instead of swapping it */ - nsib_swap_run(state, bs); - -#if defined(CONFIG_REBOOT) - /* Should also reboot at this point so the new S0/S1 update is applied */ - sys_reboot(SYS_REBOOT_COLD); -#endif - } - } else -#endif - { - swap_run(state, bs, copy_size); - } + swap_run(state, bs, copy_size); #ifdef MCUBOOT_VALIDATE_PRIMARY_SLOT extern int boot_status_fails; @@ -2986,6 +2931,12 @@ context_boot_go(struct boot_loader_state *state, struct boot_rsp *rsp) rc = boot_perform_update(state, &bs); } assert(rc == 0); +#if defined(PM_S1_ADDRESS) && defined(CONFIG_REBOOT) + if (owner_nsib[BOOT_CURR_IMG(state)]) { + sys_reboot(SYS_REBOOT_COLD); + + } +#endif break; case BOOT_SWAP_TYPE_FAIL: @@ -3053,17 +3004,13 @@ context_boot_go(struct boot_loader_state *state, struct boot_rsp *rsp) */ } +#ifdef MCUBOOT_VALIDATE_PRIMARY_SLOT #ifdef PM_S1_ADDRESS /* Patch needed for NCS. Image 1 primary is the currently * executing MCUBoot image, and is therefore already validated by NSIB and * does not need to also be validated by MCUBoot. */ - bool image_validated_by_nsib = BOOT_CURR_IMG(state) == - CONFIG_MCUBOOT_MCUBOOT_IMAGE_NUMBER; -#endif - -#ifdef MCUBOOT_VALIDATE_PRIMARY_SLOT -#ifdef PM_S1_ADDRESS + bool image_validated_by_nsib = BOOT_CURR_IMG(state) == 1; if (!image_validated_by_nsib) #endif { diff --git a/boot/bootutil/src/swap_nsib.c b/boot/bootutil/src/swap_nsib.c deleted file mode 100644 index 079e193d5..000000000 --- a/boot/bootutil/src/swap_nsib.c +++ /dev/null @@ -1,70 +0,0 @@ -/* - * SPDX-License-Identifier: Apache-2.0 - * - * Copyright (c) 2024 Nordic Semiconductor ASA - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include -#include -#include -#include -#include -#include "bootutil/bootutil.h" -#include "bootutil_priv.h" -#include "swap_priv.h" -#include "bootutil/bootutil_log.h" - -#include "mcuboot_config/mcuboot_config.h" - -BOOT_LOG_MODULE_DECLARE(mcuboot); - -void nsib_swap_run(struct boot_loader_state *state, struct boot_status *bs) -{ - uint32_t sector_sz; - uint8_t image_index; - const struct flash_area *fap_pri; - const struct flash_area *fap_sec; - int rc; - - BOOT_LOG_INF("Starting swap using nsib algorithm."); - - sector_sz = boot_img_sector_size(state, BOOT_SECONDARY_SLOT, 0); - -#if (CONFIG_NCS_IS_VARIANT_IMAGE) - rc = flash_area_open(PM_S0_ID, &fap_pri); -#else - rc = flash_area_open(PM_S1_ID, &fap_pri); -#endif - assert (rc == 0); - image_index = BOOT_CURR_IMG(state); - - rc = flash_area_open(FLASH_AREA_IMAGE_SECONDARY(image_index), &fap_sec); - assert (rc == 0); - - rc = boot_erase_region(fap_pri, 0, fap_pri->fa_size, false); - assert(rc == 0); - - rc = boot_copy_region(state, fap_sec, fap_pri, 0, 0, fap_pri->fa_size); - assert(rc == 0); - - rc = swap_scramble_trailer_sectors(state, fap_sec); - assert(rc == 0); - - rc = boot_scramble_region(fap_sec, 0, MIN((fap_pri->fa_size + sector_sz), fap_sec->fa_size), false); - assert(rc == 0); - - flash_area_close(fap_pri); - flash_area_close(fap_sec); -} diff --git a/boot/bootutil/src/swap_priv.h b/boot/bootutil/src/swap_priv.h index 90e0b3742..b564ea99e 100644 --- a/boot/bootutil/src/swap_priv.h +++ b/boot/bootutil/src/swap_priv.h @@ -130,12 +130,4 @@ bool swap_write_block_size_check(struct boot_loader_state *state); */ int app_max_size(struct boot_loader_state *state); -#if defined(PM_S1_ADDRESS) && !defined(MCUBOOT_OVERWRITE_ONLY) && \ -(CONFIG_MCUBOOT_MCUBOOT_IMAGE_NUMBER != -1 || defined(LEGACY_CHILD_PARENT_S0_S1_UPDATE_ENABLED)) -/** - * Performs an NSIB update - */ -void nsib_swap_run(struct boot_loader_state *state, struct boot_status *bs); -#endif - #endif /* H_SWAP_PRIV_ */ diff --git a/boot/zephyr/CMakeLists.txt b/boot/zephyr/CMakeLists.txt index 0bd0fb919..1db4ed270 100644 --- a/boot/zephyr/CMakeLists.txt +++ b/boot/zephyr/CMakeLists.txt @@ -181,12 +181,6 @@ else() ) endif() endif() - - if(NOT CONFIG_MCUBOOT_MCUBOOT_IMAGE_NUMBER EQUAL "-1" AND NOT CONFIG_BOOT_UPGRADE_ONLY) - zephyr_library_sources( - ${BOOT_DIR}/bootutil/src/swap_nsib.c - ) - endif() endif() if(CONFIG_BOOT_SIGNATURE_TYPE_ECDSA_P256 OR CONFIG_BOOT_ENCRYPT_EC256) diff --git a/boot/zephyr/include/sysflash/pm_sysflash.h b/boot/zephyr/include/sysflash/pm_sysflash.h index 42f25182e..db60ddd03 100644 --- a/boot/zephyr/include/sysflash/pm_sysflash.h +++ b/boot/zephyr/include/sysflash/pm_sysflash.h @@ -15,36 +15,48 @@ #ifndef CONFIG_SINGLE_APPLICATION_SLOT +#if (MCUBOOT_IMAGE_NUMBER == 2) && defined(PM_B0_ADDRESS) +/* If B0 is present then two bootloaders are present, and we must use + * a single secondary slot for both primary slots. + */ +extern uint32_t _image_1_primary_slot_id[]; +#endif /* (MCUBOOT_IMAGE_NUMBER == 2 && defined(PM_B0_ADDRESS) */ + +#if (MCUBOOT_IMAGE_NUMBER == 2) && defined(PM_B0_ADDRESS) && \ + !defined(CONFIG_NRF53_MULTI_IMAGE_UPDATE) + +#define FLASH_AREA_IMAGE_PRIMARY(x) \ + ((x == 0) ? \ + PM_MCUBOOT_PRIMARY_ID : \ + (x == 1) ? \ + (uint32_t)_image_1_primary_slot_id : \ + 255 ) + +#define FLASH_AREA_IMAGE_SECONDARY(x) \ + ((x == 0) ? \ + PM_MCUBOOT_SECONDARY_ID: \ + (x == 1) ? \ + PM_MCUBOOT_SECONDARY_ID: \ + 255 ) + +#else /* MCUBOOT_IMAGE_NUMBER == 2) && defined(PM_B0_ADDRESS) && \ + * !defined(CONFIG_NRF53_MULTI_IMAGE_UPDATE) + */ + /* Each pair of slots is separated by , and there is no terminating character */ -#define FLASH_AREA_IMAGE_0_SLOTS PM_MCUBOOT_PRIMARY_ID, PM_MCUBOOT_SECONDARY_ID, -#define FLASH_AREA_IMAGE_1_SLOTS PM_MCUBOOT_PRIMARY_1_ID, PM_MCUBOOT_SECONDARY_1_ID, -#define FLASH_AREA_IMAGE_2_SLOTS PM_MCUBOOT_PRIMARY_2_ID, PM_MCUBOOT_SECONDARY_2_ID, -#define FLASH_AREA_IMAGE_3_SLOTS PM_MCUBOOT_PRIMARY_3_ID, PM_MCUBOOT_SECONDARY_3_ID, - -#if CONFIG_MCUBOOT_MCUBOOT_IMAGE_NUMBER != -1 -#ifdef CONFIG_NCS_IS_VARIANT_IMAGE -#define MCUBOOT_S0_S1_SLOTS PM_S0_ID, PM_MCUBOOT_SECONDARY_ID, -#else -#define MCUBOOT_S0_S1_SLOTS PM_S1_ID, PM_MCUBOOT_SECONDARY_ID, -#endif -#else -#define MCUBOOT_S0_S1_SLOTS -#endif +#define FLASH_AREA_IMAGE_0_SLOTS PM_MCUBOOT_PRIMARY_ID, PM_MCUBOOT_SECONDARY_ID +#define FLASH_AREA_IMAGE_1_SLOTS PM_MCUBOOT_PRIMARY_1_ID, PM_MCUBOOT_SECONDARY_1_ID +#define FLASH_AREA_IMAGE_2_SLOTS PM_MCUBOOT_PRIMARY_2_ID, PM_MCUBOOT_SECONDARY_2_ID -#if (MCUBOOT_IMAGE_NUMBER == 1) || (MCUBOOT_IMAGE_NUMBER == 2 && CONFIG_MCUBOOT_MCUBOOT_IMAGE_NUMBER != -1) +#if (MCUBOOT_IMAGE_NUMBER == 1) #define ALL_AVAILABLE_SLOTS FLASH_AREA_IMAGE_0_SLOTS -#elif (MCUBOOT_IMAGE_NUMBER == 2) || (MCUBOOT_IMAGE_NUMBER == 3 && CONFIG_MCUBOOT_MCUBOOT_IMAGE_NUMBER != -1) -#define ALL_AVAILABLE_SLOTS FLASH_AREA_IMAGE_0_SLOTS \ +#elif (MCUBOOT_IMAGE_NUMBER == 2) +#define ALL_AVAILABLE_SLOTS FLASH_AREA_IMAGE_0_SLOTS, \ FLASH_AREA_IMAGE_1_SLOTS -#elif (MCUBOOT_IMAGE_NUMBER == 3) || (MCUBOOT_IMAGE_NUMBER == 4 && CONFIG_MCUBOOT_MCUBOOT_IMAGE_NUMBER != -1) -#define ALL_AVAILABLE_SLOTS FLASH_AREA_IMAGE_0_SLOTS \ - FLASH_AREA_IMAGE_1_SLOTS \ +#elif (MCUBOOT_IMAGE_NUMBER == 3) +#define ALL_AVAILABLE_SLOTS FLASH_AREA_IMAGE_0_SLOTS, \ + FLASH_AREA_IMAGE_1_SLOTS, \ FLASH_AREA_IMAGE_2_SLOTS -#elif (MCUBOOT_IMAGE_NUMBER == 4) -#define ALL_AVAILABLE_SLOTS FLASH_AREA_IMAGE_0_SLOTS \ - FLASH_AREA_IMAGE_1_SLOTS \ - FLASH_AREA_IMAGE_2_SLOTS \ - FLASH_AREA_IMAGE_3_SLOTS #else #error Unsupported number of images #endif @@ -53,7 +65,6 @@ static inline uint32_t __flash_area_ids_for_slot(int img, int slot) { static const int all_slots[] = { ALL_AVAILABLE_SLOTS - MCUBOOT_S0_S1_SLOTS }; return all_slots[img * 2 + slot]; }; @@ -61,8 +72,6 @@ static inline uint32_t __flash_area_ids_for_slot(int img, int slot) #undef FLASH_AREA_IMAGE_0_SLOTS #undef FLASH_AREA_IMAGE_1_SLOTS #undef FLASH_AREA_IMAGE_2_SLOTS -#undef FLASH_AREA_IMAGE_3_SLOTS -#undef MCUBOOT_S0_S1_SLOTS #undef ALL_AVAILABLE_SLOTS #define FLASH_AREA_IMAGE_PRIMARY(x) __flash_area_ids_for_slot(x, 0) @@ -72,6 +81,10 @@ static inline uint32_t __flash_area_ids_for_slot(int img, int slot) #define FLASH_AREA_IMAGE_SCRATCH PM_MCUBOOT_SCRATCH_ID #endif +#endif /* MCUBOOT_IMAGE_NUMBER == 2) && defined(PM_B0_ADDRESS) && \ + * !defined(CONFIG_NRF53_MULTI_IMAGE_UPDATE) + */ + #else /* CONFIG_SINGLE_APPLICATION_SLOT */ #define FLASH_AREA_IMAGE_PRIMARY(x) PM_MCUBOOT_PRIMARY_ID From 57d5581127f3ea57ee2fdd857e36216aa6403b78 Mon Sep 17 00:00:00 2001 From: Jukka Rissanen Date: Tue, 23 Sep 2025 13:04:30 +0300 Subject: [PATCH 232/420] Revert "[nrf noup] boot: zephyr: Do not lock PCD region with TF-M" This reverts commit 599a1b9b55e61e17e1f9f95e1d8b136d0d5a3751. Signed-off-by: Jukka Rissanen --- boot/zephyr/main.c | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/boot/zephyr/main.c b/boot/zephyr/main.c index c51616dda..64e11c3c6 100644 --- a/boot/zephyr/main.c +++ b/boot/zephyr/main.c @@ -672,11 +672,7 @@ int main(void) } #if defined(CONFIG_SOC_NRF5340_CPUAPP) && defined(PM_CPUNET_B0N_ADDRESS) && defined(CONFIG_PCD_APP) -#if defined(PM_TFM_SECURE_ADDRESS) - pcd_lock_ram(false); -#else - pcd_lock_ram(true); -#endif + pcd_lock_ram(); #endif #endif /* USE_PARTITION_MANAGER && CONFIG_FPROTECT */ From 0e83a04585d8406b57fc5414b6fa300786370b5d Mon Sep 17 00:00:00 2001 From: Jukka Rissanen Date: Tue, 23 Sep 2025 13:04:30 +0300 Subject: [PATCH 233/420] Revert "[nrf noup] boot: Add shared crypto for ECDSA and SHA" This reverts commit 2c64b71cf0f060786b0e821a6b94128d9f8e35e1. Signed-off-by: Jukka Rissanen --- boot/bootutil/include/bootutil/crypto/ecdsa.h | 66 ++----------------- boot/bootutil/include/bootutil/crypto/sha.h | 32 --------- boot/zephyr/CMakeLists.txt | 2 - boot/zephyr/external_crypto.conf | 20 ------ .../include/mcuboot_config/mcuboot_config.h | 2 - 5 files changed, 6 insertions(+), 116 deletions(-) delete mode 100644 boot/zephyr/external_crypto.conf diff --git a/boot/bootutil/include/bootutil/crypto/ecdsa.h b/boot/bootutil/include/bootutil/crypto/ecdsa.h index a5d0f8b1b..3b0541072 100644 --- a/boot/bootutil/include/bootutil/crypto/ecdsa.h +++ b/boot/bootutil/include/bootutil/crypto/ecdsa.h @@ -34,7 +34,6 @@ #if (defined(MCUBOOT_USE_TINYCRYPT) + \ defined(MCUBOOT_USE_CC310) + \ - defined(MCUBOOT_USE_NRF_EXTERNAL_CRYPTO) + \ defined(MCUBOOT_USE_PSA_OR_MBED_TLS)) != 1 #error "One crypto backend must be defined: either CC310/TINYCRYPT/MBED_TLS/PSA_CRYPTO" #endif @@ -71,18 +70,12 @@ #include "bootutil/sign_key.h" #include "common.h" -#if defined(MCUBOOT_USE_NRF_EXTERNAL_CRYPTO) - #include - #define NUM_ECC_BYTES (256 / 8) -#endif /* MCUBOOT_USE_NRF_EXTERNAL_CRYPTO */ - #ifdef __cplusplus extern "C" { #endif #if (defined(MCUBOOT_USE_TINYCRYPT) || defined(MCUBOOT_USE_MBED_TLS) || \ - defined(MCUBOOT_USE_CC310) || defined(MCUBOOT_USE_NRF_EXTERNAL_CRYPTO)) \ - && !defined(MCUBOOT_USE_PSA_CRYPTO) + defined(MCUBOOT_USE_CC310)) && !defined(MCUBOOT_USE_PSA_CRYPTO) /* * Declaring these like this adds NULL termination. */ @@ -134,7 +127,8 @@ static int bootutil_import_key(uint8_t **cp, uint8_t *end) } #endif /* (MCUBOOT_USE_TINYCRYPT || MCUBOOT_USE_MBED_TLS || MCUBOOT_USE_CC310) && !MCUBOOT_USE_PSA_CRYPTO */ -#ifndef MCUBOOT_USE_PSA_CRYPTO +#if defined(MCUBOOT_USE_TINYCRYPT) +#ifndef MCUBOOT_ECDSA_NEED_ASN1_SIG /* * cp points to ASN1 string containing an integer. * Verify the tag, and that the length is 32 bytes. Helper function. @@ -184,9 +178,8 @@ static int bootutil_decode_sig(uint8_t signature[NUM_ECC_BYTES * 2], uint8_t *cp } return 0; } -#endif /* !MCUBOOT_USE_PSA_CRYPTO */ +#endif /* not MCUBOOT_ECDSA_NEED_ASN1_SIG */ -#if defined(MCUBOOT_USE_TINYCRYPT) typedef uintptr_t bootutil_ecdsa_context; static inline void bootutil_ecdsa_init(bootutil_ecdsa_context *ctx) { @@ -255,12 +248,8 @@ static inline int bootutil_ecdsa_verify(bootutil_ecdsa_context *ctx, { (void)ctx; (void)pk_len; + (void)sig_len; (void)hash_len; - uint8_t dsig[2 * NUM_ECC_BYTES]; - - if (bootutil_decode_sig(dsig, sig, sig + sig_len)) { - return -1; - } /* Only support uncompressed keys. */ if (pk[0] != 0x04) { @@ -268,7 +257,7 @@ static inline int bootutil_ecdsa_verify(bootutil_ecdsa_context *ctx, } pk++; - return cc310_ecdsa_verify_secp256r1(hash, pk, dsig, BOOTUTIL_CRYPTO_ECDSA_P256_HASH_SIZE); + return cc310_ecdsa_verify_secp256r1(hash, pk, sig, BOOTUTIL_CRYPTO_ECDSA_P256_HASH_SIZE); } static inline int bootutil_ecdsa_parse_public_key(bootutil_ecdsa_context *ctx, @@ -624,49 +613,6 @@ static inline int bootutil_ecdsa_parse_public_key(bootutil_ecdsa_context *ctx, #endif /* MCUBOOT_USE_MBED_TLS */ -#if defined(MCUBOOT_USE_NRF_EXTERNAL_CRYPTO) -typedef uintptr_t bootutil_ecdsa_context; -static inline void bootutil_ecdsa_init(bootutil_ecdsa_context *ctx) -{ - (void)ctx; -} - -static inline void bootutil_ecdsa_drop(bootutil_ecdsa_context *ctx) -{ - (void)ctx; -} - -static inline int bootutil_ecdsa_verify(bootutil_ecdsa_context *ctx, - uint8_t *pk, size_t pk_len, - uint8_t *hash, size_t hash_len, - uint8_t *sig, size_t sig_len) -{ - (void)ctx; - (void)pk_len; - (void)hash_len; - uint8_t dsig[2 * NUM_ECC_BYTES]; - - if (bootutil_decode_sig(dsig, sig, sig + sig_len)) { - return -1; - } - - /* Only support uncompressed keys. */ - if (pk[0] != 0x04) { - return -1; - } - pk++; - - return bl_secp256r1_validate(hash, BOOTUTIL_CRYPTO_ECDSA_P256_HASH_SIZE, pk, dsig); -} - -static inline int bootutil_ecdsa_parse_public_key(bootutil_ecdsa_context *ctx, - uint8_t **cp,uint8_t *end) -{ - (void)ctx; - return bootutil_import_key(cp, end); -} -#endif /* MCUBOOT_USE_NRF_EXTERNAL_CRYPTO */ - #ifdef __cplusplus } #endif diff --git a/boot/bootutil/include/bootutil/crypto/sha.h b/boot/bootutil/include/bootutil/crypto/sha.h index b83a3ec40..6a009ff95 100644 --- a/boot/bootutil/include/bootutil/crypto/sha.h +++ b/boot/bootutil/include/bootutil/crypto/sha.h @@ -30,7 +30,6 @@ #if (defined(MCUBOOT_USE_PSA_OR_MBED_TLS) + \ defined(MCUBOOT_USE_TINYCRYPT) + \ - defined(MCUBOOT_USE_NRF_EXTERNAL_CRYPTO) + \ defined(MCUBOOT_USE_CC310)) != 1 #error "One crypto backend must be defined: either CC310/MBED_TLS/TINYCRYPT/PSA_CRYPTO" #endif @@ -271,37 +270,6 @@ static inline int bootutil_sha_finish(bootutil_sha_context *ctx, } #endif /* MCUBOOT_USE_CC310 */ -#if defined(MCUBOOT_USE_NRF_EXTERNAL_CRYPTO) - -#include - -typedef bl_sha256_ctx_t bootutil_sha_context; - -static inline void bootutil_sha_init(bootutil_sha_context *ctx) -{ - bl_sha256_init(ctx); -} - -static inline void bootutil_sha_drop(bootutil_sha_context *ctx) -{ - (void)ctx; -} - -static inline int bootutil_sha_update(bootutil_sha_context *ctx, - const void *data, - uint32_t data_len) -{ - return bl_sha256_update(ctx, data, data_len); -} - -static inline int bootutil_sha_finish(bootutil_sha_context *ctx, - uint8_t *output) -{ - bl_sha256_finalize(ctx, output); - return 0; -} -#endif /* MCUBOOT_USE_NRF_EXTERNAL_CRYPTO */ - #ifdef __cplusplus } #endif diff --git a/boot/zephyr/CMakeLists.txt b/boot/zephyr/CMakeLists.txt index 1db4ed270..3a94315f8 100644 --- a/boot/zephyr/CMakeLists.txt +++ b/boot/zephyr/CMakeLists.txt @@ -215,8 +215,6 @@ if(CONFIG_BOOT_SIGNATURE_TYPE_ECDSA_P256 OR CONFIG_BOOT_ENCRYPT_EC256) zephyr_library_sources(${NRF_DIR}/cc310_glue.c) zephyr_library_include_directories(${NRF_DIR}) zephyr_link_libraries(nrfxlib_crypto) - elseif(CONFIG_BOOT_USE_NRF_EXTERNAL_CRYPTO) - zephyr_include_directories(${BL_CRYPTO_DIR}/../include) endif() if(CONFIG_MBEDTLS_CFG_FILE) diff --git a/boot/zephyr/external_crypto.conf b/boot/zephyr/external_crypto.conf deleted file mode 100644 index 8181ad51c..000000000 --- a/boot/zephyr/external_crypto.conf +++ /dev/null @@ -1,20 +0,0 @@ -# -# Copyright (c) 2021 Nordic Semiconductor ASA -# -# SPDX-License-Identifier: LicenseRef-Nordic-5-Clause -# - -# These configurations should be used when using nrf/samples/bootloader -# as the immutable bootloader (B0), and MCUBoot as the second stage updateable -# bootloader. - -# Set ECDSA as signing mechanism -CONFIG_BOOT_SIGNATURE_TYPE_ECDSA_P256=y - -# Use crypto backend from B0 -CONFIG_BOOT_NRF_EXTERNAL_CRYPTO=y -CONFIG_SECURE_BOOT_CRYPTO=y -CONFIG_SB_CRYPTO_CLIENT_ECDSA_SECP256R1=y -CONFIG_SB_CRYPTO_CLIENT_SHA256=y -CONFIG_BL_SHA256_EXT_API_REQUIRED=y -CONFIG_BL_SECP256R1_EXT_API_REQUIRED=y diff --git a/boot/zephyr/include/mcuboot_config/mcuboot_config.h b/boot/zephyr/include/mcuboot_config/mcuboot_config.h index ae9571100..f0dc214b6 100644 --- a/boot/zephyr/include/mcuboot_config/mcuboot_config.h +++ b/boot/zephyr/include/mcuboot_config/mcuboot_config.h @@ -49,8 +49,6 @@ #endif #elif defined(CONFIG_BOOT_USE_PSA_CRYPTO) #define MCUBOOT_USE_PSA_CRYPTO -#elif defined(CONFIG_BOOT_USE_NRF_EXTERNAL_CRYPTO) -#define MCUBOOT_USE_NRF_EXTERNAL_CRYPTO #endif #ifdef CONFIG_BOOT_IMG_HASH_ALG_SHA512 From b553fc63872cd8d6843073bf89dfff3db3fdf93b Mon Sep 17 00:00:00 2001 From: Jukka Rissanen Date: Tue, 23 Sep 2025 13:04:30 +0300 Subject: [PATCH 234/420] Revert "[nrf noup] boards: nrf54l15dk: Disable FPROTECT" This reverts commit 62ddef300f7567b43014e8d8e71ca94e6bd4ef5c. Signed-off-by: Jukka Rissanen --- boot/zephyr/boards/nrf54l15dk_nrf54l15_cpuapp.conf | 3 --- 1 file changed, 3 deletions(-) diff --git a/boot/zephyr/boards/nrf54l15dk_nrf54l15_cpuapp.conf b/boot/zephyr/boards/nrf54l15dk_nrf54l15_cpuapp.conf index 1dbd7c1ab..c8fcd32c3 100644 --- a/boot/zephyr/boards/nrf54l15dk_nrf54l15_cpuapp.conf +++ b/boot/zephyr/boards/nrf54l15dk_nrf54l15_cpuapp.conf @@ -7,9 +7,6 @@ CONFIG_BOOT_MAX_IMG_SECTORS=256 # Ensure that the SPI NOR driver is disabled by default CONFIG_SPI_NOR=n -# TODO: below are not yet supported and need fixing -CONFIG_FPROTECT=n - CONFIG_BOOT_WATCHDOG_FEED=n # Ensure the fastest RRAM write operations From 1b1ce65dd36dab8290511e79353c433d3e17260b Mon Sep 17 00:00:00 2001 From: Jukka Rissanen Date: Tue, 23 Sep 2025 13:04:30 +0300 Subject: [PATCH 235/420] Revert "[nrf noup] bootutil: loader: Fix netcore address checking" This reverts commit 1f364bf2105226a6a12eb51ef25bce2a7fe1219b. Signed-off-by: Jukka Rissanen --- boot/bootutil/src/loader.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/boot/bootutil/src/loader.c b/boot/bootutil/src/loader.c index dabb562c9..f390d5aee 100644 --- a/boot/bootutil/src/loader.c +++ b/boot/bootutil/src/loader.c @@ -1516,7 +1516,7 @@ boot_validated_swap_type(struct boot_loader_state *state, #ifdef PM_S1_ADDRESS #ifdef PM_CPUNET_B0N_ADDRESS - if(!(reset_addr >= PM_CPUNET_APP_ADDRESS && reset_addr < PM_CPUNET_APP_END_ADDRESS)) + if(reset_addr < PM_CPUNET_B0N_ADDRESS) #endif { const struct flash_area *primary_fa; @@ -1589,8 +1589,7 @@ boot_validated_swap_type(struct boot_loader_state *state, * update and indicate to the caller of this function that no update is * available */ - if (upgrade_valid && reset_addr >= PM_CPUNET_APP_ADDRESS && - reset_addr < PM_CPUNET_APP_END_ADDRESS) { + if (upgrade_valid && reset_addr > PM_CPUNET_B0N_ADDRESS) { struct image_header *hdr = (struct image_header *)secondary_fa->fa_off; uint32_t vtable_addr = (uint32_t)hdr + hdr->ih_hdr_size; uint32_t *net_core_fw_addr = (uint32_t *)(vtable_addr); From 6861355162a22e4bd36c83b10f783a99a7449006 Mon Sep 17 00:00:00 2001 From: Jukka Rissanen Date: Tue, 23 Sep 2025 13:04:30 +0300 Subject: [PATCH 236/420] Revert "[nrf noup] boot/../loader: reboot after updating s0/s1" This reverts commit 674adc7d3f6508c9bfeb5f8af93ac489f93d25ce. Signed-off-by: Jukka Rissanen --- boot/bootutil/src/loader.c | 10 ---------- boot/zephyr/Kconfig | 1 - 2 files changed, 11 deletions(-) diff --git a/boot/bootutil/src/loader.c b/boot/bootutil/src/loader.c index f390d5aee..355ebf46c 100644 --- a/boot/bootutil/src/loader.c +++ b/boot/bootutil/src/loader.c @@ -50,10 +50,6 @@ #include "bootutil/boot_hooks.h" #include "bootutil/mcuboot_status.h" -#ifdef __ZEPHYR__ -#include -#endif - #if defined(CONFIG_SOC_NRF5340_CPUAPP) && defined(PM_CPUNET_B0N_ADDRESS) && defined(CONFIG_PCD_APP) #include #ifdef CONFIG_PCD_READ_NETCORE_APP_VERSION @@ -2930,12 +2926,6 @@ context_boot_go(struct boot_loader_state *state, struct boot_rsp *rsp) rc = boot_perform_update(state, &bs); } assert(rc == 0); -#if defined(PM_S1_ADDRESS) && defined(CONFIG_REBOOT) - if (owner_nsib[BOOT_CURR_IMG(state)]) { - sys_reboot(SYS_REBOOT_COLD); - - } -#endif break; case BOOT_SWAP_TYPE_FAIL: diff --git a/boot/zephyr/Kconfig b/boot/zephyr/Kconfig index 89cda41bd..c42928d1f 100644 --- a/boot/zephyr/Kconfig +++ b/boot/zephyr/Kconfig @@ -18,7 +18,6 @@ config MCUBOOT select MPU_ALLOW_FLASH_WRITE if ARM_MPU select USE_DT_CODE_PARTITION if HAS_FLASH_LOAD_OFFSET select MCUBOOT_BOOTUTIL_LIB - select REBOOT if SECURE_BOOT config BOOT_USE_MBEDTLS bool From e9dbc2886e7b71b42148de75e9512935171044d9 Mon Sep 17 00:00:00 2001 From: Jukka Rissanen Date: Tue, 23 Sep 2025 13:04:30 +0300 Subject: [PATCH 237/420] Revert "[nrf noup] boot/../loader: skip downgrade prevention for s1/s0" This reverts commit bf143850d06f24d83c51bc904034e3ccdf22290c. Signed-off-by: Jukka Rissanen --- boot/bootutil/include/bootutil/security_cnt.h | 9 -- boot/bootutil/src/image_validate.c | 20 ----- boot/bootutil/src/loader.c | 83 ------------------- 3 files changed, 112 deletions(-) diff --git a/boot/bootutil/include/bootutil/security_cnt.h b/boot/bootutil/include/bootutil/security_cnt.h index 7e1389618..e1562d2e9 100644 --- a/boot/bootutil/include/bootutil/security_cnt.h +++ b/boot/bootutil/include/bootutil/security_cnt.h @@ -39,15 +39,6 @@ extern "C" { */ fih_ret boot_nv_security_counter_init(void); -/** - * Checks if the specified image should have a security counter present on it or not - * - * @param image_index Index of the image to check (from 0). - * - * @return FIH_SUCCESS if security counter should be present; FIH_FAILURE if otherwise - */ -fih_ret boot_nv_image_should_have_security_counter(uint32_t image_index); - /** * Reads the stored value of a given image's security counter. * diff --git a/boot/bootutil/src/image_validate.c b/boot/bootutil/src/image_validate.c index ade67cc4b..17193a63d 100644 --- a/boot/bootutil/src/image_validate.c +++ b/boot/bootutil/src/image_validate.c @@ -540,15 +540,6 @@ bootutil_img_validate(struct boot_loader_state *state, fih_int security_cnt = fih_int_encode(INT_MAX); uint32_t img_security_cnt = 0; FIH_DECLARE(security_counter_valid, FIH_FAILURE); - FIH_DECLARE(security_counter_should_be_present, FIH_FAILURE); - - FIH_CALL(boot_nv_image_should_have_security_counter, security_counter_should_be_present, - image_index); - if (FIH_NOT_EQ(security_counter_should_be_present, FIH_SUCCESS) && - FIH_NOT_EQ(security_counter_should_be_present, FIH_FAILURE)) { - rc = -1; - goto out; - } #endif BOOT_LOG_DBG("bootutil_img_validate: flash area %p", fap); @@ -745,10 +736,6 @@ bootutil_img_validate(struct boot_loader_state *state, goto out; } - if (FIH_EQ(security_counter_should_be_present, FIH_FAILURE)) { - goto skip_security_counter_read; - } - FIH_CALL(boot_nv_security_counter_get, fih_rc, image_index, &security_cnt); if (FIH_NOT_EQ(fih_rc, FIH_SUCCESS)) { @@ -768,7 +755,6 @@ bootutil_img_validate(struct boot_loader_state *state, /* The image's security counter has been successfully verified. */ security_counter_valid = fih_rc; -skip_security_counter_read: break; } #endif /* MCUBOOT_HW_ROLLBACK_PROT */ @@ -788,16 +774,10 @@ bootutil_img_validate(struct boot_loader_state *state, FIH_SET(fih_rc, valid_signature); #endif #ifdef MCUBOOT_HW_ROLLBACK_PROT - if (FIH_EQ(security_counter_should_be_present, FIH_FAILURE)) { - goto skip_security_counter_check; - } - if (FIH_NOT_EQ(security_counter_valid, FIH_SUCCESS)) { rc = -1; goto out; } - -skip_security_counter_check: #endif out: diff --git a/boot/bootutil/src/loader.c b/boot/bootutil/src/loader.c index 355ebf46c..7c379a7b2 100644 --- a/boot/bootutil/src/loader.c +++ b/boot/bootutil/src/loader.c @@ -71,9 +71,6 @@ int pcd_version_cmp_net(const struct flash_area *fap, struct image_header *hdr); BOOT_LOG_MODULE_DECLARE(mcuboot); static struct boot_loader_state boot_data; -#ifdef PM_S1_ADDRESS -static bool owner_nsib[BOOT_IMAGE_NUMBER] = {false}; -#endif #if defined(MCUBOOT_SERIAL_IMG_GRP_SLOT_INFO) || defined(MCUBOOT_DATA_SHARING) static struct image_max_size image_max_sizes[BOOT_IMAGE_NUMBER] = {0}; @@ -1293,38 +1290,6 @@ boot_validate_slot(struct boot_loader_state *state, int slot, } #ifdef MCUBOOT_HW_ROLLBACK_PROT -/** - * Checks if the specified image should have a security counter present on it or not - * - * @param image_index Index of the image to check. - * - * @return true if security counter should be present; false if otherwise - */ -fih_ret boot_nv_image_should_have_security_counter(uint32_t image_index) -{ -#if defined(PM_S1_ADDRESS) - if (owner_nsib[image_index]) { - /* - * Downgrade prevention on S0/S1 image is managed by NSIB, which is a software (not - * hardware) check - */ - return FIH_FAILURE; - } -#endif - -#if defined(CONFIG_SOC_NRF5340_CPUAPP) && CONFIG_MCUBOOT_NETWORK_CORE_IMAGE_NUMBER != -1 - if (image_index == CONFIG_MCUBOOT_NETWORK_CORE_IMAGE_NUMBER) { - /* - * Downgrade prevention on network core image is managed by NSIB which is a software (not - * hardware) check - */ - return FIH_FAILURE; - } -#endif - - return FIH_SUCCESS; -} - /** * Updates the stored security counter value with the image's security counter * value which resides in the given slot, only if it's greater than the stored @@ -1346,26 +1311,6 @@ boot_update_security_counter(struct boot_loader_state *state, int slot, int hdr_ uint32_t img_security_cnt; int rc; -#if defined(PM_S1_ADDRESS) - if (owner_nsib[BOOT_CURR_IMG(state)]) { - /* - * Downgrade prevention on S0/S1 image is managed by NSIB which is a software (not - * hardware) check - */ - return 0; - } -#endif - -#if defined(CONFIG_SOC_NRF5340_CPUAPP) && CONFIG_MCUBOOT_NETWORK_CORE_IMAGE_NUMBER != -1 - if (BOOT_CURR_IMG(state) == CONFIG_MCUBOOT_NETWORK_CORE_IMAGE_NUMBER) { - /* - * Downgrade prevention on network core image is managed by NSIB which is a software (not - * hardware) check - */ - return 0; - } -#endif - fap = BOOT_IMG_AREA(state, slot); assert(fap != NULL); @@ -1482,9 +1427,6 @@ boot_validated_swap_type(struct boot_loader_state *state, int swap_type; FIH_DECLARE(fih_rc, FIH_FAILURE); bool upgrade_valid = false; -#if defined(PM_S1_ADDRESS) - owner_nsib[BOOT_CURR_IMG(state)] = false; -#endif #if defined(PM_S1_ADDRESS) || defined(CONFIG_SOC_NRF5340_CPUAPP) const struct flash_area *secondary_fa = @@ -1541,7 +1483,6 @@ boot_validated_swap_type(struct boot_loader_state *state, && reset_addr < (nsib_fa->fa_off + nsib_fa->fa_size)) { /* Set primary to be NSIB upgrade slot */ BOOT_IMG_AREA(state, 0) = nsib_fa; - owner_nsib[BOOT_CURR_IMG(state)] = true; } #else return BOOT_SWAP_TYPE_NONE; @@ -1552,10 +1493,6 @@ boot_validated_swap_type(struct boot_loader_state *state, /* The image in the secondary slot is not intended for any */ return BOOT_SWAP_TYPE_NONE; } - - if ((primary_fa->fa_off == PM_S0_ADDRESS) || (primary_fa->fa_off == PM_S1_ADDRESS)) { - owner_nsib[BOOT_CURR_IMG(state)] = true; - } } #endif /* PM_S1_ADDRESS */ sec_slot_mark_assigned(state); @@ -2694,26 +2631,6 @@ check_downgrade_prevention(struct boot_loader_state *state) uint32_t security_counter[2]; int rc; -#if defined(PM_S1_ADDRESS) - if (owner_nsib[BOOT_CURR_IMG(state)]) { - /* - * Downgrade prevention on S0/S1 image is managed by NSIB which is a software (not - * hardware) check - */ - return 0; - } -#endif - -#if defined(CONFIG_SOC_NRF5340_CPUAPP) && CONFIG_MCUBOOT_NETWORK_CORE_IMAGE_NUMBER != -1 - if (BOOT_CURR_IMG(state) == CONFIG_MCUBOOT_NETWORK_CORE_IMAGE_NUMBER) { - /* - * Downgrade prevention on network core image is managed by NSIB which is a software (not - * hardware) check - */ - return 0; - } -#endif - if (MCUBOOT_DOWNGRADE_PREVENTION_SECURITY_COUNTER) { /* If there was security no counter in slot 0, allow swap */ rc = bootutil_get_img_security_cnt(state, BOOT_PRIMARY_SLOT, From 827ac3d4d8ccf054c82310722fc81daf74d91694 Mon Sep 17 00:00:00 2001 From: Jukka Rissanen Date: Tue, 23 Sep 2025 13:04:30 +0300 Subject: [PATCH 238/420] Revert "[nrf noup] boot/zephyr: fix fw_info search" This reverts commit 8949a6a34d4522447069a6630866f136132e3ac3. Signed-off-by: Jukka Rissanen --- boot/zephyr/main.c | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-) diff --git a/boot/zephyr/main.c b/boot/zephyr/main.c index 64e11c3c6..72d0e72ff 100644 --- a/boot/zephyr/main.c +++ b/boot/zephyr/main.c @@ -201,14 +201,7 @@ static void do_boot(struct boot_rsp *rsp) #endif #if defined(CONFIG_FW_INFO) && !defined(CONFIG_EXT_API_PROVIDE_EXT_API_UNUSED) - uintptr_t fw_start_addr; - - rc = flash_device_base(rsp->br_flash_dev_id, &fw_start_addr); - assert(rc == 0); - - fw_start_addr += rsp->br_image_off + rsp->br_hdr->ih_hdr_size; - - const struct fw_info *firmware_info = fw_info_find(fw_start_addr); + const struct fw_info *firmware_info = fw_info_find((uint32_t) vt); bool provided = fw_info_ext_api_provide(firmware_info, true); #ifdef PM_S0_ADDRESS From 38ea80e5b71c6249cfd7161da712da78c09e53ac Mon Sep 17 00:00:00 2001 From: Jukka Rissanen Date: Tue, 23 Sep 2025 13:04:30 +0300 Subject: [PATCH 239/420] Revert "[nrf noup] boot: zephyr: Disable boot banner if NCS_BOOT_BANNER is used" This reverts commit b8f6a06206675d1c51009215aeb9c7b1b348d45f. Signed-off-by: Jukka Rissanen --- boot/zephyr/Kconfig | 1 - 1 file changed, 1 deletion(-) diff --git a/boot/zephyr/Kconfig b/boot/zephyr/Kconfig index c42928d1f..c37911f8e 100644 --- a/boot/zephyr/Kconfig +++ b/boot/zephyr/Kconfig @@ -1078,7 +1078,6 @@ config BOOT_DISABLE_CACHES config MCUBOOT_BOOT_BANNER bool "Use MCUboot boot banner" depends on BOOT_BANNER - depends on !NCS_BOOT_BANNER depends on "$(APP_VERSION_EXTENDED_STRING)" != "" default y help From e3603d0628659a7d2576c1379c018ded2bf0cdda Mon Sep 17 00:00:00 2001 From: Jukka Rissanen Date: Tue, 23 Sep 2025 13:04:30 +0300 Subject: [PATCH 240/420] Revert "[nrf noup] boards: thingy91x: enable serial recovery" This reverts commit f5f382f4fe888e560e0db125fded0ef49ba6e7a7. Signed-off-by: Jukka Rissanen --- boot/zephyr/boards/thingy91x_nrf5340_cpuapp.conf | 10 ++-------- boot/zephyr/boards/thingy91x_nrf9151.conf | 9 --------- 2 files changed, 2 insertions(+), 17 deletions(-) diff --git a/boot/zephyr/boards/thingy91x_nrf5340_cpuapp.conf b/boot/zephyr/boards/thingy91x_nrf5340_cpuapp.conf index 37c7e95b1..72dfa7fca 100644 --- a/boot/zephyr/boards/thingy91x_nrf5340_cpuapp.conf +++ b/boot/zephyr/boards/thingy91x_nrf5340_cpuapp.conf @@ -32,7 +32,7 @@ CONFIG_USB_COMPOSITE_DEVICE=y CONFIG_USB_MASS_STORAGE=n CONFIG_USB_DEVICE_MANUFACTURER="Nordic Semiconductor" CONFIG_USB_DEVICE_VID=0x1915 -CONFIG_USB_DEVICE_PID=0x910A +CONFIG_USB_DEVICE_PID=0x520F CONFIG_BOOT_SERIAL_BOOT_MODE=y @@ -49,12 +49,6 @@ CONFIG_FLASH_SIMULATOR_DOUBLE_WRITES=y CONFIG_FLASH_SIMULATOR_STATS=n CONFIG_BOOT_IMAGE_ACCESS_HOOKS=y - -# Makes it possible to update the network core using the flash simulator -CONFIG_NRF53_RECOVERY_NETWORK_CORE=y - CONFIG_MCUBOOT_SERIAL_DIRECT_IMAGE_UPLOAD=y -CONFIG_BOOT_SERIAL_IMG_GRP_IMAGE_STATE=y -# Skip checks on the secondary image to make it possible to update MCUBoot on S1/S0 -CONFIG_MCUBOOT_VERIFY_IMG_ADDRESS=n +CONFIG_NRF53_RECOVERY_NETWORK_CORE=y diff --git a/boot/zephyr/boards/thingy91x_nrf9151.conf b/boot/zephyr/boards/thingy91x_nrf9151.conf index 2efe1e170..33cd3301c 100644 --- a/boot/zephyr/boards/thingy91x_nrf9151.conf +++ b/boot/zephyr/boards/thingy91x_nrf9151.conf @@ -6,12 +6,3 @@ CONFIG_SPI_NOR=y CONFIG_SPI_NOR_FLASH_LAYOUT_PAGE_SIZE=4096 CONFIG_SPI_NOR_SFDP_DEVICETREE=y CONFIG_MULTITHREADING=y - -# Disable Zephyr console and use UART for MCUboot serial recovery instead -CONFIG_CONSOLE=n -CONFIG_CONSOLE_HANDLER=n -CONFIG_UART_CONSOLE=n -CONFIG_MCUBOOT_SERIAL=y - -CONFIG_MCUBOOT_SERIAL_DIRECT_IMAGE_UPLOAD=y -CONFIG_BOOT_SERIAL_IMG_GRP_IMAGE_STATE=y From 96c0f5d22a9d4379c6397280a8986723341ee8f4 Mon Sep 17 00:00:00 2001 From: Jukka Rissanen Date: Tue, 23 Sep 2025 13:04:30 +0300 Subject: [PATCH 241/420] Revert "[nrf noup] loader: remove cleanup for direct xip mode" This reverts commit 271e50509bfb6d9625f25b4b6f8ccd991799e93e. Signed-off-by: Jukka Rissanen --- boot/bootutil/src/loader.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/boot/bootutil/src/loader.c b/boot/bootutil/src/loader.c index 7c379a7b2..ab26dcdbf 100644 --- a/boot/bootutil/src/loader.c +++ b/boot/bootutil/src/loader.c @@ -1329,8 +1329,6 @@ boot_update_security_counter(struct boot_loader_state *state, int slot, int hdr_ } #endif /* MCUBOOT_HW_ROLLBACK_PROT */ -#if !defined(MCUBOOT_DIRECT_XIP) && !defined(MCUBOOT_RAM_LOAD) - #if defined(CONFIG_MCUBOOT_CLEANUP_UNUSABLE_SECONDARY) &&\ (defined(PM_S1_ADDRESS) || defined(CONFIG_SOC_NRF5340_CPUAPP)) @@ -1412,6 +1410,7 @@ static inline void sec_slot_cleanup_if_unusable(void) #endif /* defined(CONFIG_MCUBOOT_CLEANUP_UNUSABLE_SECONDARY) &&\ defined(PM_S1_ADDRESS) || defined(CONFIG_SOC_NRF5340_CPUAPP) */ +#if !defined(MCUBOOT_DIRECT_XIP) && !defined(MCUBOOT_RAM_LOAD) /** * Determines which swap operation to perform, if any. If it is determined * that a swap operation is required, the image in the secondary slot is checked From ba270064bce0ab6ba467c51a7b5e0fface875d49 Mon Sep 17 00:00:00 2001 From: Jukka Rissanen Date: Tue, 23 Sep 2025 13:04:30 +0300 Subject: [PATCH 242/420] Revert "[nrf noup] loader: introduced cleanup of unusable secondary slot" This reverts commit bd97f58190446c2a6e6a6e1a273b38a0ae848273. Signed-off-by: Jukka Rissanen --- boot/bootutil/src/loader.c | 90 -------------------------------------- 1 file changed, 90 deletions(-) diff --git a/boot/bootutil/src/loader.c b/boot/bootutil/src/loader.c index ab26dcdbf..d30470e48 100644 --- a/boot/bootutil/src/loader.c +++ b/boot/bootutil/src/loader.c @@ -1329,87 +1329,6 @@ boot_update_security_counter(struct boot_loader_state *state, int slot, int hdr_ } #endif /* MCUBOOT_HW_ROLLBACK_PROT */ -#if defined(CONFIG_MCUBOOT_CLEANUP_UNUSABLE_SECONDARY) &&\ -(defined(PM_S1_ADDRESS) || defined(CONFIG_SOC_NRF5340_CPUAPP)) - -#define SEC_SLOT_VIRGIN 0 -#define SEC_SLOT_TOUCHED 1 -#define SEC_SLOT_ASSIGNED 2 - -#if (MCUBOOT_IMAGE_NUMBER == 2) && defined(PM_B0_ADDRESS) && \ - !defined(CONFIG_NRF53_MULTI_IMAGE_UPDATE) -/* This configuration is peculiar - the one physical secondary slot is - * mocking two logical secondary - */ -#define SEC_SLOT_PHYSICAL_CNT 1 -#else -#define SEC_SLOT_PHYSICAL_CNT MCUBOOT_IMAGE_NUMBER -#endif - -static uint8_t sec_slot_assignmnet[SEC_SLOT_PHYSICAL_CNT] = {0}; - -static inline void sec_slot_touch(struct boot_loader_state *state) -{ - uint8_t idx = (SEC_SLOT_PHYSICAL_CNT == 1) ? 0 : BOOT_CURR_IMG(state); - - if (SEC_SLOT_VIRGIN == sec_slot_assignmnet[idx]) { - sec_slot_assignmnet[idx] = SEC_SLOT_TOUCHED; - } -} - -static inline void sec_slot_mark_assigned(struct boot_loader_state *state) -{ - uint8_t idx = (SEC_SLOT_PHYSICAL_CNT == 1) ? 0 : BOOT_CURR_IMG(state); - - sec_slot_assignmnet[idx] = SEC_SLOT_ASSIGNED; -} - -/** - * Cleanu up all secondary slot which couldn't be assigned to any primary slot. - * - * This function erases content of each secondary slot which contains valid - * header but couldn't be assigned to any of supported primary images. - * - * This function is supposed to be called after boot_validated_swap_type() - * iterates over all the images in context_boot_go(). - */ -static void sec_slot_cleanup_if_unusable(void) -{ - uint8_t idx; - - for (idx = 0; idx < SEC_SLOT_PHYSICAL_CNT; idx++) { - if (SEC_SLOT_TOUCHED == sec_slot_assignmnet[idx]) { - const struct flash_area *secondary_fa; - int rc; - - rc = flash_area_open(flash_area_id_from_multi_image_slot(idx, BOOT_SECONDARY_SLOT), - &secondary_fa); - if (!rc) { - rc = flash_area_erase(secondary_fa, 0, secondary_fa->fa_size); - if (!rc) { - BOOT_LOG_ERR("Cleaned-up secondary slot of %d. image.", idx); - } - } - - if (rc) { - BOOT_LOG_ERR("Can not cleanup secondary slot of %d. image.", idx); - } - } - } -} -#else -static inline void sec_slot_touch(struct boot_loader_state *state) -{ -} -static inline void sec_slot_mark_assigned(struct boot_loader_state *state) -{ -} -static inline void sec_slot_cleanup_if_unusable(void) -{ -} -#endif /* defined(CONFIG_MCUBOOT_CLEANUP_UNUSABLE_SECONDARY) &&\ - defined(PM_S1_ADDRESS) || defined(CONFIG_SOC_NRF5340_CPUAPP) */ - #if !defined(MCUBOOT_DIRECT_XIP) && !defined(MCUBOOT_RAM_LOAD) /** * Determines which swap operation to perform, if any. If it is determined @@ -1448,9 +1367,6 @@ boot_validated_swap_type(struct boot_loader_state *state, if (rc != 0) { return BOOT_SWAP_TYPE_FAIL; } - - sec_slot_touch(state); - #ifdef PM_S1_ADDRESS #ifdef PM_CPUNET_B0N_ADDRESS if(reset_addr < PM_CPUNET_B0N_ADDRESS) @@ -1485,7 +1401,6 @@ boot_validated_swap_type(struct boot_loader_state *state, } #else return BOOT_SWAP_TYPE_NONE; - #endif } else if (reset_addr > (primary_fa->fa_off + primary_fa->fa_size)) { @@ -1494,9 +1409,7 @@ boot_validated_swap_type(struct boot_loader_state *state, } } #endif /* PM_S1_ADDRESS */ - sec_slot_mark_assigned(state); } - #endif /* PM_S1_ADDRESS || CONFIG_SOC_NRF5340_CPUAPP */ swap_type = boot_swap_type_multi(BOOT_CURR_IMG(state)); @@ -2769,9 +2682,6 @@ context_boot_go(struct boot_loader_state *state, struct boot_rsp *rsp) } } - /* cleanup secondary slots which were recognized unusable*/ - sec_slot_cleanup_if_unusable(); - #if (BOOT_IMAGE_NUMBER > 1) if (has_upgrade) { /* Iterate over all the images and verify whether the image dependencies From fa54b9e685993514079d7db8c44afa7739fb0946 Mon Sep 17 00:00:00 2001 From: Jukka Rissanen Date: Tue, 23 Sep 2025 13:04:30 +0300 Subject: [PATCH 243/420] Revert "[nrf noup] sysflash: Add support for three images" This reverts commit 3b3298de5dae0055bf95c2bf62a7f45a8c36b950. Signed-off-by: Jukka Rissanen --- boot/zephyr/include/sysflash/pm_sysflash.h | 82 ++++++++++------------ 1 file changed, 37 insertions(+), 45 deletions(-) diff --git a/boot/zephyr/include/sysflash/pm_sysflash.h b/boot/zephyr/include/sysflash/pm_sysflash.h index db60ddd03..377291e8b 100644 --- a/boot/zephyr/include/sysflash/pm_sysflash.h +++ b/boot/zephyr/include/sysflash/pm_sysflash.h @@ -11,19 +11,37 @@ #include #include -#include #ifndef CONFIG_SINGLE_APPLICATION_SLOT -#if (MCUBOOT_IMAGE_NUMBER == 2) && defined(PM_B0_ADDRESS) +#if (MCUBOOT_IMAGE_NUMBER == 1) + +#define FLASH_AREA_IMAGE_PRIMARY(x) PM_MCUBOOT_PRIMARY_ID +#define FLASH_AREA_IMAGE_SECONDARY(x) PM_MCUBOOT_SECONDARY_ID + +#elif (MCUBOOT_IMAGE_NUMBER == 2) + /* If B0 is present then two bootloaders are present, and we must use * a single secondary slot for both primary slots. */ +#if defined(PM_B0_ADDRESS) extern uint32_t _image_1_primary_slot_id[]; -#endif /* (MCUBOOT_IMAGE_NUMBER == 2 && defined(PM_B0_ADDRESS) */ +#endif +#if defined(PM_B0_ADDRESS) && defined(CONFIG_NRF53_MULTI_IMAGE_UPDATE) +#define FLASH_AREA_IMAGE_PRIMARY(x) \ + ((x == 0) ? \ + PM_MCUBOOT_PRIMARY_ID : \ + (x == 1) ? \ + PM_MCUBOOT_PRIMARY_1_ID : \ + 255 ) -#if (MCUBOOT_IMAGE_NUMBER == 2) && defined(PM_B0_ADDRESS) && \ - !defined(CONFIG_NRF53_MULTI_IMAGE_UPDATE) +#define FLASH_AREA_IMAGE_SECONDARY(x) \ + ((x == 0) ? \ + PM_MCUBOOT_SECONDARY_ID: \ + (x == 1) ? \ + PM_MCUBOOT_SECONDARY_1_ID: \ + 255 ) +#elif defined(PM_B0_ADDRESS) #define FLASH_AREA_IMAGE_PRIMARY(x) \ ((x == 0) ? \ @@ -38,52 +56,26 @@ extern uint32_t _image_1_primary_slot_id[]; (x == 1) ? \ PM_MCUBOOT_SECONDARY_ID: \ 255 ) - -#else /* MCUBOOT_IMAGE_NUMBER == 2) && defined(PM_B0_ADDRESS) && \ - * !defined(CONFIG_NRF53_MULTI_IMAGE_UPDATE) - */ - -/* Each pair of slots is separated by , and there is no terminating character */ -#define FLASH_AREA_IMAGE_0_SLOTS PM_MCUBOOT_PRIMARY_ID, PM_MCUBOOT_SECONDARY_ID -#define FLASH_AREA_IMAGE_1_SLOTS PM_MCUBOOT_PRIMARY_1_ID, PM_MCUBOOT_SECONDARY_1_ID -#define FLASH_AREA_IMAGE_2_SLOTS PM_MCUBOOT_PRIMARY_2_ID, PM_MCUBOOT_SECONDARY_2_ID - -#if (MCUBOOT_IMAGE_NUMBER == 1) -#define ALL_AVAILABLE_SLOTS FLASH_AREA_IMAGE_0_SLOTS -#elif (MCUBOOT_IMAGE_NUMBER == 2) -#define ALL_AVAILABLE_SLOTS FLASH_AREA_IMAGE_0_SLOTS, \ - FLASH_AREA_IMAGE_1_SLOTS -#elif (MCUBOOT_IMAGE_NUMBER == 3) -#define ALL_AVAILABLE_SLOTS FLASH_AREA_IMAGE_0_SLOTS, \ - FLASH_AREA_IMAGE_1_SLOTS, \ - FLASH_AREA_IMAGE_2_SLOTS #else -#error Unsupported number of images -#endif -static inline uint32_t __flash_area_ids_for_slot(int img, int slot) -{ - static const int all_slots[] = { - ALL_AVAILABLE_SLOTS - }; - return all_slots[img * 2 + slot]; -}; +#define FLASH_AREA_IMAGE_PRIMARY(x) \ + ((x == 0) ? \ + PM_MCUBOOT_PRIMARY_ID : \ + (x == 1) ? \ + PM_MCUBOOT_PRIMARY_1_ID : \ + 255 ) -#undef FLASH_AREA_IMAGE_0_SLOTS -#undef FLASH_AREA_IMAGE_1_SLOTS -#undef FLASH_AREA_IMAGE_2_SLOTS -#undef ALL_AVAILABLE_SLOTS +#define FLASH_AREA_IMAGE_SECONDARY(x) \ + ((x == 0) ? \ + PM_MCUBOOT_SECONDARY_ID: \ + (x == 1) ? \ + PM_MCUBOOT_SECONDARY_1_ID: \ + 255 ) -#define FLASH_AREA_IMAGE_PRIMARY(x) __flash_area_ids_for_slot(x, 0) -#define FLASH_AREA_IMAGE_SECONDARY(x) __flash_area_ids_for_slot(x, 1) +#endif /* PM_B0_ADDRESS */ -#if !defined(CONFIG_BOOT_SWAP_USING_MOVE) -#define FLASH_AREA_IMAGE_SCRATCH PM_MCUBOOT_SCRATCH_ID #endif - -#endif /* MCUBOOT_IMAGE_NUMBER == 2) && defined(PM_B0_ADDRESS) && \ - * !defined(CONFIG_NRF53_MULTI_IMAGE_UPDATE) - */ +#define FLASH_AREA_IMAGE_SCRATCH PM_MCUBOOT_SCRATCH_ID #else /* CONFIG_SINGLE_APPLICATION_SLOT */ From 25ea28382d361f1288f85d5974c55c7507ca1c26 Mon Sep 17 00:00:00 2001 From: Jukka Rissanen Date: Tue, 23 Sep 2025 13:04:30 +0300 Subject: [PATCH 244/420] Revert "[nrf noup] sysflash: Move partition manager definitions to pm_sysflash.h" This reverts commit bc86df639008e27e8296b9253079944c689eacad. Signed-off-by: Jukka Rissanen --- boot/zephyr/include/sysflash/pm_sysflash.h | 92 ---------------------- boot/zephyr/include/sysflash/sysflash.h | 90 +++++++++++++++++++-- 2 files changed, 85 insertions(+), 97 deletions(-) delete mode 100644 boot/zephyr/include/sysflash/pm_sysflash.h diff --git a/boot/zephyr/include/sysflash/pm_sysflash.h b/boot/zephyr/include/sysflash/pm_sysflash.h deleted file mode 100644 index 377291e8b..000000000 --- a/boot/zephyr/include/sysflash/pm_sysflash.h +++ /dev/null @@ -1,92 +0,0 @@ -/* - * Copyright (c) 2023 Nordic Semiconductor ASA - * - * SPDX-License-Identifier: LicenseRef-Nordic-5-Clause - */ - -#ifndef __PM_SYSFLASH_H__ -#define __PM_SYSFLASH_H__ -/* Blocking the __SYSFLASH_H__ */ -#define __SYSFLASH_H__ - -#include -#include - -#ifndef CONFIG_SINGLE_APPLICATION_SLOT - -#if (MCUBOOT_IMAGE_NUMBER == 1) - -#define FLASH_AREA_IMAGE_PRIMARY(x) PM_MCUBOOT_PRIMARY_ID -#define FLASH_AREA_IMAGE_SECONDARY(x) PM_MCUBOOT_SECONDARY_ID - -#elif (MCUBOOT_IMAGE_NUMBER == 2) - -/* If B0 is present then two bootloaders are present, and we must use - * a single secondary slot for both primary slots. - */ -#if defined(PM_B0_ADDRESS) -extern uint32_t _image_1_primary_slot_id[]; -#endif -#if defined(PM_B0_ADDRESS) && defined(CONFIG_NRF53_MULTI_IMAGE_UPDATE) -#define FLASH_AREA_IMAGE_PRIMARY(x) \ - ((x == 0) ? \ - PM_MCUBOOT_PRIMARY_ID : \ - (x == 1) ? \ - PM_MCUBOOT_PRIMARY_1_ID : \ - 255 ) - -#define FLASH_AREA_IMAGE_SECONDARY(x) \ - ((x == 0) ? \ - PM_MCUBOOT_SECONDARY_ID: \ - (x == 1) ? \ - PM_MCUBOOT_SECONDARY_1_ID: \ - 255 ) -#elif defined(PM_B0_ADDRESS) - -#define FLASH_AREA_IMAGE_PRIMARY(x) \ - ((x == 0) ? \ - PM_MCUBOOT_PRIMARY_ID : \ - (x == 1) ? \ - (uint32_t)_image_1_primary_slot_id : \ - 255 ) - -#define FLASH_AREA_IMAGE_SECONDARY(x) \ - ((x == 0) ? \ - PM_MCUBOOT_SECONDARY_ID: \ - (x == 1) ? \ - PM_MCUBOOT_SECONDARY_ID: \ - 255 ) -#else - -#define FLASH_AREA_IMAGE_PRIMARY(x) \ - ((x == 0) ? \ - PM_MCUBOOT_PRIMARY_ID : \ - (x == 1) ? \ - PM_MCUBOOT_PRIMARY_1_ID : \ - 255 ) - -#define FLASH_AREA_IMAGE_SECONDARY(x) \ - ((x == 0) ? \ - PM_MCUBOOT_SECONDARY_ID: \ - (x == 1) ? \ - PM_MCUBOOT_SECONDARY_1_ID: \ - 255 ) - -#endif /* PM_B0_ADDRESS */ - -#endif -#define FLASH_AREA_IMAGE_SCRATCH PM_MCUBOOT_SCRATCH_ID - -#else /* CONFIG_SINGLE_APPLICATION_SLOT */ - -#define FLASH_AREA_IMAGE_PRIMARY(x) PM_MCUBOOT_PRIMARY_ID -#define FLASH_AREA_IMAGE_SECONDARY(x) PM_MCUBOOT_PRIMARY_ID -/* NOTE: Scratch parition is not used by single image DFU but some of - * functions in common files reference it, so the definitions has been - * provided to allow compilation of common units. - */ -#define FLASH_AREA_IMAGE_SCRATCH 0 - -#endif /* CONFIG_SINGLE_APPLICATION_SLOT */ - -#endif /* __PM_SYSFLASH_H__ */ diff --git a/boot/zephyr/include/sysflash/sysflash.h b/boot/zephyr/include/sysflash/sysflash.h index 3c3638d7f..f1ef4100e 100644 --- a/boot/zephyr/include/sysflash/sysflash.h +++ b/boot/zephyr/include/sysflash/sysflash.h @@ -4,15 +4,93 @@ * SPDX-License-Identifier: Apache-2.0 */ -#if USE_PARTITION_MANAGER -/* Blocking the rest of the file */ +#ifndef __SYSFLASH_H__ #define __SYSFLASH_H__ -#include + +#if USE_PARTITION_MANAGER +#include +#include + +#ifndef CONFIG_SINGLE_APPLICATION_SLOT + +#if (MCUBOOT_IMAGE_NUMBER == 1) + +#define FLASH_AREA_IMAGE_PRIMARY(x) PM_MCUBOOT_PRIMARY_ID +#define FLASH_AREA_IMAGE_SECONDARY(x) PM_MCUBOOT_SECONDARY_ID + +#elif (MCUBOOT_IMAGE_NUMBER == 2) + +/* If B0 is present then two bootloaders are present, and we must use + * a single secondary slot for both primary slots. + */ +#if defined(PM_B0_ADDRESS) +extern uint32_t _image_1_primary_slot_id[]; #endif +#if defined(PM_B0_ADDRESS) && defined(CONFIG_NRF53_MULTI_IMAGE_UPDATE) +#define FLASH_AREA_IMAGE_PRIMARY(x) \ + ((x == 0) ? \ + PM_MCUBOOT_PRIMARY_ID : \ + (x == 1) ? \ + PM_MCUBOOT_PRIMARY_1_ID : \ + 255 ) + +#define FLASH_AREA_IMAGE_SECONDARY(x) \ + ((x == 0) ? \ + PM_MCUBOOT_SECONDARY_ID: \ + (x == 1) ? \ + PM_MCUBOOT_SECONDARY_1_ID: \ + 255 ) +#elif defined(PM_B0_ADDRESS) + +#define FLASH_AREA_IMAGE_PRIMARY(x) \ + ((x == 0) ? \ + PM_MCUBOOT_PRIMARY_ID : \ + (x == 1) ? \ + (uint32_t)_image_1_primary_slot_id : \ + 255 ) + +#define FLASH_AREA_IMAGE_SECONDARY(x) \ + ((x == 0) ? \ + PM_MCUBOOT_SECONDARY_ID: \ + (x == 1) ? \ + PM_MCUBOOT_SECONDARY_ID: \ + 255 ) +#else + +#define FLASH_AREA_IMAGE_PRIMARY(x) \ + ((x == 0) ? \ + PM_MCUBOOT_PRIMARY_ID : \ + (x == 1) ? \ + PM_MCUBOOT_PRIMARY_1_ID : \ + 255 ) + +#define FLASH_AREA_IMAGE_SECONDARY(x) \ + ((x == 0) ? \ + PM_MCUBOOT_SECONDARY_ID: \ + (x == 1) ? \ + PM_MCUBOOT_SECONDARY_1_ID: \ + 255 ) + +#endif /* PM_B0_ADDRESS */ -#ifndef __SYSFLASH_H__ -#define __SYSFLASH_H__ +#endif +#define FLASH_AREA_IMAGE_SCRATCH PM_MCUBOOT_SCRATCH_ID + +#else /* CONFIG_SINGLE_APPLICATION_SLOT */ + +#define FLASH_AREA_IMAGE_PRIMARY(x) PM_MCUBOOT_PRIMARY_ID +#define FLASH_AREA_IMAGE_SECONDARY(x) PM_MCUBOOT_PRIMARY_ID +/* NOTE: Scratch parition is not used by single image DFU but some of + * functions in common files reference it, so the definitions has been + * provided to allow compilation of common units. + */ +#define FLASH_AREA_IMAGE_SCRATCH 0 + +#endif /* CONFIG_SINGLE_APPLICATION_SLOT */ +#else + +#include #include #include #include @@ -71,4 +149,6 @@ static inline uint32_t __flash_area_ids_for_slot(int img, int slot) #endif /* CONFIG_SINGLE_APPLICATION_SLOT */ +#endif /* USE_PARTITION_MANAGER */ + #endif /* __SYSFLASH_H__ */ From 5cdd38b9fe7c443a45f118af85103a01101c657e Mon Sep 17 00:00:00 2001 From: Jukka Rissanen Date: Tue, 23 Sep 2025 13:04:30 +0300 Subject: [PATCH 245/420] Revert "[nrf noup] boot: Add support for NSIB and multi-image" This reverts commit 75073fd88eca232c350c9a0af3c859815cb1ca4e. Signed-off-by: Jukka Rissanen --- boot/bootutil/src/loader.c | 42 ++++++------------------- boot/zephyr/include/sysflash/sysflash.h | 19 ++--------- 2 files changed, 11 insertions(+), 50 deletions(-) diff --git a/boot/bootutil/src/loader.c b/boot/bootutil/src/loader.c index d30470e48..301e528c4 100644 --- a/boot/bootutil/src/loader.c +++ b/boot/bootutil/src/loader.c @@ -1256,11 +1256,6 @@ boot_validate_slot(struct boot_loader_state *state, int slot, if (BOOT_CURR_IMG(state) == 1) { min_addr = PM_CPUNET_APP_ADDRESS; max_addr = PM_CPUNET_APP_ADDRESS + PM_CPUNET_APP_SIZE; -#ifdef PM_S1_ADDRESS - } else if (BOOT_CURR_IMG(state) == 0) { - min_addr = PM_S0_ADDRESS; - max_addr = pri_fa->fa_off + pri_fa->fa_size; -#endif } else #endif { @@ -1374,37 +1369,18 @@ boot_validated_swap_type(struct boot_loader_state *state, { const struct flash_area *primary_fa; rc = flash_area_open(flash_area_id_from_multi_image_slot( - BOOT_CURR_IMG(state), BOOT_PRIMARY_SLOT), - &primary_fa); + BOOT_CURR_IMG(state), + BOOT_PRIMARY_SLOT), + &primary_fa); + if (rc != 0) { return BOOT_SWAP_TYPE_FAIL; } - - /* Check start and end of primary slot for current image */ - if (reset_addr < primary_fa->fa_off) { -#if defined(CONFIG_SOC_NRF5340_CPUAPP) && defined(CONFIG_NRF53_MULTI_IMAGE_UPDATE) - const struct flash_area *nsib_fa; - - /* NSIB upgrade slot */ - rc = flash_area_open((uint32_t)_image_1_primary_slot_id, - &nsib_fa); - - if (rc != 0) { - return BOOT_SWAP_TYPE_FAIL; - } - - /* Image is placed before Primary and within the NSIB slot */ - if (reset_addr > nsib_fa->fa_off - && reset_addr < (nsib_fa->fa_off + nsib_fa->fa_size)) { - /* Set primary to be NSIB upgrade slot */ - BOOT_IMG_AREA(state, 0) = nsib_fa; - } -#else - return BOOT_SWAP_TYPE_NONE; -#endif - - } else if (reset_addr > (primary_fa->fa_off + primary_fa->fa_size)) { - /* The image in the secondary slot is not intended for any */ + /* Get start and end of primary slot for current image */ + if (reset_addr < primary_fa->fa_off || + reset_addr > (primary_fa->fa_off + primary_fa->fa_size)) { + /* The image in the secondary slot is not intended for this image + */ return BOOT_SWAP_TYPE_NONE; } } diff --git a/boot/zephyr/include/sysflash/sysflash.h b/boot/zephyr/include/sysflash/sysflash.h index f1ef4100e..7112f9baa 100644 --- a/boot/zephyr/include/sysflash/sysflash.h +++ b/boot/zephyr/include/sysflash/sysflash.h @@ -23,24 +23,9 @@ /* If B0 is present then two bootloaders are present, and we must use * a single secondary slot for both primary slots. */ -#if defined(PM_B0_ADDRESS) -extern uint32_t _image_1_primary_slot_id[]; -#endif -#if defined(PM_B0_ADDRESS) && defined(CONFIG_NRF53_MULTI_IMAGE_UPDATE) -#define FLASH_AREA_IMAGE_PRIMARY(x) \ - ((x == 0) ? \ - PM_MCUBOOT_PRIMARY_ID : \ - (x == 1) ? \ - PM_MCUBOOT_PRIMARY_1_ID : \ - 255 ) +#ifdef PM_B0_ADDRESS -#define FLASH_AREA_IMAGE_SECONDARY(x) \ - ((x == 0) ? \ - PM_MCUBOOT_SECONDARY_ID: \ - (x == 1) ? \ - PM_MCUBOOT_SECONDARY_1_ID: \ - 255 ) -#elif defined(PM_B0_ADDRESS) +extern uint32_t _image_1_primary_slot_id[]; #define FLASH_AREA_IMAGE_PRIMARY(x) \ ((x == 0) ? \ From ce1f6d948510d44187e8de171c91a9b491f70b99 Mon Sep 17 00:00:00 2001 From: Jukka Rissanen Date: Tue, 23 Sep 2025 13:04:30 +0300 Subject: [PATCH 246/420] Revert "[nrf noup] loader: Fix missing PCD define check" This reverts commit 1ca64e93ce9f7484e9033989ff7dbfcacab0864b. Signed-off-by: Jukka Rissanen --- boot/bootutil/src/loader.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/boot/bootutil/src/loader.c b/boot/bootutil/src/loader.c index 301e528c4..a596f8f56 100644 --- a/boot/bootutil/src/loader.c +++ b/boot/bootutil/src/loader.c @@ -1405,7 +1405,7 @@ boot_validated_swap_type(struct boot_loader_state *state, } #if defined(CONFIG_SOC_NRF5340_CPUAPP) && defined(PM_CPUNET_B0N_ADDRESS) \ - && !defined(CONFIG_NRF53_MULTI_IMAGE_UPDATE) && defined(CONFIG_PCD_APP) + && !defined(CONFIG_NRF53_MULTI_IMAGE_UPDATE) /* If the update is valid, and it targets the network core: perform the * update and indicate to the caller of this function that no update is * available @@ -1433,8 +1433,7 @@ boot_validated_swap_type(struct boot_loader_state *state, swap_type = BOOT_SWAP_TYPE_NONE; } } -#endif /* CONFIG_SOC_NRF5340_CPUAPP && PM_CPUNET_B0N_ADDRESS && - !CONFIG_NRF53_MULTI_IMAGE_UPDATE && CONFIG_PCD_APP */ +#endif /* CONFIG_SOC_NRF5340_CPUAPP */ } return swap_type; From c879500b97cf7066fd04024ddc57a6b32f7330c2 Mon Sep 17 00:00:00 2001 From: Jukka Rissanen Date: Tue, 23 Sep 2025 13:04:30 +0300 Subject: [PATCH 247/420] Revert "[nrf noup] loader: work-around for multi-image builds" This reverts commit 470e7cb53980087f835c81eedd2b4c11180fde41. Signed-off-by: Jukka Rissanen --- boot/bootutil/src/loader.c | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/boot/bootutil/src/loader.c b/boot/bootutil/src/loader.c index a596f8f56..a14215c28 100644 --- a/boot/bootutil/src/loader.c +++ b/boot/bootutil/src/loader.c @@ -547,7 +547,7 @@ boot_verify_dependencies(struct boot_loader_state *state) if (rc == 0) { /* All dependencies've been satisfied, continue with next image. */ BOOT_CURR_IMG(state)++; - } else if (rc == BOOT_EBADIMAGE) { + } else { /* Cannot upgrade due to non-met dependencies, so disable all * image upgrades. */ @@ -556,10 +556,7 @@ boot_verify_dependencies(struct boot_loader_state *state) BOOT_SWAP_TYPE(state) = BOOT_SWAP_TYPE_NONE; } break; - } else { - /* Other error happened, images are inconsistent */ - return rc; - } + } } return rc; } From b815b3da9d11c7bee4599f168f62685e89cb598f Mon Sep 17 00:00:00 2001 From: Jukka Rissanen Date: Tue, 23 Sep 2025 13:04:30 +0300 Subject: [PATCH 248/420] Revert "[nrf noup] boards: thingy53: disable GPIO ISR support" This reverts commit 937e0f6d566c43d7b2445bd74b586ef28fb64aff. Signed-off-by: Jukka Rissanen --- boot/zephyr/boards/thingy53_nrf5340_cpuapp.conf | 1 - 1 file changed, 1 deletion(-) diff --git a/boot/zephyr/boards/thingy53_nrf5340_cpuapp.conf b/boot/zephyr/boards/thingy53_nrf5340_cpuapp.conf index d68509786..93be36738 100644 --- a/boot/zephyr/boards/thingy53_nrf5340_cpuapp.conf +++ b/boot/zephyr/boards/thingy53_nrf5340_cpuapp.conf @@ -21,7 +21,6 @@ CONFIG_UART_LINE_CTRL=y # MCUBoot serial CONFIG_GPIO=y -CONFIG_GPIO_NRFX_INTERRUPT=n CONFIG_MCUBOOT_SERIAL=y CONFIG_MCUBOOT_SERIAL_DIRECT_IMAGE_UPLOAD=y CONFIG_BOOT_SERIAL_CDC_ACM=y From 5962e99f8bb4ca4a014ff98d746e7a32f9a8551b Mon Sep 17 00:00:00 2001 From: Jukka Rissanen Date: Tue, 23 Sep 2025 13:04:30 +0300 Subject: [PATCH 249/420] =?UTF-8?q?Revert=20"[nrf=20noup]=C2=A0loader:=20A?= =?UTF-8?q?dd=20firmware=20version=20check=20downgrade=20prevention"?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This reverts commit 420ac794db054e9a3bae31c6627d5b08920de0ed. Signed-off-by: Jukka Rissanen --- boot/bootutil/src/loader.c | 22 +++------------------- 1 file changed, 3 insertions(+), 19 deletions(-) diff --git a/boot/bootutil/src/loader.c b/boot/bootutil/src/loader.c index a14215c28..6f33cad72 100644 --- a/boot/bootutil/src/loader.c +++ b/boot/bootutil/src/loader.c @@ -52,10 +52,6 @@ #if defined(CONFIG_SOC_NRF5340_CPUAPP) && defined(PM_CPUNET_B0N_ADDRESS) && defined(CONFIG_PCD_APP) #include -#ifdef CONFIG_PCD_READ_NETCORE_APP_VERSION -#include -int pcd_version_cmp_net(const struct flash_area *fap, struct image_header *hdr); -#endif #endif #ifdef MCUBOOT_ENC_IMAGES @@ -1163,21 +1159,9 @@ boot_validate_slot(struct boot_loader_state *state, int slot, int rc; /* Check if version of secondary slot is sufficient */ - -#if defined(CONFIG_SOC_NRF5340_CPUAPP) && defined(CONFIG_NRF53_MULTI_IMAGE_UPDATE) \ - && defined(CONFIG_PCD_APP) && defined(CONFIG_PCD_READ_NETCORE_APP_VERSION) - if (BOOT_CURR_IMG(state) == 1) { - rc = pcd_version_cmp_net(fap, boot_img_hdr(state, BOOT_SECONDARY_SLOT)); - } else { - rc = boot_version_cmp( - &boot_img_hdr(state, BOOT_SECONDARY_SLOT)->ih_ver, - &boot_img_hdr(state, BOOT_PRIMARY_SLOT)->ih_ver); - } -#else - rc = boot_version_cmp( - &boot_img_hdr(state, BOOT_SECONDARY_SLOT)->ih_ver, - &boot_img_hdr(state, BOOT_PRIMARY_SLOT)->ih_ver); -#endif + rc = boot_version_cmp( + &boot_img_hdr(state, BOOT_SECONDARY_SLOT)->ih_ver, + &boot_img_hdr(state, BOOT_PRIMARY_SLOT)->ih_ver); if (rc < 0 && boot_check_header_erased(state, BOOT_PRIMARY_SLOT)) { BOOT_LOG_ERR("insufficient version in secondary slot"); boot_scramble_slot(fap, slot); From bd97bab28e00ee8c13983db835ec64d443acb9c1 Mon Sep 17 00:00:00 2001 From: Jukka Rissanen Date: Tue, 23 Sep 2025 13:04:30 +0300 Subject: [PATCH 250/420] Revert "[nrf noup] zephyr: Boot even if EXT_ABI is not provided" This reverts commit d07555bf0439aeec7c15609c46a85a06fa9be807. Signed-off-by: Jukka Rissanen --- boot/zephyr/main.c | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/boot/zephyr/main.c b/boot/zephyr/main.c index 72d0e72ff..8f846ac05 100644 --- a/boot/zephyr/main.c +++ b/boot/zephyr/main.c @@ -201,16 +201,13 @@ static void do_boot(struct boot_rsp *rsp) #endif #if defined(CONFIG_FW_INFO) && !defined(CONFIG_EXT_API_PROVIDE_EXT_API_UNUSED) - const struct fw_info *firmware_info = fw_info_find((uint32_t) vt); - bool provided = fw_info_ext_api_provide(firmware_info, true); + bool provided = fw_info_ext_api_provide(fw_info_find((uint32_t)vt), true); #ifdef PM_S0_ADDRESS /* Only fail if the immutable bootloader is present. */ if (!provided) { - if (firmware_info == NULL) { - BOOT_LOG_WRN("Unable to find firmware info structure in %p", vt); - } - BOOT_LOG_ERR("Failed to provide EXT_APIs to %p", vt); + BOOT_LOG_ERR("Failed to provide EXT_APIs\n"); + return; } #endif #endif From 2fc18b53e1db6ebec27457817d979f7c9941b861 Mon Sep 17 00:00:00 2001 From: Jukka Rissanen Date: Tue, 23 Sep 2025 13:04:30 +0300 Subject: [PATCH 251/420] Revert "[nrf noup] zephyr: Add RAM flash configuration to cache for sysbuild" This reverts commit c8d8f5a48cf1f17bad6cbc41dfd83a5f584ab005. Signed-off-by: Jukka Rissanen --- boot/zephyr/CMakeLists.txt | 11 ----------- 1 file changed, 11 deletions(-) diff --git a/boot/zephyr/CMakeLists.txt b/boot/zephyr/CMakeLists.txt index 3a94315f8..424cf1315 100644 --- a/boot/zephyr/CMakeLists.txt +++ b/boot/zephyr/CMakeLists.txt @@ -725,14 +725,3 @@ zephyr_library_sources( ${BOOT_DIR}/zephyr/nrf_cleanup.c ) endif() - -if(SYSBUILD AND CONFIG_PCD_APP) - # Sysbuild requires details of the RAM flash device are stored to the cache of MCUboot so - # that they can be read when running partition manager - dt_nodelabel(ram_flash_dev NODELABEL flash_sim0) - dt_reg_addr(ram_flash_addr PATH ${ram_flash_dev}) - dt_reg_size(ram_flash_size PATH ${ram_flash_dev}) - - set(RAM_FLASH_ADDR "${ram_flash_addr}" CACHE STRING "" FORCE) - set(RAM_FLASH_SIZE "${ram_flash_size}" CACHE STRING "" FORCE) -endif() From 0f2ddafbe84c00a1b3b6c2f99c3e36b9424a3902 Mon Sep 17 00:00:00 2001 From: Jukka Rissanen Date: Tue, 23 Sep 2025 13:04:30 +0300 Subject: [PATCH 252/420] Revert "[nrf noup] loader: Do not check reset vector for XIP image" This reverts commit 1ec17e963cb21d6978792e2aaf504838f20b52d8. Signed-off-by: Jukka Rissanen --- boot/bootutil/src/loader.c | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/boot/bootutil/src/loader.c b/boot/bootutil/src/loader.c index 6f33cad72..3e77a0cfb 100644 --- a/boot/bootutil/src/loader.c +++ b/boot/bootutil/src/loader.c @@ -1206,16 +1206,6 @@ boot_validate_slot(struct boot_loader_state *state, int slot, * overwriting an application written to the incorrect slot. * This feature is only supported by ARM platforms. */ -#if MCUBOOT_IMAGE_NUMBER >= 3 - /* Currently the MCUboot can be configured for up to 3 image, where image number 2 is - * designated for XIP, where it is the second part of image stored in slots of image - * 0. This part of image is not bootable, as the XIP setup is done by the app in - * image 0 slot, and it does not carry the reset vector. - */ - if (fap == state->imgs[2][BOOT_SECONDARY_SLOT].area) { - goto out; - } -#endif if (fap == BOOT_IMG_AREA(state, BOOT_SECONDARY_SLOT)) { const struct flash_area *pri_fa = BOOT_IMG_AREA(state, BOOT_PRIMARY_SLOT); struct image_header *secondary_hdr = boot_img_hdr(state, slot); From 82455dd4613e07058515e4aeb08bcf7ce69e7b6f Mon Sep 17 00:00:00 2001 From: Jukka Rissanen Date: Tue, 23 Sep 2025 13:04:30 +0300 Subject: [PATCH 253/420] Revert "[nrf noup] loader: Fix reading reset addr to support ext flash" This reverts commit c1cf5e424057fea8a317bccd88dff62888453ccf. Signed-off-by: Jukka Rissanen --- boot/bootutil/src/loader.c | 25 ++++++++++--------------- 1 file changed, 10 insertions(+), 15 deletions(-) diff --git a/boot/bootutil/src/loader.c b/boot/bootutil/src/loader.c index 3e77a0cfb..9a6f3015c 100644 --- a/boot/bootutil/src/loader.c +++ b/boot/bootutil/src/loader.c @@ -1315,9 +1315,10 @@ boot_validated_swap_type(struct boot_loader_state *state, #if defined(PM_S1_ADDRESS) || defined(CONFIG_SOC_NRF5340_CPUAPP) const struct flash_area *secondary_fa = BOOT_IMG_AREA(state, BOOT_SECONDARY_SLOT); - struct image_header *hdr = boot_img_hdr(state, BOOT_SECONDARY_SLOT); + struct image_header *hdr = (struct image_header *)secondary_fa->fa_off; + uint32_t vtable_addr = 0; + uint32_t *vtable = 0; uint32_t reset_addr = 0; - int rc = 0; /* Patch needed for NCS. Since image 0 (the app) and image 1 (the other * B1 slot S0 or S1) share the same secondary slot, we need to check * whether the update candidate in the secondary slot is intended for @@ -1327,19 +1328,16 @@ boot_validated_swap_type(struct boot_loader_state *state, */ if (hdr->ih_magic == IMAGE_MAGIC) { - rc = flash_area_read(secondary_fa, hdr->ih_hdr_size + - sizeof(uint32_t), &reset_addr, - sizeof(reset_addr)); - if (rc != 0) { - return BOOT_SWAP_TYPE_FAIL; - } + vtable_addr = (uint32_t)hdr + hdr->ih_hdr_size; + vtable = (uint32_t *)(vtable_addr); + reset_addr = vtable[1]; #ifdef PM_S1_ADDRESS #ifdef PM_CPUNET_B0N_ADDRESS if(reset_addr < PM_CPUNET_B0N_ADDRESS) #endif { const struct flash_area *primary_fa; - rc = flash_area_open(flash_area_id_from_multi_image_slot( + int rc = flash_area_open(flash_area_id_from_multi_image_slot( BOOT_CURR_IMG(state), BOOT_PRIMARY_SLOT), &primary_fa); @@ -1375,19 +1373,16 @@ boot_validated_swap_type(struct boot_loader_state *state, upgrade_valid = true; } -#if defined(CONFIG_SOC_NRF5340_CPUAPP) && defined(PM_CPUNET_B0N_ADDRESS) \ - && !defined(CONFIG_NRF53_MULTI_IMAGE_UPDATE) +#if defined(CONFIG_SOC_NRF5340_CPUAPP) && defined(PM_CPUNET_B0N_ADDRESS) /* If the update is valid, and it targets the network core: perform the * update and indicate to the caller of this function that no update is * available */ if (upgrade_valid && reset_addr > PM_CPUNET_B0N_ADDRESS) { - struct image_header *hdr = (struct image_header *)secondary_fa->fa_off; - uint32_t vtable_addr = (uint32_t)hdr + hdr->ih_hdr_size; - uint32_t *net_core_fw_addr = (uint32_t *)(vtable_addr); uint32_t fw_size = hdr->ih_img_size; + BOOT_LOG_INF("Starting network core update"); - rc = pcd_network_core_update(net_core_fw_addr, fw_size); + int rc = pcd_network_core_update(vtable, fw_size); if (rc != 0) { swap_type = BOOT_SWAP_TYPE_FAIL; From 18456267f7a863f25b28028776b6c34517a5addd Mon Sep 17 00:00:00 2001 From: Jukka Rissanen Date: Tue, 23 Sep 2025 13:04:30 +0300 Subject: [PATCH 254/420] Revert "[nrf noup] zephyr: Clean up non-secure RAM if enabled" This reverts commit c9f632d1ddd6774e750577a83b562f5b739249fc. Signed-off-by: Jukka Rissanen --- boot/zephyr/CMakeLists.txt | 2 +- boot/zephyr/include/nrf_cleanup.h | 5 -- boot/zephyr/main.c | 5 +- boot/zephyr/nrf_cleanup.c | 79 ++++++++----------------------- 4 files changed, 22 insertions(+), 69 deletions(-) diff --git a/boot/zephyr/CMakeLists.txt b/boot/zephyr/CMakeLists.txt index 424cf1315..e19f10455 100644 --- a/boot/zephyr/CMakeLists.txt +++ b/boot/zephyr/CMakeLists.txt @@ -720,7 +720,7 @@ if(SYSBUILD) set(mcuboot_image_upgrade_footer_size ${required_upgrade_size} CACHE INTERNAL "Estimated MCUboot update image trailer size" FORCE) endif() -if(CONFIG_MCUBOOT_NRF_CLEANUP_PERIPHERAL OR CONFIG_MCUBOOT_CLEANUP_NONSECURE_RAM) +if(CONFIG_MCUBOOT_NRF_CLEANUP_PERIPHERAL) zephyr_library_sources( ${BOOT_DIR}/zephyr/nrf_cleanup.c ) diff --git a/boot/zephyr/include/nrf_cleanup.h b/boot/zephyr/include/nrf_cleanup.h index 9e87e13f5..6b04cedfe 100644 --- a/boot/zephyr/include/nrf_cleanup.h +++ b/boot/zephyr/include/nrf_cleanup.h @@ -16,9 +16,4 @@ */ void nrf_cleanup_peripheral(void); -/** - * Perform cleanup of non-secure RAM that may have been used by MCUBoot. - */ -void nrf_cleanup_ns_ram(void); - #endif diff --git a/boot/zephyr/main.c b/boot/zephyr/main.c index 8f846ac05..d3d88980a 100644 --- a/boot/zephyr/main.c +++ b/boot/zephyr/main.c @@ -144,7 +144,7 @@ K_SEM_DEFINE(boot_log_sem, 1, 1); #include #endif -#if CONFIG_MCUBOOT_NRF_CLEANUP_PERIPHERAL || CONFIG_MCUBOOT_NRF_CLEANUP_NONSECURE_RAM +#if CONFIG_MCUBOOT_NRF_CLEANUP_PERIPHERAL #include #endif @@ -214,9 +214,6 @@ static void do_boot(struct boot_rsp *rsp) #if CONFIG_MCUBOOT_NRF_CLEANUP_PERIPHERAL nrf_cleanup_peripheral(); #endif -#if CONFIG_MCUBOOT_NRF_CLEANUP_NONSECURE_RAM && defined(PM_SRAM_NONSECURE_NAME) - nrf_cleanup_ns_ram(); -#endif #if CONFIG_MCUBOOT_CLEANUP_ARM_CORE cleanup_arm_nvic(); /* cleanup NVIC registers */ diff --git a/boot/zephyr/nrf_cleanup.c b/boot/zephyr/nrf_cleanup.c index 051705ec9..5bab26b24 100644 --- a/boot/zephyr/nrf_cleanup.c +++ b/boot/zephyr/nrf_cleanup.c @@ -5,8 +5,9 @@ */ #include -#include -#include +#if defined(NRF_UARTE0) || defined(NRF_UARTE1) + #include +#endif #if defined(NRF_RTC0) || defined(NRF_RTC1) || defined(NRF_RTC2) #include #endif @@ -19,15 +20,6 @@ #include -#if USE_PARTITION_MANAGER -#include -#endif - -#if defined(NRF_UARTE0) || defined(NRF_UARTE1) || defined(NRF_UARTE20) || \ - defined(NRF_UARTE30) -#define NRF_UARTE_CLEANUP -#endif - #define NRF_UARTE_SUBSCRIBE_CONF_OFFS offsetof(NRF_UARTE_Type, SUBSCRIBE_STARTRX) #define NRF_UARTE_SUBSCRIBE_CONF_SIZE (offsetof(NRF_UARTE_Type, EVENTS_CTS) -\ NRF_UARTE_SUBSCRIBE_CONF_OFFS) @@ -45,23 +37,6 @@ static inline void nrf_cleanup_rtc(NRF_RTC_Type * rtc_reg) } #endif -#if defined(NRF_UARTE_CLEANUP) -static NRF_UARTE_Type *nrf_uarte_to_clean[] = { -#if defined(NRF_UARTE0) - NRF_UARTE0, -#endif -#if defined(NRF_UARTE1) - NRF_UARTE1, -#endif -#if defined(NRF_UARTE20) - NRF_UARTE20, -#endif -#if defined(NRF_UARTE30) - NRF_UARTE30, -#endif -}; -#endif - static void nrf_cleanup_clock(void) { nrf_clock_int_disable(NRF_CLOCK, 0xFFFFFFFF); @@ -78,31 +53,26 @@ void nrf_cleanup_peripheral(void) #if defined(NRF_RTC2) nrf_cleanup_rtc(NRF_RTC2); #endif - -#if defined(NRF_UARTE_CLEANUP) - for (int i = 0; i < sizeof(nrf_uarte_to_clean) / sizeof(nrf_uarte_to_clean[0]); ++i) { - NRF_UARTE_Type *current = nrf_uarte_to_clean[i]; - - nrfy_uarte_int_disable(current, 0xFFFFFFFF); - nrfy_uarte_int_uninit(current); - nrfy_uarte_task_trigger(current, NRF_UARTE_TASK_STOPRX); - - nrfy_uarte_event_clear(current, NRF_UARTE_EVENT_RXSTARTED); - nrfy_uarte_event_clear(current, NRF_UARTE_EVENT_ENDRX); - nrfy_uarte_event_clear(current, NRF_UARTE_EVENT_RXTO); - nrfy_uarte_disable(current); - +#if defined(NRF_UARTE0) + nrf_uarte_disable(NRF_UARTE0); + nrf_uarte_int_disable(NRF_UARTE0, 0xFFFFFFFF); #if defined(NRF_DPPIC) - /* Clear all SUBSCRIBE configurations. */ - memset((uint8_t *)current + NRF_UARTE_SUBSCRIBE_CONF_OFFS, 0, - NRF_UARTE_SUBSCRIBE_CONF_SIZE); - /* Clear all PUBLISH configurations. */ - memset((uint8_t *)current + NRF_UARTE_PUBLISH_CONF_OFFS, 0, - NRF_UARTE_PUBLISH_CONF_SIZE); + /* Clear all SUBSCRIBE configurations. */ + memset((uint8_t *)NRF_UARTE0 + NRF_UARTE_SUBSCRIBE_CONF_OFFS, 0, NRF_UARTE_SUBSCRIBE_CONF_SIZE); + /* Clear all PUBLISH configurations. */ + memset((uint8_t *)NRF_UARTE0 + NRF_UARTE_PUBLISH_CONF_OFFS, 0, NRF_UARTE_PUBLISH_CONF_SIZE); +#endif +#endif +#if defined(NRF_UARTE1) + nrf_uarte_disable(NRF_UARTE1); + nrf_uarte_int_disable(NRF_UARTE1, 0xFFFFFFFF); +#if defined(NRF_DPPIC) + /* Clear all SUBSCRIBE configurations. */ + memset((uint8_t *)NRF_UARTE1 + NRF_UARTE_SUBSCRIBE_CONF_OFFS, 0, NRF_UARTE_SUBSCRIBE_CONF_SIZE); + /* Clear all PUBLISH configurations. */ + memset((uint8_t *)NRF_UARTE1 + NRF_UARTE_PUBLISH_CONF_OFFS, 0, NRF_UARTE_PUBLISH_CONF_SIZE); #endif - } #endif - #if defined(NRF_PPI) nrf_ppi_channels_disable_all(NRF_PPI); #endif @@ -111,12 +81,3 @@ void nrf_cleanup_peripheral(void) #endif nrf_cleanup_clock(); } - -#if USE_PARTITION_MANAGER \ - && defined(CONFIG_ARM_TRUSTZONE_M) \ - && defined(PM_SRAM_NONSECURE_NAME) -void nrf_cleanup_ns_ram(void) -{ - memset((void *) PM_SRAM_NONSECURE_ADDRESS, 0, PM_SRAM_NONSECURE_SIZE); -} -#endif From d376a7080fb699008a6ce9e391cde75ba54c4f8d Mon Sep 17 00:00:00 2001 From: Jukka Rissanen Date: Tue, 23 Sep 2025 13:04:30 +0300 Subject: [PATCH 255/420] Revert "[nrf noup] zephyr: clean peripherals state before boot" This reverts commit 0f2061be7ecee80c2b2c6772efc719415e89b880. Signed-off-by: Jukka Rissanen --- boot/zephyr/CMakeLists.txt | 6 --- boot/zephyr/include/nrf_cleanup.h | 19 ------- boot/zephyr/main.c | 8 +-- boot/zephyr/nrf_cleanup.c | 83 ------------------------------- 4 files changed, 1 insertion(+), 115 deletions(-) delete mode 100644 boot/zephyr/include/nrf_cleanup.h delete mode 100644 boot/zephyr/nrf_cleanup.c diff --git a/boot/zephyr/CMakeLists.txt b/boot/zephyr/CMakeLists.txt index e19f10455..9424efcc3 100644 --- a/boot/zephyr/CMakeLists.txt +++ b/boot/zephyr/CMakeLists.txt @@ -719,9 +719,3 @@ if(SYSBUILD) set(mcuboot_image_footer_size ${required_size} CACHE INTERNAL "Estimated MCUboot image trailer size" FORCE) set(mcuboot_image_upgrade_footer_size ${required_upgrade_size} CACHE INTERNAL "Estimated MCUboot update image trailer size" FORCE) endif() - -if(CONFIG_MCUBOOT_NRF_CLEANUP_PERIPHERAL) -zephyr_library_sources( - ${BOOT_DIR}/zephyr/nrf_cleanup.c -) -endif() diff --git a/boot/zephyr/include/nrf_cleanup.h b/boot/zephyr/include/nrf_cleanup.h deleted file mode 100644 index 6b04cedfe..000000000 --- a/boot/zephyr/include/nrf_cleanup.h +++ /dev/null @@ -1,19 +0,0 @@ -/* - * Copyright (c) 2020 Nordic Semiconductor ASA - * - * SPDX-License-Identifier: LicenseRef-Nordic-5-Clause - */ - -#ifndef H_NRF_CLEANUP_ -#define H_NRF_CLEANUP_ - -/** - * Perform cleanup on some peripheral resources used by MCUBoot prior chainload - * the application. - * - * This function disables all RTC instances and UARTE instances. - * It Disables their interrupts signals as well. - */ -void nrf_cleanup_peripheral(void); - -#endif diff --git a/boot/zephyr/main.c b/boot/zephyr/main.c index d3d88980a..c243a1ac7 100644 --- a/boot/zephyr/main.c +++ b/boot/zephyr/main.c @@ -144,10 +144,6 @@ K_SEM_DEFINE(boot_log_sem, 1, 1); #include #endif -#if CONFIG_MCUBOOT_NRF_CLEANUP_PERIPHERAL -#include -#endif - BOOT_LOG_MODULE_REGISTER(mcuboot); void os_heap_init(void); @@ -211,9 +207,7 @@ static void do_boot(struct boot_rsp *rsp) } #endif #endif -#if CONFIG_MCUBOOT_NRF_CLEANUP_PERIPHERAL - nrf_cleanup_peripheral(); -#endif + #if CONFIG_MCUBOOT_CLEANUP_ARM_CORE cleanup_arm_nvic(); /* cleanup NVIC registers */ diff --git a/boot/zephyr/nrf_cleanup.c b/boot/zephyr/nrf_cleanup.c deleted file mode 100644 index 5bab26b24..000000000 --- a/boot/zephyr/nrf_cleanup.c +++ /dev/null @@ -1,83 +0,0 @@ -/* - * Copyright (c) 2020 Nordic Semiconductor ASA - * - * SPDX-License-Identifier: LicenseRef-Nordic-5-Clause - */ - -#include -#if defined(NRF_UARTE0) || defined(NRF_UARTE1) - #include -#endif -#if defined(NRF_RTC0) || defined(NRF_RTC1) || defined(NRF_RTC2) - #include -#endif -#if defined(NRF_PPI) - #include -#endif -#if defined(NRF_DPPIC) - #include -#endif - -#include - -#define NRF_UARTE_SUBSCRIBE_CONF_OFFS offsetof(NRF_UARTE_Type, SUBSCRIBE_STARTRX) -#define NRF_UARTE_SUBSCRIBE_CONF_SIZE (offsetof(NRF_UARTE_Type, EVENTS_CTS) -\ - NRF_UARTE_SUBSCRIBE_CONF_OFFS) - -#define NRF_UARTE_PUBLISH_CONF_OFFS offsetof(NRF_UARTE_Type, PUBLISH_CTS) -#define NRF_UARTE_PUBLISH_CONF_SIZE (offsetof(NRF_UARTE_Type, SHORTS) -\ - NRF_UARTE_PUBLISH_CONF_OFFS) - -#if defined(NRF_RTC0) || defined(NRF_RTC1) || defined(NRF_RTC2) -static inline void nrf_cleanup_rtc(NRF_RTC_Type * rtc_reg) -{ - nrf_rtc_task_trigger(rtc_reg, NRF_RTC_TASK_STOP); - nrf_rtc_event_disable(rtc_reg, 0xFFFFFFFF); - nrf_rtc_int_disable(rtc_reg, 0xFFFFFFFF); -} -#endif - -static void nrf_cleanup_clock(void) -{ - nrf_clock_int_disable(NRF_CLOCK, 0xFFFFFFFF); -} - -void nrf_cleanup_peripheral(void) -{ -#if defined(NRF_RTC0) - nrf_cleanup_rtc(NRF_RTC0); -#endif -#if defined(NRF_RTC1) - nrf_cleanup_rtc(NRF_RTC1); -#endif -#if defined(NRF_RTC2) - nrf_cleanup_rtc(NRF_RTC2); -#endif -#if defined(NRF_UARTE0) - nrf_uarte_disable(NRF_UARTE0); - nrf_uarte_int_disable(NRF_UARTE0, 0xFFFFFFFF); -#if defined(NRF_DPPIC) - /* Clear all SUBSCRIBE configurations. */ - memset((uint8_t *)NRF_UARTE0 + NRF_UARTE_SUBSCRIBE_CONF_OFFS, 0, NRF_UARTE_SUBSCRIBE_CONF_SIZE); - /* Clear all PUBLISH configurations. */ - memset((uint8_t *)NRF_UARTE0 + NRF_UARTE_PUBLISH_CONF_OFFS, 0, NRF_UARTE_PUBLISH_CONF_SIZE); -#endif -#endif -#if defined(NRF_UARTE1) - nrf_uarte_disable(NRF_UARTE1); - nrf_uarte_int_disable(NRF_UARTE1, 0xFFFFFFFF); -#if defined(NRF_DPPIC) - /* Clear all SUBSCRIBE configurations. */ - memset((uint8_t *)NRF_UARTE1 + NRF_UARTE_SUBSCRIBE_CONF_OFFS, 0, NRF_UARTE_SUBSCRIBE_CONF_SIZE); - /* Clear all PUBLISH configurations. */ - memset((uint8_t *)NRF_UARTE1 + NRF_UARTE_PUBLISH_CONF_OFFS, 0, NRF_UARTE_PUBLISH_CONF_SIZE); -#endif -#endif -#if defined(NRF_PPI) - nrf_ppi_channels_disable_all(NRF_PPI); -#endif -#if defined(NRF_DPPIC) - nrf_dppi_channels_disable_all(NRF_DPPIC); -#endif - nrf_cleanup_clock(); -} From 3854eda483451c4f4970130363f264ee34d50926 Mon Sep 17 00:00:00 2001 From: Jukka Rissanen Date: Tue, 23 Sep 2025 13:04:30 +0300 Subject: [PATCH 256/420] Revert "[nrf noup] boot: nrf53-specific customizations" This reverts commit 2cdbcb02a960f625e7a067f37ab573a4ebaa03a7. Signed-off-by: Jukka Rissanen --- boot/bootutil/src/loader.c | 96 +++++-------------- .../boards/thingy53_nrf5340_cpuapp.conf | 74 +------------- boot/zephyr/include/sysflash/sysflash.h | 23 ----- boot/zephyr/main.c | 7 -- boot/zephyr/pm.yml | 13 --- 5 files changed, 28 insertions(+), 185 deletions(-) diff --git a/boot/bootutil/src/loader.c b/boot/bootutil/src/loader.c index 9a6f3015c..d6092d86b 100644 --- a/boot/bootutil/src/loader.c +++ b/boot/bootutil/src/loader.c @@ -50,10 +50,6 @@ #include "bootutil/boot_hooks.h" #include "bootutil/mcuboot_status.h" -#if defined(CONFIG_SOC_NRF5340_CPUAPP) && defined(PM_CPUNET_B0N_ADDRESS) && defined(CONFIG_PCD_APP) -#include -#endif - #ifdef MCUBOOT_ENC_IMAGES #include "bootutil/enc_key.h" #endif @@ -1310,15 +1306,7 @@ boot_validated_swap_type(struct boot_loader_state *state, { int swap_type; FIH_DECLARE(fih_rc, FIH_FAILURE); - bool upgrade_valid = false; - -#if defined(PM_S1_ADDRESS) || defined(CONFIG_SOC_NRF5340_CPUAPP) - const struct flash_area *secondary_fa = - BOOT_IMG_AREA(state, BOOT_SECONDARY_SLOT); - struct image_header *hdr = (struct image_header *)secondary_fa->fa_off; - uint32_t vtable_addr = 0; - uint32_t *vtable = 0; - uint32_t reset_addr = 0; +#ifdef PM_S1_ADDRESS /* Patch needed for NCS. Since image 0 (the app) and image 1 (the other * B1 slot S0 or S1) share the same secondary slot, we need to check * whether the update candidate in the secondary slot is intended for @@ -1326,36 +1314,34 @@ boot_validated_swap_type(struct boot_loader_state *state, * vector. Note that there are good reasons for not using img_num from * the swap info. */ + const struct flash_area *secondary_fa = + BOOT_IMG_AREA(state, BOOT_SECONDARY_SLOT); + struct image_header *hdr = + (struct image_header *)secondary_fa->fa_off; if (hdr->ih_magic == IMAGE_MAGIC) { - vtable_addr = (uint32_t)hdr + hdr->ih_hdr_size; - vtable = (uint32_t *)(vtable_addr); - reset_addr = vtable[1]; -#ifdef PM_S1_ADDRESS -#ifdef PM_CPUNET_B0N_ADDRESS - if(reset_addr < PM_CPUNET_B0N_ADDRESS) -#endif - { - const struct flash_area *primary_fa; - int rc = flash_area_open(flash_area_id_from_multi_image_slot( - BOOT_CURR_IMG(state), - BOOT_PRIMARY_SLOT), - &primary_fa); - - if (rc != 0) { - return BOOT_SWAP_TYPE_FAIL; - } - /* Get start and end of primary slot for current image */ - if (reset_addr < primary_fa->fa_off || - reset_addr > (primary_fa->fa_off + primary_fa->fa_size)) { - /* The image in the secondary slot is not intended for this image - */ - return BOOT_SWAP_TYPE_NONE; - } - } -#endif /* PM_S1_ADDRESS */ + const struct flash_area *primary_fa; + uint32_t vtable_addr = (uint32_t)hdr + hdr->ih_hdr_size; + uint32_t *vtable = (uint32_t *)(vtable_addr); + uint32_t reset_addr = vtable[1]; + int rc = flash_area_open( + flash_area_id_from_multi_image_slot( + BOOT_CURR_IMG(state), + BOOT_PRIMARY_SLOT), + &primary_fa); + + if (rc != 0) { + return BOOT_SWAP_TYPE_FAIL; + } + /* Get start and end of primary slot for current image */ + if (reset_addr < primary_fa->fa_off || + reset_addr > (primary_fa->fa_off + primary_fa->fa_size)) { + /* The image in the secondary slot is not intended for this image + */ + return BOOT_SWAP_TYPE_NONE; + } } -#endif /* PM_S1_ADDRESS || CONFIG_SOC_NRF5340_CPUAPP */ +#endif swap_type = boot_swap_type_multi(BOOT_CURR_IMG(state)); if (BOOT_IS_UPGRADE(swap_type)) { @@ -1369,37 +1355,7 @@ boot_validated_swap_type(struct boot_loader_state *state, } else { swap_type = BOOT_SWAP_TYPE_FAIL; } - } else { - upgrade_valid = true; - } - -#if defined(CONFIG_SOC_NRF5340_CPUAPP) && defined(PM_CPUNET_B0N_ADDRESS) - /* If the update is valid, and it targets the network core: perform the - * update and indicate to the caller of this function that no update is - * available - */ - if (upgrade_valid && reset_addr > PM_CPUNET_B0N_ADDRESS) { - uint32_t fw_size = hdr->ih_img_size; - - BOOT_LOG_INF("Starting network core update"); - int rc = pcd_network_core_update(vtable, fw_size); - - if (rc != 0) { - swap_type = BOOT_SWAP_TYPE_FAIL; - } else { - BOOT_LOG_INF("Done updating network core"); -#if defined(MCUBOOT_SWAP_USING_SCRATCH) || defined(MCUBOOT_SWAP_USING_MOVE) - /* swap_erase_trailer_sectors is undefined if upgrade only - * method is used. There is no need to erase sectors, because - * the image cannot be reverted. - */ - rc = swap_erase_trailer_sectors(state, - secondary_fa); -#endif - swap_type = BOOT_SWAP_TYPE_NONE; - } } -#endif /* CONFIG_SOC_NRF5340_CPUAPP */ } return swap_type; diff --git a/boot/zephyr/boards/thingy53_nrf5340_cpuapp.conf b/boot/zephyr/boards/thingy53_nrf5340_cpuapp.conf index 93be36738..f2e42fd64 100644 --- a/boot/zephyr/boards/thingy53_nrf5340_cpuapp.conf +++ b/boot/zephyr/boards/thingy53_nrf5340_cpuapp.conf @@ -1,73 +1,3 @@ -CONFIG_SIZE_OPTIMIZATIONS=y - -CONFIG_SYSTEM_CLOCK_NO_WAIT=y -CONFIG_PM=n - -CONFIG_MAIN_STACK_SIZE=10240 -CONFIG_MBEDTLS_CFG_FILE="mcuboot-mbedtls-cfg.h" - -CONFIG_BOOT_MAX_IMG_SECTORS=2048 -CONFIG_BOOT_SIGNATURE_TYPE_RSA=y - -# Flash -CONFIG_FLASH=y -CONFIG_BOOT_ERASE_PROGRESSIVELY=y -CONFIG_SOC_FLASH_NRF_EMULATE_ONE_BYTE_WRITE_ACCESS=y -CONFIG_FPROTECT=y - -# Serial -CONFIG_SERIAL=y -CONFIG_UART_LINE_CTRL=y - -# MCUBoot serial -CONFIG_GPIO=y -CONFIG_MCUBOOT_SERIAL=y -CONFIG_MCUBOOT_SERIAL_DIRECT_IMAGE_UPLOAD=y -CONFIG_BOOT_SERIAL_CDC_ACM=y - -# Required by QSPI -CONFIG_NORDIC_QSPI_NOR=y -CONFIG_NORDIC_QSPI_NOR_FLASH_LAYOUT_PAGE_SIZE=4096 -CONFIG_NORDIC_QSPI_NOR_STACK_WRITE_BUFFER_SIZE=16 - -# Required by USB -CONFIG_MULTITHREADING=y - -# USB -CONFIG_BOARD_SERIAL_BACKEND_CDC_ACM=n -CONFIG_USB_DEVICE_REMOTE_WAKEUP=n -CONFIG_USB_DEVICE_MANUFACTURER="Nordic Semiconductor ASA" -CONFIG_USB_DEVICE_PRODUCT="Bootloader Thingy:53" -CONFIG_USB_DEVICE_VID=0x1915 -CONFIG_USB_DEVICE_PID=0x5300 -CONFIG_USB_CDC_ACM=y - -# Decrease memory footprint -CONFIG_CBPRINTF_NANO=y -CONFIG_TIMESLICING=n -CONFIG_BOOT_BANNER=n -CONFIG_CONSOLE=n -CONFIG_CONSOLE_HANDLER=n -CONFIG_UART_CONSOLE=n -CONFIG_USE_SEGGER_RTT=n -CONFIG_LOG=n -CONFIG_ERRNO=n -CONFIG_PRINTK=n -CONFIG_RESET_ON_FATAL_ERROR=n +CONFIG_NORDIC_QSPI_NOR=n CONFIG_SPI=n -CONFIG_I2C=n -CONFIG_UART_NRFX=n - -# The following configurations are required to support simultaneous multi image update -CONFIG_PCD_APP=y -CONFIG_UPDATEABLE_IMAGE_NUMBER=2 -CONFIG_BOOT_UPGRADE_ONLY=y -# The network core cannot access external flash directly. The flash simulator must be used to -# provide a memory region that is used to forward the new firmware to the network core. -CONFIG_FLASH_SIMULATOR=y -CONFIG_FLASH_SIMULATOR_DOUBLE_WRITES=y -CONFIG_FLASH_SIMULATOR_STATS=n - -# Enable custom command to erase settings partition. -CONFIG_ENABLE_MGMT_PERUSER=y -CONFIG_BOOT_MGMT_CUSTOM_STORAGE_ERASE=y +CONFIG_MULTITHREADING=y diff --git a/boot/zephyr/include/sysflash/sysflash.h b/boot/zephyr/include/sysflash/sysflash.h index 7112f9baa..99cbf56b7 100644 --- a/boot/zephyr/include/sysflash/sysflash.h +++ b/boot/zephyr/include/sysflash/sysflash.h @@ -20,11 +20,6 @@ #elif (MCUBOOT_IMAGE_NUMBER == 2) -/* If B0 is present then two bootloaders are present, and we must use - * a single secondary slot for both primary slots. - */ -#ifdef PM_B0_ADDRESS - extern uint32_t _image_1_primary_slot_id[]; #define FLASH_AREA_IMAGE_PRIMARY(x) \ @@ -40,24 +35,6 @@ extern uint32_t _image_1_primary_slot_id[]; (x == 1) ? \ PM_MCUBOOT_SECONDARY_ID: \ 255 ) -#else - -#define FLASH_AREA_IMAGE_PRIMARY(x) \ - ((x == 0) ? \ - PM_MCUBOOT_PRIMARY_ID : \ - (x == 1) ? \ - PM_MCUBOOT_PRIMARY_1_ID : \ - 255 ) - -#define FLASH_AREA_IMAGE_SECONDARY(x) \ - ((x == 0) ? \ - PM_MCUBOOT_SECONDARY_ID: \ - (x == 1) ? \ - PM_MCUBOOT_SECONDARY_1_ID: \ - 255 ) - -#endif /* PM_B0_ADDRESS */ - #endif #define FLASH_AREA_IMAGE_SCRATCH PM_MCUBOOT_SCRATCH_ID diff --git a/boot/zephyr/main.c b/boot/zephyr/main.c index c243a1ac7..b61b535e0 100644 --- a/boot/zephyr/main.c +++ b/boot/zephyr/main.c @@ -93,10 +93,6 @@ const struct boot_uart_funcs boot_funcs = { #include #endif -#if defined(CONFIG_SOC_NRF5340_CPUAPP) && defined(PM_CPUNET_B0N_ADDRESS) && defined(CONFIG_PCD_APP) -#include -#endif - /* CONFIG_LOG_MINIMAL is the legacy Kconfig property, * replaced by CONFIG_LOG_MODE_MINIMAL. */ @@ -652,9 +648,6 @@ int main(void) ; } -#if defined(CONFIG_SOC_NRF5340_CPUAPP) && defined(PM_CPUNET_B0N_ADDRESS) && defined(CONFIG_PCD_APP) - pcd_lock_ram(); -#endif #endif /* USE_PARTITION_MANAGER && CONFIG_FPROTECT */ ZEPHYR_BOOT_LOG_STOP(); diff --git a/boot/zephyr/pm.yml b/boot/zephyr/pm.yml index 13ffc44aa..5df9ae547 100644 --- a/boot/zephyr/pm.yml +++ b/boot/zephyr/pm.yml @@ -75,16 +75,3 @@ mcuboot_pad: #ifdef CONFIG_FPROTECT align: {start: CONFIG_FPROTECT_BLOCK_SIZE} #endif - -#if (CONFIG_NRF53_MCUBOOT_PRIMARY_1_RAM_FLASH) -mcuboot_primary_1: - region: ram_flash - size: CONFIG_NRF53_RAM_FLASH_SIZE -#endif /* CONFIG_NRF53_MULTI_IMAGE_UPDATE */ - -#if (CONFIG_NRF53_MULTI_IMAGE_UPDATE) -mcuboot_secondary_1: - region: external_flash - size: CONFIG_NRF53_RAM_FLASH_SIZE - -#endif /* CONFIG_NRF53_MULTI_IMAGE_UPDATE */ From 521ea52b53cbc8e7a9a118c53a79f176d8077b27 Mon Sep 17 00:00:00 2001 From: Jukka Rissanen Date: Tue, 23 Sep 2025 13:04:30 +0300 Subject: [PATCH 257/420] Revert "[nrf noup] treewide: add NCS partition manager support" This reverts commit 89361bdec45690575952743ef65bc357977ddbb9. Signed-off-by: Jukka Rissanen --- boot/bootutil/src/loader.c | 95 +++---------------------- boot/bootutil/src/swap_move.c | 13 ---- boot/bootutil/src/swap_scratch.c | 13 ---- boot/zephyr/CMakeLists.txt | 7 -- boot/zephyr/Kconfig | 2 - boot/zephyr/include/sysflash/sysflash.h | 48 ------------- boot/zephyr/include/target.h | 4 -- boot/zephyr/main.c | 45 ------------ boot/zephyr/pm.yml | 77 -------------------- boot/zephyr/prj.conf | 1 - ext/nrf/cc310_glue.h | 2 +- zephyr/module.yml | 3 +- 12 files changed, 11 insertions(+), 299 deletions(-) delete mode 100644 boot/zephyr/pm.yml diff --git a/boot/bootutil/src/loader.c b/boot/bootutil/src/loader.c index d6092d86b..8c73f7652 100644 --- a/boot/bootutil/src/loader.c +++ b/boot/bootutil/src/loader.c @@ -145,15 +145,6 @@ boot_read_image_headers(struct boot_loader_state *state, bool require_all, * * Failure to read any headers is a fatal error. */ -#ifdef PM_S1_ADDRESS - /* Patch needed for NCS. The primary slot of the second image - * (image 1) will not contain a valid image header until an upgrade - * of mcuboot has happened (filling S1 with the new version). - */ - if (BOOT_CURR_IMG(state) == 1 && i == 0) { - continue; - } -#endif /* PM_S1_ADDRESS */ if (i > 0 && !require_all) { return 0; } else { @@ -1213,24 +1204,7 @@ boot_validate_slot(struct boot_loader_state *state, int slot, goto out; } - uint32_t min_addr, max_addr; - -#ifdef PM_CPUNET_APP_ADDRESS - /* The primary slot for the network core is emulated in RAM. - * Its flash_area hasn't got relevant boundaries. - * Therfore need to override its boundaries for the check. - */ - if (BOOT_CURR_IMG(state) == 1) { - min_addr = PM_CPUNET_APP_ADDRESS; - max_addr = PM_CPUNET_APP_ADDRESS + PM_CPUNET_APP_SIZE; - } else -#endif - { - min_addr = pri_fa->fa_off; - max_addr = pri_fa->fa_off + pri_fa->fa_size; - } - - if (reset_value < min_addr || reset_value> (max_addr)) { + if (reset_value < pri_fa->fa_off || reset_value> (pri_fa->fa_off + pri_fa->fa_size)) { BOOT_LOG_ERR("Reset address of image in secondary slot is not in the primary slot"); BOOT_LOG_ERR("Erasing image from secondary slot"); @@ -1306,42 +1280,6 @@ boot_validated_swap_type(struct boot_loader_state *state, { int swap_type; FIH_DECLARE(fih_rc, FIH_FAILURE); -#ifdef PM_S1_ADDRESS - /* Patch needed for NCS. Since image 0 (the app) and image 1 (the other - * B1 slot S0 or S1) share the same secondary slot, we need to check - * whether the update candidate in the secondary slot is intended for - * image 0 or image 1 primary by looking at the address of the reset - * vector. Note that there are good reasons for not using img_num from - * the swap info. - */ - const struct flash_area *secondary_fa = - BOOT_IMG_AREA(state, BOOT_SECONDARY_SLOT); - struct image_header *hdr = - (struct image_header *)secondary_fa->fa_off; - - if (hdr->ih_magic == IMAGE_MAGIC) { - const struct flash_area *primary_fa; - uint32_t vtable_addr = (uint32_t)hdr + hdr->ih_hdr_size; - uint32_t *vtable = (uint32_t *)(vtable_addr); - uint32_t reset_addr = vtable[1]; - int rc = flash_area_open( - flash_area_id_from_multi_image_slot( - BOOT_CURR_IMG(state), - BOOT_PRIMARY_SLOT), - &primary_fa); - - if (rc != 0) { - return BOOT_SWAP_TYPE_FAIL; - } - /* Get start and end of primary slot for current image */ - if (reset_addr < primary_fa->fa_off || - reset_addr > (primary_fa->fa_off + primary_fa->fa_size)) { - /* The image in the secondary slot is not intended for this image - */ - return BOOT_SWAP_TYPE_NONE; - } - } -#endif swap_type = boot_swap_type_multi(BOOT_CURR_IMG(state)); if (BOOT_IS_UPGRADE(swap_type)) { @@ -2717,25 +2655,15 @@ context_boot_go(struct boot_loader_state *state, struct boot_rsp *rsp) } #ifdef MCUBOOT_VALIDATE_PRIMARY_SLOT -#ifdef PM_S1_ADDRESS - /* Patch needed for NCS. Image 1 primary is the currently - * executing MCUBoot image, and is therefore already validated by NSIB and - * does not need to also be validated by MCUBoot. + FIH_CALL(boot_validate_slot, fih_rc, state, BOOT_PRIMARY_SLOT, NULL, 0); + /* Check for all possible values is redundant in normal operation it + * is meant to prevent FI attack. */ - bool image_validated_by_nsib = BOOT_CURR_IMG(state) == 1; - if (!image_validated_by_nsib) -#endif - { - FIH_CALL(boot_validate_slot, fih_rc, state, BOOT_PRIMARY_SLOT, NULL, 0); - /* Check for all possible values is redundant in normal operation it - * is meant to prevent FI attack. - */ - if (FIH_NOT_EQ(fih_rc, FIH_SUCCESS) || - FIH_EQ(fih_rc, FIH_FAILURE) || - FIH_EQ(fih_rc, FIH_NO_BOOTABLE_IMAGE)) { - FIH_SET(fih_rc, FIH_FAILURE); - goto out; - } + if (FIH_NOT_EQ(fih_rc, FIH_SUCCESS) || + FIH_EQ(fih_rc, FIH_FAILURE) || + FIH_EQ(fih_rc, FIH_NO_BOOTABLE_IMAGE)) { + FIH_SET(fih_rc, FIH_FAILURE); + goto out; } #else /* Even if we're not re-validating the primary slot, we could be booting @@ -2752,16 +2680,11 @@ context_boot_go(struct boot_loader_state *state, struct boot_rsp *rsp) } #endif /* MCUBOOT_VALIDATE_PRIMARY_SLOT */ -#ifdef PM_S1_ADDRESS - if (!image_validated_by_nsib) -#endif - { rc = boot_update_hw_rollback_protection(state); if (rc != 0) { FIH_SET(fih_rc, FIH_FAILURE); goto out; } - } rc = boot_add_shared_data(state, BOOT_PRIMARY_SLOT); if (rc != 0) { diff --git a/boot/bootutil/src/swap_move.c b/boot/bootutil/src/swap_move.c index ed0947076..8b7bcab13 100644 --- a/boot/bootutil/src/swap_move.c +++ b/boot/bootutil/src/swap_move.c @@ -230,18 +230,6 @@ boot_status_internal_off(const struct boot_status *bs, int elem_sz) int boot_slots_compatible(struct boot_loader_state *state) { -#ifdef PM_S1_ADDRESS - /* Patch needed for NCS. In this case, image 1 primary points to the other - * B1 slot (ie S0 or S1), and image 0 primary points to the app. - * With this configuration, image 0 and image 1 share the secondary slot. - * Hence, the primary slot of image 1 will be *smaller* than image 1's - * secondary slot. This is not allowed in upstream mcuboot, so we need - * this patch to allow it. Also, all of these checks are redundant when - * partition manager is in use, and since we have the same sector size - * in all of our flash. - */ - return 1; -#else size_t num_sectors_pri; size_t num_sectors_sec; size_t sector_sz_pri = 0; @@ -307,7 +295,6 @@ boot_slots_compatible(struct boot_loader_state *state) } return 1; -#endif /* PM_S1_ADDRESS */ } #define BOOT_LOG_SWAP_STATE(area, state) \ diff --git a/boot/bootutil/src/swap_scratch.c b/boot/bootutil/src/swap_scratch.c index 360dbe88c..e1d49de49 100644 --- a/boot/bootutil/src/swap_scratch.c +++ b/boot/bootutil/src/swap_scratch.c @@ -271,18 +271,6 @@ boot_status_internal_off(const struct boot_status *bs, int elem_sz) int boot_slots_compatible(struct boot_loader_state *state) { -#ifdef PM_S1_ADDRESS - /* Patch needed for NCS. In this case, image 1 primary points to the other - * B1 slot (ie S0 or S1), and image 0 primary points to the app. - * With this configuration, image 0 and image 1 share the secondary slot. - * Hence, the primary slot of image 1 will be *smaller* than image 1's - * secondary slot. This is not allowed in upstream mcuboot, so we need - * this patch to allow it. Also, all of these checks are redundant when - * partition manager is in use, and since we have the same sector size - * in all of our flash. - */ - return 1; -#else size_t num_sectors_primary; size_t num_sectors_secondary; size_t sz0, sz1; @@ -380,7 +368,6 @@ boot_slots_compatible(struct boot_loader_state *state) #endif return 1; -#endif /* PM_S1_ADDRESS */ } #define BOOT_LOG_SWAP_STATE(area, state) \ diff --git a/boot/zephyr/CMakeLists.txt b/boot/zephyr/CMakeLists.txt index 9424efcc3..b0e43cd50 100644 --- a/boot/zephyr/CMakeLists.txt +++ b/boot/zephyr/CMakeLists.txt @@ -355,13 +355,6 @@ if(NOT CONFIG_BOOT_SIGNATURE_KEY_FILE STREQUAL "") endif() message("MCUBoot bootloader key file: ${KEY_FILE}") - set_property( - GLOBAL - PROPERTY - KEY_FILE - ${KEY_FILE} - ) - set(mcuboot_default_signature_files ${MCUBOOT_DIR}/root-ec-p256-pkcs8.pem ${MCUBOOT_DIR}/root-ec-p384.pem diff --git a/boot/zephyr/Kconfig b/boot/zephyr/Kconfig index c37911f8e..0e8265002 100644 --- a/boot/zephyr/Kconfig +++ b/boot/zephyr/Kconfig @@ -9,8 +9,6 @@ mainmenu "MCUboot configuration" comment "MCUboot-specific configuration options" -source "$(ZEPHYR_NRF_MODULE_DIR)/modules/mcuboot/boot/zephyr/Kconfig" - # Hidden option to mark a project as MCUboot config MCUBOOT default y diff --git a/boot/zephyr/include/sysflash/sysflash.h b/boot/zephyr/include/sysflash/sysflash.h index 99cbf56b7..16d222280 100644 --- a/boot/zephyr/include/sysflash/sysflash.h +++ b/boot/zephyr/include/sysflash/sysflash.h @@ -7,52 +7,6 @@ #ifndef __SYSFLASH_H__ #define __SYSFLASH_H__ -#if USE_PARTITION_MANAGER -#include -#include - -#ifndef CONFIG_SINGLE_APPLICATION_SLOT - -#if (MCUBOOT_IMAGE_NUMBER == 1) - -#define FLASH_AREA_IMAGE_PRIMARY(x) PM_MCUBOOT_PRIMARY_ID -#define FLASH_AREA_IMAGE_SECONDARY(x) PM_MCUBOOT_SECONDARY_ID - -#elif (MCUBOOT_IMAGE_NUMBER == 2) - -extern uint32_t _image_1_primary_slot_id[]; - -#define FLASH_AREA_IMAGE_PRIMARY(x) \ - ((x == 0) ? \ - PM_MCUBOOT_PRIMARY_ID : \ - (x == 1) ? \ - (uint32_t)_image_1_primary_slot_id : \ - 255 ) - -#define FLASH_AREA_IMAGE_SECONDARY(x) \ - ((x == 0) ? \ - PM_MCUBOOT_SECONDARY_ID: \ - (x == 1) ? \ - PM_MCUBOOT_SECONDARY_ID: \ - 255 ) -#endif -#define FLASH_AREA_IMAGE_SCRATCH PM_MCUBOOT_SCRATCH_ID - -#else /* CONFIG_SINGLE_APPLICATION_SLOT */ - -#define FLASH_AREA_IMAGE_PRIMARY(x) PM_MCUBOOT_PRIMARY_ID -#define FLASH_AREA_IMAGE_SECONDARY(x) PM_MCUBOOT_PRIMARY_ID -/* NOTE: Scratch parition is not used by single image DFU but some of - * functions in common files reference it, so the definitions has been - * provided to allow compilation of common units. - */ -#define FLASH_AREA_IMAGE_SCRATCH 0 - -#endif /* CONFIG_SINGLE_APPLICATION_SLOT */ - -#else - -#include #include #include #include @@ -111,6 +65,4 @@ static inline uint32_t __flash_area_ids_for_slot(int img, int slot) #endif /* CONFIG_SINGLE_APPLICATION_SLOT */ -#endif /* USE_PARTITION_MANAGER */ - #endif /* __SYSFLASH_H__ */ diff --git a/boot/zephyr/include/target.h b/boot/zephyr/include/target.h index 856686785..ea160752e 100644 --- a/boot/zephyr/include/target.h +++ b/boot/zephyr/include/target.h @@ -8,8 +8,6 @@ #ifndef H_TARGETS_TARGET_ #define H_TARGETS_TARGET_ -#ifndef USE_PARTITION_MANAGER - #if defined(MCUBOOT_TARGET_CONFIG) /* * Target-specific definitions are permitted in legacy cases that @@ -49,6 +47,4 @@ #error "Target support is incomplete; cannot build mcuboot." #endif -#endif /* ifndef USE_PARTITION_MANAGER */ - #endif /* H_TARGETS_TARGET_ */ diff --git a/boot/zephyr/main.c b/boot/zephyr/main.c index b61b535e0..0cb793b2d 100644 --- a/boot/zephyr/main.c +++ b/boot/zephyr/main.c @@ -71,10 +71,6 @@ #endif /* CONFIG_SOC_FAMILY_ESPRESSIF_ESP32 */ -#ifdef CONFIG_FW_INFO -#include -#endif - #ifdef CONFIG_MCUBOOT_SERIAL #include "boot_serial/boot_serial.h" #include "serial_adapter/serial_adapter.h" @@ -135,11 +131,6 @@ K_SEM_DEFINE(boot_log_sem, 1, 1); * !defined(ZEPHYR_LOG_MODE_MINIMAL) */ -#if USE_PARTITION_MANAGER && CONFIG_FPROTECT -#include -#include -#endif - BOOT_LOG_MODULE_REGISTER(mcuboot); void os_heap_init(void); @@ -191,19 +182,6 @@ static void do_boot(struct boot_rsp *rsp) /* Disable the USB to prevent it from firing interrupts */ usb_disable(); #endif - -#if defined(CONFIG_FW_INFO) && !defined(CONFIG_EXT_API_PROVIDE_EXT_API_UNUSED) - bool provided = fw_info_ext_api_provide(fw_info_find((uint32_t)vt), true); - -#ifdef PM_S0_ADDRESS - /* Only fail if the immutable bootloader is present. */ - if (!provided) { - BOOT_LOG_ERR("Failed to provide EXT_APIs\n"); - return; - } -#endif -#endif - #if CONFIG_MCUBOOT_CLEANUP_ARM_CORE cleanup_arm_nvic(); /* cleanup NVIC registers */ @@ -628,30 +606,7 @@ int main(void) mcuboot_status_change(MCUBOOT_STATUS_BOOTABLE_IMAGE_FOUND); -#if USE_PARTITION_MANAGER && CONFIG_FPROTECT - -#ifdef PM_S1_ADDRESS -/* MCUBoot is stored in either S0 or S1, protect both */ -#define PROTECT_SIZE (PM_MCUBOOT_PRIMARY_ADDRESS - PM_S0_ADDRESS) -#define PROTECT_ADDR PM_S0_ADDRESS -#else -/* There is only one instance of MCUBoot */ -#define PROTECT_SIZE (PM_MCUBOOT_PRIMARY_ADDRESS - PM_MCUBOOT_ADDRESS) -#define PROTECT_ADDR PM_MCUBOOT_ADDRESS -#endif - - rc = fprotect_area(PROTECT_ADDR, PROTECT_SIZE); - - if (rc != 0) { - BOOT_LOG_ERR("Protect mcuboot flash failed, cancel startup."); - while (1) - ; - } - -#endif /* USE_PARTITION_MANAGER && CONFIG_FPROTECT */ - ZEPHYR_BOOT_LOG_STOP(); - do_boot(&rsp); mcuboot_status_change(MCUBOOT_STATUS_BOOT_FAILED); diff --git a/boot/zephyr/pm.yml b/boot/zephyr/pm.yml deleted file mode 100644 index 5df9ae547..000000000 --- a/boot/zephyr/pm.yml +++ /dev/null @@ -1,77 +0,0 @@ -#include - -mcuboot: - size: CONFIG_PM_PARTITION_SIZE_MCUBOOT - placement: - before: [mcuboot_primary] -#if defined(CONFIG_HIDE_CHILD_PARENT_CONFIG) - align: {end: 0x1000} -#endif - -mcuboot_primary_app: - # All images to be placed in MCUboot's slot 0 should be placed in this - # partition - span: [app] - -mcuboot_primary: - span: [mcuboot_pad, mcuboot_primary_app] - -# Partition for secondary slot is not created if building in single application -# slot configuration. -#if !defined(CONFIG_SINGLE_APPLICATION_SLOT) && !defined(CONFIG_BOOT_DIRECT_XIP) -mcuboot_secondary: - share_size: [mcuboot_primary] -#if defined(CONFIG_PM_EXTERNAL_FLASH_MCUBOOT_SECONDARY) - region: external_flash - placement: - align: {start: 4} -#else - placement: - align: {start: CONFIG_FPROTECT_BLOCK_SIZE} - align_next: CONFIG_FPROTECT_BLOCK_SIZE # Ensure that the next partition does not interfere with this image - after: mcuboot_primary -#endif /* CONFIG_PM_EXTERNAL_FLASH_MCUBOOT_SECONDARY */ - -#endif /* !defined(CONFIG_SINGLE_APPLICATION_SLOT) && !defined(CONFIG_BOOT_DIRECT_XIP) */ - -#if CONFIG_BOOT_DIRECT_XIP - -# Direct XIP is enabled, reserve area for metadata (padding) and name the -# partition so that its clear that it is not the secondary slot, but the direct -# XIP alternative. - -mcuboot_secondary_pad: - share_size: mcuboot_pad - placement: - after: mcuboot_primary - align: {start: CONFIG_FPROTECT_BLOCK_SIZE} - -mcuboot_secondary_app: - share_size: mcuboot_primary_app - placement: - after: mcuboot_secondary_pad - -mcuboot_secondary: - span: [mcuboot_secondary_pad, mcuboot_secondary_app] - -#endif /* CONFIG_BOOT_DIRECT_XIP */ - -#if CONFIG_BOOT_SWAP_USING_SCRATCH -mcuboot_scratch: - size: CONFIG_PM_PARTITION_SIZE_MCUBOOT_SCRATCH - placement: - after: app - align: {start: CONFIG_FPROTECT_BLOCK_SIZE} -#endif /* CONFIG_BOOT_SWAP_USING_SCRATCH */ - -# Padding placed before image to boot. This reserves space for the MCUboot image header -# and it ensures that the boot image gets linked with the correct address offset in flash. -mcuboot_pad: - # MCUboot pad must be placed before the primary application partition. - # The primary application partition includes the secure firmware if present. - size: CONFIG_PM_PARTITION_SIZE_MCUBOOT_PAD - placement: - before: [mcuboot_primary_app] -#ifdef CONFIG_FPROTECT - align: {start: CONFIG_FPROTECT_BLOCK_SIZE} -#endif diff --git a/boot/zephyr/prj.conf b/boot/zephyr/prj.conf index 734e319fb..119e07579 100644 --- a/boot/zephyr/prj.conf +++ b/boot/zephyr/prj.conf @@ -18,7 +18,6 @@ CONFIG_BOOT_BOOTSTRAP=n # CONFIG_TINYCRYPT_SHA256 is not set CONFIG_FLASH=y -CONFIG_FPROTECT=y ### Various Zephyr boards enable features that we don't want. # CONFIG_BT is not set diff --git a/ext/nrf/cc310_glue.h b/ext/nrf/cc310_glue.h index 22eb94911..ed3ed5c00 100644 --- a/ext/nrf/cc310_glue.h +++ b/ext/nrf/cc310_glue.h @@ -22,7 +22,7 @@ #include #include #include -#include +#include #include /* diff --git a/zephyr/module.yml b/zephyr/module.yml index b73ae2a0d..d2af55384 100644 --- a/zephyr/module.yml +++ b/zephyr/module.yml @@ -1,8 +1,7 @@ samples: - boot/zephyr build: - cmake-ext: True - kconfig-ext: True + cmake: ./boot/bootutil/zephyr sysbuild-cmake: boot/zephyr/sysbuild package-managers: pip: From 7efda26fa2290e7715a4736f87ebbb60d5642f97 Mon Sep 17 00:00:00 2001 From: Jukka Rissanen Date: Tue, 23 Sep 2025 13:04:30 +0300 Subject: [PATCH 258/420] Revert "[nrf noup] boards: thingy91x: add board config" This reverts commit 19d7a4e5526a1b6d7d9282508d1089add9936df6. Signed-off-by: Jukka Rissanen --- .../boards/thingy91x_nrf5340_cpuapp.conf | 54 ------------------- boot/zephyr/boards/thingy91x_nrf9151.conf | 8 --- 2 files changed, 62 deletions(-) delete mode 100644 boot/zephyr/boards/thingy91x_nrf5340_cpuapp.conf delete mode 100644 boot/zephyr/boards/thingy91x_nrf9151.conf diff --git a/boot/zephyr/boards/thingy91x_nrf5340_cpuapp.conf b/boot/zephyr/boards/thingy91x_nrf5340_cpuapp.conf deleted file mode 100644 index 72dfa7fca..000000000 --- a/boot/zephyr/boards/thingy91x_nrf5340_cpuapp.conf +++ /dev/null @@ -1,54 +0,0 @@ -# MCUBoot settings -CONFIG_BOOT_MAX_IMG_SECTORS=110 - -# MCUboot serial recovery -CONFIG_MCUBOOT_SERIAL=y - -# Disable Zephyr console -CONFIG_LOG=n -CONFIG_CONSOLE=n -CONFIG_CONSOLE_HANDLER=n -CONFIG_UART_CONSOLE=n - -# Serial -CONFIG_SERIAL=y -CONFIG_UART_NRFX=y -CONFIG_UART_INTERRUPT_DRIVEN=y -CONFIG_UART_LINE_CTRL=y - -# MCUboot serial recovery -CONFIG_GPIO=y -CONFIG_MCUBOOT_SERIAL=y -CONFIG_BOOT_SERIAL_CDC_ACM=y - -# Required by USB -CONFIG_MULTITHREADING=y - -# USB -CONFIG_USB_DEVICE_STACK=y -CONFIG_USB_DEVICE_PRODUCT="MCUBOOT" -CONFIG_USB_CDC_ACM=y -CONFIG_USB_COMPOSITE_DEVICE=y -CONFIG_USB_MASS_STORAGE=n -CONFIG_USB_DEVICE_MANUFACTURER="Nordic Semiconductor" -CONFIG_USB_DEVICE_VID=0x1915 -CONFIG_USB_DEVICE_PID=0x520F - -CONFIG_BOOT_SERIAL_BOOT_MODE=y - -CONFIG_PM_PARTITION_SIZE_MCUBOOT=0x13E00 - -# The following configurations are required to support simultaneous multi image update -CONFIG_PCD_APP=y -CONFIG_UPDATEABLE_IMAGE_NUMBER=2 -CONFIG_BOOT_UPGRADE_ONLY=y -# The network core cannot access external flash directly. The flash simulator must be used to -# provide a memory region that is used to forward the new firmware to the network core. -CONFIG_FLASH_SIMULATOR=y -CONFIG_FLASH_SIMULATOR_DOUBLE_WRITES=y -CONFIG_FLASH_SIMULATOR_STATS=n - -CONFIG_BOOT_IMAGE_ACCESS_HOOKS=y -CONFIG_MCUBOOT_SERIAL_DIRECT_IMAGE_UPLOAD=y - -CONFIG_NRF53_RECOVERY_NETWORK_CORE=y diff --git a/boot/zephyr/boards/thingy91x_nrf9151.conf b/boot/zephyr/boards/thingy91x_nrf9151.conf deleted file mode 100644 index 33cd3301c..000000000 --- a/boot/zephyr/boards/thingy91x_nrf9151.conf +++ /dev/null @@ -1,8 +0,0 @@ -# MCUBoot settings -CONFIG_BOOT_MAX_IMG_SECTORS=512 - -CONFIG_SPI=y -CONFIG_SPI_NOR=y -CONFIG_SPI_NOR_FLASH_LAYOUT_PAGE_SIZE=4096 -CONFIG_SPI_NOR_SFDP_DEVICETREE=y -CONFIG_MULTITHREADING=y From b67bceb79782ad380a8ba4f6fc5b43be201f0d42 Mon Sep 17 00:00:00 2001 From: Jukka Rissanen Date: Tue, 23 Sep 2025 13:04:30 +0300 Subject: [PATCH 259/420] Revert "[nrf noup] boards: add support for Thingy:91" This reverts commit 313de9ca5b4e9015642b100007f4314483121f68. Signed-off-by: Jukka Rissanen --- boot/zephyr/boards/thingy91_nrf52840.conf | 34 ----------------------- boot/zephyr/boards/thingy91_nrf9160.conf | 13 --------- 2 files changed, 47 deletions(-) delete mode 100644 boot/zephyr/boards/thingy91_nrf52840.conf delete mode 100644 boot/zephyr/boards/thingy91_nrf9160.conf diff --git a/boot/zephyr/boards/thingy91_nrf52840.conf b/boot/zephyr/boards/thingy91_nrf52840.conf deleted file mode 100644 index c0d183401..000000000 --- a/boot/zephyr/boards/thingy91_nrf52840.conf +++ /dev/null @@ -1,34 +0,0 @@ -# Disable Zephyr console -CONFIG_LOG=n -CONFIG_CONSOLE=n -CONFIG_CONSOLE_HANDLER=n -CONFIG_UART_CONSOLE=n - -# The build won't fit on the partition allocated for it without size -# optimizations. -CONFIG_SIZE_OPTIMIZATIONS=y -CONFIG_PM_PARTITION_SIZE_MCUBOOT=0x12000 - -# Serial -CONFIG_SERIAL=y -CONFIG_UART_NRFX=y -CONFIG_UART_INTERRUPT_DRIVEN=y -CONFIG_UART_LINE_CTRL=y - -# MCUboot serial recovery -CONFIG_GPIO=y -CONFIG_MCUBOOT_SERIAL=y -CONFIG_BOOT_SERIAL_CDC_ACM=y - -# Required by USB -CONFIG_MULTITHREADING=y - -# USB -CONFIG_USB_DEVICE_STACK=y -CONFIG_USB_DEVICE_PRODUCT="MCUBOOT" -CONFIG_USB_CDC_ACM=y -CONFIG_USB_COMPOSITE_DEVICE=y -CONFIG_USB_MASS_STORAGE=n -CONFIG_USB_DEVICE_MANUFACTURER="Nordic Semiconductor" -CONFIG_USB_DEVICE_VID=0x1915 -CONFIG_USB_DEVICE_PID=0x520F diff --git a/boot/zephyr/boards/thingy91_nrf9160.conf b/boot/zephyr/boards/thingy91_nrf9160.conf deleted file mode 100644 index 1bf2e424d..000000000 --- a/boot/zephyr/boards/thingy91_nrf9160.conf +++ /dev/null @@ -1,13 +0,0 @@ -# Disable Zephyr console -CONFIG_CONSOLE=n -CONFIG_CONSOLE_HANDLER=n -CONFIG_UART_CONSOLE=n - -# Disable Flash protection -CONFIG_FPROTECT=n - -# MCUBoot settings -CONFIG_BOOT_MAX_IMG_SECTORS=256 - -# MCUboot serial recovery -CONFIG_MCUBOOT_SERIAL=y From 56f13e8c9d726376ee079687bf26837011ddcf3b Mon Sep 17 00:00:00 2001 From: Jukka Rissanen Date: Tue, 23 Sep 2025 13:04:30 +0300 Subject: [PATCH 260/420] Revert "[nrf noup] zephyr: Remove duplication from cmake" This reverts commit 7ac4eeb0b9ad01f90d002cf34d1e84a6b0e539ab. Signed-off-by: Jukka Rissanen --- boot/zephyr/CMakeLists.txt | 2 ++ 1 file changed, 2 insertions(+) diff --git a/boot/zephyr/CMakeLists.txt b/boot/zephyr/CMakeLists.txt index b0e43cd50..76ada498e 100644 --- a/boot/zephyr/CMakeLists.txt +++ b/boot/zephyr/CMakeLists.txt @@ -50,6 +50,8 @@ if(NOT EXISTS ${NRFXLIB_DIR}) To use the tinycrypt set `CONFIG_BOOT_ECDSA_TINYCRYPT` to y. ------------------------------------------------------------------------") endif() +# Don't include this if we are using west + add_subdirectory(${NRFXLIB_DIR} ${PROJECT_BINARY_DIR}/nrfxlib) endif() zephyr_library_include_directories( From 94a0209c88feb05fe08298801a57b41ad2ae1530 Mon Sep 17 00:00:00 2001 From: Jukka Rissanen Date: Tue, 23 Sep 2025 13:04:30 +0300 Subject: [PATCH 261/420] Revert "[nrf noup] github: Add a commit tags check workflow" This reverts commit 727cc28fcc10b78fc2f8b3fb5fd60ea71596160f. Signed-off-by: Jukka Rissanen --- .github/workflows/commit-tags.yml | 28 ---------------------------- 1 file changed, 28 deletions(-) delete mode 100644 .github/workflows/commit-tags.yml diff --git a/.github/workflows/commit-tags.yml b/.github/workflows/commit-tags.yml deleted file mode 100644 index 534ed5b58..000000000 --- a/.github/workflows/commit-tags.yml +++ /dev/null @@ -1,28 +0,0 @@ -name: Commit tags - -on: - pull_request: - types: [synchronize, opened, reopened, edited, labeled, unlabeled, - milestoned, demilestoned, assigned, unassigned, ready_for_review, - review_requested] - -jobs: - commit_tags: - runs-on: ubuntu-22.04 - name: Run commit tags checks on patch series (PR) - steps: - - name: Update PATH for west - run: | - echo "$HOME/.local/bin" >> $GITHUB_PATH - - - name: Checkout the code - uses: actions/checkout@v3 - with: - ref: ${{ github.event.pull_request.head.sha }} - fetch-depth: 0 - - - name: Run the commit tags - uses: nrfconnect/action-commit-tags@main - with: - target: . - upstream: mcu-tools/mcuboot/main From 1dcb1598f77b31bbbaac5d87d589786e4f80cfe2 Mon Sep 17 00:00:00 2001 From: Jukka Rissanen Date: Tue, 23 Sep 2025 13:04:30 +0300 Subject: [PATCH 262/420] Revert "[nrf fromtree] zephyr: Enable building ECDSA PSA variant" This reverts commit 7ad728fef39f60eee0c09e6a2300a17b1ccee212. Signed-off-by: Jukka Rissanen --- boot/zephyr/CMakeLists.txt | 5 +---- boot/zephyr/Kconfig | 18 ------------------ 2 files changed, 1 insertion(+), 22 deletions(-) diff --git a/boot/zephyr/CMakeLists.txt b/boot/zephyr/CMakeLists.txt index 76ada498e..159962543 100644 --- a/boot/zephyr/CMakeLists.txt +++ b/boot/zephyr/CMakeLists.txt @@ -186,10 +186,7 @@ else() endif() if(CONFIG_BOOT_SIGNATURE_TYPE_ECDSA_P256 OR CONFIG_BOOT_ENCRYPT_EC256) - # When ECDSA PSA is used, do not pull in additional ASN.1 include - # directories or sources, as it would cause incorrect header files - # to be included. - if(MBEDTLS_ASN1_DIR AND NOT CONFIG_BOOT_ECDSA_PSA) + if(MBEDTLS_ASN1_DIR) zephyr_library_include_directories( ${MBEDTLS_ASN1_DIR}/include ) diff --git a/boot/zephyr/Kconfig b/boot/zephyr/Kconfig index 0e8265002..fcd9f5d35 100644 --- a/boot/zephyr/Kconfig +++ b/boot/zephyr/Kconfig @@ -113,14 +113,6 @@ config BOOT_X25519_PSA_DEPENDENCIES endif # BOOT_ENCRYPT_IMAGE -config BOOT_ECDSA_PSA_DEPENDENCIES - bool - select PSA_WANT_ALG_ECDSA - select PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_IMPORT - select PSA_WANT_ECC_SECP_R1_256 - help - Dependencies for ECDSA signature - if MBEDTLS_ENABLE_HEAP config MBEDTLS_HEAP_SIZE @@ -290,16 +282,6 @@ config BOOT_ECDSA_CC310 select NRF_CC310_BL select NRFXLIB_CRYPTO select BOOT_USE_CC310 - -config BOOT_ECDSA_PSA - bool "Use psa cryptoo" - select BOOT_USE_PSA_CRYPTO - select PSA_CRYPTO_CLIENT - select PSA_CRYPTO_C - select BOOT_IMG_HASH_ALG_SHA256_ALLOW - select BOOT_IMG_HASH_ALG_SHA512_ALLOW - select BOOT_ECDSA_PSA_DEPENDENCIES - endchoice # Ecdsa implementation endif From 171e71cff3da056f49de39cab26da54105ce9e7f Mon Sep 17 00:00:00 2001 From: Jukka Rissanen Date: Tue, 23 Sep 2025 13:04:30 +0300 Subject: [PATCH 263/420] Revert "[nrf fromtree] loader: Allow to specify slot number in version" This reverts commit d8bd9285ea84ab0d71b95c8f02d76844f69a83a6. Signed-off-by: Jukka Rissanen --- boot/bootutil/include/bootutil/image.h | 8 - boot/bootutil/src/loader.c | 167 +----------------- boot/zephyr/Kconfig | 9 - .../include/mcuboot_config/mcuboot_config.h | 4 - docs/design.md | 17 -- docs/imgtool.md | 13 +- scripts/imgtool/image.py | 3 +- scripts/imgtool/main.py | 32 +--- 8 files changed, 6 insertions(+), 247 deletions(-) diff --git a/boot/bootutil/include/bootutil/image.h b/boot/bootutil/include/bootutil/image.h index 52fa6d1bb..11c54b633 100644 --- a/boot/bootutil/include/bootutil/image.h +++ b/boot/bootutil/include/bootutil/image.h @@ -144,10 +144,6 @@ extern "C" { */ #define IMAGE_TLV_ANY 0xffff /* Used to iterate over all TLV */ -#define VERSION_DEP_SLOT_ACTIVE 0x00 /* Check dependency against active slot. */ -#define VERSION_DEP_SLOT_PRIMARY 0x01 /* Check dependency against primary slot. */ -#define VERSION_DEP_SLOT_SECONDARY 0x02 /* Check dependency against secondary slot. */ - STRUCT_PACKED image_version { uint8_t iv_major; uint8_t iv_minor; @@ -157,11 +153,7 @@ STRUCT_PACKED image_version { struct image_dependency { uint8_t image_id; /* Image index (from 0) */ -#ifdef MCUBOOT_VERSION_CMP_USE_SLOT_NUMBER - uint8_t slot; /* Image slot */ -#else uint8_t _pad1; -#endif /* MCUBOOT_VERSION_CMP_USE_SLOT_NUMBER */ uint16_t _pad2; struct image_version image_min_version; /* Indicates at minimum which * version of firmware must be diff --git a/boot/bootutil/src/loader.c b/boot/bootutil/src/loader.c index 8c73f7652..6654245ad 100644 --- a/boot/bootutil/src/loader.c +++ b/boot/bootutil/src/loader.c @@ -424,24 +424,6 @@ boot_verify_slot_dependency(struct boot_loader_state *state, uint8_t swap_type = state->swap_type[dep->image_id]; dep_slot = BOOT_IS_UPGRADE(swap_type) ? BOOT_SECONDARY_SLOT : BOOT_PRIMARY_SLOT; -#elif defined(MCUBOOT_VERSION_CMP_USE_SLOT_NUMBER) - switch(dep->slot) { - case VERSION_DEP_SLOT_ACTIVE: - dep_slot = state->slot_usage[dep->image_id].active_slot; - break; - case VERSION_DEP_SLOT_PRIMARY: - dep_slot = BOOT_PRIMARY_SLOT; - break; - case VERSION_DEP_SLOT_SECONDARY: - dep_slot = BOOT_SECONDARY_SLOT; - break; - default: - return -1; - } - - if (!state->slot_usage[dep->image_id].slot_available[dep_slot]) { - return -1; - } #else dep_slot = state->slot_usage[dep->image_id].active_slot; #endif @@ -479,27 +461,7 @@ boot_verify_slot_dependency(struct boot_loader_state *state, } #endif -#ifdef MCUBOOT_VERSION_CMP_USE_SLOT_NUMBER - if (rc == 0) { - switch(dep->slot) { - case VERSION_DEP_SLOT_PRIMARY: - state->slot_usage[dep->image_id].slot_available[BOOT_PRIMARY_SLOT] = true; - state->slot_usage[dep->image_id].slot_available[BOOT_SECONDARY_SLOT] = false; - state->slot_usage[dep->image_id].active_slot = BOOT_PRIMARY_SLOT; - break; - case VERSION_DEP_SLOT_SECONDARY: - state->slot_usage[dep->image_id].slot_available[BOOT_PRIMARY_SLOT] = false; - state->slot_usage[dep->image_id].slot_available[BOOT_SECONDARY_SLOT] = true; - state->slot_usage[dep->image_id].active_slot = BOOT_SECONDARY_SLOT; - break; - case VERSION_DEP_SLOT_ACTIVE: - default: - break; - } - } -#endif /* MCUBOOT_VERSION_CMP_USE_SLOT_NUMBER */ - -return rc; + return rc; } #if !defined(MCUBOOT_DIRECT_XIP) && !defined(MCUBOOT_RAM_LOAD) @@ -644,19 +606,6 @@ boot_verify_slot_dependencies(struct boot_loader_state *state, uint32_t slot) goto done; } -#ifdef MCUBOOT_VERSION_CMP_USE_SLOT_NUMBER - /* Validate against possible dependency slot values. */ - switch(dep->slot) { - case VERSION_DEP_SLOT_ACTIVE: - case VERSION_DEP_SLOT_PRIMARY: - case VERSION_DEP_SLOT_SECONDARY: - break; - default: - rc = BOOT_EBADARGS; - goto done; - } -#endif /* MCUBOOT_VERSION_CMP_USE_SLOT_NUMBER */ - /* Verify dependency and modify the swap type if not satisfied. */ rc = boot_verify_slot_dependency(state, &dep); if (rc != 0) { @@ -2983,119 +2932,6 @@ boot_select_or_erase(struct boot_loader_state *state) } #endif /* MCUBOOT_DIRECT_XIP && MCUBOOT_DIRECT_XIP_REVERT */ -#ifdef MCUBOOT_VERSION_CMP_USE_SLOT_NUMBER -/** - * Tries to load a slot for all the images with validation. - * - * @param state Boot loader status information. - * - * @return 0 on success; nonzero on failure. - */ -fih_ret -boot_load_and_validate_images(struct boot_loader_state *state) -{ - uint32_t active_slot; - int rc; - fih_ret fih_rc; - uint32_t slot; - - /* Go over all the images and all slots and validate them */ - IMAGES_ITER(BOOT_CURR_IMG(state)) { - for (slot = 0; slot < BOOT_NUM_SLOTS; slot++) { -#if BOOT_IMAGE_NUMBER > 1 - if (state->img_mask[BOOT_CURR_IMG(state)]) { - continue; - } -#endif - - /* Save the number of the active slot. */ - state->slot_usage[BOOT_CURR_IMG(state)].active_slot = slot; - -#ifdef MCUBOOT_DIRECT_XIP - rc = boot_rom_address_check(state); - if (rc != 0) { - /* The image is placed in an unsuitable slot. */ - state->slot_usage[BOOT_CURR_IMG(state)].slot_available[slot] = false; - state->slot_usage[BOOT_CURR_IMG(state)].active_slot = NO_ACTIVE_SLOT; - continue; - } - -#ifdef MCUBOOT_DIRECT_XIP_REVERT - rc = boot_select_or_erase(state); - if (rc != 0) { - /* The selected image slot has been erased. */ - state->slot_usage[BOOT_CURR_IMG(state)].slot_available[slot] = false; - state->slot_usage[BOOT_CURR_IMG(state)].active_slot = NO_ACTIVE_SLOT; - continue; - } -#endif /* MCUBOOT_DIRECT_XIP_REVERT */ -#endif /* MCUBOOT_DIRECT_XIP */ - -#ifdef MCUBOOT_RAM_LOAD - /* Image is first loaded to RAM and authenticated there in order to - * prevent TOCTOU attack during image copy. This could be applied - * when loading images from external (untrusted) flash to internal - * (trusted) RAM and image is authenticated before copying. - */ - rc = boot_load_image_to_sram(state); - if (rc != 0 ) { - /* Image cannot be ramloaded. */ - boot_remove_image_from_flash(state, slot); - state->slot_usage[BOOT_CURR_IMG(state)].slot_available[slot] = false; - state->slot_usage[BOOT_CURR_IMG(state)].active_slot = NO_ACTIVE_SLOT; - continue; - } -#endif /* MCUBOOT_RAM_LOAD */ - - FIH_CALL(boot_validate_slot, fih_rc, state, slot, NULL, 0); - if (FIH_NOT_EQ(fih_rc, FIH_SUCCESS)) { - /* Image is invalid. */ -#ifdef MCUBOOT_RAM_LOAD - boot_remove_image_from_sram(state); -#endif /* MCUBOOT_RAM_LOAD */ - state->slot_usage[BOOT_CURR_IMG(state)].slot_available[slot] = false; - state->slot_usage[BOOT_CURR_IMG(state)].active_slot = NO_ACTIVE_SLOT; - continue; - } - - /* Valid image loaded from a slot, go to the next slot. */ - state->slot_usage[BOOT_CURR_IMG(state)].active_slot = NO_ACTIVE_SLOT; - } - } - - /* Go over all the images and all slots and validate them */ - IMAGES_ITER(BOOT_CURR_IMG(state)) { - /* All slots tried until a valid image found. Breaking from this loop - * means that a valid image found or already loaded. If no slot is - * found the function returns with error code. */ - while (true) { - /* Go over all the slots and try to load one */ - active_slot = state->slot_usage[BOOT_CURR_IMG(state)].active_slot; - if (active_slot != NO_ACTIVE_SLOT){ - /* A slot is already active, go to next image. */ - break; - } - - active_slot = find_slot_with_highest_version(state); - if (active_slot == NO_ACTIVE_SLOT) { - BOOT_LOG_INF("No slot to load for image %d", - BOOT_CURR_IMG(state)); - FIH_RET(FIH_FAILURE); - } - - /* Save the number of the active slot. */ - state->slot_usage[BOOT_CURR_IMG(state)].active_slot = active_slot; - - /* Valid image loaded from a slot, go to the next image. */ - break; - } - } - - FIH_RET(FIH_SUCCESS); -} - -#else /* MCUBOOT_VERSION_CMP_USE_SLOT_NUMBER */ - /** * Tries to load a slot for all the images with validation. * @@ -3193,7 +3029,6 @@ boot_load_and_validate_images(struct boot_loader_state *state) FIH_RET(FIH_SUCCESS); } -#endif /* MCUBOOT_VERSION_CMP_USE_SLOT_NUMBER */ /** * Updates the security counter for the current image. diff --git a/boot/zephyr/Kconfig b/boot/zephyr/Kconfig index fcd9f5d35..ef9eb2433 100644 --- a/boot/zephyr/Kconfig +++ b/boot/zephyr/Kconfig @@ -949,15 +949,6 @@ config BOOT_VERSION_CMP_USE_BUILD_NUMBER minor and revision. Enable this option to take into account the build number as well. -config BOOT_VERSION_CMP_USE_SLOT_NUMBER - bool "Use slot number while comparing image version" - depends on (UPDATEABLE_IMAGE_NUMBER > 1) || BOOT_DIRECT_XIP || \ - BOOT_RAM_LOAD || MCUBOOT_DOWNGRADE_PREVENTION - help - By default, the image slot comparison relies only on active slot. - Enable this option to take into account the specified slot number - instead. - choice BOOT_DOWNGRADE_PREVENTION_CHOICE prompt "Downgrade prevention" optional diff --git a/boot/zephyr/include/mcuboot_config/mcuboot_config.h b/boot/zephyr/include/mcuboot_config/mcuboot_config.h index f0dc214b6..820ffd752 100644 --- a/boot/zephyr/include/mcuboot_config/mcuboot_config.h +++ b/boot/zephyr/include/mcuboot_config/mcuboot_config.h @@ -120,10 +120,6 @@ #define MCUBOOT_VERSION_CMP_USE_BUILD_NUMBER #endif -#ifdef CONFIG_BOOT_VERSION_CMP_USE_SLOT_NUMBER -#define MCUBOOT_VERSION_CMP_USE_SLOT_NUMBER -#endif - #ifdef CONFIG_BOOT_SWAP_SAVE_ENCTLV #define MCUBOOT_SWAP_SAVE_ENCTLV 1 #endif diff --git a/docs/design.md b/docs/design.md index c080b2b82..66fcd45f9 100755 --- a/docs/design.md +++ b/docs/design.md @@ -890,23 +890,6 @@ process is presented below. + Boot into image in the primary slot of the 0th image position\ (other image in the boot chain is started by another image). -By enabling the `MCUBOOT_VERSION_CMP_USE_SLOT_NUMBER` configuration option, -the dependency check may be extended to match for a specified slot of a specific -image. This functionality is useful in a multi-core system when Direct XIP mode -is used. -In this case, the main image can be started from one of the two (primary or -secondary) slots. -If there is a fixed connection between the slots of two different images, -e.g. if the main image always chainloads a companion image from the same slot, -the check must take this into account and only consider a matching slot when -resolving dependencies. - -There are three values that can be passed when specifying dependencies: - -1. ``active``: the dependency should be checked against either primary or secondary slot. -2. ``primary``: the dependency should be checked only against primary slot. -3. ``secondary``: the dependency should be checked only against secondary slot. - ### [Multiple image boot for RAM loading and direct-xip](#multiple-image-boot-for-ram-loading-and-direct-xip) The operation of the bootloader is different when the ram-load or the diff --git a/docs/imgtool.md b/docs/imgtool.md index c68652dca..958e1af15 100644 --- a/docs/imgtool.md +++ b/docs/imgtool.md @@ -91,8 +91,7 @@ primary slot and adds a header and trailer that the bootloader is expecting: the `auto` keyword to automatically generate it from the image version. -d, --dependencies TEXT Add dependence on another image, format: - "(,[,] - ), ... " + "(,), ... " --pad-sig Add 0-2 bytes of padding to ECDSA signature (for mcuboot <1.5) -H, --header-size INTEGER [required] @@ -183,16 +182,6 @@ which the current image depends on. The `image_version` is the minimum version of that image to satisfy compliance. For example `-d "(1, 1.2.3+0)"` means this image depends on Image 1 which version has to be at least 1.2.3+0. -In addition, a dependency can specify the slot as follows: -`-d "(image_id, slot, image_version)"`. The `image_id` is the number of the -image on which the current image depends. -The slot specifies which slots of the image are to be taken into account -(`active`: primary or secondary, `primary`: only primary `secondary`: only -secondary slot). The `image_version` is the minimum version of that image to -fulfill the requirements. -For example `-d "(1, primary, 1.2.3+0)"` means that this image depends on the -primary slot of the Image 1, whose version must be at least 1.2.3+0. - The `--public-key-format` argument can be used to distinguish where the public key is stored for image authentication. The `hash` option is used by default, in which case only the hash of the public key is added to the TLV area (the full diff --git a/scripts/imgtool/image.py b/scripts/imgtool/image.py index 4e2830370..03e2cbb62 100644 --- a/scripts/imgtool/image.py +++ b/scripts/imgtool/image.py @@ -589,9 +589,8 @@ def create(self, key, public_key_format, enckey, dependencies=None, if dependencies is not None: for i in range(dependencies_num): payload = struct.pack( - e + 'BB2x' + 'BBHI', + e + 'B3x' + 'BBHI', int(dependencies[DEP_IMAGES_KEY][i]), - dependencies[DEP_VERSIONS_KEY][i].slot, dependencies[DEP_VERSIONS_KEY][i].major, dependencies[DEP_VERSIONS_KEY][i].minor, dependencies[DEP_VERSIONS_KEY][i].revision, diff --git a/scripts/imgtool/main.py b/scripts/imgtool/main.py index 7f9a53657..5ff1f8f9f 100755 --- a/scripts/imgtool/main.py +++ b/scripts/imgtool/main.py @@ -27,7 +27,6 @@ import lzma import hashlib import base64 -from collections import namedtuple from imgtool import image, imgtool_version from imgtool.version import decode_version from imgtool.dumpinfo import dump_imginfo @@ -46,14 +45,6 @@ sys.exit("Python %s.%s or newer is required by imgtool." % MIN_PYTHON_VERSION) -SlottedSemiSemVersion = namedtuple('SemiSemVersion', ['major', 'minor', 'revision', - 'build', 'slot']) - -DEPENDENCY_SLOT_VALUES = { - 'active': 0x00, - 'primary': 0x01, - 'secondary': 0x02 -} def gen_rsa2048(keyfile, passwd): keys.RSA.generate().export_private(path=keyfile, passwd=passwd) @@ -310,33 +301,16 @@ def get_dependencies(ctx, param, value): if len(images) == 0: raise click.BadParameter( "Image dependency format is invalid: {}".format(value)) - raw_versions = re.findall(r",\s*((active|primary|secondary)\s*,)?\s*([0-9.+]+)\)", value) + raw_versions = re.findall(r",\s*([0-9.+]+)\)", value) if len(images) != len(raw_versions): raise click.BadParameter( '''There's a mismatch between the number of dependency images and versions in: {}'''.format(value)) for raw_version in raw_versions: try: - decoded_version = decode_version(raw_version[2]) - if len(raw_version[1]) > 0: - slotted_version = SlottedSemiSemVersion( - decoded_version.major, - decoded_version.minor, - decoded_version.revision, - decoded_version.build, - DEPENDENCY_SLOT_VALUES[raw_version[1]] - ) - else: - slotted_version = SlottedSemiSemVersion( - decoded_version.major, - decoded_version.minor, - decoded_version.revision, - decoded_version.build, - 0 - ) + versions.append(decode_version(raw_version)) except ValueError as e: raise click.BadParameter("{}".format(e)) - versions.append(slotted_version) dependencies = dict() dependencies[image.DEP_IMAGES_KEY] = images dependencies[image.DEP_VERSIONS_KEY] = versions @@ -431,7 +405,7 @@ def convert(self, value, param, ctx): '(for mcuboot <1.5)') @click.option('-d', '--dependencies', callback=get_dependencies, required=False, help='''Add dependence on another image, format: - "(,[,]), ... "''') + "(,), ... "''') @click.option('-s', '--security-counter', callback=validate_security_counter, help='Specify the value of security counter. Use the `auto` ' 'keyword to automatically generate it from the image version.') From 6e7853ae69efb6b0f2a94931bbe4444bb06c5fb5 Mon Sep 17 00:00:00 2001 From: Jukka Rissanen Date: Tue, 23 Sep 2025 13:04:30 +0300 Subject: [PATCH 264/420] Revert "[nrf fromlist] zephyr: Improve SHA support selectors" This reverts commit edbba12dec2fae0c51c03304c798d4ec0ad35d3a. Signed-off-by: Jukka Rissanen --- boot/zephyr/Kconfig | 64 +++++---------------------------------------- 1 file changed, 6 insertions(+), 58 deletions(-) diff --git a/boot/zephyr/Kconfig b/boot/zephyr/Kconfig index ef9eb2433..4b58f3fab 100644 --- a/boot/zephyr/Kconfig +++ b/boot/zephyr/Kconfig @@ -70,20 +70,15 @@ if BOOT_USE_PSA_CRYPTO config BOOT_PSA_IMG_HASH_ALG_SHA256_DEPENDENCIES bool - default y if BOOT_SOMETHING_USES_SHA256 + default y if BOOT_IMG_HASH_ALG_SHA256 select PSA_WANT_ALG_SHA_256 help Dependencies for hashing with SHA256 -config BOOT_PSA_IMG_HASH_ALG_SHA512_DEPENDENCIES - bool - default y if BOOT_SOMETHING_USES_SHA512 - select PSA_WANT_ALG_SHA_512 - help - Dependencies for hashing with SHA512 - config BOOT_ED25519_PSA_DEPENDENCIES bool + select PSA_WANT_ALG_SHA_256 + select PSA_WANT_ALG_SHA_512 select PSA_WANT_ALG_PURE_EDDSA # Seems that upstream mbedTLS does not have TE #select PSA_WANT_ECC_TWISTED_EDWARDS_255 @@ -134,30 +129,6 @@ config SINGLE_APPLICATION_SLOT uploading a new application overwrites the one that previously occupied the area. -config BOOT_SOMETHING_USES_SHA256 - bool - help - Hidden option that should be selected when something requires - SHA256 implementation in any form. It should be used by crypto - backends to enable support for SHA256 in code and/or hardware - drivers. - -config BOOT_SOMETHING_USES_SHA384 - bool - help - Hidden option that should be selected when something requires - SHA384 implementation in any form. It should be used by crypto - backends to enable support for SHA384 in code and/or hardware - drivers. - -config BOOT_SOMETHING_USES_SHA512 - bool - help - Hidden option that should be selected when something requires - SHA512 implementation in any form. It should be used by crypto - backends to enable support for SHA512 in code and/or hardware - drivers. - config BOOT_IMG_HASH_ALG_SHA256_ALLOW bool help @@ -202,21 +173,18 @@ choice BOOT_IMG_HASH_ALG config BOOT_IMG_HASH_ALG_SHA256 bool "SHA256" depends on BOOT_IMG_HASH_ALG_SHA256_ALLOW - select BOOT_SOMETHING_USES_SHA256 help SHA256 algorithm config BOOT_IMG_HASH_ALG_SHA384 bool "SHA384" depends on BOOT_IMG_HASH_ALG_SHA384_ALLOW - select BOOT_SOMETHING_USES_SHA384 help SHA384 algorithm config BOOT_IMG_HASH_ALG_SHA512 bool "SHA512" depends on BOOT_IMG_HASH_ALG_SHA512_ALLOW - select BOOT_SOMETHING_USES_SHA512 help SHA512 algorithm @@ -640,34 +608,14 @@ config BOOT_ENCRYPT_X25519 help Hidden option selecting x25519 encryption. -if BOOT_ENCRYPT_X25519 && BOOT_USE_PSA_CRYPTO - -choice BOOT_HMAC_SHA - prompt "SHA used for HMAC and HKDF in encryption key exchange" - default BOOT_HMAC_SHA256 - help - HMAC/HKDF sha algorithm may be selected to synchronize sha - usage with other places in code and reduce compiled in - implementations. - -config BOOT_HMAC_SHA256 - bool "Use SHA256 for HMAC/HKDF" - select BOOT_SOMETHING_USES_SHA256 - help - This is default for ED25519. - config BOOT_HMAC_SHA512 bool "Use SHA512 for HMAC/HKDF" depends on BOOT_ENCRYPT_X25519 depends on BOOT_USE_PSA_CRYPTO - select BOOT_SOMETHING_USES_SHA512 help - With ED25519, this option is worth selecting when SHA512 is used - for hashing of an image to reduce number of compiled sha algorithms. - -endchoice # BOOT_HMAC_SHA - -endif # BOOT_ENCRYPT_X25519 && BOOT_USE_PSA_CRYPTO + By default SHA256 is used for HKDF/HMAC in key exchange expansion + and verification. This options switches to SHA512. The option is + mainly useful to reduce numer of compiled in SHA algorithms. config BOOT_ENCRYPTION_KEY_FILE string "Encryption key file" From 5c9d12c957108a27513200cb906ecda235e04741 Mon Sep 17 00:00:00 2001 From: Jukka Rissanen Date: Tue, 23 Sep 2025 13:04:30 +0300 Subject: [PATCH 265/420] Revert "[nrf fromtree] boot: zephyr: RAM cleanup debug loop" This reverts commit cf5187c5df8e1270f66ae48978eeea5be7a4d4ed. Signed-off-by: Jukka Rissanen --- boot/zephyr/Kconfig | 7 ------- boot/zephyr/main.c | 3 --- 2 files changed, 10 deletions(-) diff --git a/boot/zephyr/Kconfig b/boot/zephyr/Kconfig index 4b58f3fab..dc445b4ed 100644 --- a/boot/zephyr/Kconfig +++ b/boot/zephyr/Kconfig @@ -364,13 +364,6 @@ config MCUBOOT_CLEANUP_RAM help Sets contents of memory to 0 before jumping to application. -config MCUBOOT_INFINITE_LOOP_AFTER_RAM_CLEANUP - bool "Infinite loop after RAM cleanup" - depends on MCUBOOT_CLEANUP_RAM - help - Verification option that keeps execution in infinite loop after - RAM cleanup has been performed. - config MBEDTLS_CFG_FILE # It might be awkward to define an Mbed TLS header file when TinyCrypt # is used, but the fact is that Mbed TLS' ASN1 parse module is used diff --git a/boot/zephyr/main.c b/boot/zephyr/main.c index 0cb793b2d..2e57bd999 100644 --- a/boot/zephyr/main.c +++ b/boot/zephyr/main.c @@ -249,9 +249,6 @@ static void do_boot(struct boot_rsp *rsp) " b clear\n" "out:\n" " dsb\n" -#if CONFIG_MCUBOOT_INFINITE_LOOP_AFTER_RAM_CLEANUP - " b out\n" -#endif /*CONFIG_MCUBOOT_INFINITE_LOOP_AFTER_RAM_CLEANUP */ /* jump to reset vector of an app */ " bx r0\n" : From 5dda3d45ceb4d4994ac07441f7ce5a123c0ba197 Mon Sep 17 00:00:00 2001 From: Jukka Rissanen Date: Tue, 23 Sep 2025 13:04:30 +0300 Subject: [PATCH 266/420] Revert "[nrf fromlist] zephyr: boards: nrf - remove redundant multithreading configuration" This reverts commit b0ad970425de01e09370badbc2ab449aa6292649. Signed-off-by: Jukka Rissanen --- boot/zephyr/boards/nrf52840dk_qspi_secondary_boot.conf | 1 + boot/zephyr/boards/nrf54h20dk_nrf54h20_cpuapp_iron.conf | 2 ++ 2 files changed, 3 insertions(+) diff --git a/boot/zephyr/boards/nrf52840dk_qspi_secondary_boot.conf b/boot/zephyr/boards/nrf52840dk_qspi_secondary_boot.conf index 5f3b7808b..9f984be4f 100644 --- a/boot/zephyr/boards/nrf52840dk_qspi_secondary_boot.conf +++ b/boot/zephyr/boards/nrf52840dk_qspi_secondary_boot.conf @@ -1 +1,2 @@ +CONFIG_MULTITHREADING=y CONFIG_BOOT_MAX_IMG_SECTORS=256 diff --git a/boot/zephyr/boards/nrf54h20dk_nrf54h20_cpuapp_iron.conf b/boot/zephyr/boards/nrf54h20dk_nrf54h20_cpuapp_iron.conf index 12c96ff0f..50d349255 100644 --- a/boot/zephyr/boards/nrf54h20dk_nrf54h20_cpuapp_iron.conf +++ b/boot/zephyr/boards/nrf54h20dk_nrf54h20_cpuapp_iron.conf @@ -7,3 +7,5 @@ CONFIG_SPI_NOR=n CONFIG_BOOT_WATCHDOG_FEED=n + +CONFIG_MULTITHREADING=y From 1d52879b0c5bdfa59732592ab1382fa3761c98eb Mon Sep 17 00:00:00 2001 From: Jukka Rissanen Date: Tue, 23 Sep 2025 13:04:30 +0300 Subject: [PATCH 267/420] Revert "[nrf fromlist] bootutil: Unify app_max_size() implementations" This reverts commit 422c6370ef884e9953b41662f6e51147ff14bea0. Signed-off-by: Jukka Rissanen --- .../include/bootutil/bootutil_public.h | 6 - boot/bootutil/src/bootutil_misc.c | 102 +++++++++++- boot/bootutil/src/bootutil_priv.h | 18 ++- boot/bootutil/src/swap_move.c | 55 ++++--- boot/bootutil/src/swap_offset.c | 64 +++++--- boot/bootutil/src/swap_scratch.c | 146 +----------------- 6 files changed, 189 insertions(+), 202 deletions(-) diff --git a/boot/bootutil/include/bootutil/bootutil_public.h b/boot/bootutil/include/bootutil/bootutil_public.h index 421d854b1..933553f9f 100644 --- a/boot/bootutil/include/bootutil/bootutil_public.h +++ b/boot/bootutil/include/bootutil/bootutil_public.h @@ -295,12 +295,6 @@ boot_set_next(const struct flash_area *fa, bool active, bool confirm); /** * Attempts to load image header from flash; verifies flash header fields. * - * The selected update method (i.e. swap move) may impose additional restrictions - * on the image size (i.e. due to the presence of the image trailer). - * Such restrictions are not verified by this function. - * These checks are implemented as part of the boot_image_validate(..) that uses - * sizes from the bootutil_max_image_size(..). - * * @param[in] fa_p flash area pointer * @param[out] hdr buffer for image header * diff --git a/boot/bootutil/src/bootutil_misc.c b/boot/bootutil/src/bootutil_misc.c index 17ed4c616..56e791043 100644 --- a/boot/bootutil/src/bootutil_misc.c +++ b/boot/bootutil/src/bootutil_misc.c @@ -42,10 +42,6 @@ #ifdef MCUBOOT_ENC_IMAGES #include "bootutil/enc_key.h" #endif -#if defined(MCUBOOT_SWAP_USING_MOVE) || defined(MCUBOOT_SWAP_USING_OFFSET) || \ - defined(MCUBOOT_SWAP_USING_SCRATCH) -#include "swap_priv.h" -#endif BOOT_LOG_MODULE_DECLARE(mcuboot); @@ -239,7 +235,8 @@ int boot_header_scramble_off_sz(const struct flash_area *fa, int slot, size_t *o * status during the swap of the last sector from primary/secondary (which * is the first swap operation) and thus only requires space for one swap. */ -uint32_t boot_scratch_trailer_sz(uint32_t min_write_sz) +static uint32_t +boot_scratch_trailer_sz(uint32_t min_write_sz) { return boot_status_entry_sz(min_write_sz) + boot_trailer_info_sz(); } @@ -425,6 +422,44 @@ boot_write_enc_key(const struct flash_area *fap, uint8_t slot, } #endif +#ifdef MCUBOOT_SWAP_USING_SCRATCH +size_t +boot_get_first_trailer_sector(struct boot_loader_state *state, size_t slot, size_t trailer_sz) +{ + size_t first_trailer_sector = boot_img_num_sectors(state, slot) - 1; + size_t sector_sz = boot_img_sector_size(state, slot, first_trailer_sector); + size_t trailer_sector_sz = sector_sz; + + while (trailer_sector_sz < trailer_sz) { + /* Consider that the image trailer may span across sectors of different sizes */ + --first_trailer_sector; + sector_sz = boot_img_sector_size(state, slot, first_trailer_sector); + + trailer_sector_sz += sector_sz; + } + + return first_trailer_sector; +} + +/** + * Returns the offset to the end of the first sector of a given slot that holds image trailer data. + * + * @param state Current bootloader's state. + * @param slot The index of the slot to consider. + * @param trailer_sz The size of the trailer, in bytes. + * + * @return The offset to the end of the first sector of the slot that holds image trailer data. + */ +static uint32_t +get_first_trailer_sector_end_off(struct boot_loader_state *state, size_t slot, size_t trailer_sz) +{ + size_t first_trailer_sector = boot_get_first_trailer_sector(state, slot, trailer_sz); + + return boot_img_sector_off(state, slot, first_trailer_sector) + + boot_img_sector_size(state, slot, first_trailer_sector); +} +#endif /* MCUBOOT_SWAP_USING_SCRATCH */ + uint32_t bootutil_max_image_size(struct boot_loader_state *state, const struct flash_area *fap) { #if defined(MCUBOOT_SINGLE_APPLICATION_SLOT) || \ @@ -432,10 +467,61 @@ uint32_t bootutil_max_image_size(struct boot_loader_state *state, const struct f defined(MCUBOOT_SINGLE_APPLICATION_SLOT_RAM_LOAD) (void) state; return boot_status_off(fap); -#elif defined(MCUBOOT_SWAP_USING_MOVE) || defined(MCUBOOT_SWAP_USING_OFFSET) \ - || defined(MCUBOOT_SWAP_USING_SCRATCH) +#elif defined(MCUBOOT_SWAP_USING_SCRATCH) + size_t slot_trailer_sz = boot_trailer_sz(BOOT_WRITE_SZ(state)); + size_t slot_trailer_off = flash_area_get_size(fap) - slot_trailer_sz; + + /* If the trailer doesn't fit in the last sector of the primary or secondary slot, some padding + * might have to be inserted between the end of the firmware image and the beginning of the + * trailer to ensure there is enough space for the trailer in the scratch area when the last + * sector of the secondary will be copied to the scratch area. + * + * The value of the padding depends on the amount of trailer data that is contained in the first + * trailer containing part of the trailer in the primary and secondary slot. + */ + size_t trailer_sector_primary_end_off = + get_first_trailer_sector_end_off(state, BOOT_PRIMARY_SLOT, slot_trailer_sz); + size_t trailer_sector_secondary_end_off = + get_first_trailer_sector_end_off(state, BOOT_SECONDARY_SLOT, slot_trailer_sz); + + size_t trailer_sz_in_first_sector; + + if (trailer_sector_primary_end_off > trailer_sector_secondary_end_off) { + trailer_sz_in_first_sector = trailer_sector_primary_end_off - slot_trailer_off; + } else { + trailer_sz_in_first_sector = trailer_sector_secondary_end_off - slot_trailer_off; + } + + size_t trailer_padding = 0; + size_t scratch_trailer_sz = boot_scratch_trailer_sz(BOOT_WRITE_SZ(state)); + + if (scratch_trailer_sz > trailer_sz_in_first_sector) { + trailer_padding = scratch_trailer_sz - trailer_sz_in_first_sector; + } + + return slot_trailer_off - trailer_padding; +#elif defined(MCUBOOT_SWAP_USING_MOVE) || defined(MCUBOOT_SWAP_USING_OFFSET) (void) fap; - return app_max_size(state); + + /* The slot whose size is used to compute the maximum image size must be the one containing the + * padding required for the swap. */ +#ifdef MCUBOOT_SWAP_USING_MOVE + size_t slot = BOOT_PRIMARY_SLOT; +#else + size_t slot = BOOT_SECONDARY_SLOT; +#endif + + const struct flash_area *fap_padded_slot = BOOT_IMG_AREA(state, slot); + assert(fap_padded_slot != NULL); + + size_t trailer_sz = boot_trailer_sz(BOOT_WRITE_SZ(state)); + size_t sector_sz = boot_img_sector_size(state, slot, 0); + size_t padding_sz = sector_sz; + + /* The trailer size needs to be sector-aligned */ + trailer_sz = ALIGN_UP(trailer_sz, sector_sz); + + return flash_area_get_size(fap_padded_slot) - trailer_sz - padding_sz; #elif defined(MCUBOOT_OVERWRITE_ONLY) (void) state; return boot_swap_info_off(fap); diff --git a/boot/bootutil/src/bootutil_priv.h b/boot/bootutil/src/bootutil_priv.h index 5d5a58a04..72e94aee9 100644 --- a/boot/bootutil/src/bootutil_priv.h +++ b/boot/bootutil/src/bootutil_priv.h @@ -363,14 +363,18 @@ int boot_read_enc_key(const struct flash_area *fap, uint8_t slot, struct boot_status *bs); #endif -#if MCUBOOT_SWAP_USING_SCRATCH -/* - * Similar to `boot_trailer_sz` but this function returns the space used to - * store status in the scratch partition. The scratch partition only stores - * status during the swap of the last sector from primary/secondary (which - * is the first swap operation) and thus only requires space for one swap. +#ifdef MCUBOOT_SWAP_USING_SCRATCH +/** + * Finds the first sector of a given slot that holds image trailer data. + * + * @param state Current bootloader's state. + * @param slot The index of the slot to consider. + * @param trailer_sz The size of the trailer, in bytes. + * + * @return The index of the first sector of the slot that holds image trailer data. */ -uint32_t boot_scratch_trailer_sz(uint32_t min_write_sz); +size_t +boot_get_first_trailer_sector(struct boot_loader_state *state, size_t slot, size_t trailer_sz); #endif /** diff --git a/boot/bootutil/src/swap_move.c b/boot/bootutil/src/swap_move.c index 8b7bcab13..9349cde37 100644 --- a/boot/bootutil/src/swap_move.c +++ b/boot/bootutil/src/swap_move.c @@ -227,6 +227,29 @@ boot_status_internal_off(const struct boot_status *bs, int elem_sz) return off; } +static int app_max_sectors(struct boot_loader_state *state) +{ + uint32_t sz = 0; + uint32_t sector_sz; + uint32_t trailer_sz; + uint32_t first_trailer_idx; + + sector_sz = boot_img_sector_size(state, BOOT_PRIMARY_SLOT, 0); + trailer_sz = boot_trailer_sz(BOOT_WRITE_SZ(state)); + /* subtract 1 for swap and at least 1 for trailer */ + first_trailer_idx = boot_img_num_sectors(state, BOOT_PRIMARY_SLOT) - 2; + + while (1) { + sz += sector_sz; + if (sz >= trailer_sz) { + break; + } + first_trailer_idx--; + } + + return first_trailer_idx; +} + int boot_slots_compatible(struct boot_loader_state *state) { @@ -235,16 +258,19 @@ boot_slots_compatible(struct boot_loader_state *state) size_t sector_sz_pri = 0; size_t sector_sz_sec = 0; size_t i; + size_t num_usable_sectors_pri; num_sectors_pri = boot_img_num_sectors(state, BOOT_PRIMARY_SLOT); num_sectors_sec = boot_img_num_sectors(state, BOOT_SECONDARY_SLOT); + num_usable_sectors_pri = app_max_sectors(state); if ((num_sectors_pri != num_sectors_sec) && - (num_sectors_pri != (num_sectors_sec + 1))) { + (num_sectors_pri != (num_sectors_sec + 1)) && + (num_usable_sectors_pri != (num_sectors_sec + 1))) { BOOT_LOG_WRN("Cannot upgrade: not a compatible amount of sectors"); BOOT_LOG_DBG("slot0 sectors: %d, slot1 sectors: %d, usable slot0 sectors: %d", (int)num_sectors_pri, (int)num_sectors_sec, - (int)(num_sectors_pri - 1)); + (int)(num_usable_sectors_pri - 1)); return 0; } else if (num_sectors_pri > BOOT_MAX_IMG_SECTORS) { BOOT_LOG_WRN("Cannot upgrade: more sectors than allowed"); @@ -254,7 +280,7 @@ boot_slots_compatible(struct boot_loader_state *state) /* Optimal says primary has one more than secondary. Always. Both have trailers. */ if (num_sectors_pri != (num_sectors_sec + 1)) { BOOT_LOG_DBG("Non-optimal sector distribution, slot0 has %d usable sectors (%d assigned) " - "but slot1 has %d assigned", (int)(num_sectors_pri - 1), + "but slot1 has %d assigned", (int)num_usable_sectors_pri, (int)num_sectors_pri, (int)num_sectors_sec); } @@ -314,6 +340,7 @@ swap_status_source(struct boot_loader_state *state) struct boot_swap_state state_primary_slot; struct boot_swap_state state_secondary_slot; int rc; + uint8_t source; uint8_t image_index; #if (BOOT_IMAGE_NUMBER == 1) @@ -338,8 +365,10 @@ swap_status_source(struct boot_loader_state *state) state_primary_slot.copy_done == BOOT_FLAG_UNSET && state_secondary_slot.magic != BOOT_MAGIC_GOOD) { + source = BOOT_STATUS_SOURCE_PRIMARY_SLOT; + BOOT_LOG_INF("Boot source: primary slot"); - return BOOT_STATUS_SOURCE_PRIMARY_SLOT; + return source; } BOOT_LOG_INF("Boot source: none"); @@ -561,23 +590,11 @@ swap_run(struct boot_loader_state *state, struct boot_status *bs, int app_max_size(struct boot_loader_state *state) { - uint32_t available_pri_sz; - uint32_t available_sec_sz; - - size_t trailer_sz = boot_trailer_sz(BOOT_WRITE_SZ(state)); - size_t sector_sz = boot_img_sector_size(state, BOOT_PRIMARY_SLOT, 0); - size_t padding_sz = sector_sz; + uint32_t sector_sz_primary; - /* The trailer size needs to be sector-aligned */ - trailer_sz = ALIGN_UP(trailer_sz, sector_sz); - - /* The slot whose size is used to compute the maximum image size must be the one containing the - * padding required for the swap. - */ - available_pri_sz = boot_img_num_sectors(state, BOOT_PRIMARY_SLOT) * sector_sz - trailer_sz - padding_sz; - available_sec_sz = boot_img_num_sectors(state, BOOT_SECONDARY_SLOT) * sector_sz - trailer_sz; + sector_sz_primary = boot_img_sector_size(state, BOOT_PRIMARY_SLOT, 0); - return (available_pri_sz < available_sec_sz ? available_pri_sz : available_sec_sz); + return app_max_sectors(state) * sector_sz_primary; } #endif diff --git a/boot/bootutil/src/swap_offset.c b/boot/bootutil/src/swap_offset.c index d8bfac318..8bc6e760a 100644 --- a/boot/bootutil/src/swap_offset.c +++ b/boot/bootutil/src/swap_offset.c @@ -302,6 +302,33 @@ uint32_t boot_status_internal_off(const struct boot_status *bs, int elem_sz) return off; } +static int app_max_sectors(struct boot_loader_state *state) +{ + uint32_t sz = 0; + uint32_t sector_sz; + uint32_t trailer_sz; + uint32_t available_sectors_pri; + uint32_t available_sectors_sec; + uint32_t trailer_sectors = 0; + + sector_sz = boot_img_sector_size(state, BOOT_PRIMARY_SLOT, 0); + trailer_sz = boot_trailer_sz(BOOT_WRITE_SZ(state)); + + while (1) { + sz += sector_sz; + ++trailer_sectors; + + if (sz >= trailer_sz) { + break; + } + } + + available_sectors_pri = boot_img_num_sectors(state, BOOT_PRIMARY_SLOT) - trailer_sectors; + available_sectors_sec = boot_img_num_sectors(state, BOOT_SECONDARY_SLOT) - 1; + + return (available_sectors_pri < available_sectors_sec ? available_sectors_pri : available_sectors_sec); +} + int boot_slots_compatible(struct boot_loader_state *state) { size_t num_sectors_pri; @@ -309,30 +336,32 @@ int boot_slots_compatible(struct boot_loader_state *state) size_t sector_sz_pri = 0; size_t sector_sz_sec = 0; size_t i; + size_t num_usable_sectors; num_sectors_pri = boot_img_num_sectors(state, BOOT_PRIMARY_SLOT); num_sectors_sec = boot_img_num_sectors(state, BOOT_SECONDARY_SLOT); + num_usable_sectors = app_max_sectors(state); if (num_sectors_pri != num_sectors_sec && - (num_sectors_pri + 1) != num_sectors_sec) { + (num_sectors_pri + 1) != num_sectors_sec && + num_usable_sectors != (num_sectors_sec - 1)) { BOOT_LOG_WRN("Cannot upgrade: not a compatible amount of sectors"); BOOT_LOG_DBG("slot0 sectors: %d, slot1 sectors: %d, usable sectors: %d", (int)num_sectors_pri, (int)num_sectors_sec, - (int)(num_sectors_sec - 1)); + (int)(num_usable_sectors)); return 0; } else if (num_sectors_pri > BOOT_MAX_IMG_SECTORS) { BOOT_LOG_WRN("Cannot upgrade: more sectors than allowed"); return 0; } - /* Optimal says secondary has one more than primary. Always. Both have trailers. */ - if ((num_sectors_pri + 1) != num_sectors_sec) { + if ((num_usable_sectors + 1) != num_sectors_sec) { BOOT_LOG_DBG("Non-optimal sector distribution, slot0 has %d usable sectors " - "but slot1 has %d usable sectors", (int)(num_sectors_pri), + "but slot1 has %d usable sectors", (int)(num_usable_sectors), ((int)num_sectors_sec - 1)); } - for (i = 0; i < (num_sectors_sec - 1); i++) { + for (i = 0; i < num_usable_sectors; i++) { sector_sz_pri = boot_img_sector_size(state, BOOT_PRIMARY_SLOT, i); sector_sz_sec = boot_img_sector_size(state, BOOT_SECONDARY_SLOT, i); @@ -388,6 +417,7 @@ int swap_status_source(struct boot_loader_state *state) struct boot_swap_state state_primary_slot; struct boot_swap_state state_secondary_slot; int rc; + uint8_t source; uint8_t image_index; #if (BOOT_IMAGE_NUMBER == 1) @@ -409,8 +439,10 @@ int swap_status_source(struct boot_loader_state *state) state_primary_slot.copy_done == BOOT_FLAG_UNSET && state_secondary_slot.magic != BOOT_MAGIC_GOOD) { + source = BOOT_STATUS_SOURCE_PRIMARY_SLOT; + BOOT_LOG_INF("Boot source: primary slot"); - return BOOT_STATUS_SOURCE_PRIMARY_SLOT; + return source; } BOOT_LOG_INF("Boot source: none"); @@ -697,23 +729,11 @@ void swap_run(struct boot_loader_state *state, struct boot_status *bs, int app_max_size(struct boot_loader_state *state) { - uint32_t available_pri_sz; - uint32_t available_sec_sz; - - size_t trailer_sz = boot_trailer_sz(BOOT_WRITE_SZ(state)); - size_t sector_sz = boot_img_sector_size(state, BOOT_PRIMARY_SLOT, 0); - size_t padding_sz = sector_sz; - - /* The trailer size needs to be sector-aligned */ - trailer_sz = ALIGN_UP(trailer_sz, sector_sz); + uint32_t sector_sz_primary; - /* The slot whose size is used to compute the maximum image size must be the one containing the - * padding required for the swap. - */ - available_pri_sz = boot_img_num_sectors(state, BOOT_PRIMARY_SLOT) * sector_sz - trailer_sz; - available_sec_sz = boot_img_num_sectors(state, BOOT_SECONDARY_SLOT) * sector_sz - trailer_sz - padding_sz; + sector_sz_primary = boot_img_sector_size(state, BOOT_PRIMARY_SLOT, 0); - return (available_pri_sz < available_sec_sz ? available_pri_sz : available_sec_sz); + return app_max_sectors(state) * sector_sz_primary; } /* Compute the total size of the given image. Includes the size of the TLVs. */ diff --git a/boot/bootutil/src/swap_scratch.c b/boot/bootutil/src/swap_scratch.c index e1d49de49..f9dbb7103 100644 --- a/boot/bootutil/src/swap_scratch.c +++ b/boot/bootutil/src/swap_scratch.c @@ -47,136 +47,6 @@ int boot_status_fails = 0; #define BOOT_STATUS_ASSERT(x) ASSERT(x) #endif -#if MCUBOOT_SWAP_USING_SCRATCH -/** - * Finds the first sector of a given slot that holds image trailer data. - * - * @param state Current bootloader's state. - * @param slot The index of the slot to consider. - * @param trailer_sz The size of the trailer, in bytes. - * - * @return The index of the first sector of the slot that holds image trailer data. - */ -static size_t -boot_get_first_trailer_sector(struct boot_loader_state *state, size_t slot, size_t trailer_sz) -{ - size_t first_trailer_sector = boot_img_num_sectors(state, slot) - 1; - size_t sector_sz = boot_img_sector_size(state, slot, first_trailer_sector); - size_t trailer_sector_sz = sector_sz; - - while (trailer_sector_sz < trailer_sz) { - /* Consider that the image trailer may span across sectors of different sizes */ - --first_trailer_sector; - sector_sz = boot_img_sector_size(state, slot, first_trailer_sector); - - trailer_sector_sz += sector_sz; - } - - return first_trailer_sector; -} - -/** - * Returns the offset to the end of the first sector of a given slot that holds image trailer data. - * - * @param state Current bootloader's state. - * @param slot The index of the slot to consider. - * @param trailer_sz The size of the trailer, in bytes. - * - * @return The offset to the end of the first sector of the slot that holds image trailer data. - */ -static uint32_t -get_first_trailer_sector_end_off(struct boot_loader_state *state, size_t slot, size_t trailer_sz) -{ - size_t first_trailer_sector = boot_get_first_trailer_sector(state, slot, trailer_sz); - - return boot_img_sector_off(state, slot, first_trailer_sector) + - boot_img_sector_size(state, slot, first_trailer_sector); -} - -/** - * Returns the size of the part of the slot that can be used for storing image data. - * - * @param state Current bootloader's state. - * @param slot_size The size of the slot partition. - * - * @return The offset to the end of the first sector of the slot that holds image trailer data. - */ -static size_t app_max_size_adjust_to_trailer(struct boot_loader_state *state, size_t slot_size) -{ - size_t slot_trailer_sz = boot_trailer_sz(BOOT_WRITE_SZ(state)); - size_t slot_trailer_off = slot_size - slot_trailer_sz; - size_t trailer_sz_in_first_sector; - size_t trailer_sector_end_off; - - - size_t trailer_sector_primary_end_off = - get_first_trailer_sector_end_off(state, BOOT_PRIMARY_SLOT, slot_trailer_sz); - size_t trailer_sector_secondary_end_off = - get_first_trailer_sector_end_off(state, BOOT_SECONDARY_SLOT, slot_trailer_sz); - - /* If slots have sectors of different sizes, we need to find the "common" sector - * boundary (slot compatibility checks ensure that the larger sector contains a multiple - * of the smaller sector size). This will be the larger of the - * trailer_sector_primary_end_off/trailer_sector_secondary_end_off. - * - * <-------copy size-------> <--------copy size------> <----copy size---> - * v v v v - * +------------+------------+-------------------------+------------------+ - * | sector | sector | sector | sector | - * +------------+------------+------------+------------+------------------+ - * | sector | sector | sector | sector | - * +-------------------------+------------+------------+------------------+ - * - * The swap logic always uses the common boundary when performing the copy. - * Hence, the first trailer sector used for calculation is the larger - * sector from the two slots. - * - * <-----------copy size---------------> - * | sector | sector | - * +-----------------------------------+ - * | sector | - * +-----------------------------------+ - * |Image->| |<-trailer------------| - * +-----------------------------------+ - * | |<-scratch trailer>| - * +-----------------------------------+ - */ - if (trailer_sector_primary_end_off > trailer_sector_secondary_end_off) { - trailer_sector_end_off = trailer_sector_primary_end_off; - } else { - trailer_sector_end_off = trailer_sector_secondary_end_off; - } - - trailer_sz_in_first_sector = trailer_sector_end_off - slot_trailer_off; - - size_t trailer_padding = 0; - size_t scratch_trailer_sz = boot_scratch_trailer_sz(BOOT_WRITE_SZ(state)); - - /* Some padding might have to be inserted between the end of the firmware image and the - * beginning of the trailer to ensure there is enough space for the trailer in the scratch area - * when the last sector of the secondary will be copied to the scratch area. - * - * +-----------------------------------+-----------------------------------+ - * | sector | sector | - * +-----------------------------------+-----------------------------------+ - * |Image->| |<--trailer---|-----------trailer (cont.)-------->| - * +-----------------------------------+-----------------------------------+ - * | |<----scratch trailer---->| - * +-----------------------------------+ - * <-padding-> - * <--------scratch area size--------> - * - * The value of the padding depends on the amount of trailer data that is contained in the first - * sector containing part of the trailer in the primary and secondary slot. - */ - if (scratch_trailer_sz > trailer_sz_in_first_sector) { - trailer_padding = scratch_trailer_sz - trailer_sz_in_first_sector; - } - - return slot_trailer_off - trailer_padding; -} -#endif /* MCUBOOT_SWAP_USING_SCRATCH */ - #if !defined(MCUBOOT_DIRECT_XIP) && !defined(MCUBOOT_RAM_LOAD) /** * Reads the status of a partially-completed swap, if any. This is necessary @@ -951,8 +821,8 @@ int app_max_size(struct boot_loader_state *state) size_t num_sectors_primary; size_t num_sectors_secondary; size_t sz0, sz1; + size_t primary_slot_sz, secondary_slot_sz; #ifndef MCUBOOT_OVERWRITE_ONLY - size_t slot_sz; size_t scratch_sz; #endif size_t i, j; @@ -972,11 +842,8 @@ int app_max_size(struct boot_loader_state *state) * number of a slot's sectors are able to fit into another, which only * excludes cases where sector sizes are not a multiple of each other. */ -#ifndef MCUBOOT_OVERWRITE_ONLY - slot_sz = 0; -#endif - i = sz0 = 0; - j = sz1 = 0; + i = sz0 = primary_slot_sz = 0; + j = sz1 = secondary_slot_sz = 0; smaller = 0; while (i < num_sectors_primary || j < num_sectors_secondary) { if (sz0 == sz1) { @@ -1009,7 +876,8 @@ int app_max_size(struct boot_loader_state *state) } #ifndef MCUBOOT_OVERWRITE_ONLY if (sz0 == sz1) { - slot_sz += sz0; + primary_slot_sz += sz0; + secondary_slot_sz += sz1; /* Scratch has to fit each swap operation to the size of the larger * sector among the primary slot and the secondary slot. */ @@ -1024,10 +892,8 @@ int app_max_size(struct boot_loader_state *state) #ifdef MCUBOOT_OVERWRITE_ONLY return (sz1 < sz0 ? sz1 : sz0); -#elif MCUBOOT_SWAP_USING_SCRATCH - return app_max_size_adjust_to_trailer(state, slot_sz); #else - return slot_sz; + return (secondary_slot_sz < primary_slot_sz ? secondary_slot_sz : primary_slot_sz); #endif } #else From e538cc5e74e89ceefa8254694c7ee0983db6ee60 Mon Sep 17 00:00:00 2001 From: Jukka Rissanen Date: Tue, 23 Sep 2025 13:04:30 +0300 Subject: [PATCH 268/420] Revert "[nrf fromlist] boot: zephyr: boards: Remove outdated nrf54l15pdk board config" This reverts commit 22199979e37e55cbf37053fa099baf29550967e1. Signed-off-by: Jukka Rissanen --- boot/zephyr/boards/nrf54l15pdk_nrf54l15_cpuapp.conf | 10 ++++++++++ 1 file changed, 10 insertions(+) create mode 100644 boot/zephyr/boards/nrf54l15pdk_nrf54l15_cpuapp.conf diff --git a/boot/zephyr/boards/nrf54l15pdk_nrf54l15_cpuapp.conf b/boot/zephyr/boards/nrf54l15pdk_nrf54l15_cpuapp.conf new file mode 100644 index 000000000..43d8cebe3 --- /dev/null +++ b/boot/zephyr/boards/nrf54l15pdk_nrf54l15_cpuapp.conf @@ -0,0 +1,10 @@ +# Copyright (c) 2024 Nordic Semiconductor ASA +# +# SPDX-License-Identifier: Apache-2.0 +# +CONFIG_BOOT_MAX_IMG_SECTORS=256 + +# Ensure that the SPI NOR driver is disabled by default +CONFIG_SPI_NOR=n + +CONFIG_BOOT_WATCHDOG_FEED=n From 1b1a3db34d150243ab5b2c48529a43456bd0560a Mon Sep 17 00:00:00 2001 From: Jukka Rissanen Date: Tue, 23 Sep 2025 13:04:30 +0300 Subject: [PATCH 269/420] Revert "[nrf fromtree] bootutil: Use flash base address for direct hash" This reverts commit 80f8e8c926b6e4c7e8a3fca4e97867575ed39300. Signed-off-by: Jukka Rissanen --- boot/bootutil/src/image_validate.c | 11 +---------- docs/release-notes.d/fix-direct-hash-base-address.md | 2 -- 2 files changed, 1 insertion(+), 12 deletions(-) delete mode 100644 docs/release-notes.d/fix-direct-hash-base-address.md diff --git a/boot/bootutil/src/image_validate.c b/boot/bootutil/src/image_validate.c index 17193a63d..f6d4ba224 100644 --- a/boot/bootutil/src/image_validate.c +++ b/boot/bootutil/src/image_validate.c @@ -87,10 +87,6 @@ bootutil_img_hash(struct boot_loader_state *state, uint32_t off; uint32_t blk_sz; #endif -#ifdef MCUBOOT_HASH_STORAGE_DIRECTLY - uintptr_t base = 0; - int fa_ret; -#endif #if defined(MCUBOOT_ENC_IMAGES) struct enc_key_data *enc_state; int image_index; @@ -164,12 +160,7 @@ bootutil_img_hash(struct boot_loader_state *state, /* No chunk loading, storage is mapped to address space and can * be directly given to hashing function. */ - fa_ret = flash_device_base(flash_area_get_device_id(fap), &base); - if (fa_ret != 0) { - base = 0; - } - - bootutil_sha_update(&sha_ctx, (void *)(base + flash_area_get_off(fap)), size); + bootutil_sha_update(&sha_ctx, (void *)flash_area_get_off(fap), size); #else /* MCUBOOT_HASH_STORAGE_DIRECTLY */ #ifdef MCUBOOT_RAM_LOAD bootutil_sha_update(&sha_ctx, diff --git a/docs/release-notes.d/fix-direct-hash-base-address.md b/docs/release-notes.d/fix-direct-hash-base-address.md deleted file mode 100644 index 041a45134..000000000 --- a/docs/release-notes.d/fix-direct-hash-base-address.md +++ /dev/null @@ -1,2 +0,0 @@ - - Fixed issue in image_validate when `MCUBOOT_HASH_STORAGE_DIRECTLY` is enabled - for platforms with NVM memory that does not start at 0x00. From 3af1060fb6106e43fd0bef43537ddc0f72e353f4 Mon Sep 17 00:00:00 2001 From: Jukka Rissanen Date: Tue, 23 Sep 2025 13:04:30 +0300 Subject: [PATCH 270/420] Revert "[nrf fromtree] imgtool: Add support for HMAC/HKDF-SHA512 with ECIES-X25519" This reverts commit c4c82e20aed038dc62fef8d2499afa162d3d8e9d. Signed-off-by: Jukka Rissanen --- scripts/imgtool/image.py | 37 ++++++++++--------------------------- scripts/imgtool/main.py | 11 ++++------- 2 files changed, 14 insertions(+), 34 deletions(-) diff --git a/scripts/imgtool/image.py b/scripts/imgtool/image.py index 03e2cbb62..c7fb9e553 100644 --- a/scripts/imgtool/image.py +++ b/scripts/imgtool/image.py @@ -88,7 +88,6 @@ 'ENCKW': 0x31, 'ENCEC256': 0x32, 'ENCX25519': 0x33, - 'ENCX25519_SHA512': 0x34, 'DEPENDENCY': 0x40, 'SEC_CNT': 0x50, 'BOOT_RECORD': 0x60, @@ -436,7 +435,7 @@ def check_trailer(self): len(self.payload), tsize, self.slot_size) raise click.UsageError(msg) - def ecies_hkdf(self, enckey, plainkey, hmac_sha_alg): + def ecies_hkdf(self, enckey, plainkey): if isinstance(enckey, ecdsa.ECDSA256P1Public): newpk = ec.generate_private_key(ec.SECP256R1(), default_backend()) shared = newpk.exchange(ec.ECDH(), enckey._get_public()) @@ -444,13 +443,13 @@ def ecies_hkdf(self, enckey, plainkey, hmac_sha_alg): newpk = X25519PrivateKey.generate() shared = newpk.exchange(enckey._get_public()) derived_key = HKDF( - algorithm=hmac_sha_alg, length=48, salt=None, + algorithm=hashes.SHA256(), length=48, salt=None, info=b'MCUBoot_ECIES_v1', backend=default_backend()).derive(shared) encryptor = Cipher(algorithms.AES(derived_key[:16]), modes.CTR(bytes([0] * 16)), backend=default_backend()).encryptor() cipherkey = encryptor.update(plainkey) + encryptor.finalize() - mac = hmac.HMAC(derived_key[16:], hmac_sha_alg, + mac = hmac.HMAC(derived_key[16:], hashes.SHA256(), backend=default_backend()) mac.update(cipherkey) ciphermac = mac.finalize() @@ -468,8 +467,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', hmac_sha='auto', is_pure=False, keep_comp_size=False, - dont_encrypt=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 @@ -676,17 +674,6 @@ def create(self, key, public_key_format, enckey, dependencies=None, else: plainkey = os.urandom(16) - if not isinstance(enckey, rsa.RSAPublic): - if hmac_sha == 'auto' or hmac_sha == '256': - hmac_sha = '256' - hmac_sha_alg = hashes.SHA256() - elif hmac_sha == '512': - if not isinstance(enckey, x25519.X25519Public): - raise click.UsageError("Currently only ECIES-X25519 supports HMAC-SHA512") - hmac_sha_alg = hashes.SHA512() - else: - raise click.UsageError("Unsupported HMAC-SHA") - if isinstance(enckey, rsa.RSAPublic): cipherkey = enckey._get_public().encrypt( plainkey, padding.OAEP( @@ -695,19 +682,15 @@ def create(self, key, public_key_format, enckey, dependencies=None, label=None)) self.enctlv_len = len(cipherkey) tlv.add('ENCRSA2048', cipherkey) - elif isinstance(enckey, ecdsa.ECDSA256P1Public): - cipherkey, mac, pubk = self.ecies_hkdf(enckey, plainkey, hmac_sha_alg) - enctlv = pubk + mac + cipherkey - self.enctlv_len = len(enctlv) - tlv.add('ENCEC256', enctlv) - elif isinstance(enckey, x25519.X25519Public): - cipherkey, mac, pubk = self.ecies_hkdf(enckey, plainkey, hmac_sha_alg) + elif isinstance(enckey, (ecdsa.ECDSA256P1Public, + x25519.X25519Public)): + cipherkey, mac, pubk = self.ecies_hkdf(enckey, plainkey) enctlv = pubk + mac + cipherkey self.enctlv_len = len(enctlv) - if (hmac_sha == '256'): - tlv.add('ENCX25519', enctlv) + if isinstance(enckey, ecdsa.ECDSA256P1Public): + tlv.add('ENCEC256', enctlv) else: - tlv.add('ENCX25519_SHA512', enctlv) + tlv.add('ENCX25519', enctlv) if not clear: nonce = bytes([0] * 16) diff --git a/scripts/imgtool/main.py b/scripts/imgtool/main.py index 5ff1f8f9f..78f2e77ec 100755 --- a/scripts/imgtool/main.py +++ b/scripts/imgtool/main.py @@ -84,7 +84,6 @@ def gen_x25519(keyfile, passwd): } valid_formats = ['openssl', 'pkcs8'] valid_sha = [ 'auto', '256', '384', '512' ] -valid_hmac_sha = [ 'auto', '256', '512' ] def load_signature(sigfile): @@ -438,8 +437,6 @@ def convert(self, value, param, ctx): @click.option('--sha', 'user_sha', type=click.Choice(valid_sha), default='auto', help='selected sha algorithm to use; defaults to "auto" which is 256 if ' 'no cryptographic signature is used, or default for signature type') -@click.option('--hmac-sha', 'hmac_sha', type=click.Choice(valid_hmac_sha), default='auto', - help='sha algorithm used in HKDF/HMAC in ECIES key exchange TLV') @click.option('--vector-to-sign', type=click.Choice(['payload', 'digest']), help='send to OUTFILE the payload or payload''s digest instead ' 'of complied image. These data can be used for external image ' @@ -452,7 +449,7 @@ 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, hmac_sha, is_pure, + clear, fix_sig, fix_sig_pubkey, sig_out, user_sha, is_pure, vector_to_sign, non_bootable): if confirm: @@ -529,7 +526,7 @@ def sign(key, public_key_format, align, version, pad_sig, header_size, 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, - hmac_sha=hmac_sha, is_pure=is_pure, keep_comp_size=False, dont_encrypt=True) + 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), @@ -573,14 +570,14 @@ 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, hmac_sha=hmac_sha, + pub_key, vector_to_sign, user_sha=user_sha, 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, - hmac_sha=hmac_sha, is_pure=is_pure) + is_pure=is_pure) img.save(outfile, hex_addr) if sig_out is not None: new_signature = img.get_signature() From 89d5036e1f36ef9c6aa9b1a32f15961c53770e35 Mon Sep 17 00:00:00 2001 From: Jukka Rissanen Date: Tue, 23 Sep 2025 13:04:30 +0300 Subject: [PATCH 271/420] Revert "[nrf fromtree] zephyr: Support for HKDF/HMAC with SHA512" This reverts commit 1a457e304f3c879db9a5a170992a3af376b1d430. Signed-off-by: Jukka Rissanen --- boot/zephyr/Kconfig | 9 --------- boot/zephyr/include/mcuboot_config/mcuboot_config.h | 7 ------- 2 files changed, 16 deletions(-) diff --git a/boot/zephyr/Kconfig b/boot/zephyr/Kconfig index dc445b4ed..acc0314a6 100644 --- a/boot/zephyr/Kconfig +++ b/boot/zephyr/Kconfig @@ -601,15 +601,6 @@ config BOOT_ENCRYPT_X25519 help Hidden option selecting x25519 encryption. -config BOOT_HMAC_SHA512 - bool "Use SHA512 for HMAC/HKDF" - depends on BOOT_ENCRYPT_X25519 - depends on BOOT_USE_PSA_CRYPTO - help - By default SHA256 is used for HKDF/HMAC in key exchange expansion - and verification. This options switches to SHA512. The option is - mainly useful to reduce numer of compiled in SHA algorithms. - config BOOT_ENCRYPTION_KEY_FILE string "Encryption key file" depends on BOOT_ENCRYPT_IMAGE diff --git a/boot/zephyr/include/mcuboot_config/mcuboot_config.h b/boot/zephyr/include/mcuboot_config/mcuboot_config.h index 820ffd752..fd003565a 100644 --- a/boot/zephyr/include/mcuboot_config/mcuboot_config.h +++ b/boot/zephyr/include/mcuboot_config/mcuboot_config.h @@ -153,13 +153,6 @@ #define MCUBOOT_ENCRYPT_X25519 #endif -/* Support for HMAC/HKDF using SHA512; this is used in key exchange where - * HKDF is used for key expansion and HMAC is used for key verification. - */ -#ifdef CONFIG_BOOT_HMAC_SHA512 -#define MCUBOOT_HMAC_SHA512 -#endif - #ifdef CONFIG_BOOT_DECOMPRESSION #define MCUBOOT_DECOMPRESS_IMAGES #endif From b838a07c7b35a1f1f17670bd3370080f6cb28cf5 Mon Sep 17 00:00:00 2001 From: Jukka Rissanen Date: Tue, 23 Sep 2025 13:04:30 +0300 Subject: [PATCH 272/420] Revert "[nrf fromtree] bootutil: Add support for HAMC-SHA512 with ECIES-X25519" This reverts commit 736d33ee0e557481df17bec4ecfe9990f562340c. Signed-off-by: Jukka Rissanen --- boot/bootutil/include/bootutil/enc_key_public.h | 17 ++--------------- boot/bootutil/include/bootutil/image.h | 3 --- boot/bootutil/src/encrypted_psa.c | 12 +++--------- boot/bootutil/src/image_validate.c | 4 ---- 4 files changed, 5 insertions(+), 31 deletions(-) diff --git a/boot/bootutil/include/bootutil/enc_key_public.h b/boot/bootutil/include/bootutil/enc_key_public.h index 4582dfcf7..55b06b025 100644 --- a/boot/bootutil/include/bootutil/enc_key_public.h +++ b/boot/bootutil/include/bootutil/enc_key_public.h @@ -70,19 +70,10 @@ extern "C" { # define BOOT_ENC_KEY_SIZE 16 #endif -#ifdef MCUBOOT_HMAC_SHA512 -# define BOOT_HMAC_SIZE 64 -#else -# define BOOT_HMAC_SIZE 32 -#endif - #if defined(MCUBOOT_ENCRYPT_RSA) # define BOOT_ENC_TLV_SIZE (256) # define BOOT_ENC_TLV IMAGE_TLV_ENC_RSA2048 #elif defined(MCUBOOT_ENCRYPT_EC256) -# if defined(MCUBOOT_HMAC_SHA512) -# error "ECIES-P256 does not support HMAC-SHA512" -# endif # define EC_PUBK_LEN (65) # define EC_PRIVK_LEN (32) # define EC_SHARED_LEN (32) @@ -91,11 +82,7 @@ extern "C" { # define EC_PUBK_LEN (32) # define EC_PRIVK_LEN (32) # define EC_SHARED_LEN (32) -# if !defined(MCUBOOT_HMAC_SHA512) -# define BOOT_ENC_TLV IMAGE_TLV_ENC_X25519 -# else -# define BOOT_ENC_TLV IMAGE_TLV_ENC_X25519_SHA512 -# endif +# define BOOT_ENC_TLV IMAGE_TLV_ENC_X25519 #elif defined(MCUBOOT_ENCRYPT_KW) # define BOOT_ENC_TLV_SIZE (BOOT_ENC_KEY_SIZE + 8) # define BOOT_ENC_TLV IMAGE_TLV_ENC_KW @@ -104,7 +91,7 @@ extern "C" { /* Common ECIES definitions */ #if defined(EC_PUBK_LEN) # define EC_PUBK_INDEX (0) -# define EC_TAG_LEN (BOOT_HMAC_SIZE) +# define EC_TAG_LEN (32) # define EC_TAG_INDEX (EC_PUBK_INDEX + EC_PUBK_LEN) # define EC_CIPHERKEY_INDEX (EC_TAG_INDEX + EC_TAG_LEN) # define EC_CIPHERKEY_LEN BOOT_ENC_KEY_SIZE diff --git a/boot/bootutil/include/bootutil/image.h b/boot/bootutil/include/bootutil/image.h index 11c54b633..f49eab347 100644 --- a/boot/bootutil/include/bootutil/image.h +++ b/boot/bootutil/include/bootutil/image.h @@ -113,9 +113,6 @@ extern "C" { #define IMAGE_TLV_ENC_KW 0x31 /* Key encrypted with AES-KW 128 or 256*/ #define IMAGE_TLV_ENC_EC256 0x32 /* Key encrypted with ECIES-EC256 */ #define IMAGE_TLV_ENC_X25519 0x33 /* Key encrypted with ECIES-X25519 */ -#define IMAGE_TLV_ENC_X25519_SHA512 0x34 /* Key exchange using ECIES-X25519 and SHA512 for MAC - * tag and HKDF in key derivation process - */ #define IMAGE_TLV_DEPENDENCY 0x40 /* Image depends on other image */ #define IMAGE_TLV_SEC_CNT 0x50 /* security counter */ #define IMAGE_TLV_BOOT_RECORD 0x60 /* measured boot record */ diff --git a/boot/bootutil/src/encrypted_psa.c b/boot/bootutil/src/encrypted_psa.c index 0cfdc9768..6f60a1955 100644 --- a/boot/bootutil/src/encrypted_psa.c +++ b/boot/bootutil/src/encrypted_psa.c @@ -27,12 +27,6 @@ BOOT_LOG_MODULE_DECLARE(mcuboot_psa_enc); -#if defined(MCUBOOT_HMAC_SHA512) -#define PSA_HMAC_HKDF_SHA PSA_ALG_SHA_512 -#else -#define PSA_HMAC_HKDF_SHA PSA_ALG_SHA_256 -#endif - #define X25519_OID "\x6e" static const uint8_t ec_pubkey_oid[] = MBEDTLS_OID_ISO_IDENTIFIED_ORG \ MBEDTLS_OID_ORG_GOV X25519_OID; @@ -168,7 +162,7 @@ boot_decrypt_key(const uint8_t *buf, uint8_t *enckey) return -1; } - key_do_alg = PSA_ALG_KEY_AGREEMENT(PSA_ALG_ECDH, PSA_ALG_HKDF(PSA_HMAC_HKDF_SHA)); + key_do_alg = PSA_ALG_KEY_AGREEMENT(PSA_ALG_ECDH, PSA_ALG_HKDF(PSA_ALG_SHA_256)); psa_ret = psa_key_derivation_setup(&key_do, key_do_alg); if (psa_ret != PSA_SUCCESS) { @@ -231,7 +225,7 @@ boot_decrypt_key(const uint8_t *buf, uint8_t *enckey) */ psa_set_key_type(&kattr, PSA_KEY_TYPE_HMAC); psa_set_key_usage_flags(&kattr, PSA_KEY_USAGE_VERIFY_MESSAGE); - psa_set_key_algorithm(&kattr, PSA_ALG_HMAC(PSA_HMAC_HKDF_SHA)); + psa_set_key_algorithm(&kattr, PSA_ALG_HMAC(PSA_ALG_SHA_256)); /* Import the MAC tag key part of derived key */ psa_ret = psa_import_key(&kattr, @@ -245,7 +239,7 @@ boot_decrypt_key(const uint8_t *buf, uint8_t *enckey) } /* Verify the MAC tag of the random encryption key */ - psa_ret = psa_mac_verify(kid, PSA_ALG_HMAC(PSA_HMAC_HKDF_SHA), + psa_ret = psa_mac_verify(kid, PSA_ALG_HMAC(PSA_ALG_SHA_256), &buf[EC_CIPHERKEY_INDEX], EC_CIPHERKEY_LEN, &buf[EC_TAG_INDEX], EC_TAG_LEN); diff --git a/boot/bootutil/src/image_validate.c b/boot/bootutil/src/image_validate.c index f6d4ba224..eec678724 100644 --- a/boot/bootutil/src/image_validate.c +++ b/boot/bootutil/src/image_validate.c @@ -474,11 +474,7 @@ static const uint16_t allowed_unprot_tlvs[] = { IMAGE_TLV_ENC_RSA2048, IMAGE_TLV_ENC_KW, IMAGE_TLV_ENC_EC256, -#if !defined(MCUBOOT_HMAC_SHA512) IMAGE_TLV_ENC_X25519, -#else - IMAGE_TLV_ENC_X25519_SHA512, -#endif /* Mark end with ANY. */ IMAGE_TLV_ANY, }; From 47b261fb18df1661e144e1c4f80a345a79e16f59 Mon Sep 17 00:00:00 2001 From: Jukka Rissanen Date: Tue, 23 Sep 2025 13:04:30 +0300 Subject: [PATCH 273/420] Revert "[nrf fromtree] doc: Add information on supporting SHA512 with ECIES-X25519" This reverts commit 860d366a4b150918b7abf27df20d5246eb4cb235. Signed-off-by: Jukka Rissanen --- docs/encrypted_images.md | 21 ++++++--------------- 1 file changed, 6 insertions(+), 15 deletions(-) diff --git a/docs/encrypted_images.md b/docs/encrypted_images.md index 5f775ef18..ebc4f46ed 100644 --- a/docs/encrypted_images.md +++ b/docs/encrypted_images.md @@ -92,33 +92,24 @@ libraries. The whole key encryption can be summarized as: keypair. Those keys will be our ephemeral keys. * Generate a new secret (DH) using the ephemeral private key and the public key that corresponds to the private key embedded in the HW. -* Derive the new keys from the secret using HKDF. We are not using a `salt` - and using an `info` of `MCUBoot_ECIES_v1`, generating 48 bytes of key material. +* Derive the new keys from the secret using HKDF (built on HMAC-SHA256). We + are not using a `salt` and using an `info` of `MCUBoot_ECIES_v1`, generating + 48 bytes of key material. * A new random encryption key is generated (for AES). This is the AES key used to encrypt the images. * The key is encrypted with AES-128-CTR or AES-256-CTR and a `nonce` of 0 using the first 16 bytes of key material generated previously by the HKDF. -* The encrypted key now goes through a HMAC using the remaining 32 +* The encrypted key now goes through a HMAC-SHA256 using the remaining 32 bytes of key material from the HKDF. -There are different TLVs for ECIES-P256, ECIES-X25519 with SHA256 HKDF/HMAC -and ECIES-X25519 with SHA512 HKDF/HMAC. The final TLV is built from the 65 bytes for ECIES-P256 or 32 bytes for ECIES-X25519, which correspond to the ephemeral public key, followed by the -MAC tag and the 16 or 32 bytes of the encrypted key, resulting in final TLV -length: - * ECIES-P256 has TLV length 113 to 129 bytes, depending on AES key length. - * ECIES-X25519 on SHA256 TLV length is 80 or 96 bytes, depending on AES key - length. - * ECIES-X25519 on SHA512 TLV length is 112 or 128, depending on AES key - length. +32 bytes of MAC tag and the 16 or 32 bytes of the encrypted key, resulting in +a TLV of 113 or 129 bytes for ECIES-P256 and 80 or 96 bytes for ECIES-X25519. The implemenation of ECIES-P256 is named ENC_EC256 in the source code and artifacts while ECIES-X25519 is named ENC_X25519. -Note that MCUboot is built to support only one ECIES and HMAC SHA at once, -and truncated HMAC is not supported at this time - ## [Upgrade process](#upgrade-process) When starting a new upgrade process, `MCUboot` checks that the image in the From ffc5bb702dc25d62cb3b7b434ed9c5f9f654f48f Mon Sep 17 00:00:00 2001 From: Jukka Rissanen Date: Tue, 23 Sep 2025 13:04:30 +0300 Subject: [PATCH 274/420] Revert "[nrf fromtree] bootutil: Small cleanup in image.h" This reverts commit 0529cbe7a955f006b5f5f2b7e22788cdde541483. Signed-off-by: Jukka Rissanen --- boot/bootutil/include/bootutil/image.h | 105 +++++++++++++------------ 1 file changed, 53 insertions(+), 52 deletions(-) diff --git a/boot/bootutil/include/bootutil/image.h b/boot/bootutil/include/bootutil/image.h index f49eab347..15de3e01a 100644 --- a/boot/bootutil/include/bootutil/image.h +++ b/boot/bootutil/include/bootutil/image.h @@ -46,6 +46,8 @@ extern "C" { #define STRUCT_PACKED struct __attribute__((__packed__)) #endif +struct flash_area; + #define IMAGE_MAGIC 0x96f3b83d #define IMAGE_MAGIC_V1 0x96f3b83c #define IMAGE_MAGIC_NONE 0xffffffff @@ -96,50 +98,50 @@ extern "C" { * 1st on identifies the public key which should be used to verify it. * 2nd one is the actual signature. */ -#define IMAGE_TLV_KEYHASH 0x01 /* hash of the public key */ -#define IMAGE_TLV_PUBKEY 0x02 /* public key */ -#define IMAGE_TLV_SHA256 0x10 /* SHA256 of image hdr and body */ -#define IMAGE_TLV_SHA384 0x11 /* SHA384 of image hdr and body */ -#define IMAGE_TLV_SHA512 0x12 /* SHA512 of image hdr and body */ -#define IMAGE_TLV_RSA2048_PSS 0x20 /* RSA2048 of hash output */ -#define IMAGE_TLV_ECDSA224 0x21 /* ECDSA of hash output - Not supported anymore */ -#define IMAGE_TLV_ECDSA_SIG 0x22 /* ECDSA of hash output */ -#define IMAGE_TLV_RSA3072_PSS 0x23 /* RSA3072 of hash output */ -#define IMAGE_TLV_ED25519 0x24 /* ed25519 of hash output */ -#define IMAGE_TLV_SIG_PURE 0x25 /* Indicator that attached signature has been prepared - * over image rather than its digest. - */ -#define IMAGE_TLV_ENC_RSA2048 0x30 /* Key encrypted with RSA-OAEP-2048 */ -#define IMAGE_TLV_ENC_KW 0x31 /* Key encrypted with AES-KW 128 or 256*/ -#define IMAGE_TLV_ENC_EC256 0x32 /* Key encrypted with ECIES-EC256 */ -#define IMAGE_TLV_ENC_X25519 0x33 /* Key encrypted with ECIES-X25519 */ -#define IMAGE_TLV_DEPENDENCY 0x40 /* Image depends on other image */ -#define IMAGE_TLV_SEC_CNT 0x50 /* security counter */ -#define IMAGE_TLV_BOOT_RECORD 0x60 /* measured boot record */ +#define IMAGE_TLV_KEYHASH 0x01 /* hash of the public key */ +#define IMAGE_TLV_PUBKEY 0x02 /* public key */ +#define IMAGE_TLV_SHA256 0x10 /* SHA256 of image hdr and body */ +#define IMAGE_TLV_SHA384 0x11 /* SHA384 of image hdr and body */ +#define IMAGE_TLV_SHA512 0x12 /* SHA512 of image hdr and body */ +#define IMAGE_TLV_RSA2048_PSS 0x20 /* RSA2048 of hash output */ +#define IMAGE_TLV_ECDSA224 0x21 /* ECDSA of hash output - Not supported anymore */ +#define IMAGE_TLV_ECDSA_SIG 0x22 /* ECDSA of hash output */ +#define IMAGE_TLV_RSA3072_PSS 0x23 /* RSA3072 of hash output */ +#define IMAGE_TLV_ED25519 0x24 /* ed25519 of hash output */ +#define IMAGE_TLV_SIG_PURE 0x25 /* Indicator that attached signature has been prepared + * over image rather than its digest. + */ +#define IMAGE_TLV_ENC_RSA2048 0x30 /* Key encrypted with RSA-OAEP-2048 */ +#define IMAGE_TLV_ENC_KW 0x31 /* Key encrypted with AES-KW 128 or 256*/ +#define IMAGE_TLV_ENC_EC256 0x32 /* Key encrypted with ECIES-EC256 */ +#define IMAGE_TLV_ENC_X25519 0x33 /* Key encrypted with ECIES-X25519 */ +#define IMAGE_TLV_DEPENDENCY 0x40 /* Image depends on other image */ +#define IMAGE_TLV_SEC_CNT 0x50 /* security counter */ +#define IMAGE_TLV_BOOT_RECORD 0x60 /* measured boot record */ /* The following flags relate to compressed images and are for the decompressed image data */ -#define IMAGE_TLV_DECOMP_SIZE 0x70 /* Decompressed image size excluding header/TLVs */ -#define IMAGE_TLV_DECOMP_SHA 0x71 /* - * Decompressed image shaX hash, this field must match - * the format and size of the raw slot (compressed) - * shaX hash - */ -#define IMAGE_TLV_DECOMP_SIGNATURE 0x72 /* - * Decompressed image signature, this field must match - * 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 - * range. Examples: - * 0x00a0 - 0x00ff - * 0x01a0 - 0x01ff - * 0x02a0 - 0x02ff - * ... - * 0xffa0 - 0xfffe - */ -#define IMAGE_TLV_ANY 0xffff /* Used to iterate over all TLV */ +#define IMAGE_TLV_DECOMP_SIZE 0x70 /* Decompressed image size excluding header/TLVs */ +#define IMAGE_TLV_DECOMP_SHA 0x71 /* + * Decompressed image shaX hash, this field must match + * the format and size of the raw slot (compressed) + * shaX hash + */ +#define IMAGE_TLV_DECOMP_SIGNATURE 0x72 /* + * Decompressed image signature, this field must match + * 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 + * range. Examples: + * 0x00a0 - 0x00ff + * 0x01a0 - 0x01ff + * 0x02a0 - 0x02ff + * ... + * 0xffa0 - 0xfffe + */ +#define IMAGE_TLV_ANY 0xffff /* Used to iterate over all TLV */ STRUCT_PACKED image_version { uint8_t iv_major; @@ -162,10 +164,10 @@ struct image_dependency { STRUCT_PACKED image_header { uint32_t ih_magic; uint32_t ih_load_addr; - uint16_t ih_hdr_size; /* Size of image header (bytes). */ - uint16_t ih_protect_tlv_size; /* Size of protected TLV area (bytes). */ - uint32_t ih_img_size; /* Does not include header. */ - uint32_t ih_flags; /* IMAGE_F_[...]. */ + uint16_t ih_hdr_size; /* Size of image header (bytes). */ + uint16_t ih_protect_tlv_size; /* Size of protected TLV area (bytes). */ + uint32_t ih_img_size; /* Does not include header. */ + uint32_t ih_flags; /* IMAGE_F_[...]. */ struct image_version ih_ver; uint32_t _pad1; }; @@ -173,13 +175,13 @@ STRUCT_PACKED image_header { /** Image TLV header. All fields in little endian. */ STRUCT_PACKED image_tlv_info { uint16_t it_magic; - uint16_t it_tlv_tot; /* size of TLV area (including tlv_info header) */ + uint16_t it_tlv_tot; /* size of TLV area (including tlv_info header) */ }; /** Image trailer TLV format. All fields in little endian. */ STRUCT_PACKED image_tlv { - uint16_t it_type; /* IMAGE_TLV_[...]. */ - uint16_t it_len; /* Data length (not including TLV header). */ + uint16_t it_type; /* IMAGE_TLV_[...]. */ + uint16_t it_len; /* Data length (not including TLV header). */ }; #define ENCRYPTIONFLAGS (IMAGE_F_ENCRYPTED_AES128 | IMAGE_F_ENCRYPTED_AES256) @@ -197,9 +199,8 @@ STRUCT_PACKED image_tlv { _Static_assert(sizeof(struct image_header) == IMAGE_HEADER_SIZE, "struct image_header not required size"); +struct enc_key_data; struct boot_loader_state; -struct flash_area; - fih_ret bootutil_img_validate(struct boot_loader_state *state, struct image_header *hdr, const struct flash_area *fap, From 4334aa10efa6b5106f51c2b603c19140851dc645 Mon Sep 17 00:00:00 2001 From: Jukka Rissanen Date: Tue, 23 Sep 2025 13:04:30 +0300 Subject: [PATCH 275/420] Revert "[nrf fromtree] zephyr: Improve logging" This reverts commit eaa6a90bce63822bfb2e3691681e39abe739dcd8. Signed-off-by: Jukka Rissanen --- boot/zephyr/firmware_loader.c | 8 -------- boot/zephyr/main.c | 8 -------- boot/zephyr/single_loader.c | 6 ------ 3 files changed, 22 deletions(-) diff --git a/boot/zephyr/firmware_loader.c b/boot/zephyr/firmware_loader.c index 1df848634..d0f70af4a 100644 --- a/boot/zephyr/firmware_loader.c +++ b/boot/zephyr/firmware_loader.c @@ -40,8 +40,6 @@ boot_image_validate(const struct flash_area *fa_p, static uint8_t tmpbuf[BOOT_TMPBUF_SZ]; FIH_DECLARE(fih_rc, FIH_FAILURE); - BOOT_LOG_DBG("boot_image_validate: encrypted == %d", (int)IS_ENCRYPTED(hdr)); - /* NOTE: The first argument to boot_image_validate, for enc_state pointer, * is allowed to be NULL only because the single image loader compiles * with BOOT_IMAGE_NUMBER == 1, which excludes the code that uses @@ -73,8 +71,6 @@ boot_image_validate_once(const struct flash_area *fa_p, int rc; FIH_DECLARE(fih_rc, FIH_FAILURE); - BOOT_LOG_DBG("boot_image_validate_once: flash area %p", fap_p); - memset(&state, 0, sizeof(struct boot_swap_state)); rc = boot_read_swap_state(fa_p, &state); if (rc != 0) @@ -112,8 +108,6 @@ static fih_ret validate_image_slot(int slot, struct boot_rsp *rsp) int rc = -1; FIH_DECLARE(fih_rc, FIH_FAILURE); - BOOT_LOG_DBG("validate_image_slot: slot %d", slot); - rc = flash_area_open(slot, &_fa_p); assert(rc == 0); @@ -162,8 +156,6 @@ boot_go(struct boot_rsp *rsp) bool boot_firmware_loader = false; FIH_DECLARE(fih_rc, FIH_FAILURE); - BOOT_LOG_DBG("boot_go: firmware loader"); - #ifdef CONFIG_BOOT_FIRMWARE_LOADER_ENTRANCE_GPIO if (io_detect_pin() && !io_boot_skip_serial_recovery()) { diff --git a/boot/zephyr/main.c b/boot/zephyr/main.c index 2e57bd999..ddea864de 100644 --- a/boot/zephyr/main.c +++ b/boot/zephyr/main.c @@ -463,7 +463,6 @@ int main(void) mcuboot_status_change(MCUBOOT_STATUS_STARTUP); #ifdef CONFIG_BOOT_SERIAL_ENTRANCE_GPIO - BOOT_LOG_DBG("Checking GPIO for serial recovery"); if (io_detect_pin() && !io_boot_skip_serial_recovery()) { boot_serial_enter(); @@ -471,17 +470,13 @@ int main(void) #endif #ifdef CONFIG_BOOT_SERIAL_PIN_RESET - BOOT_LOG_DBG("Checking RESET pin for serial recovery"); if (io_detect_pin_reset()) { boot_serial_enter(); } #endif #if defined(CONFIG_BOOT_USB_DFU_GPIO) - BOOT_LOG_DBG("Checking GPIO for USB DFU request"); if (io_detect_pin()) { - BOOT_LOG_DBG("Entering USB DFU"); - usb_dfu_requested = true; #ifdef CONFIG_MCUBOOT_INDICATION_LED @@ -503,7 +498,6 @@ int main(void) BOOT_LOG_INF("Waiting for USB DFU"); #if defined(CONFIG_BOOT_USB_DFU_WAIT) - BOOT_LOG_DBG("Waiting for USB DFU for %dms", CONFIG_BOOT_USB_DFU_WAIT_DELAY_MS); mcuboot_status_change(MCUBOOT_STATUS_USB_DFU_WAITING); wait_for_usb_dfu(K_MSEC(CONFIG_BOOT_USB_DFU_WAIT_DELAY_MS)); BOOT_LOG_INF("USB DFU wait time elapsed"); @@ -535,14 +529,12 @@ int main(void) if (FIH_EQ(fih_rc, FIH_BOOT_HOOK_REGULAR)) { FIH_CALL(boot_go, fih_rc, &rsp); } - BOOT_LOG_DBG("Left boot_go with success == %d", FIH_EQ(fih_rc, FIH_SUCCESS) ? 1 : 0); #ifdef CONFIG_BOOT_SERIAL_BOOT_MODE if (io_detect_boot_mode()) { /* Boot mode to stay in bootloader, clear status and enter serial * recovery mode */ - BOOT_LOG_DBG("Staying in serial recovery"); boot_serial_enter(); } #endif diff --git a/boot/zephyr/single_loader.c b/boot/zephyr/single_loader.c index 31c4a8bf7..28e9cdf15 100644 --- a/boot/zephyr/single_loader.c +++ b/boot/zephyr/single_loader.c @@ -44,8 +44,6 @@ boot_image_validate(const struct flash_area *fa_p, static uint8_t tmpbuf[BOOT_TMPBUF_SZ]; FIH_DECLARE(fih_rc, FIH_FAILURE); - BOOT_LOG_DBG("boot_image_validate: encrypted == %d", (int)IS_ENCRYPTED(hdr)); - /* NOTE: The first argument to boot_image_validate, for enc_state pointer, * is allowed to be NULL only because the single image loader compiles * with BOOT_IMAGE_NUMBER == 1, which excludes the code that uses @@ -77,8 +75,6 @@ boot_image_validate_once(const struct flash_area *fa_p, int rc; FIH_DECLARE(fih_rc, FIH_FAILURE); - BOOT_LOG_DBG("boot_image_validate_once: flash area %p", fap_p); - memset(&state, 0, sizeof(struct boot_swap_state)); rc = boot_read_swap_state(fa_p, &state); if (rc != 0) @@ -116,8 +112,6 @@ boot_go(struct boot_rsp *rsp) int rc = -1; FIH_DECLARE(fih_rc, FIH_FAILURE); - BOOT_LOG_DBG("boot_go: Single loader"); - rc = flash_area_open(FLASH_AREA_IMAGE_PRIMARY(0), &_fa_p); assert(rc == 0); From 9bd2f192c0a89a31785bca98e43046f0fa33a804 Mon Sep 17 00:00:00 2001 From: Jukka Rissanen Date: Tue, 23 Sep 2025 13:04:30 +0300 Subject: [PATCH 276/420] Revert "[nrf fromtree] bootutil: Improve logging coverage" This reverts commit b7f129b42e6ee98b18c1fbe2ac0ea59109663e57. Signed-off-by: Jukka Rissanen --- boot/bootutil/src/bootutil_misc.c | 17 ---------------- boot/bootutil/src/bootutil_public.c | 22 ++++----------------- boot/bootutil/src/ed25519_psa.c | 2 -- boot/bootutil/src/encrypted.c | 8 -------- boot/bootutil/src/encrypted_psa.c | 4 +--- boot/bootutil/src/image_ecdsa.c | 7 ------- boot/bootutil/src/image_ed25519.c | 17 +--------------- boot/bootutil/src/image_rsa.c | 5 ----- boot/bootutil/src/image_validate.c | 23 +--------------------- boot/bootutil/src/loader.c | 30 ----------------------------- boot/bootutil/src/swap_misc.c | 2 +- boot/bootutil/src/tlv.c | 14 -------------- 12 files changed, 8 insertions(+), 143 deletions(-) diff --git a/boot/bootutil/src/bootutil_misc.c b/boot/bootutil/src/bootutil_misc.c index 56e791043..0091165d5 100644 --- a/boot/bootutil/src/bootutil_misc.c +++ b/boot/bootutil/src/bootutil_misc.c @@ -155,9 +155,6 @@ int boot_trailer_scramble_offset(const struct flash_area *fa, size_t alignment, { int ret = 0; - BOOT_LOG_DBG("boot_trailer_scramble_offset: flash_area %p, alignment %u", - fa, (unsigned int)alignment); - /* Not allowed to enforce alignment smaller than device allows */ if (alignment < flash_area_align(fa)) { alignment = flash_area_align(fa); @@ -179,9 +176,6 @@ int boot_trailer_scramble_offset(const struct flash_area *fa, size_t alignment, *off = flash_area_get_size(fa) - ALIGN_DOWN(boot_trailer_sz(alignment), alignment); } - BOOT_LOG_DBG("boot_trailer_scramble_offset: final alignment %u, offset %u", - (unsigned int)alignment, (unsigned int)*off); - return ret; } @@ -193,8 +187,6 @@ int boot_header_scramble_off_sz(const struct flash_area *fa, int slot, size_t *o size_t loff = 0; struct flash_sector sector; - BOOT_LOG_DBG("boot_header_scramble_off_sz: slot %d", slot); - (void)slot; #if defined(MCUBOOT_SWAP_USING_OFFSET) /* In case of swap offset, header of secondary slot image is positioned @@ -223,8 +215,6 @@ int boot_header_scramble_off_sz(const struct flash_area *fa, int slot, size_t *o } *off = loff; - BOOT_LOG_DBG("boot_header_scramble_off_sz: size %u", (unsigned int)*size); - return ret; } @@ -611,9 +601,6 @@ boot_erase_region(const struct flash_area *fa, uint32_t off, uint32_t size, bool { int rc = 0; - BOOT_LOG_DBG("boot_erase_region: flash_area %p, offset %d, size %d, backwards == %d", - fa, off, size, (int)backwards); - if (off >= flash_area_get_size(fa) || (flash_area_get_size(fa) - off) < size) { rc = -1; goto end; @@ -621,8 +608,6 @@ boot_erase_region(const struct flash_area *fa, uint32_t off, uint32_t size, bool uint32_t end_offset = 0; struct flash_sector sector; - BOOT_LOG_DBG("boot_erase_region: device with erase"); - if (backwards) { /* Get the lowest page offset first */ rc = flash_area_get_sector(fa, off, §or); @@ -696,8 +681,6 @@ boot_erase_region(const struct flash_area *fa, uint32_t off, uint32_t size, bool off += 1; } } - } else { - BOOT_LOG_DBG("boot_erase_region: device without erase"); } end: diff --git a/boot/bootutil/src/bootutil_public.c b/boot/bootutil/src/bootutil_public.c index 8860fca41..102118864 100644 --- a/boot/bootutil/src/bootutil_public.c +++ b/boot/bootutil/src/bootutil_public.c @@ -324,7 +324,7 @@ boot_write_magic(const struct flash_area *fap) memset(&magic[0], erased_val, sizeof(magic)); memcpy(&magic[BOOT_MAGIC_ALIGN_SIZE - BOOT_MAGIC_SZ], BOOT_IMG_MAGIC, BOOT_MAGIC_SZ); - BOOT_LOG_DBG("boot_write_magic: fa_id=%d off=0x%lx (0x%lx)", + BOOT_LOG_DBG("writing magic; fa_id=%d off=0x%lx (0x%lx)", flash_area_get_id(fap), (unsigned long)off, (unsigned long)(flash_area_get_off(fap) + off)); rc = flash_area_write(fap, pad_off, &magic[0], BOOT_MAGIC_ALIGN_SIZE); @@ -350,14 +350,9 @@ boot_write_trailer(const struct flash_area *fap, uint32_t off, uint32_t align; int rc; - BOOT_LOG_DBG("boot_write_trailer: for %p at %d, size = %d", - fap, off, inlen); - align = flash_area_align(fap); align = ALIGN_UP(inlen, align); if (align > BOOT_MAX_ALIGN) { - /* This should never happen */ - assert(0); return -1; } erased_val = flash_area_erased_val(fap); @@ -601,9 +596,6 @@ boot_set_next(const struct flash_area *fa, bool active, bool confirm) struct boot_swap_state slot_state; int rc; - BOOT_LOG_DBG("boot_set_next: fa %p active == %d, confirm == %d", - fa, (int)active, (int)confirm); - if (active) { /* The only way to set active slot for next boot is to confirm it, * as DirectXIP will conclude that, since slot has not been confirmed @@ -614,7 +606,6 @@ boot_set_next(const struct flash_area *fa, bool active, bool confirm) rc = boot_read_swap_state(fa, &slot_state); if (rc != 0) { - BOOT_LOG_DBG("boot_set_next: error %d reading state", rc); return rc; } @@ -742,8 +733,6 @@ boot_set_confirmed_multi(int image_index) rc = flash_area_open(FLASH_AREA_IMAGE_PRIMARY(image_index), &fap); if (rc != 0) { - BOOT_LOG_DBG("boot_set_confirmed_multi: error %d opening image %d", - rc, image_index); return BOOT_EFLASH; } @@ -771,14 +760,13 @@ int boot_image_load_header(const struct flash_area *fa_p, struct image_header *hdr) { - uint32_t size = 0; + uint32_t size; int rc = flash_area_read(fa_p, 0, hdr, sizeof *hdr); - BOOT_LOG_DBG("boot_image_load_header: from %p, result %d", fa_p, rc); - if (rc != 0) { + rc = BOOT_EFLASH; BOOT_LOG_ERR("Failed reading image header"); - return BOOT_EFLASH; + return BOOT_EFLASH; } if (hdr->ih_magic != IMAGE_MAGIC) { @@ -795,8 +783,6 @@ boot_image_load_header(const struct flash_area *fa_p, if (!boot_u32_safe_add(&size, hdr->ih_img_size, hdr->ih_hdr_size) || size >= flash_area_get_size(fa_p)) { - BOOT_LOG_ERR("Image size bigger than designated area: %lu > %lu", - (unsigned long)size, (unsigned long)flash_area_get_size(fa_p)); return BOOT_EBADIMAGE; } diff --git a/boot/bootutil/src/ed25519_psa.c b/boot/bootutil/src/ed25519_psa.c index 5b8a4ed7c..12ba20ac1 100644 --- a/boot/bootutil/src/ed25519_psa.c +++ b/boot/bootutil/src/ed25519_psa.c @@ -29,8 +29,6 @@ int ED25519_verify(const uint8_t *message, size_t message_len, psa_key_id_t kid; int ret = 0; /* Fail by default */ - BOOT_LOG_DBG("ED25519_verify: PSA implementation"); - /* Initialize PSA Crypto */ status = psa_crypto_init(); if (status != PSA_SUCCESS) { diff --git a/boot/bootutil/src/encrypted.c b/boot/bootutil/src/encrypted.c index cf6f380e2..e0078a7be 100644 --- a/boot/bootutil/src/encrypted.c +++ b/boot/bootutil/src/encrypted.c @@ -43,9 +43,6 @@ #include "bootutil/enc_key.h" #include "bootutil/sign_key.h" #include "bootutil/crypto/common.h" -#include "bootutil/bootutil_log.h" - -BOOT_LOG_MODULE_DECLARE(mcuboot); #include "bootutil_priv.h" @@ -386,8 +383,6 @@ boot_decrypt_key(const uint8_t *buf, uint8_t *enckey) uint8_t *cpend; size_t olen; #endif - - BOOT_LOG_DBG("boot_decrypt_key"); #if defined(MCUBOOT_ENCRYPT_EC256) bootutil_ecdh_p256_context ecdh_p256; #endif @@ -605,11 +600,8 @@ boot_enc_load(struct boot_loader_state *state, int slot, #endif int rc; - BOOT_LOG_DBG("boot_enc_load: slot %d", slot); - /* Already loaded... */ if (enc_state[slot].valid) { - BOOT_LOG_DBG("boot_enc_load: already loaded"); return 1; } diff --git a/boot/bootutil/src/encrypted_psa.c b/boot/bootutil/src/encrypted_psa.c index 6f60a1955..04b5fbee4 100644 --- a/boot/bootutil/src/encrypted_psa.c +++ b/boot/bootutil/src/encrypted_psa.c @@ -134,11 +134,9 @@ boot_decrypt_key(const uint8_t *buf, uint8_t *enckey) uint8_t iv_and_key[PSA_CIPHER_IV_LENGTH(PSA_KEY_TYPE_AES, PSA_ALG_CTR) + BOOT_ENC_KEY_SIZE]; - BOOT_LOG_DBG("boot_decrypt_key: PSA ED25519"); - psa_ret = psa_crypto_init(); if (psa_ret != PSA_SUCCESS) { - BOOT_LOG_ERR("PSA crypto init failed %d", psa_ret); + BOOT_LOG_ERR("AES crypto init failed %d", psa_ret); return -1; } diff --git a/boot/bootutil/src/image_ecdsa.c b/boot/bootutil/src/image_ecdsa.c index 30c7d0d0f..4604913b4 100644 --- a/boot/bootutil/src/image_ecdsa.c +++ b/boot/bootutil/src/image_ecdsa.c @@ -28,9 +28,6 @@ #include #include "mcuboot_config/mcuboot_config.h" -#include "bootutil/bootutil_log.h" - -BOOT_LOG_MODULE_DECLARE(mcuboot); #if defined(MCUBOOT_SIGN_EC256) || defined(MCUBOOT_SIGN_EC384) @@ -49,8 +46,6 @@ bootutil_verify_sig(uint8_t *hash, uint32_t hlen, uint8_t *sig, size_t slen, uint8_t *pubkey; uint8_t *end; - BOOT_LOG_DBG("bootutil_verify_sig: ECDSA builtin key %d", key_id); - pubkey = (uint8_t *)bootutil_keys[key_id].key; end = pubkey + *bootutil_keys[key_id].len; bootutil_ecdsa_init(&ctx); @@ -80,8 +75,6 @@ bootutil_verify_sig(uint8_t *hash, uint32_t hlen, uint8_t *sig, size_t slen, bootutil_ecdsa_context ctx; FIH_DECLARE(fih_rc, FIH_FAILURE); - BOOT_LOG_DBG("bootutil_verify_sig: ECDSA embedded key %hhd", key_id); - /* Use builtin key for image verification, no key parsing is required. */ ctx.key_id = key_id; bootutil_ecdsa_init(&ctx); diff --git a/boot/bootutil/src/image_ed25519.c b/boot/bootutil/src/image_ed25519.c index 4d83bb3d7..ffb8cec3b 100644 --- a/boot/bootutil/src/image_ed25519.c +++ b/boot/bootutil/src/image_ed25519.c @@ -21,11 +21,8 @@ #include "bootutil/crypto/common.h" #endif -#include "bootutil/bootutil_log.h" -#include "bootutil/crypto/sha.h" #include "bootutil_priv.h" - -BOOT_LOG_MODULE_DECLARE(mcuboot); +#include "bootutil/crypto/sha.h" #define EDDSA_SIGNATURE_LENGTH 64 #define NUM_ED25519_BYTES 32 @@ -93,11 +90,7 @@ bootutil_verify(uint8_t *buf, uint32_t blen, uint8_t *pubkey; uint8_t *end; - BOOT_LOG_DBG("bootutil_verify: ED25519 key_id %d", (int)key_id); - if (slen != EDDSA_SIGNATURE_LENGTH) { - BOOT_LOG_DBG("bootutil_verify: expected slen %d, got %u", - EDDSA_SIGNATURE_LENGTH, (unsigned int)slen); FIH_SET(fih_rc, FIH_FAILURE); goto out; } @@ -108,7 +101,6 @@ bootutil_verify(uint8_t *buf, uint32_t blen, #if !defined(MCUBOOT_KEY_IMPORT_BYPASS_ASN) rc = bootutil_import_key(&pubkey, end); if (rc) { - BOOT_LOG_DBG("bootutil_verify: import key failed %d", rc); FIH_SET(fih_rc, FIH_FAILURE); goto out; } @@ -118,7 +110,6 @@ bootutil_verify(uint8_t *buf, uint32_t blen, * There is no check whether this is the correct key, * here, by the algorithm selected. */ - BOOT_LOG_DBG("bootutil_verify: bypass ASN1"); if (*bootutil_keys[key_id].len < NUM_ED25519_BYTES) { FIH_SET(fih_rc, FIH_FAILURE); goto out; @@ -153,11 +144,7 @@ bootutil_verify_sig(uint8_t *hash, uint32_t hlen, { FIH_DECLARE(fih_rc, FIH_FAILURE); - BOOT_LOG_DBG("bootutil_verify_sig: ED25519 key_id %d", (int)key_id); - if (hlen != IMAGE_HASH_SIZE) { - BOOT_LOG_DBG("bootutil_verify_sig: expected hlen %d, got %d", - IMAGE_HASH_SIZE, hlen); FIH_SET(fih_rc, FIH_FAILURE); goto out; } @@ -180,8 +167,6 @@ bootutil_verify_img(uint8_t *img, uint32_t size, { FIH_DECLARE(fih_rc, FIH_FAILURE); - BOOT_LOG_DBG("bootutil_verify_img: ED25519 key_id %d", (int)key_id); - FIH_CALL(bootutil_verify, fih_rc, img, size, sig, slen, key_id); diff --git a/boot/bootutil/src/image_rsa.c b/boot/bootutil/src/image_rsa.c index 5479b75eb..778a92b46 100644 --- a/boot/bootutil/src/image_rsa.c +++ b/boot/bootutil/src/image_rsa.c @@ -28,9 +28,6 @@ #include #include "mcuboot_config/mcuboot_config.h" -#include "bootutil/bootutil_log.h" - -BOOT_LOG_MODULE_DECLARE(mcuboot); #ifdef MCUBOOT_SIGN_RSA #include "bootutil_priv.h" @@ -270,8 +267,6 @@ bootutil_verify_sig(uint8_t *hash, uint32_t hlen, uint8_t *sig, size_t slen, uint8_t *cp; uint8_t *end; - BOOT_LOG_DBG("bootutil_verify_sig: RSA key_id %d", key_id); - bootutil_rsa_init(&ctx); cp = (uint8_t *)bootutil_keys[key_id].key; diff --git a/boot/bootutil/src/image_validate.c b/boot/bootutil/src/image_validate.c index eec678724..521251a40 100644 --- a/boot/bootutil/src/image_validate.c +++ b/boot/bootutil/src/image_validate.c @@ -41,9 +41,6 @@ #include "bootutil/fault_injection_hardening.h" #include "mcuboot_config/mcuboot_config.h" -#include "bootutil/bootutil_log.h" - -BOOT_LOG_MODULE_DECLARE(mcuboot); #ifdef MCUBOOT_ENC_IMAGES #include "bootutil/enc_key.h" @@ -110,7 +107,6 @@ bootutil_img_hash(struct boot_loader_state *state, (void)tmp_buf_sz; #endif #endif - BOOT_LOG_DBG("bootutil_img_hash"); #ifdef MCUBOOT_ENC_IMAGES if (state == NULL) { @@ -124,7 +120,6 @@ bootutil_img_hash(struct boot_loader_state *state, /* Encrypted images only exist in the secondary slot */ if (MUST_DECRYPT(fap, image_index, hdr) && !boot_enc_valid(enc_state, 1)) { - BOOT_LOG_DBG("bootutil_img_hash: error encrypted image found in primary slot"); return -1; } #endif @@ -192,8 +187,6 @@ bootutil_img_hash(struct boot_loader_state *state, #endif if (rc) { bootutil_sha_drop(&sha_ctx); - BOOT_LOG_DBG("bootutil_img_validate Error %d reading data chunk %p %u %u", - rc, fap, off, blk_sz); return rc; } #ifdef MCUBOOT_ENC_IMAGES @@ -287,8 +280,6 @@ bootutil_find_key(uint8_t *keyhash, uint8_t keyhash_len) const struct bootutil_key *key; uint8_t hash[IMAGE_HASH_SIZE]; - BOOT_LOG_DBG("bootutil_find_key"); - if (keyhash_len > IMAGE_HASH_SIZE) { return -1; } @@ -317,8 +308,6 @@ bootutil_find_key(uint8_t image_index, uint8_t *key, uint16_t key_len) int rc; FIH_DECLARE(fih_rc, FIH_FAILURE); - BOOT_LOG_DBG("bootutil_find_key: image_index %d", image_index); - bootutil_sha_init(&sha_ctx); bootutil_sha_update(&sha_ctx, key, key_len); bootutil_sha_finish(&sha_ctx, hash); @@ -529,8 +518,6 @@ bootutil_img_validate(struct boot_loader_state *state, FIH_DECLARE(security_counter_valid, FIH_FAILURE); #endif - BOOT_LOG_DBG("bootutil_img_validate: flash area %p", fap); - #if defined(EXPECTED_HASH_TLV) && !defined(MCUBOOT_SIGN_PURE) #if defined(MCUBOOT_SWAP_USING_OFFSET) && defined(MCUBOOT_SERIAL_RECOVERY) rc = bootutil_img_hash(state, hdr, fap, tmp_buf, tmp_buf_sz, hash, seed, seed_len, @@ -551,8 +538,7 @@ bootutil_img_validate(struct boot_loader_state *state, /* If Pure type signature is expected then it has to be there */ rc = bootutil_check_for_pure(hdr, fap); if (rc != 0) { - BOOT_LOG_DBG("bootutil_img_validate: pure expected"); - goto out; + goto out; } #endif @@ -566,7 +552,6 @@ bootutil_img_validate(struct boot_loader_state *state, rc = bootutil_tlv_iter_begin(&it, hdr, fap, IMAGE_TLV_ANY, false); if (rc) { - BOOT_LOG_DBG("bootutil_img_validate: TLV iteration failed %d", rc); goto out; } @@ -575,11 +560,9 @@ bootutil_img_validate(struct boot_loader_state *state, #else img_sz = it.tlv_end; #endif - BOOT_LOG_DBG("bootutil_img_validate: TLV off %u, end %u", it.tlv_off, it.tlv_end); if (img_sz > bootutil_max_image_size(state, fap)) { rc = -1; - BOOT_LOG_DBG("bootutil_img_validate: TLV beyond image size"); goto out; } @@ -610,7 +593,6 @@ bootutil_img_validate(struct boot_loader_state *state, } } if (!found) { - BOOT_LOG_DBG("bootutil_img_validate: TLV %d not permitted", type); FIH_SET(fih_rc, FIH_FAILURE); goto out; } @@ -620,7 +602,6 @@ bootutil_img_validate(struct boot_loader_state *state, #if defined(EXPECTED_HASH_TLV) && !defined(MCUBOOT_SIGN_PURE) case EXPECTED_HASH_TLV: { - BOOT_LOG_DBG("bootutil_img_validate: EXPECTED_HASH_TLV == %d", EXPECTED_HASH_TLV); /* Verify the image hash. This must always be present. */ if (len != sizeof(hash)) { rc = -1; @@ -644,7 +625,6 @@ bootutil_img_validate(struct boot_loader_state *state, #ifdef EXPECTED_KEY_TLV case EXPECTED_KEY_TLV: { - BOOT_LOG_DBG("bootutil_img_validate: EXPECTED_KEY_TLV == %d", EXPECTED_KEY_TLV); /* * Determine which key we should be checking. */ @@ -675,7 +655,6 @@ bootutil_img_validate(struct boot_loader_state *state, #ifdef EXPECTED_SIG_TLV case EXPECTED_SIG_TLV: { - BOOT_LOG_DBG("bootutil_img_validate: EXPECTED_SIG_TLV == %d", EXPECTED_SIG_TLV); /* Ignore this signature if it is out of bounds. */ if (key_id < 0 || key_id >= bootutil_key_cnt) { key_id = -1; diff --git a/boot/bootutil/src/loader.c b/boot/bootutil/src/loader.c index 6654245ad..62f980b69 100644 --- a/boot/bootutil/src/loader.c +++ b/boot/bootutil/src/loader.c @@ -283,19 +283,6 @@ static int boot_version_cmp(const struct image_version *ver1, const struct image_version *ver2) { -#if !defined(MCUBOOT_VERSION_CMP_USE_BUILD_NUMBER) - BOOT_LOG_DBG("boot_version_cmp: ver1 %u.%u.%u vs ver2 %u.%u.%u", - (unsigned)ver1->iv_major, (unsigned)ver1->iv_minor, - (unsigned)ver1->iv_revision, (unsigned)ver2->iv_major, - (unsigned)ver2->iv_minor, (unsigned)ver2->iv_revision); -#else - BOOT_LOG_DBG("boot_version_cmp: ver1 %u.%u.%u.%u vs ver2 %u.%u.%u.%u", - (unsigned)ver1->iv_major, (unsigned)ver1->iv_minor, - (unsigned)ver1->iv_revision, (unsigned)ver1->iv_build_num, - (unsigned)ver2->iv_major, (unsigned)ver2->iv_minor, - (unsigned)ver2->iv_revision, (unsigned)ver2->iv_build_num); -#endif - if (ver1->iv_major > ver2->iv_major) { return 1; } @@ -567,7 +554,6 @@ boot_verify_slot_dependencies(struct boot_loader_state *state, uint32_t slot) fap = BOOT_IMG_AREA(state, slot); assert(fap != NULL); - BOOT_LOG_DBG("boot_verify_slot_dependencies"); #if defined(MCUBOOT_SWAP_USING_OFFSET) it.start_off = boot_get_state_secondary_offset(state, fap); #endif @@ -595,8 +581,6 @@ boot_verify_slot_dependencies(struct boot_loader_state *state, uint32_t slot) rc = LOAD_IMAGE_DATA(boot_img_hdr(state, slot), fap, off, &dep, len); if (rc != 0) { - BOOT_LOG_DBG("boot_verify_slot_dependencies: error %d reading dependency %p %d %d", - rc, fap, off, len); rc = BOOT_EFLASH; goto done; } @@ -609,7 +593,6 @@ boot_verify_slot_dependencies(struct boot_loader_state *state, uint32_t slot) /* Verify dependency and modify the swap type if not satisfied. */ rc = boot_verify_slot_dependency(state, &dep); if (rc != 0) { - BOOT_LOG_DBG("boot_verify_slot_dependencies: not satisfied"); /* Dependency not satisfied */ goto done; } @@ -1022,9 +1005,6 @@ boot_validate_slot(struct boot_loader_state *state, int slot, struct image_header *hdr; FIH_DECLARE(fih_rc, FIH_FAILURE); - BOOT_LOG_DBG("boot_validate_slot: slot %d, expected_swap_type %d", - slot, expected_swap_type); - #if !defined(MCUBOOT_SWAP_USING_OFFSET) (void)expected_swap_type; #endif @@ -1270,8 +1250,6 @@ boot_scramble_region(const struct flash_area *fa, uint32_t off, uint32_t size, b { int rc = 0; - BOOT_LOG_DBG("boot_scramble_region: %p %d %d %d", fa, off, size, (int)backwards); - if (size == 0) { goto done; } @@ -1286,7 +1264,6 @@ boot_scramble_region(const struct flash_area *fa, uint32_t off, uint32_t size, b const size_t write_block = flash_area_align(fa); uint32_t end_offset; - BOOT_LOG_DBG("boot_scramble_region: device without erase, overwriting"); memset(buf, flash_area_erased_val(fa), sizeof(buf)); if (backwards) { @@ -1296,14 +1273,11 @@ boot_scramble_region(const struct flash_area *fa, uint32_t off, uint32_t size, b } else { end_offset = ALIGN_DOWN((off + size), write_block); } - BOOT_LOG_DBG("boot_scramble_region: start offset %u, end offset %u", off, end_offset); while (off != end_offset) { /* Write over the area to scramble data that is there */ rc = flash_area_write(fa, off, buf, write_block); if (rc != 0) { - BOOT_LOG_DBG("boot_scramble_region: error %d for %p %d %u", - rc, fa, off, (unsigned int)write_block); break; } @@ -2374,8 +2348,6 @@ context_boot_go(struct boot_loader_state *state, struct boot_rsp *rsp) bool has_upgrade; volatile int fih_cnt; - BOOT_LOG_DBG("context_boot_go"); - #if defined(__BOOTSIM__) /* The array of slot sectors are defined here (as opposed to file scope) so * that they don't get allocated for non-boot-loader apps. This is @@ -3244,8 +3216,6 @@ static void boot_fetch_slot_state_sizes(void) assert(rc == 0); if (rc != 0) { - BOOT_LOG_DBG("boot_fetch_slot_state_sizes: error %d for %d", - rc, fa_id); goto finish; } } diff --git a/boot/bootutil/src/swap_misc.c b/boot/bootutil/src/swap_misc.c index a4c39c20a..ac9412b0f 100644 --- a/boot/bootutil/src/swap_misc.c +++ b/boot/bootutil/src/swap_misc.c @@ -80,7 +80,7 @@ swap_scramble_trailer_sectors(const struct boot_loader_state *state, size_t off; int rc; - BOOT_LOG_DBG("swap_scramble_trailer_sectors: fa_id=%d", flash_area_get_id(fap)); + BOOT_LOG_DBG("Scrambling trailer; fa_id=%d", flash_area_get_id(fap)); /* Delete starting from last sector and moving to beginning */ rc = boot_trailer_scramble_offset(fap, BOOT_WRITE_SZ(state), &off); diff --git a/boot/bootutil/src/tlv.c b/boot/bootutil/src/tlv.c index a69b3d8bd..629bc235d 100644 --- a/boot/bootutil/src/tlv.c +++ b/boot/bootutil/src/tlv.c @@ -21,12 +21,9 @@ #include #include "bootutil/bootutil.h" -#include "bootutil/bootutil_log.h" #include "bootutil/image.h" #include "bootutil_priv.h" -BOOT_LOG_MODULE_DECLARE(mcuboot); - /* * Initialize a TLV iterator. * @@ -46,8 +43,6 @@ bootutil_tlv_iter_begin(struct image_tlv_iter *it, const struct image_header *hd uint32_t off_; struct image_tlv_info info; - BOOT_LOG_DBG("bootutil_tlv_iter_begin: type %d, prot == %d", type, (int)prot); - if (it == NULL || hdr == NULL || fap == NULL) { return -1; } @@ -113,9 +108,6 @@ bootutil_tlv_iter_next(struct image_tlv_iter *it, uint32_t *off, uint16_t *len, return -1; } - BOOT_LOG_DBG("bootutil_tlv_iter_next: searching for %d (%d is any) starting at %d ending at %d", - it->type, IMAGE_TLV_ANY, it->tlv_off, it->tlv_end); - while (it->tlv_off < it->tlv_end) { if (it->hdr->ih_protect_tlv_size > 0 && it->tlv_off == it->prot_end) { it->tlv_off += sizeof(struct image_tlv_info); @@ -123,14 +115,11 @@ bootutil_tlv_iter_next(struct image_tlv_iter *it, uint32_t *off, uint16_t *len, rc = LOAD_IMAGE_DATA(it->hdr, it->fap, it->tlv_off, &tlv, sizeof tlv); if (rc) { - BOOT_LOG_DBG("bootutil_tlv_iter_next: load failed with %d for %p %d", - rc, it->fap, it->tlv_off); return -1; } /* No more TLVs in the protected area */ if (it->prot && it->tlv_off >= it->prot_end) { - BOOT_LOG_DBG("bootutil_tlv_iter_next: protected TLV %d not found", it->type); return 1; } @@ -141,15 +130,12 @@ bootutil_tlv_iter_next(struct image_tlv_iter *it, uint32_t *off, uint16_t *len, *off = it->tlv_off + sizeof(tlv); *len = tlv.it_len; it->tlv_off += sizeof(tlv) + tlv.it_len; - BOOT_LOG_DBG("bootutil_tlv_iter_next: TLV %d found at %d (size %d)", - *type, *off, *len); return 0; } it->tlv_off += sizeof(tlv) + tlv.it_len; } - BOOT_LOG_DBG("bootutil_tlv_iter_next: TLV %d not found", it->type); return 1; } From 94578d59556c266f02007efd8553b0a25ac781f1 Mon Sep 17 00:00:00 2001 From: Jukka Rissanen Date: Tue, 23 Sep 2025 13:04:30 +0300 Subject: [PATCH 277/420] Revert "[nrf fromtree] boot: zephyr: Refactor DFU entry logic" This reverts commit 657e048b0f4b043893a48704bab23afe5f4b2221. Signed-off-by: Jukka Rissanen --- boot/zephyr/main.c | 38 ++++++++++++++++---------------------- 1 file changed, 16 insertions(+), 22 deletions(-) diff --git a/boot/zephyr/main.c b/boot/zephyr/main.c index ddea864de..4ecf191e7 100644 --- a/boot/zephyr/main.c +++ b/boot/zephyr/main.c @@ -2,7 +2,6 @@ * Copyright (c) 2012-2014 Wind River Systems, Inc. * Copyright (c) 2020 Arm Limited * Copyright (c) 2021-2023 Nordic Semiconductor ASA - * Copyright (c) 2025 Aerlync Labs Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -435,9 +434,6 @@ int main(void) { struct boot_rsp rsp; int rc; -#if defined(CONFIG_BOOT_USB_DFU_GPIO) || defined(CONFIG_BOOT_USB_DFU_WAIT) - bool usb_dfu_requested = false; -#endif FIH_DECLARE(fih_rc, FIH_FAILURE); MCUBOOT_WATCHDOG_SETUP(); @@ -477,37 +473,35 @@ int main(void) #if defined(CONFIG_BOOT_USB_DFU_GPIO) if (io_detect_pin()) { - usb_dfu_requested = true; - #ifdef CONFIG_MCUBOOT_INDICATION_LED io_led_set(1); #endif mcuboot_status_change(MCUBOOT_STATUS_USB_DFU_ENTERED); - } -#elif defined(CONFIG_BOOT_USB_DFU_WAIT) - usb_dfu_requested = true; -#endif -#if defined(CONFIG_BOOT_USB_DFU_GPIO) || defined(CONFIG_BOOT_USB_DFU_WAIT) - if (usb_dfu_requested) { rc = usb_enable(NULL); if (rc) { - BOOT_LOG_ERR("Cannot enable USB: %d", rc); + BOOT_LOG_ERR("Cannot enable USB"); } else { BOOT_LOG_INF("Waiting for USB DFU"); - -#if defined(CONFIG_BOOT_USB_DFU_WAIT) - mcuboot_status_change(MCUBOOT_STATUS_USB_DFU_WAITING); - wait_for_usb_dfu(K_MSEC(CONFIG_BOOT_USB_DFU_WAIT_DELAY_MS)); - BOOT_LOG_INF("USB DFU wait time elapsed"); - mcuboot_status_change(MCUBOOT_STATUS_USB_DFU_TIMED_OUT); -#else wait_for_usb_dfu(K_FOREVER); - BOOT_LOG_INF("USB DFU wait terminated"); -#endif + BOOT_LOG_INF("USB DFU wait time elapsed"); } } +#elif defined(CONFIG_BOOT_USB_DFU_WAIT) + rc = usb_enable(NULL); + if (rc) { + BOOT_LOG_ERR("Cannot enable USB"); + } else { + BOOT_LOG_INF("Waiting for USB DFU"); + + mcuboot_status_change(MCUBOOT_STATUS_USB_DFU_WAITING); + + wait_for_usb_dfu(K_MSEC(CONFIG_BOOT_USB_DFU_WAIT_DELAY_MS)); + BOOT_LOG_INF("USB DFU wait time elapsed"); + + mcuboot_status_change(MCUBOOT_STATUS_USB_DFU_TIMED_OUT); + } #endif #ifdef CONFIG_BOOT_SERIAL_WAIT_FOR_DFU From 9ed584065ae5c9c8400a2dbb8139ace786970217 Mon Sep 17 00:00:00 2001 From: Jukka Rissanen Date: Tue, 23 Sep 2025 13:04:30 +0300 Subject: [PATCH 278/420] Revert "[nrf fromtree] bootutil: loader: overwrite-only mode fix for trailer erase" This reverts commit 57ceb536003462cbed6dde26221667d64fbbbc0e. Signed-off-by: Jukka Rissanen --- boot/bootutil/src/loader.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/boot/bootutil/src/loader.c b/boot/bootutil/src/loader.c index 62f980b69..44275fcb9 100644 --- a/boot/bootutil/src/loader.c +++ b/boot/bootutil/src/loader.c @@ -1687,19 +1687,19 @@ boot_copy_image(struct boot_loader_state *state, struct boot_status *bs) * trailer that was left might trigger a new upgrade. */ BOOT_LOG_DBG("erasing secondary header"); - rc = boot_scramble_region(fap_secondary_slot, - boot_img_sector_off(state, BOOT_SECONDARY_SLOT, 0), - boot_img_sector_size(state, BOOT_SECONDARY_SLOT, 0), false); + rc = boot_erase_region(fap_secondary_slot, + boot_img_sector_off(state, BOOT_SECONDARY_SLOT, 0), + boot_img_sector_size(state, BOOT_SECONDARY_SLOT, 0), false); assert(rc == 0); #endif last_sector = boot_img_num_sectors(state, BOOT_SECONDARY_SLOT) - 1; BOOT_LOG_DBG("erasing secondary trailer"); - rc = boot_scramble_region(fap_secondary_slot, - boot_img_sector_off(state, BOOT_SECONDARY_SLOT, - last_sector), - boot_img_sector_size(state, BOOT_SECONDARY_SLOT, - last_sector), false); + rc = boot_erase_region(fap_secondary_slot, + boot_img_sector_off(state, BOOT_SECONDARY_SLOT, + last_sector), + boot_img_sector_size(state, BOOT_SECONDARY_SLOT, + last_sector), false); assert(rc == 0); /* TODO: Perhaps verify the primary slot's signature again? */ From 8a40a15f51c8ef41397cae62a4c88d9169b9e683 Mon Sep 17 00:00:00 2001 From: Jukka Rissanen Date: Tue, 23 Sep 2025 13:04:30 +0300 Subject: [PATCH 279/420] Revert "[nrf fromlist] zephyr: Fix pinreset trigger" This reverts commit 6a4025b10a7901c20d08814dd6ed228a0ee01a2f. Signed-off-by: Jukka Rissanen --- boot/zephyr/io.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/boot/zephyr/io.c b/boot/zephyr/io.c index f2342c1ad..309f1ab94 100644 --- a/boot/zephyr/io.c +++ b/boot/zephyr/io.c @@ -181,7 +181,7 @@ bool io_detect_pin_reset(void) rc = hwinfo_get_reset_cause(&reset_cause); - if (rc == 0 && (reset_cause & RESET_PIN)) { + if (rc == 0 && reset_cause == RESET_PIN) { (void)hwinfo_clear_reset_cause(); return true; } From f7d3a0c7e26fd2b8485236fd8d6cb13a4eb701d4 Mon Sep 17 00:00:00 2001 From: Jukka Rissanen Date: Tue, 23 Sep 2025 13:04:30 +0300 Subject: [PATCH 280/420] Revert "[nrf fromtree] scripts: imgtool: Compression of no header-padded images" This reverts commit 46980ce0bf11ad8966783c2bfe53a6223c332066. Signed-off-by: Jukka Rissanen --- scripts/imgtool/image.py | 24 +++++++++--------------- scripts/imgtool/main.py | 8 +++----- 2 files changed, 12 insertions(+), 20 deletions(-) diff --git a/scripts/imgtool/image.py b/scripts/imgtool/image.py index c7fb9e553..566a47e00 100644 --- a/scripts/imgtool/image.py +++ b/scripts/imgtool/image.py @@ -348,6 +348,7 @@ def load(self, path): self.payload = copy.copy(self.infile_data) except FileNotFoundError: raise click.UsageError("Input file not found") + self.image_size = len(self.payload) # Add the image header if needed. if self.pad_header and self.header_size > 0: @@ -357,8 +358,6 @@ def load(self, path): self.payload = bytes([self.erased_val] * self.header_size) + \ self.payload - self.image_size = len(self.payload) - self.header_size - self.check_header() def load_compressed(self, data, compression_header): @@ -367,19 +366,14 @@ def load_compressed(self, data, compression_header): self.image_size = len(self.payload) # Add the image header if needed. - if self.header_size > 0: - if self.pad_header: - if self.base_addr: - # Adjust base_addr for new header - self.base_addr -= self.header_size - self.payload = bytes([self.erased_val] * self.header_size) + \ - self.payload - else: - # Fill header padding with zeros to align with what is expected - # for uncompressed images when no pad_header is requested - # (see self.check_header()) - self.payload = bytes([0] * self.header_size) + \ - self.payload + if self.pad_header and self.header_size > 0: + if self.base_addr: + # Adjust base_addr for new header + self.base_addr -= self.header_size + self.payload = bytes([self.erased_val] * self.header_size) + \ + self.payload + + self.check_header() def save(self, path, hex_addr=None): """Save an image from a given file""" diff --git a/scripts/imgtool/main.py b/scripts/imgtool/main.py index 78f2e77ec..1cdb792a5 100755 --- a/scripts/imgtool/main.py +++ b/scripts/imgtool/main.py @@ -542,11 +542,9 @@ def sign(key, public_key_format, align, version, pad_sig, header_size, ] if compression == "lzma2armthumb": compression_filters.insert(0, {"id":lzma.FILTER_ARMTHUMB}) - - infile_offset = 0 if pad_header else header_size - compressed_data = lzma.compress(img.get_infile_data()[infile_offset:], - filters=compression_filters, format=lzma.FORMAT_RAW) - uncompressed_size = len(img.get_infile_data()[infile_offset:]) + compressed_data = lzma.compress(img.get_infile_data(),filters=compression_filters, + format=lzma.FORMAT_RAW) + uncompressed_size = len(img.get_infile_data()) compressed_size = len(compressed_data) print(f"compressed image size: {compressed_size} bytes") print(f"original image size: {uncompressed_size} bytes") From 19cf8caa48a646f420abff7ab0013316dd9c8537 Mon Sep 17 00:00:00 2001 From: Jukka Rissanen Date: Tue, 23 Sep 2025 13:04:30 +0300 Subject: [PATCH 281/420] Revert "[nrf fromlist] bootutil: Fix boot_scramble_region escaping flash area" This reverts commit 884efcadeffbf61483f9ee1c9171b0e1806ba704. Signed-off-by: Jukka Rissanen --- boot/bootutil/src/loader.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/boot/bootutil/src/loader.c b/boot/bootutil/src/loader.c index 44275fcb9..ffd2456a7 100644 --- a/boot/bootutil/src/loader.c +++ b/boot/bootutil/src/loader.c @@ -1274,7 +1274,7 @@ boot_scramble_region(const struct flash_area *fa, uint32_t off, uint32_t size, b end_offset = ALIGN_DOWN((off + size), write_block); } - while (off != end_offset) { + while (true) { /* Write over the area to scramble data that is there */ rc = flash_area_write(fa, off, buf, write_block); if (rc != 0) { @@ -1291,12 +1291,12 @@ boot_scramble_region(const struct flash_area *fa, uint32_t off, uint32_t size, b off -= write_block; } else { - off += write_block; - - if (end_offset <= off) { + if (end_offset < off) { /* Reached the end offset in range and already scrambled it */ break; } + + off += write_block; } } } From 0ef308d709d5110e2828cba6ddc22a256b165d45 Mon Sep 17 00:00:00 2001 From: Jukka Rissanen Date: Tue, 23 Sep 2025 13:04:30 +0300 Subject: [PATCH 282/420] Revert "[nrf fromlist] bootutil: Replace local identifiers with common definitions" This reverts commit 6e4285ae3e5c759082c8c7e0c067efb012a4b9bc. Signed-off-by: Jukka Rissanen --- boot/bootutil/src/encrypted.c | 21 ++++++++++++--------- boot/bootutil/src/encrypted_psa.c | 8 +++++--- 2 files changed, 17 insertions(+), 12 deletions(-) diff --git a/boot/bootutil/src/encrypted.c b/boot/bootutil/src/encrypted.c index e0078a7be..f64493656 100644 --- a/boot/bootutil/src/encrypted.c +++ b/boot/bootutil/src/encrypted.c @@ -97,6 +97,9 @@ key_unwrap(const uint8_t *wrapped, uint8_t *enckey, struct bootutil_key *bootuti static const uint8_t ec_pubkey_oid[] = MBEDTLS_OID_EC_ALG_UNRESTRICTED; static const uint8_t ec_secp256r1_oid[] = MBEDTLS_OID_EC_GRP_SECP256R1; +#define SHARED_KEY_LEN NUM_ECC_BYTES +#define PRIV_KEY_LEN NUM_ECC_BYTES + /* * Parses the output of `imgtool keygen`, which produces a PKCS#8 elliptic * curve keypair. See RFC5208 and RFC5915. @@ -176,6 +179,9 @@ parse_ec256_enckey(uint8_t **p, uint8_t *end, uint8_t *private_key) static const uint8_t ec_pubkey_oid[] = MBEDTLS_OID_ISO_IDENTIFIED_ORG \ MBEDTLS_OID_ORG_GOV X25519_OID; +#define SHARED_KEY_LEN 32 +#define PRIV_KEY_LEN 32 + static int parse_x25519_enckey(uint8_t **p, uint8_t *end, uint8_t *private_key) { @@ -215,11 +221,11 @@ parse_x25519_enckey(uint8_t **p, uint8_t *end, uint8_t *private_key) return -7; } - if (len != EC_PRIVK_LEN) { + if (len != PRIV_KEY_LEN) { return -8; } - memcpy(private_key, *p, EC_PRIVK_LEN); + memcpy(private_key, *p, PRIV_KEY_LEN); return 0; } #endif /* defined(MCUBOOT_ENCRYPT_X25519) */ @@ -393,11 +399,11 @@ boot_decrypt_key(const uint8_t *buf, uint8_t *enckey) bootutil_hmac_sha256_context hmac; bootutil_aes_ctr_context aes_ctr; uint8_t tag[BOOTUTIL_CRYPTO_SHA256_DIGEST_SIZE]; - uint8_t shared[EC_SHARED_LEN]; + uint8_t shared[SHARED_KEY_LEN]; uint8_t derived_key[BOOT_ENC_KEY_SIZE + BOOTUTIL_CRYPTO_SHA256_DIGEST_SIZE]; uint8_t *cp; uint8_t *cpend; - uint8_t private_key[EC_PRIVK_LEN]; + uint8_t private_key[PRIV_KEY_LEN]; uint8_t counter[BOOT_ENC_BLOCK_SIZE]; uint16_t len; #endif @@ -503,7 +509,7 @@ boot_decrypt_key(const uint8_t *buf, uint8_t *enckey) */ len = BOOT_ENC_KEY_SIZE + BOOTUTIL_CRYPTO_SHA256_DIGEST_SIZE; - rc = hkdf(shared, EC_SHARED_LEN, (uint8_t *)"MCUBoot_ECIES_v1", 16, + rc = hkdf(shared, SHARED_KEY_LEN, (uint8_t *)"MCUBoot_ECIES_v1", 16, derived_key, &len); if (rc != 0 || len != (BOOT_ENC_KEY_SIZE + BOOTUTIL_CRYPTO_SHA256_DIGEST_SIZE)) { return -1; @@ -515,9 +521,6 @@ boot_decrypt_key(const uint8_t *buf, uint8_t *enckey) bootutil_hmac_sha256_init(&hmac); - /* First BOOT_ENC_KEY_SIZE are used for decryption, remaining 32 bytes are used - * for MAC tag key - */ rc = bootutil_hmac_sha256_set_key(&hmac, &derived_key[BOOT_ENC_KEY_SIZE], 32); if (rc != 0) { (void)bootutil_hmac_sha256_drop(&hmac); @@ -537,7 +540,7 @@ boot_decrypt_key(const uint8_t *buf, uint8_t *enckey) return -1; } - if (bootutil_constant_time_compare(tag, &buf[EC_TAG_INDEX], EC_TAG_LEN) != 0) { + if (bootutil_constant_time_compare(tag, &buf[EC_TAG_INDEX], 32) != 0) { (void)bootutil_hmac_sha256_drop(&hmac); return -1; } diff --git a/boot/bootutil/src/encrypted_psa.c b/boot/bootutil/src/encrypted_psa.c index 04b5fbee4..d604df201 100644 --- a/boot/bootutil/src/encrypted_psa.c +++ b/boot/bootutil/src/encrypted_psa.c @@ -31,6 +31,8 @@ BOOT_LOG_MODULE_DECLARE(mcuboot_psa_enc); static const uint8_t ec_pubkey_oid[] = MBEDTLS_OID_ISO_IDENTIFIED_ORG \ MBEDTLS_OID_ORG_GOV X25519_OID; +#define PRIV_KEY_LEN 32 + /* Partitioning of HKDF derived material, from the exchange derived key */ /* AES key encryption key */ #define HKDF_AES_KEY_INDEX 0 @@ -81,11 +83,11 @@ parse_x25519_enckey(uint8_t **p, uint8_t *end, uint8_t *private_key) return -7; } - if (len != EC_PRIVK_LEN) { + if (len != PRIV_KEY_LEN) { return -8; } - memcpy(private_key, *p, EC_PRIVK_LEN); + memcpy(private_key, *p, PRIV_KEY_LEN); return 0; } @@ -115,7 +117,7 @@ boot_decrypt_key(const uint8_t *buf, uint8_t *enckey) uint8_t derived_key[HKDF_SIZE]; uint8_t *cp; uint8_t *cpend; - uint8_t private_key[EC_PRIVK_LEN]; + uint8_t private_key[PRIV_KEY_LEN]; size_t len; psa_status_t psa_ret = PSA_ERROR_BAD_STATE; psa_status_t psa_cleanup_ret = PSA_ERROR_BAD_STATE; From 52b6dc87ec11108a42e4bb0c86279ff6084a708e Mon Sep 17 00:00:00 2001 From: Jukka Rissanen Date: Tue, 23 Sep 2025 13:04:30 +0300 Subject: [PATCH 283/420] Revert "[nrf fromlist] bootutil: Remove redundant ALIGN definitions" This reverts commit 4fb63a68022b62451bdcca2b2c25a3968eaaedbc. Signed-off-by: Jukka Rissanen --- boot/bootutil/include/bootutil/bootutil_public.h | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/boot/bootutil/include/bootutil/bootutil_public.h b/boot/bootutil/include/bootutil/bootutil_public.h index 933553f9f..e2795ab3e 100644 --- a/boot/bootutil/include/bootutil/bootutil_public.h +++ b/boot/bootutil/include/bootutil/bootutil_public.h @@ -43,13 +43,20 @@ #include #include #include -#include #include #ifdef __cplusplus extern "C" { #endif +#ifndef ALIGN_UP +#define ALIGN_UP(num, align) (((num) + ((align) - 1)) & ~((align) - 1)) +#endif + +#ifndef ALIGN_DOWN +#define ALIGN_DOWN(num, align) ((num) & ~((align) - 1)) +#endif + /** Attempt to boot the contents of the primary slot. */ #define BOOT_SWAP_TYPE_NONE 1 From 86697dc3f4d93cb962fe50702315a370b2e09e08 Mon Sep 17 00:00:00 2001 From: Jukka Rissanen Date: Tue, 23 Sep 2025 13:04:30 +0300 Subject: [PATCH 284/420] Revert "[nrf fromlist] bootutil: Move all encryption TLV helper identifiers into one place" This reverts commit ba56472ac54b08aefb50ff45bb1377105ece1099. Signed-off-by: Jukka Rissanen --- .../include/bootutil/bootutil_macros.h | 19 ----- boot/bootutil/include/bootutil/crypto/rsa.h | 4 +- boot/bootutil/include/bootutil/enc_key.h | 2 + .../include/bootutil/enc_key_public.h | 77 ++++--------------- boot/bootutil/src/encrypted.c | 32 ++++++-- boot/bootutil/src/encrypted_psa.c | 10 +++ 6 files changed, 58 insertions(+), 86 deletions(-) delete mode 100644 boot/bootutil/include/bootutil/bootutil_macros.h diff --git a/boot/bootutil/include/bootutil/bootutil_macros.h b/boot/bootutil/include/bootutil/bootutil_macros.h deleted file mode 100644 index e8d27b792..000000000 --- a/boot/bootutil/include/bootutil/bootutil_macros.h +++ /dev/null @@ -1,19 +0,0 @@ -/* - * SPDX-License-Identifier: Apache-2.0 - * - * Copyright (c) 2025 Nordic Semiconductor ASA - * - */ - -#ifndef H_BOOTUTIL_MACROS -#define H_BOOTUTIL_MACROS - -#ifndef ALIGN_UP -#define ALIGN_UP(num, align) (((num) + ((align) - 1)) & ~((align) - 1)) -#endif - -#ifndef ALIGN_DOWN -#define ALIGN_DOWN(num, align) ((num) & ~((align) - 1)) -#endif - -#endif diff --git a/boot/bootutil/include/bootutil/crypto/rsa.h b/boot/bootutil/include/bootutil/crypto/rsa.h index 87ab1de56..581e4ec9b 100644 --- a/boot/bootutil/include/bootutil/crypto/rsa.h +++ b/boot/bootutil/include/bootutil/crypto/rsa.h @@ -100,12 +100,12 @@ static int bootutil_rsa_oaep_decrypt( return -1; } size_t input_size = PSA_BITS_TO_BYTES(psa_get_key_bits(&key_attr)); - if (input_size != BOOT_ENC_TLV_SIZE) { + if (input_size != TLV_ENC_RSA_SZ) { return -1; } status = psa_asymmetric_decrypt(ctx->key_id, PSA_ALG_RSA_OAEP(PSA_ALG_SHA_256), - input, BOOT_ENC_TLV_SIZE, NULL, 0, + input, TLV_ENC_RSA_SZ, NULL, 0, output, output_max_len, olen); return (int)status; } diff --git a/boot/bootutil/include/bootutil/enc_key.h b/boot/bootutil/include/bootutil/enc_key.h index 85cb7e1b9..9240d699d 100644 --- a/boot/bootutil/include/bootutil/enc_key.h +++ b/boot/bootutil/include/bootutil/enc_key.h @@ -39,6 +39,8 @@ extern "C" { #endif +#define BOOT_ENC_TLV_ALIGN_SIZE ALIGN_UP(BOOT_ENC_TLV_SIZE, BOOT_MAX_ALIGN) + struct enc_key_data { uint8_t valid; bootutil_aes_ctr_context aes_ctr; diff --git a/boot/bootutil/include/bootutil/enc_key_public.h b/boot/bootutil/include/bootutil/enc_key_public.h index 55b06b025..6874cfbc8 100644 --- a/boot/bootutil/include/bootutil/enc_key_public.h +++ b/boot/bootutil/include/bootutil/enc_key_public.h @@ -28,80 +28,37 @@ #ifndef BOOTUTIL_ENC_KEY_PUBLIC_H #define BOOTUTIL_ENC_KEY_PUBLIC_H #include -#include - #ifdef __cplusplus extern "C" { #endif -/* The unit provides following system wide definitions: - * BOOT_ENC_TLV_SIZE -- is the complete size of TLV with encryption data. - * BOOT_ENC_TLV -- is the encryption TLV type, should be given value - * of one of IMAGE_TVL_ENC_ identifiers. - * BOOT_ENC_KEY_SIZE -- is the encryption key size; this includes portion - * of TLV data stream taken by key. - * - * For ECIES based key exchange there is additionally provided: - * EC_PUBK_LEN -- is the length, in bytes, of a public key; depends - * selected key exchange. - * EC_PRIVK_LEN -- is the length, in bytes, of a private key; depends - * on selected key exchange. - * EC_SHARED_LEN -- is the length, in bytes, of a shared key resulting - * from processing of private and public key; depends - * on selected key exchange parameters. - * - * ECIES TLV processing uses following TLVs, from this header: - * EC_TAG_INDEX -- is the HMAC tag of encryption key index within TLV data - * stream. - * EC_TAG_LEN -- is the HMAC tag length. - * EC_PUBK_INDEX -- is the index of shared public key within TLV data stream; - * EC_PUBK_LEN represents length in bytes. - * EC_CIPHERKEY_INDEX -- is the encryption key index within TLV data stream. - * EC_CIPHERKEY_LEN -- is the length of an encryption key; depends on selected - * encryption. - * - * Note that in case of ECIES, the BOOT_ENC_TLV_SIZE will be defined as - * a sum of EC_*_LEN TLV components, defined for selected key exchange. - */ +#ifndef ALIGN_UP +#define ALIGN_UP(num, align) (((num) + ((align) - 1)) & ~((align) - 1)) +#endif #ifdef MCUBOOT_AES_256 -# define BOOT_ENC_KEY_SIZE 32 +#define BOOT_ENC_KEY_SIZE 32 #else -# define BOOT_ENC_KEY_SIZE 16 +#define BOOT_ENC_KEY_SIZE 16 #endif +#define BOOT_ENC_KEY_ALIGN_SIZE ALIGN_UP(BOOT_ENC_KEY_SIZE, BOOT_MAX_ALIGN) + +#define TLV_ENC_RSA_SZ 256 +#define TLV_ENC_KW_SZ (BOOT_ENC_KEY_SIZE + 8) +#define TLV_ENC_EC256_SZ (65 + 32 + BOOT_ENC_KEY_SIZE) +#define TLV_ENC_X25519_SZ (32 + 32 + BOOT_ENC_KEY_SIZE) + #if defined(MCUBOOT_ENCRYPT_RSA) -# define BOOT_ENC_TLV_SIZE (256) -# define BOOT_ENC_TLV IMAGE_TLV_ENC_RSA2048 +#define BOOT_ENC_TLV_SIZE TLV_ENC_RSA_SZ #elif defined(MCUBOOT_ENCRYPT_EC256) -# define EC_PUBK_LEN (65) -# define EC_PRIVK_LEN (32) -# define EC_SHARED_LEN (32) -# define BOOT_ENC_TLV IMAGE_TLV_ENC_EC256 +#define BOOT_ENC_TLV_SIZE TLV_ENC_EC256_SZ #elif defined(MCUBOOT_ENCRYPT_X25519) -# define EC_PUBK_LEN (32) -# define EC_PRIVK_LEN (32) -# define EC_SHARED_LEN (32) -# define BOOT_ENC_TLV IMAGE_TLV_ENC_X25519 -#elif defined(MCUBOOT_ENCRYPT_KW) -# define BOOT_ENC_TLV_SIZE (BOOT_ENC_KEY_SIZE + 8) -# define BOOT_ENC_TLV IMAGE_TLV_ENC_KW -#endif - -/* Common ECIES definitions */ -#if defined(EC_PUBK_LEN) -# define EC_PUBK_INDEX (0) -# define EC_TAG_LEN (32) -# define EC_TAG_INDEX (EC_PUBK_INDEX + EC_PUBK_LEN) -# define EC_CIPHERKEY_INDEX (EC_TAG_INDEX + EC_TAG_LEN) -# define EC_CIPHERKEY_LEN BOOT_ENC_KEY_SIZE -# define EC_SHARED_KEY_LEN (32) -# define BOOT_ENC_TLV_SIZE (EC_PUBK_LEN + EC_TAG_LEN + EC_CIPHERKEY_LEN) +#define BOOT_ENC_TLV_SIZE TLV_ENC_X25519_SZ +#else +#define BOOT_ENC_TLV_SIZE TLV_ENC_KW_SZ #endif -#define BOOT_ENC_KEY_ALIGN_SIZE ALIGN_UP(BOOT_ENC_KEY_SIZE, BOOT_MAX_ALIGN) -#define BOOT_ENC_TLV_ALIGN_SIZE ALIGN_UP(BOOT_ENC_TLV_SIZE, BOOT_MAX_ALIGN) - #ifdef __cplusplus } #endif diff --git a/boot/bootutil/src/encrypted.c b/boot/bootutil/src/encrypted.c index f64493656..bbe40751f 100644 --- a/boot/bootutil/src/encrypted.c +++ b/boot/bootutil/src/encrypted.c @@ -46,6 +46,28 @@ #include "bootutil_priv.h" +#define EXPECTED_ENC_LEN BOOT_ENC_TLV_SIZE + +#if defined(MCUBOOT_ENCRYPT_RSA) +# define EXPECTED_ENC_TLV IMAGE_TLV_ENC_RSA2048 +#elif defined(MCUBOOT_ENCRYPT_KW) +# define EXPECTED_ENC_TLV IMAGE_TLV_ENC_KW +#elif defined(MCUBOOT_ENCRYPT_EC256) +# define EXPECTED_ENC_TLV IMAGE_TLV_ENC_EC256 +# define EC_PUBK_INDEX (0) +# define EC_TAG_INDEX (65) +# define EC_CIPHERKEY_INDEX (65 + 32) +_Static_assert(EC_CIPHERKEY_INDEX + BOOT_ENC_KEY_SIZE == EXPECTED_ENC_LEN, + "Please fix ECIES-P256 component indexes"); +#elif defined(MCUBOOT_ENCRYPT_X25519) +# define EXPECTED_ENC_TLV IMAGE_TLV_ENC_X25519 +# define EC_PUBK_INDEX (0) +# define EC_TAG_INDEX (32) +# define EC_CIPHERKEY_INDEX (32 + 32) +_Static_assert(EC_CIPHERKEY_INDEX + BOOT_ENC_KEY_SIZE == EXPECTED_ENC_LEN, + "Please fix ECIES-X25519 component indexes"); +#endif + /* NOUP Fixme: */ #if !defined(CONFIG_BOOT_ED25519_PSA) #if defined(MCUBOOT_ENCRYPT_EC256) || defined(MCUBOOT_ENCRYPT_X25519) @@ -82,7 +104,7 @@ key_unwrap(const uint8_t *wrapped, uint8_t *enckey, struct bootutil_key *bootuti if (rc != 0) { goto done; } - rc = bootutil_aes_kw_unwrap(&aes_kw, wrapped, BOOT_ENC_TLV_SIZE, enckey, BOOT_ENC_KEY_SIZE); + rc = bootutil_aes_kw_unwrap(&aes_kw, wrapped, TLV_ENC_KW_SZ, enckey, BOOT_ENC_KEY_SIZE); if (rc != 0) { goto done; } @@ -599,7 +621,7 @@ boot_enc_load(struct boot_loader_state *state, int slot, #if MCUBOOT_SWAP_SAVE_ENCTLV uint8_t *buf; #else - uint8_t buf[BOOT_ENC_TLV_SIZE]; + uint8_t buf[EXPECTED_ENC_LEN]; #endif int rc; @@ -619,7 +641,7 @@ boot_enc_load(struct boot_loader_state *state, int slot, #endif #endif - rc = bootutil_tlv_iter_begin(&it, hdr, fap, BOOT_ENC_TLV, false); + rc = bootutil_tlv_iter_begin(&it, hdr, fap, EXPECTED_ENC_TLV, false); if (rc) { return -1; } @@ -629,7 +651,7 @@ boot_enc_load(struct boot_loader_state *state, int slot, return rc; } - if (len != BOOT_ENC_TLV_SIZE) { + if (len != EXPECTED_ENC_LEN) { return -1; } @@ -638,7 +660,7 @@ boot_enc_load(struct boot_loader_state *state, int slot, memset(buf, 0xff, BOOT_ENC_TLV_ALIGN_SIZE); #endif - rc = flash_area_read(fap, off, buf, BOOT_ENC_TLV_SIZE); + rc = flash_area_read(fap, off, buf, EXPECTED_ENC_LEN); if (rc) { return -1; } diff --git a/boot/bootutil/src/encrypted_psa.c b/boot/bootutil/src/encrypted_psa.c index d604df201..313372fb1 100644 --- a/boot/bootutil/src/encrypted_psa.c +++ b/boot/bootutil/src/encrypted_psa.c @@ -27,6 +27,16 @@ BOOT_LOG_MODULE_DECLARE(mcuboot_psa_enc); +#define EXPECTED_ENC_LEN BOOT_ENC_TLV_SIZE +#define EC_PUBK_INDEX (0) +#define EC_PUBK_LEN (32) +#define EC_TAG_INDEX (EC_PUBK_INDEX + EC_PUBK_LEN) +#define EC_TAG_LEN (32) +#define EC_CIPHERKEY_INDEX (EC_TAG_INDEX + EC_TAG_LEN) +#define EC_CIPHERKEY_LEN BOOT_ENC_KEY_SIZE +_Static_assert(EC_CIPHERKEY_INDEX + BOOT_ENC_KEY_SIZE == EXPECTED_ENC_LEN, + "Please fix ECIES-X25519 component indexes"); + #define X25519_OID "\x6e" static const uint8_t ec_pubkey_oid[] = MBEDTLS_OID_ISO_IDENTIFIED_ORG \ MBEDTLS_OID_ORG_GOV X25519_OID; From bda016719c38a860e531bb51600b855d9af21004 Mon Sep 17 00:00:00 2001 From: Carles Cufi Date: Tue, 10 Oct 2023 15:51:54 +0200 Subject: [PATCH 285/420] [nrf noup] github: Add a commit tags check workflow Use the generic commit-tags action to provide sauce tag checks. Signed-off-by: Carles Cufi (cherry picked from commit 727cc28fcc10b78fc2f8b3fb5fd60ea71596160f) --- .github/workflows/commit-tags.yml | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) create mode 100644 .github/workflows/commit-tags.yml diff --git a/.github/workflows/commit-tags.yml b/.github/workflows/commit-tags.yml new file mode 100644 index 000000000..534ed5b58 --- /dev/null +++ b/.github/workflows/commit-tags.yml @@ -0,0 +1,28 @@ +name: Commit tags + +on: + pull_request: + types: [synchronize, opened, reopened, edited, labeled, unlabeled, + milestoned, demilestoned, assigned, unassigned, ready_for_review, + review_requested] + +jobs: + commit_tags: + runs-on: ubuntu-22.04 + name: Run commit tags checks on patch series (PR) + steps: + - name: Update PATH for west + run: | + echo "$HOME/.local/bin" >> $GITHUB_PATH + + - name: Checkout the code + uses: actions/checkout@v3 + with: + ref: ${{ github.event.pull_request.head.sha }} + fetch-depth: 0 + + - name: Run the commit tags + uses: nrfconnect/action-commit-tags@main + with: + target: . + upstream: mcu-tools/mcuboot/main From 9507c25dd41289ec312a06f74327ac4cd925f34a Mon Sep 17 00:00:00 2001 From: Sigvart Hovland Date: Tue, 26 Mar 2019 15:42:38 +0100 Subject: [PATCH 286/420] [nrf noup] zephyr: Remove duplication from cmake MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Removes the `add_subdirectory` of nrfxlib it will still check that the nrfxlib is located outside the mcuboot directory. Signed-off-by: Sigvart Hovland Signed-off-by: Andrzej Puzdrowski Signed-off-by: Martí Bolívar Signed-off-by: Emil Obalski Signed-off-by: Andrzej Puzdrowski Signed-off-by: Håkon Øye Amundsen Signed-off-by: Ioannis Glaropoulos Signed-off-by: Torsten Rasmussen Signed-off-by: Jamie McCrae Signed-off-by: Dominik Ermel (cherry picked from commit 7ac4eeb0b9ad01f90d002cf34d1e84a6b0e539ab) --- boot/zephyr/CMakeLists.txt | 2 -- 1 file changed, 2 deletions(-) diff --git a/boot/zephyr/CMakeLists.txt b/boot/zephyr/CMakeLists.txt index d5964efe9..011a67e84 100644 --- a/boot/zephyr/CMakeLists.txt +++ b/boot/zephyr/CMakeLists.txt @@ -50,8 +50,6 @@ if(NOT EXISTS ${NRFXLIB_DIR}) To use the tinycrypt set `CONFIG_BOOT_ECDSA_TINYCRYPT` to y. ------------------------------------------------------------------------") endif() -# Don't include this if we are using west - add_subdirectory(${NRFXLIB_DIR} ${PROJECT_BINARY_DIR}/nrfxlib) endif() zephyr_library_include_directories( From 11916fe64d76d0d14255fe99aa869632a00b0f80 Mon Sep 17 00:00:00 2001 From: Bernt Johan Damslora Date: Fri, 20 Sep 2019 18:25:41 +0200 Subject: [PATCH 287/420] [nrf noup] boards: add support for Thingy:91 Adds project configurations for the two systems on the Thingy:91 (PCA-20035) board. The bootloader that is factory-programmed on thing91 does not support ECDSA signature type. Hence this commit also sets the signature type to RSA for applications built for Thingy:91. Signed-off-by: Bernt Johan Damslora Signed-off-by: Sigvart Hovland Signed-off-by: Jon Helge Nistad Signed-off-by: Balaji Srinivasan Signed-off-by: Robert Lubos Signed-off-by: Torsten Rasmussen Signed-off-by: Jamie McCrae Signed-off-by: Marek Pieta Signed-off-by: Dominik Ermel (cherry picked from commit 313de9ca5b4e9015642b100007f4314483121f68) --- boot/zephyr/boards/thingy91_nrf52840.conf | 34 +++++++++++++++++++++++ boot/zephyr/boards/thingy91_nrf9160.conf | 13 +++++++++ 2 files changed, 47 insertions(+) create mode 100644 boot/zephyr/boards/thingy91_nrf52840.conf create mode 100644 boot/zephyr/boards/thingy91_nrf9160.conf diff --git a/boot/zephyr/boards/thingy91_nrf52840.conf b/boot/zephyr/boards/thingy91_nrf52840.conf new file mode 100644 index 000000000..c0d183401 --- /dev/null +++ b/boot/zephyr/boards/thingy91_nrf52840.conf @@ -0,0 +1,34 @@ +# Disable Zephyr console +CONFIG_LOG=n +CONFIG_CONSOLE=n +CONFIG_CONSOLE_HANDLER=n +CONFIG_UART_CONSOLE=n + +# The build won't fit on the partition allocated for it without size +# optimizations. +CONFIG_SIZE_OPTIMIZATIONS=y +CONFIG_PM_PARTITION_SIZE_MCUBOOT=0x12000 + +# Serial +CONFIG_SERIAL=y +CONFIG_UART_NRFX=y +CONFIG_UART_INTERRUPT_DRIVEN=y +CONFIG_UART_LINE_CTRL=y + +# MCUboot serial recovery +CONFIG_GPIO=y +CONFIG_MCUBOOT_SERIAL=y +CONFIG_BOOT_SERIAL_CDC_ACM=y + +# Required by USB +CONFIG_MULTITHREADING=y + +# USB +CONFIG_USB_DEVICE_STACK=y +CONFIG_USB_DEVICE_PRODUCT="MCUBOOT" +CONFIG_USB_CDC_ACM=y +CONFIG_USB_COMPOSITE_DEVICE=y +CONFIG_USB_MASS_STORAGE=n +CONFIG_USB_DEVICE_MANUFACTURER="Nordic Semiconductor" +CONFIG_USB_DEVICE_VID=0x1915 +CONFIG_USB_DEVICE_PID=0x520F diff --git a/boot/zephyr/boards/thingy91_nrf9160.conf b/boot/zephyr/boards/thingy91_nrf9160.conf new file mode 100644 index 000000000..1bf2e424d --- /dev/null +++ b/boot/zephyr/boards/thingy91_nrf9160.conf @@ -0,0 +1,13 @@ +# Disable Zephyr console +CONFIG_CONSOLE=n +CONFIG_CONSOLE_HANDLER=n +CONFIG_UART_CONSOLE=n + +# Disable Flash protection +CONFIG_FPROTECT=n + +# MCUBoot settings +CONFIG_BOOT_MAX_IMG_SECTORS=256 + +# MCUboot serial recovery +CONFIG_MCUBOOT_SERIAL=y From fff02ed5ca355e43f9f540e6a98b4b145617d6ea Mon Sep 17 00:00:00 2001 From: Maximilian Deubel Date: Fri, 8 Dec 2023 13:18:12 +0100 Subject: [PATCH 288/420] [nrf noup] boards: thingy91x: add board config This patch adds board configuration for the Thingy:91 X. Signed-off-by: Maximilian Deubel (cherry picked from commit 19d7a4e5526a1b6d7d9282508d1089add9936df6) --- .../boards/thingy91x_nrf5340_cpuapp.conf | 54 +++++++++++++++++++ boot/zephyr/boards/thingy91x_nrf9151.conf | 8 +++ 2 files changed, 62 insertions(+) create mode 100644 boot/zephyr/boards/thingy91x_nrf5340_cpuapp.conf create mode 100644 boot/zephyr/boards/thingy91x_nrf9151.conf diff --git a/boot/zephyr/boards/thingy91x_nrf5340_cpuapp.conf b/boot/zephyr/boards/thingy91x_nrf5340_cpuapp.conf new file mode 100644 index 000000000..72dfa7fca --- /dev/null +++ b/boot/zephyr/boards/thingy91x_nrf5340_cpuapp.conf @@ -0,0 +1,54 @@ +# MCUBoot settings +CONFIG_BOOT_MAX_IMG_SECTORS=110 + +# MCUboot serial recovery +CONFIG_MCUBOOT_SERIAL=y + +# Disable Zephyr console +CONFIG_LOG=n +CONFIG_CONSOLE=n +CONFIG_CONSOLE_HANDLER=n +CONFIG_UART_CONSOLE=n + +# Serial +CONFIG_SERIAL=y +CONFIG_UART_NRFX=y +CONFIG_UART_INTERRUPT_DRIVEN=y +CONFIG_UART_LINE_CTRL=y + +# MCUboot serial recovery +CONFIG_GPIO=y +CONFIG_MCUBOOT_SERIAL=y +CONFIG_BOOT_SERIAL_CDC_ACM=y + +# Required by USB +CONFIG_MULTITHREADING=y + +# USB +CONFIG_USB_DEVICE_STACK=y +CONFIG_USB_DEVICE_PRODUCT="MCUBOOT" +CONFIG_USB_CDC_ACM=y +CONFIG_USB_COMPOSITE_DEVICE=y +CONFIG_USB_MASS_STORAGE=n +CONFIG_USB_DEVICE_MANUFACTURER="Nordic Semiconductor" +CONFIG_USB_DEVICE_VID=0x1915 +CONFIG_USB_DEVICE_PID=0x520F + +CONFIG_BOOT_SERIAL_BOOT_MODE=y + +CONFIG_PM_PARTITION_SIZE_MCUBOOT=0x13E00 + +# The following configurations are required to support simultaneous multi image update +CONFIG_PCD_APP=y +CONFIG_UPDATEABLE_IMAGE_NUMBER=2 +CONFIG_BOOT_UPGRADE_ONLY=y +# The network core cannot access external flash directly. The flash simulator must be used to +# provide a memory region that is used to forward the new firmware to the network core. +CONFIG_FLASH_SIMULATOR=y +CONFIG_FLASH_SIMULATOR_DOUBLE_WRITES=y +CONFIG_FLASH_SIMULATOR_STATS=n + +CONFIG_BOOT_IMAGE_ACCESS_HOOKS=y +CONFIG_MCUBOOT_SERIAL_DIRECT_IMAGE_UPLOAD=y + +CONFIG_NRF53_RECOVERY_NETWORK_CORE=y diff --git a/boot/zephyr/boards/thingy91x_nrf9151.conf b/boot/zephyr/boards/thingy91x_nrf9151.conf new file mode 100644 index 000000000..33cd3301c --- /dev/null +++ b/boot/zephyr/boards/thingy91x_nrf9151.conf @@ -0,0 +1,8 @@ +# MCUBoot settings +CONFIG_BOOT_MAX_IMG_SECTORS=512 + +CONFIG_SPI=y +CONFIG_SPI_NOR=y +CONFIG_SPI_NOR_FLASH_LAYOUT_PAGE_SIZE=4096 +CONFIG_SPI_NOR_SFDP_DEVICETREE=y +CONFIG_MULTITHREADING=y From 008144597fd759be49af8eed7dd837b1f07f68f0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebastian=20B=C3=B8e?= Date: Wed, 12 Dec 2018 08:59:47 +0100 Subject: [PATCH 289/420] [nrf noup] treewide: add NCS partition manager support MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Partition Manager is an nRF Connect SDK component which uses yaml files to resolve flash partition placement with a holistic view of the device. This component's MCUboot portions began life as upstream mcuboot PR#430. This added support for being built as a sub image from the downstream Nordic patch set for a zephyr multi image build system (mcuboot 430 was combined with effor submitted to upstream zephyr as PR#13672, which was ultimately reworked after being rejected for mainline at the ELCE 2019 conference in Lyon). It has since evolved over time. This is the version that will go into NCS v1.3. It features: - page size aligned partitions for all partitions used by mcuboot. - image swaps without scratch partitions Add support for configurations where there exists two primary slots but only one secondary slot, which is shared. These two primary slots are the regular application and B1. B1 can be either S0 or S1 depending on the state of the device. Decide where an upgrade should be stored by looking at the vector table. Provide update candidates for both s0 and s1. These candidates must be signed with mcuboot after being signed by b0. Additional notes: - we make update.hex without trailer data This is needed for serial recovery to work using hex files. Prior to this the update.hex got TLV data at the end of the partition, which caused many blank pages to be included, which made it hard to use in a serial recovery scheme. Instead, make update.hex without TLV data at the end, and provide a new file test_update.hex which contains the TLV data, and can be directly flashed to test the upgrade procedure. - we use a function for signing the application as future-proofing for when other components must be signed as well - this includes an update to single image applications that enables support for partition manager; when single image DFU is used, a scratch partition is not needed. - In NCS, image 1 primary slot is the upgrade bank for mcuboot (IE S0 or S1 depending on the active slot). It is not required that this slot contains any valid data. - The nRF boards all have a single flash page size, and partition manager deals with the size of the update partitions and so on, so we must skip a boot_slots_compatible() check to avoid getting an error. - There is no need to verify the target when using partition manager. - We lock mcuboot using fprotect before jumping, to enable the secure boot property of the system. - Call fw_info_ext_api_provide() before booting if EXT_API_PROVIDE EXT_API is enabled. This is relevant only when the immutable bootloader has booted mcuboot. Signed-off-by: Håkon Øye Amundsen Signed-off-by: Øyvind Rønningstad Signed-off-by: Sebastian Bøe Signed-off-by: Sigvart Hovland Signed-off-by: Martí Bolívar Signed-off-by: Torsten Rasmussen Signed-off-by: Andrzej Głąbek Signed-off-by: Robert Lubos Signed-off-by: Andrzej Puzdrowski Signed-off-by: Emil Obalski Signed-off-by: Pawel Dunaj Signed-off-by: Ioannis Glaropoulos Signed-off-by: Johann Fischer Signed-off-by: Vidar Berg Signed-off-by: Draus, Sebastian Signed-off-by: Trond Einar Snekvik Signed-off-by: Jamie McCrae Signed-off-by: Joakim Andersson Signed-off-by: Georgios Vasilakis Signed-off-by: Dominik Ermel (cherry picked from commit 9554013f013d5bc067b41d9ad470bc09c346eb71) (cherry picked from commit 89361bdec45690575952743ef65bc357977ddbb9) --- boot/bootutil/src/loader.c | 95 ++++++++++++++++++++++--- boot/bootutil/src/swap_move.c | 13 ++++ boot/bootutil/src/swap_scratch.c | 13 ++++ boot/zephyr/CMakeLists.txt | 7 ++ boot/zephyr/Kconfig | 2 + boot/zephyr/include/sysflash/sysflash.h | 48 +++++++++++++ boot/zephyr/include/target.h | 4 ++ boot/zephyr/main.c | 45 ++++++++++++ boot/zephyr/pm.yml | 77 ++++++++++++++++++++ boot/zephyr/prj.conf | 1 + ext/nrf/cc310_glue.h | 2 +- zephyr/module.yml | 3 +- 12 files changed, 299 insertions(+), 11 deletions(-) create mode 100644 boot/zephyr/pm.yml diff --git a/boot/bootutil/src/loader.c b/boot/bootutil/src/loader.c index 9769428b4..30d8129b1 100644 --- a/boot/bootutil/src/loader.c +++ b/boot/bootutil/src/loader.c @@ -129,6 +129,15 @@ boot_read_image_headers(struct boot_loader_state *state, bool require_all, * * Failure to read any headers is a fatal error. */ +#ifdef PM_S1_ADDRESS + /* Patch needed for NCS. The primary slot of the second image + * (image 1) will not contain a valid image header until an upgrade + * of mcuboot has happened (filling S1 with the new version). + */ + if (BOOT_CURR_IMG(state) == 1 && i == 0) { + continue; + } +#endif /* PM_S1_ADDRESS */ if (i > 0 && !require_all) { return 0; } else { @@ -1019,7 +1028,24 @@ boot_validate_slot(struct boot_loader_state *state, int slot, goto out; } - if (reset_value < pri_fa->fa_off || reset_value> (pri_fa->fa_off + pri_fa->fa_size)) { + uint32_t min_addr, max_addr; + +#ifdef PM_CPUNET_APP_ADDRESS + /* The primary slot for the network core is emulated in RAM. + * Its flash_area hasn't got relevant boundaries. + * Therfore need to override its boundaries for the check. + */ + if (BOOT_CURR_IMG(state) == 1) { + min_addr = PM_CPUNET_APP_ADDRESS; + max_addr = PM_CPUNET_APP_ADDRESS + PM_CPUNET_APP_SIZE; + } else +#endif + { + min_addr = pri_fa->fa_off; + max_addr = pri_fa->fa_off + pri_fa->fa_size; + } + + if (reset_value < min_addr || reset_value> (max_addr)) { BOOT_LOG_ERR("Reset address of image in secondary slot is not in the primary slot"); BOOT_LOG_ERR("Erasing image from secondary slot"); @@ -1095,6 +1121,42 @@ boot_validated_swap_type(struct boot_loader_state *state, { int swap_type; FIH_DECLARE(fih_rc, FIH_FAILURE); +#ifdef PM_S1_ADDRESS + /* Patch needed for NCS. Since image 0 (the app) and image 1 (the other + * B1 slot S0 or S1) share the same secondary slot, we need to check + * whether the update candidate in the secondary slot is intended for + * image 0 or image 1 primary by looking at the address of the reset + * vector. Note that there are good reasons for not using img_num from + * the swap info. + */ + const struct flash_area *secondary_fa = + BOOT_IMG_AREA(state, BOOT_SECONDARY_SLOT); + struct image_header *hdr = + (struct image_header *)secondary_fa->fa_off; + + if (hdr->ih_magic == IMAGE_MAGIC) { + const struct flash_area *primary_fa; + uint32_t vtable_addr = (uint32_t)hdr + hdr->ih_hdr_size; + uint32_t *vtable = (uint32_t *)(vtable_addr); + uint32_t reset_addr = vtable[1]; + int rc = flash_area_open( + flash_area_id_from_multi_image_slot( + BOOT_CURR_IMG(state), + BOOT_PRIMARY_SLOT), + &primary_fa); + + if (rc != 0) { + return BOOT_SWAP_TYPE_FAIL; + } + /* Get start and end of primary slot for current image */ + if (reset_addr < primary_fa->fa_off || + reset_addr > (primary_fa->fa_off + primary_fa->fa_size)) { + /* The image in the secondary slot is not intended for this image + */ + return BOOT_SWAP_TYPE_NONE; + } + } +#endif swap_type = boot_swap_type_multi(BOOT_CURR_IMG(state)); if (BOOT_IS_UPGRADE(swap_type)) { @@ -2407,15 +2469,25 @@ context_boot_go(struct boot_loader_state *state, struct boot_rsp *rsp) } #ifdef MCUBOOT_VALIDATE_PRIMARY_SLOT - FIH_CALL(boot_validate_slot, fih_rc, state, BOOT_SLOT_PRIMARY, NULL, 0); - /* Check for all possible values is redundant in normal operation it - * is meant to prevent FI attack. +#ifdef PM_S1_ADDRESS + /* Patch needed for NCS. Image 1 primary is the currently + * executing MCUBoot image, and is therefore already validated by NSIB and + * does not need to also be validated by MCUBoot. */ - if (FIH_NOT_EQ(fih_rc, FIH_SUCCESS) || - FIH_EQ(fih_rc, FIH_FAILURE) || - FIH_EQ(fih_rc, FIH_NO_BOOTABLE_IMAGE)) { - FIH_SET(fih_rc, FIH_FAILURE); - goto out; + bool image_validated_by_nsib = BOOT_CURR_IMG(state) == 1; + if (!image_validated_by_nsib) +#endif + { + FIH_CALL(boot_validate_slot, fih_rc, state, BOOT_PRIMARY_SLOT, NULL, 0); + /* Check for all possible values is redundant in normal operation it + * is meant to prevent FI attack. + */ + if (FIH_NOT_EQ(fih_rc, FIH_SUCCESS) || + FIH_EQ(fih_rc, FIH_FAILURE) || + FIH_EQ(fih_rc, FIH_NO_BOOTABLE_IMAGE)) { + FIH_SET(fih_rc, FIH_FAILURE); + goto out; + } } #else /* Even if we're not re-validating the primary slot, we could be booting @@ -2432,11 +2504,16 @@ context_boot_go(struct boot_loader_state *state, struct boot_rsp *rsp) } #endif /* MCUBOOT_VALIDATE_PRIMARY_SLOT */ +#ifdef PM_S1_ADDRESS + if (!image_validated_by_nsib) +#endif + { rc = boot_update_hw_rollback_protection(state); if (rc != 0) { FIH_SET(fih_rc, FIH_FAILURE); goto out; } + } rc = boot_add_shared_data(state, BOOT_SLOT_PRIMARY); if (rc != 0) { diff --git a/boot/bootutil/src/swap_move.c b/boot/bootutil/src/swap_move.c index 88a117f59..75dadfe91 100644 --- a/boot/bootutil/src/swap_move.c +++ b/boot/bootutil/src/swap_move.c @@ -230,6 +230,18 @@ boot_status_internal_off(const struct boot_status *bs, int elem_sz) int boot_slots_compatible(struct boot_loader_state *state) { +#ifdef PM_S1_ADDRESS + /* Patch needed for NCS. In this case, image 1 primary points to the other + * B1 slot (ie S0 or S1), and image 0 primary points to the app. + * With this configuration, image 0 and image 1 share the secondary slot. + * Hence, the primary slot of image 1 will be *smaller* than image 1's + * secondary slot. This is not allowed in upstream mcuboot, so we need + * this patch to allow it. Also, all of these checks are redundant when + * partition manager is in use, and since we have the same sector size + * in all of our flash. + */ + return 1; +#else size_t num_sectors_pri; size_t num_sectors_sec; size_t sector_sz_pri = 0; @@ -295,6 +307,7 @@ boot_slots_compatible(struct boot_loader_state *state) } return 1; +#endif /* PM_S1_ADDRESS */ } #define BOOT_LOG_SWAP_STATE(area, state) \ diff --git a/boot/bootutil/src/swap_scratch.c b/boot/bootutil/src/swap_scratch.c index 0a994d862..f01f407b2 100644 --- a/boot/bootutil/src/swap_scratch.c +++ b/boot/bootutil/src/swap_scratch.c @@ -271,6 +271,18 @@ boot_status_internal_off(const struct boot_status *bs, int elem_sz) int boot_slots_compatible(struct boot_loader_state *state) { +#ifdef PM_S1_ADDRESS + /* Patch needed for NCS. In this case, image 1 primary points to the other + * B1 slot (ie S0 or S1), and image 0 primary points to the app. + * With this configuration, image 0 and image 1 share the secondary slot. + * Hence, the primary slot of image 1 will be *smaller* than image 1's + * secondary slot. This is not allowed in upstream mcuboot, so we need + * this patch to allow it. Also, all of these checks are redundant when + * partition manager is in use, and since we have the same sector size + * in all of our flash. + */ + return 1; +#else size_t num_sectors_primary; size_t num_sectors_secondary; size_t sz0, sz1; @@ -368,6 +380,7 @@ boot_slots_compatible(struct boot_loader_state *state) #endif return 1; +#endif /* PM_S1_ADDRESS */ } #define BOOT_LOG_SWAP_STATE(area, state) \ diff --git a/boot/zephyr/CMakeLists.txt b/boot/zephyr/CMakeLists.txt index 011a67e84..b6833bd62 100644 --- a/boot/zephyr/CMakeLists.txt +++ b/boot/zephyr/CMakeLists.txt @@ -358,6 +358,13 @@ if(NOT CONFIG_BOOT_SIGNATURE_KEY_FILE STREQUAL "") endif() message("MCUBoot bootloader key file: ${KEY_FILE}") + set_property( + GLOBAL + PROPERTY + KEY_FILE + ${KEY_FILE} + ) + set(mcuboot_default_signature_files ${MCUBOOT_DIR}/root-ec-p256-pkcs8.pem ${MCUBOOT_DIR}/root-ec-p384.pem diff --git a/boot/zephyr/Kconfig b/boot/zephyr/Kconfig index 467b848dc..bf9b4d511 100644 --- a/boot/zephyr/Kconfig +++ b/boot/zephyr/Kconfig @@ -9,6 +9,8 @@ mainmenu "MCUboot configuration" comment "MCUboot-specific configuration options" +source "$(ZEPHYR_NRF_MODULE_DIR)/modules/mcuboot/boot/zephyr/Kconfig" + # Hidden option to mark a project as MCUboot config MCUBOOT default y diff --git a/boot/zephyr/include/sysflash/sysflash.h b/boot/zephyr/include/sysflash/sysflash.h index 16d222280..99cbf56b7 100644 --- a/boot/zephyr/include/sysflash/sysflash.h +++ b/boot/zephyr/include/sysflash/sysflash.h @@ -7,6 +7,52 @@ #ifndef __SYSFLASH_H__ #define __SYSFLASH_H__ +#if USE_PARTITION_MANAGER +#include +#include + +#ifndef CONFIG_SINGLE_APPLICATION_SLOT + +#if (MCUBOOT_IMAGE_NUMBER == 1) + +#define FLASH_AREA_IMAGE_PRIMARY(x) PM_MCUBOOT_PRIMARY_ID +#define FLASH_AREA_IMAGE_SECONDARY(x) PM_MCUBOOT_SECONDARY_ID + +#elif (MCUBOOT_IMAGE_NUMBER == 2) + +extern uint32_t _image_1_primary_slot_id[]; + +#define FLASH_AREA_IMAGE_PRIMARY(x) \ + ((x == 0) ? \ + PM_MCUBOOT_PRIMARY_ID : \ + (x == 1) ? \ + (uint32_t)_image_1_primary_slot_id : \ + 255 ) + +#define FLASH_AREA_IMAGE_SECONDARY(x) \ + ((x == 0) ? \ + PM_MCUBOOT_SECONDARY_ID: \ + (x == 1) ? \ + PM_MCUBOOT_SECONDARY_ID: \ + 255 ) +#endif +#define FLASH_AREA_IMAGE_SCRATCH PM_MCUBOOT_SCRATCH_ID + +#else /* CONFIG_SINGLE_APPLICATION_SLOT */ + +#define FLASH_AREA_IMAGE_PRIMARY(x) PM_MCUBOOT_PRIMARY_ID +#define FLASH_AREA_IMAGE_SECONDARY(x) PM_MCUBOOT_PRIMARY_ID +/* NOTE: Scratch parition is not used by single image DFU but some of + * functions in common files reference it, so the definitions has been + * provided to allow compilation of common units. + */ +#define FLASH_AREA_IMAGE_SCRATCH 0 + +#endif /* CONFIG_SINGLE_APPLICATION_SLOT */ + +#else + +#include #include #include #include @@ -65,4 +111,6 @@ static inline uint32_t __flash_area_ids_for_slot(int img, int slot) #endif /* CONFIG_SINGLE_APPLICATION_SLOT */ +#endif /* USE_PARTITION_MANAGER */ + #endif /* __SYSFLASH_H__ */ diff --git a/boot/zephyr/include/target.h b/boot/zephyr/include/target.h index ea160752e..856686785 100644 --- a/boot/zephyr/include/target.h +++ b/boot/zephyr/include/target.h @@ -8,6 +8,8 @@ #ifndef H_TARGETS_TARGET_ #define H_TARGETS_TARGET_ +#ifndef USE_PARTITION_MANAGER + #if defined(MCUBOOT_TARGET_CONFIG) /* * Target-specific definitions are permitted in legacy cases that @@ -47,4 +49,6 @@ #error "Target support is incomplete; cannot build mcuboot." #endif +#endif /* ifndef USE_PARTITION_MANAGER */ + #endif /* H_TARGETS_TARGET_ */ diff --git a/boot/zephyr/main.c b/boot/zephyr/main.c index 1494002e7..e9a4e20b0 100644 --- a/boot/zephyr/main.c +++ b/boot/zephyr/main.c @@ -76,6 +76,10 @@ #endif /* CONFIG_SOC_FAMILY_ESPRESSIF_ESP32 */ +#ifdef CONFIG_FW_INFO +#include +#endif + #ifdef CONFIG_MCUBOOT_SERIAL #include "boot_serial/boot_serial.h" #include "serial_adapter/serial_adapter.h" @@ -122,6 +126,11 @@ K_SEM_DEFINE(boot_log_sem, 1, 1); * !defined(CONFIG_LOG_MODE_MINIMAL) */ +#if USE_PARTITION_MANAGER && CONFIG_FPROTECT +#include +#include +#endif + BOOT_LOG_MODULE_REGISTER(mcuboot); void os_heap_init(void); @@ -184,6 +193,19 @@ static void do_boot(struct boot_rsp *rsp) /* Disable the USB to prevent it from firing interrupts */ usb_disable(); #endif + +#if defined(CONFIG_FW_INFO) && !defined(CONFIG_EXT_API_PROVIDE_EXT_API_UNUSED) + bool provided = fw_info_ext_api_provide(fw_info_find((uint32_t)vt), true); + +#ifdef PM_S0_ADDRESS + /* Only fail if the immutable bootloader is present. */ + if (!provided) { + BOOT_LOG_ERR("Failed to provide EXT_APIs\n"); + return; + } +#endif +#endif + #if CONFIG_MCUBOOT_CLEANUP_ARM_CORE cleanup_arm_interrupts(); /* Disable and acknowledge all interrupts */ @@ -674,7 +696,30 @@ int main(void) mcuboot_status_change(MCUBOOT_STATUS_BOOTABLE_IMAGE_FOUND); +#if USE_PARTITION_MANAGER && CONFIG_FPROTECT + +#ifdef PM_S1_ADDRESS +/* MCUBoot is stored in either S0 or S1, protect both */ +#define PROTECT_SIZE (PM_MCUBOOT_PRIMARY_ADDRESS - PM_S0_ADDRESS) +#define PROTECT_ADDR PM_S0_ADDRESS +#else +/* There is only one instance of MCUBoot */ +#define PROTECT_SIZE (PM_MCUBOOT_PRIMARY_ADDRESS - PM_MCUBOOT_ADDRESS) +#define PROTECT_ADDR PM_MCUBOOT_ADDRESS +#endif + + rc = fprotect_area(PROTECT_ADDR, PROTECT_SIZE); + + if (rc != 0) { + BOOT_LOG_ERR("Protect mcuboot flash failed, cancel startup."); + while (1) + ; + } + +#endif /* USE_PARTITION_MANAGER && CONFIG_FPROTECT */ + ZEPHYR_BOOT_LOG_STOP(); + do_boot(&rsp); mcuboot_status_change(MCUBOOT_STATUS_BOOT_FAILED); diff --git a/boot/zephyr/pm.yml b/boot/zephyr/pm.yml new file mode 100644 index 000000000..5df9ae547 --- /dev/null +++ b/boot/zephyr/pm.yml @@ -0,0 +1,77 @@ +#include + +mcuboot: + size: CONFIG_PM_PARTITION_SIZE_MCUBOOT + placement: + before: [mcuboot_primary] +#if defined(CONFIG_HIDE_CHILD_PARENT_CONFIG) + align: {end: 0x1000} +#endif + +mcuboot_primary_app: + # All images to be placed in MCUboot's slot 0 should be placed in this + # partition + span: [app] + +mcuboot_primary: + span: [mcuboot_pad, mcuboot_primary_app] + +# Partition for secondary slot is not created if building in single application +# slot configuration. +#if !defined(CONFIG_SINGLE_APPLICATION_SLOT) && !defined(CONFIG_BOOT_DIRECT_XIP) +mcuboot_secondary: + share_size: [mcuboot_primary] +#if defined(CONFIG_PM_EXTERNAL_FLASH_MCUBOOT_SECONDARY) + region: external_flash + placement: + align: {start: 4} +#else + placement: + align: {start: CONFIG_FPROTECT_BLOCK_SIZE} + align_next: CONFIG_FPROTECT_BLOCK_SIZE # Ensure that the next partition does not interfere with this image + after: mcuboot_primary +#endif /* CONFIG_PM_EXTERNAL_FLASH_MCUBOOT_SECONDARY */ + +#endif /* !defined(CONFIG_SINGLE_APPLICATION_SLOT) && !defined(CONFIG_BOOT_DIRECT_XIP) */ + +#if CONFIG_BOOT_DIRECT_XIP + +# Direct XIP is enabled, reserve area for metadata (padding) and name the +# partition so that its clear that it is not the secondary slot, but the direct +# XIP alternative. + +mcuboot_secondary_pad: + share_size: mcuboot_pad + placement: + after: mcuboot_primary + align: {start: CONFIG_FPROTECT_BLOCK_SIZE} + +mcuboot_secondary_app: + share_size: mcuboot_primary_app + placement: + after: mcuboot_secondary_pad + +mcuboot_secondary: + span: [mcuboot_secondary_pad, mcuboot_secondary_app] + +#endif /* CONFIG_BOOT_DIRECT_XIP */ + +#if CONFIG_BOOT_SWAP_USING_SCRATCH +mcuboot_scratch: + size: CONFIG_PM_PARTITION_SIZE_MCUBOOT_SCRATCH + placement: + after: app + align: {start: CONFIG_FPROTECT_BLOCK_SIZE} +#endif /* CONFIG_BOOT_SWAP_USING_SCRATCH */ + +# Padding placed before image to boot. This reserves space for the MCUboot image header +# and it ensures that the boot image gets linked with the correct address offset in flash. +mcuboot_pad: + # MCUboot pad must be placed before the primary application partition. + # The primary application partition includes the secure firmware if present. + size: CONFIG_PM_PARTITION_SIZE_MCUBOOT_PAD + placement: + before: [mcuboot_primary_app] +#ifdef CONFIG_FPROTECT + align: {start: CONFIG_FPROTECT_BLOCK_SIZE} +#endif diff --git a/boot/zephyr/prj.conf b/boot/zephyr/prj.conf index b824ca1b1..615daf599 100644 --- a/boot/zephyr/prj.conf +++ b/boot/zephyr/prj.conf @@ -12,6 +12,7 @@ CONFIG_BOOT_BOOTSTRAP=n # CONFIG_HEAP_MEM_POOL_SIZE is not set CONFIG_FLASH=y +CONFIG_FPROTECT=y ### Various Zephyr boards enable features that we don't want. # CONFIG_BT is not set diff --git a/ext/nrf/cc310_glue.h b/ext/nrf/cc310_glue.h index ed3ed5c00..22eb94911 100644 --- a/ext/nrf/cc310_glue.h +++ b/ext/nrf/cc310_glue.h @@ -22,7 +22,7 @@ #include #include #include -#include +#include #include /* diff --git a/zephyr/module.yml b/zephyr/module.yml index 7a80d166f..65af58bb5 100644 --- a/zephyr/module.yml +++ b/zephyr/module.yml @@ -1,7 +1,8 @@ samples: - boot/zephyr build: - cmake: ./boot/bootutil/zephyr + cmake-ext: True + kconfig-ext: True sysbuild-cmake: boot/zephyr/sysbuild package-managers: pip: From 7f1fb0c77a823c3824d5fa640f29c8bd28aaeeb5 Mon Sep 17 00:00:00 2001 From: Sigvart Hovland Date: Thu, 27 Aug 2020 14:29:31 +0200 Subject: [PATCH 290/420] [nrf noup] boot: nrf53-specific customizations MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Add network core bootloader implementation Enables network core updates of nrf53 using MCUBoot by identifying images through their start addresses. Also implements the control and transfer using the PCD module. - Add support for multi image DFU using partition manager. - Add check for netcore addr if NSIB is enabled so netcore updates works - boot: zephyr: move thingy53_nrf5340_cpuapp.conf downstream Moved the board configuration for Thingy:53 Application Core to the nRF Connect SDK MCUboot downstream repository. The configuration file contains references to the Kconfig modules that are only available in the nRF Connect SDK. The current configuration is set up to work in the nRF Connect SDK environment and cannot be used upstream. - pm: enable ram flash partition using common flag This patch makes mcuboot_primary_1 ram-flash partition selectable using CONFIG_NRF53_MCUBOOT_PRIMARY_1_RAM_FLASH property. This is needed since CONFIG_NRF53_MULTI_IMAGE_UPDATE become not only configuration which requires that partition. - MCUBoot configures USB CDC by its own. There is no need for BOARD_SERIAL_BACKEND_CDC_ACM option to configure anything which is later overwritten anyway. Jira: NCSDK-18596 Signed-off-by: Andrzej Puzdrowski Signed-off-by: Emil Obalski Signed-off-by: Håkon Øye Amundsen Signed-off-by: Ioannis Glaropoulos Signed-off-by: Jamie McCrae Signed-off-by: Johann Fischer Signed-off-by: Kamil Piszczek Signed-off-by: Ole Sæther Signed-off-by: Sigvart Hovland Signed-off-by: Simon Iversen Signed-off-by: Torsten Rasmussen Signed-off-by: Trond Einar Snekvik Signed-off-by: Mateusz Kapala Signed-off-by: Dominik Ermel Signed-off-by: Michal Kozikowski (cherry picked from commit 3db6eca8c7968a1eb1cb11fda08f763004f8226d) (cherry picked from commit 2cdbcb02a960f625e7a067f37ab573a4ebaa03a7) --- boot/bootutil/src/loader.c | 96 ++++++++++++++----- .../boards/thingy53_nrf5340_cpuapp.conf | 74 +++++++++++++- boot/zephyr/include/sysflash/sysflash.h | 23 +++++ boot/zephyr/main.c | 25 ++++- boot/zephyr/pm.yml | 13 +++ 5 files changed, 201 insertions(+), 30 deletions(-) diff --git a/boot/bootutil/src/loader.c b/boot/bootutil/src/loader.c index 30d8129b1..8938c387a 100644 --- a/boot/bootutil/src/loader.c +++ b/boot/bootutil/src/loader.c @@ -50,6 +50,10 @@ #include "bootutil/boot_hooks.h" #include "bootutil/mcuboot_status.h" +#if defined(CONFIG_SOC_NRF5340_CPUAPP) && defined(PM_CPUNET_B0N_ADDRESS) && defined(CONFIG_PCD_APP) +#include +#endif + #ifdef MCUBOOT_ENC_IMAGES #include "bootutil/enc_key.h" #endif @@ -1121,7 +1125,15 @@ boot_validated_swap_type(struct boot_loader_state *state, { int swap_type; FIH_DECLARE(fih_rc, FIH_FAILURE); -#ifdef PM_S1_ADDRESS + bool upgrade_valid = false; + +#if defined(PM_S1_ADDRESS) || defined(CONFIG_SOC_NRF5340_CPUAPP) + const struct flash_area *secondary_fa = + BOOT_IMG_AREA(state, BOOT_SECONDARY_SLOT); + struct image_header *hdr = (struct image_header *)secondary_fa->fa_off; + uint32_t vtable_addr = 0; + uint32_t *vtable = 0; + uint32_t reset_addr = 0; /* Patch needed for NCS. Since image 0 (the app) and image 1 (the other * B1 slot S0 or S1) share the same secondary slot, we need to check * whether the update candidate in the secondary slot is intended for @@ -1129,34 +1141,36 @@ boot_validated_swap_type(struct boot_loader_state *state, * vector. Note that there are good reasons for not using img_num from * the swap info. */ - const struct flash_area *secondary_fa = - BOOT_IMG_AREA(state, BOOT_SECONDARY_SLOT); - struct image_header *hdr = - (struct image_header *)secondary_fa->fa_off; if (hdr->ih_magic == IMAGE_MAGIC) { - const struct flash_area *primary_fa; - uint32_t vtable_addr = (uint32_t)hdr + hdr->ih_hdr_size; - uint32_t *vtable = (uint32_t *)(vtable_addr); - uint32_t reset_addr = vtable[1]; - int rc = flash_area_open( - flash_area_id_from_multi_image_slot( - BOOT_CURR_IMG(state), - BOOT_PRIMARY_SLOT), - &primary_fa); - - if (rc != 0) { - return BOOT_SWAP_TYPE_FAIL; - } - /* Get start and end of primary slot for current image */ - if (reset_addr < primary_fa->fa_off || - reset_addr > (primary_fa->fa_off + primary_fa->fa_size)) { - /* The image in the secondary slot is not intended for this image - */ - return BOOT_SWAP_TYPE_NONE; - } - } + vtable_addr = (uint32_t)hdr + hdr->ih_hdr_size; + vtable = (uint32_t *)(vtable_addr); + reset_addr = vtable[1]; +#ifdef PM_S1_ADDRESS +#ifdef PM_CPUNET_B0N_ADDRESS + if(reset_addr < PM_CPUNET_B0N_ADDRESS) #endif + { + const struct flash_area *primary_fa; + int rc = flash_area_open(flash_area_id_from_multi_image_slot( + BOOT_CURR_IMG(state), + BOOT_PRIMARY_SLOT), + &primary_fa); + + if (rc != 0) { + return BOOT_SWAP_TYPE_FAIL; + } + /* Get start and end of primary slot for current image */ + if (reset_addr < primary_fa->fa_off || + reset_addr > (primary_fa->fa_off + primary_fa->fa_size)) { + /* The image in the secondary slot is not intended for this image + */ + return BOOT_SWAP_TYPE_NONE; + } + } +#endif /* PM_S1_ADDRESS */ + } +#endif /* PM_S1_ADDRESS || CONFIG_SOC_NRF5340_CPUAPP */ swap_type = boot_swap_type_multi(BOOT_CURR_IMG(state)); if (BOOT_IS_UPGRADE(swap_type)) { @@ -1170,7 +1184,37 @@ boot_validated_swap_type(struct boot_loader_state *state, } else { swap_type = BOOT_SWAP_TYPE_FAIL; } + } else { + upgrade_valid = true; + } + +#if defined(CONFIG_SOC_NRF5340_CPUAPP) && defined(PM_CPUNET_B0N_ADDRESS) + /* If the update is valid, and it targets the network core: perform the + * update and indicate to the caller of this function that no update is + * available + */ + if (upgrade_valid && reset_addr > PM_CPUNET_B0N_ADDRESS) { + uint32_t fw_size = hdr->ih_img_size; + + BOOT_LOG_INF("Starting network core update"); + int rc = pcd_network_core_update(vtable, fw_size); + + if (rc != 0) { + swap_type = BOOT_SWAP_TYPE_FAIL; + } else { + BOOT_LOG_INF("Done updating network core"); +#if defined(MCUBOOT_SWAP_USING_SCRATCH) || defined(MCUBOOT_SWAP_USING_MOVE) + /* swap_erase_trailer_sectors is undefined if upgrade only + * method is used. There is no need to erase sectors, because + * the image cannot be reverted. + */ + rc = swap_erase_trailer_sectors(state, + secondary_fa); +#endif + swap_type = BOOT_SWAP_TYPE_NONE; + } } +#endif /* CONFIG_SOC_NRF5340_CPUAPP */ } return swap_type; diff --git a/boot/zephyr/boards/thingy53_nrf5340_cpuapp.conf b/boot/zephyr/boards/thingy53_nrf5340_cpuapp.conf index f2e42fd64..93be36738 100644 --- a/boot/zephyr/boards/thingy53_nrf5340_cpuapp.conf +++ b/boot/zephyr/boards/thingy53_nrf5340_cpuapp.conf @@ -1,3 +1,73 @@ -CONFIG_NORDIC_QSPI_NOR=n -CONFIG_SPI=n +CONFIG_SIZE_OPTIMIZATIONS=y + +CONFIG_SYSTEM_CLOCK_NO_WAIT=y +CONFIG_PM=n + +CONFIG_MAIN_STACK_SIZE=10240 +CONFIG_MBEDTLS_CFG_FILE="mcuboot-mbedtls-cfg.h" + +CONFIG_BOOT_MAX_IMG_SECTORS=2048 +CONFIG_BOOT_SIGNATURE_TYPE_RSA=y + +# Flash +CONFIG_FLASH=y +CONFIG_BOOT_ERASE_PROGRESSIVELY=y +CONFIG_SOC_FLASH_NRF_EMULATE_ONE_BYTE_WRITE_ACCESS=y +CONFIG_FPROTECT=y + +# Serial +CONFIG_SERIAL=y +CONFIG_UART_LINE_CTRL=y + +# MCUBoot serial +CONFIG_GPIO=y +CONFIG_MCUBOOT_SERIAL=y +CONFIG_MCUBOOT_SERIAL_DIRECT_IMAGE_UPLOAD=y +CONFIG_BOOT_SERIAL_CDC_ACM=y + +# Required by QSPI +CONFIG_NORDIC_QSPI_NOR=y +CONFIG_NORDIC_QSPI_NOR_FLASH_LAYOUT_PAGE_SIZE=4096 +CONFIG_NORDIC_QSPI_NOR_STACK_WRITE_BUFFER_SIZE=16 + +# Required by USB CONFIG_MULTITHREADING=y + +# USB +CONFIG_BOARD_SERIAL_BACKEND_CDC_ACM=n +CONFIG_USB_DEVICE_REMOTE_WAKEUP=n +CONFIG_USB_DEVICE_MANUFACTURER="Nordic Semiconductor ASA" +CONFIG_USB_DEVICE_PRODUCT="Bootloader Thingy:53" +CONFIG_USB_DEVICE_VID=0x1915 +CONFIG_USB_DEVICE_PID=0x5300 +CONFIG_USB_CDC_ACM=y + +# Decrease memory footprint +CONFIG_CBPRINTF_NANO=y +CONFIG_TIMESLICING=n +CONFIG_BOOT_BANNER=n +CONFIG_CONSOLE=n +CONFIG_CONSOLE_HANDLER=n +CONFIG_UART_CONSOLE=n +CONFIG_USE_SEGGER_RTT=n +CONFIG_LOG=n +CONFIG_ERRNO=n +CONFIG_PRINTK=n +CONFIG_RESET_ON_FATAL_ERROR=n +CONFIG_SPI=n +CONFIG_I2C=n +CONFIG_UART_NRFX=n + +# The following configurations are required to support simultaneous multi image update +CONFIG_PCD_APP=y +CONFIG_UPDATEABLE_IMAGE_NUMBER=2 +CONFIG_BOOT_UPGRADE_ONLY=y +# The network core cannot access external flash directly. The flash simulator must be used to +# provide a memory region that is used to forward the new firmware to the network core. +CONFIG_FLASH_SIMULATOR=y +CONFIG_FLASH_SIMULATOR_DOUBLE_WRITES=y +CONFIG_FLASH_SIMULATOR_STATS=n + +# Enable custom command to erase settings partition. +CONFIG_ENABLE_MGMT_PERUSER=y +CONFIG_BOOT_MGMT_CUSTOM_STORAGE_ERASE=y diff --git a/boot/zephyr/include/sysflash/sysflash.h b/boot/zephyr/include/sysflash/sysflash.h index 99cbf56b7..7112f9baa 100644 --- a/boot/zephyr/include/sysflash/sysflash.h +++ b/boot/zephyr/include/sysflash/sysflash.h @@ -20,6 +20,11 @@ #elif (MCUBOOT_IMAGE_NUMBER == 2) +/* If B0 is present then two bootloaders are present, and we must use + * a single secondary slot for both primary slots. + */ +#ifdef PM_B0_ADDRESS + extern uint32_t _image_1_primary_slot_id[]; #define FLASH_AREA_IMAGE_PRIMARY(x) \ @@ -35,6 +40,24 @@ extern uint32_t _image_1_primary_slot_id[]; (x == 1) ? \ PM_MCUBOOT_SECONDARY_ID: \ 255 ) +#else + +#define FLASH_AREA_IMAGE_PRIMARY(x) \ + ((x == 0) ? \ + PM_MCUBOOT_PRIMARY_ID : \ + (x == 1) ? \ + PM_MCUBOOT_PRIMARY_1_ID : \ + 255 ) + +#define FLASH_AREA_IMAGE_SECONDARY(x) \ + ((x == 0) ? \ + PM_MCUBOOT_SECONDARY_ID: \ + (x == 1) ? \ + PM_MCUBOOT_SECONDARY_1_ID: \ + 255 ) + +#endif /* PM_B0_ADDRESS */ + #endif #define FLASH_AREA_IMAGE_SCRATCH PM_MCUBOOT_SCRATCH_ID diff --git a/boot/zephyr/main.c b/boot/zephyr/main.c index e9a4e20b0..b41a9c4d4 100644 --- a/boot/zephyr/main.c +++ b/boot/zephyr/main.c @@ -98,8 +98,26 @@ const struct boot_uart_funcs boot_funcs = { #include #endif -#if defined(CONFIG_LOG) && !defined(CONFIG_LOG_MODE_IMMEDIATE) && \ - !defined(CONFIG_LOG_MODE_MINIMAL) +#if defined(CONFIG_SOC_NRF5340_CPUAPP) && defined(PM_CPUNET_B0N_ADDRESS) && defined(CONFIG_PCD_APP) +#include +#endif + +/* CONFIG_LOG_MINIMAL is the legacy Kconfig property, + * replaced by CONFIG_LOG_MODE_MINIMAL. + */ +#if (defined(CONFIG_LOG_MODE_MINIMAL) || defined(CONFIG_LOG_MINIMAL)) +#define ZEPHYR_LOG_MODE_MINIMAL 1 +#endif + +/* CONFIG_LOG_IMMEDIATE is the legacy Kconfig property, + * replaced by CONFIG_LOG_MODE_IMMEDIATE. + */ +#if (defined(CONFIG_LOG_MODE_IMMEDIATE) || defined(CONFIG_LOG_IMMEDIATE)) +#define ZEPHYR_LOG_MODE_IMMEDIATE 1 +#endif + +#if defined(CONFIG_LOG) && !defined(ZEPHYR_LOG_MODE_IMMEDIATE) && \ + !defined(ZEPHYR_LOG_MODE_MINIMAL) #ifdef CONFIG_LOG_PROCESS_THREAD #warning "The log internal thread for log processing can't transfer the log"\ "well for MCUBoot." @@ -716,6 +734,9 @@ int main(void) ; } +#if defined(CONFIG_SOC_NRF5340_CPUAPP) && defined(PM_CPUNET_B0N_ADDRESS) && defined(CONFIG_PCD_APP) + pcd_lock_ram(); +#endif #endif /* USE_PARTITION_MANAGER && CONFIG_FPROTECT */ ZEPHYR_BOOT_LOG_STOP(); diff --git a/boot/zephyr/pm.yml b/boot/zephyr/pm.yml index 5df9ae547..13ffc44aa 100644 --- a/boot/zephyr/pm.yml +++ b/boot/zephyr/pm.yml @@ -75,3 +75,16 @@ mcuboot_pad: #ifdef CONFIG_FPROTECT align: {start: CONFIG_FPROTECT_BLOCK_SIZE} #endif + +#if (CONFIG_NRF53_MCUBOOT_PRIMARY_1_RAM_FLASH) +mcuboot_primary_1: + region: ram_flash + size: CONFIG_NRF53_RAM_FLASH_SIZE +#endif /* CONFIG_NRF53_MULTI_IMAGE_UPDATE */ + +#if (CONFIG_NRF53_MULTI_IMAGE_UPDATE) +mcuboot_secondary_1: + region: external_flash + size: CONFIG_NRF53_RAM_FLASH_SIZE + +#endif /* CONFIG_NRF53_MULTI_IMAGE_UPDATE */ From d6a003b8ebce039fb9bff4e8571cc59f159aa4a4 Mon Sep 17 00:00:00 2001 From: Andrzej Puzdrowski Date: Thu, 27 Feb 2020 12:48:56 +0100 Subject: [PATCH 291/420] [nrf noup] zephyr: clean peripherals state before boot MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Do some cleanup of nRF peripherals. This is necessary since Zephyr doesn't have any driver deinitialization functionality, and we'd like to leave peripherals in a more predictable state before booting the Zephyr image. This should be re-worked when the zephyr driver model allows us to deinitialize devices cleanly before jumping to the chain-loaded image. Signed-off-by: Andrzej Puzdrowski Signed-off-by: Robert Lubos Signed-off-by: Torsten Rasmussen Signed-off-by: Øyvind Rønningstad Signed-off-by: Martí Bolívar Signed-off-by: Håkon Øye Amundsen Signed-off-by: Ioannis Glaropoulos Signed-off-by: Johann Fischer Signed-off-by: Trond Einar Snekvik Signed-off-by: Torsten Rasmussen Signed-off-by: Jamie McCrae Signed-off-by: Dominik Ermel (cherry picked from commit 0f2061be7ecee80c2b2c6772efc719415e89b880) --- boot/zephyr/CMakeLists.txt | 6 +++ boot/zephyr/include/nrf_cleanup.h | 19 +++++++ boot/zephyr/main.c | 8 ++- boot/zephyr/nrf_cleanup.c | 83 +++++++++++++++++++++++++++++++ 4 files changed, 115 insertions(+), 1 deletion(-) create mode 100644 boot/zephyr/include/nrf_cleanup.h create mode 100644 boot/zephyr/nrf_cleanup.c diff --git a/boot/zephyr/CMakeLists.txt b/boot/zephyr/CMakeLists.txt index b6833bd62..513125b0c 100644 --- a/boot/zephyr/CMakeLists.txt +++ b/boot/zephyr/CMakeLists.txt @@ -734,3 +734,9 @@ if(SYSBUILD) set(mcuboot_image_footer_size ${required_size} CACHE INTERNAL "Estimated MCUboot image trailer size" FORCE) set(mcuboot_image_upgrade_footer_size ${required_upgrade_size} CACHE INTERNAL "Estimated MCUboot update image trailer size" FORCE) endif() + +if(CONFIG_MCUBOOT_NRF_CLEANUP_PERIPHERAL) +zephyr_library_sources( + ${BOOT_DIR}/zephyr/nrf_cleanup.c +) +endif() diff --git a/boot/zephyr/include/nrf_cleanup.h b/boot/zephyr/include/nrf_cleanup.h new file mode 100644 index 000000000..6b04cedfe --- /dev/null +++ b/boot/zephyr/include/nrf_cleanup.h @@ -0,0 +1,19 @@ +/* + * Copyright (c) 2020 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: LicenseRef-Nordic-5-Clause + */ + +#ifndef H_NRF_CLEANUP_ +#define H_NRF_CLEANUP_ + +/** + * Perform cleanup on some peripheral resources used by MCUBoot prior chainload + * the application. + * + * This function disables all RTC instances and UARTE instances. + * It Disables their interrupts signals as well. + */ +void nrf_cleanup_peripheral(void); + +#endif diff --git a/boot/zephyr/main.c b/boot/zephyr/main.c index b41a9c4d4..2f39bbabe 100644 --- a/boot/zephyr/main.c +++ b/boot/zephyr/main.c @@ -149,6 +149,10 @@ K_SEM_DEFINE(boot_log_sem, 1, 1); #include #endif +#if CONFIG_MCUBOOT_NRF_CLEANUP_PERIPHERAL +#include +#endif + BOOT_LOG_MODULE_REGISTER(mcuboot); void os_heap_init(void); @@ -223,7 +227,9 @@ static void do_boot(struct boot_rsp *rsp) } #endif #endif - +#if CONFIG_MCUBOOT_NRF_CLEANUP_PERIPHERAL + nrf_cleanup_peripheral(); +#endif #if CONFIG_MCUBOOT_CLEANUP_ARM_CORE cleanup_arm_interrupts(); /* Disable and acknowledge all interrupts */ diff --git a/boot/zephyr/nrf_cleanup.c b/boot/zephyr/nrf_cleanup.c new file mode 100644 index 000000000..5bab26b24 --- /dev/null +++ b/boot/zephyr/nrf_cleanup.c @@ -0,0 +1,83 @@ +/* + * Copyright (c) 2020 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: LicenseRef-Nordic-5-Clause + */ + +#include +#if defined(NRF_UARTE0) || defined(NRF_UARTE1) + #include +#endif +#if defined(NRF_RTC0) || defined(NRF_RTC1) || defined(NRF_RTC2) + #include +#endif +#if defined(NRF_PPI) + #include +#endif +#if defined(NRF_DPPIC) + #include +#endif + +#include + +#define NRF_UARTE_SUBSCRIBE_CONF_OFFS offsetof(NRF_UARTE_Type, SUBSCRIBE_STARTRX) +#define NRF_UARTE_SUBSCRIBE_CONF_SIZE (offsetof(NRF_UARTE_Type, EVENTS_CTS) -\ + NRF_UARTE_SUBSCRIBE_CONF_OFFS) + +#define NRF_UARTE_PUBLISH_CONF_OFFS offsetof(NRF_UARTE_Type, PUBLISH_CTS) +#define NRF_UARTE_PUBLISH_CONF_SIZE (offsetof(NRF_UARTE_Type, SHORTS) -\ + NRF_UARTE_PUBLISH_CONF_OFFS) + +#if defined(NRF_RTC0) || defined(NRF_RTC1) || defined(NRF_RTC2) +static inline void nrf_cleanup_rtc(NRF_RTC_Type * rtc_reg) +{ + nrf_rtc_task_trigger(rtc_reg, NRF_RTC_TASK_STOP); + nrf_rtc_event_disable(rtc_reg, 0xFFFFFFFF); + nrf_rtc_int_disable(rtc_reg, 0xFFFFFFFF); +} +#endif + +static void nrf_cleanup_clock(void) +{ + nrf_clock_int_disable(NRF_CLOCK, 0xFFFFFFFF); +} + +void nrf_cleanup_peripheral(void) +{ +#if defined(NRF_RTC0) + nrf_cleanup_rtc(NRF_RTC0); +#endif +#if defined(NRF_RTC1) + nrf_cleanup_rtc(NRF_RTC1); +#endif +#if defined(NRF_RTC2) + nrf_cleanup_rtc(NRF_RTC2); +#endif +#if defined(NRF_UARTE0) + nrf_uarte_disable(NRF_UARTE0); + nrf_uarte_int_disable(NRF_UARTE0, 0xFFFFFFFF); +#if defined(NRF_DPPIC) + /* Clear all SUBSCRIBE configurations. */ + memset((uint8_t *)NRF_UARTE0 + NRF_UARTE_SUBSCRIBE_CONF_OFFS, 0, NRF_UARTE_SUBSCRIBE_CONF_SIZE); + /* Clear all PUBLISH configurations. */ + memset((uint8_t *)NRF_UARTE0 + NRF_UARTE_PUBLISH_CONF_OFFS, 0, NRF_UARTE_PUBLISH_CONF_SIZE); +#endif +#endif +#if defined(NRF_UARTE1) + nrf_uarte_disable(NRF_UARTE1); + nrf_uarte_int_disable(NRF_UARTE1, 0xFFFFFFFF); +#if defined(NRF_DPPIC) + /* Clear all SUBSCRIBE configurations. */ + memset((uint8_t *)NRF_UARTE1 + NRF_UARTE_SUBSCRIBE_CONF_OFFS, 0, NRF_UARTE_SUBSCRIBE_CONF_SIZE); + /* Clear all PUBLISH configurations. */ + memset((uint8_t *)NRF_UARTE1 + NRF_UARTE_PUBLISH_CONF_OFFS, 0, NRF_UARTE_PUBLISH_CONF_SIZE); +#endif +#endif +#if defined(NRF_PPI) + nrf_ppi_channels_disable_all(NRF_PPI); +#endif +#if defined(NRF_DPPIC) + nrf_dppi_channels_disable_all(NRF_DPPIC); +#endif + nrf_cleanup_clock(); +} From 92da561256d98db5ca2cf07078469d9681c1d4de Mon Sep 17 00:00:00 2001 From: Sigvart Hovland Date: Fri, 6 Jan 2023 12:24:48 +0100 Subject: [PATCH 292/420] [nrf noup] zephyr: Clean up non-secure RAM if enabled MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit To ensure that MCUBoot does not leak keys or other material through memory to non-secure side we clear the memory before jumping to the next image. Signed-off-by: Sigvart Hovland Signed-off-by: Dominik Ermel Signed-off-by: Ole Sæther (cherry picked from commit c9f632d1ddd6774e750577a83b562f5b739249fc) --- boot/zephyr/CMakeLists.txt | 2 +- boot/zephyr/include/nrf_cleanup.h | 5 ++ boot/zephyr/main.c | 5 +- boot/zephyr/nrf_cleanup.c | 79 +++++++++++++++++++++++-------- 4 files changed, 69 insertions(+), 22 deletions(-) diff --git a/boot/zephyr/CMakeLists.txt b/boot/zephyr/CMakeLists.txt index 513125b0c..a9a869921 100644 --- a/boot/zephyr/CMakeLists.txt +++ b/boot/zephyr/CMakeLists.txt @@ -735,7 +735,7 @@ if(SYSBUILD) set(mcuboot_image_upgrade_footer_size ${required_upgrade_size} CACHE INTERNAL "Estimated MCUboot update image trailer size" FORCE) endif() -if(CONFIG_MCUBOOT_NRF_CLEANUP_PERIPHERAL) +if(CONFIG_MCUBOOT_NRF_CLEANUP_PERIPHERAL OR CONFIG_MCUBOOT_CLEANUP_NONSECURE_RAM) zephyr_library_sources( ${BOOT_DIR}/zephyr/nrf_cleanup.c ) diff --git a/boot/zephyr/include/nrf_cleanup.h b/boot/zephyr/include/nrf_cleanup.h index 6b04cedfe..9e87e13f5 100644 --- a/boot/zephyr/include/nrf_cleanup.h +++ b/boot/zephyr/include/nrf_cleanup.h @@ -16,4 +16,9 @@ */ void nrf_cleanup_peripheral(void); +/** + * Perform cleanup of non-secure RAM that may have been used by MCUBoot. + */ +void nrf_cleanup_ns_ram(void); + #endif diff --git a/boot/zephyr/main.c b/boot/zephyr/main.c index 2f39bbabe..71ec93775 100644 --- a/boot/zephyr/main.c +++ b/boot/zephyr/main.c @@ -149,7 +149,7 @@ K_SEM_DEFINE(boot_log_sem, 1, 1); #include #endif -#if CONFIG_MCUBOOT_NRF_CLEANUP_PERIPHERAL +#if CONFIG_MCUBOOT_NRF_CLEANUP_PERIPHERAL || CONFIG_MCUBOOT_NRF_CLEANUP_NONSECURE_RAM #include #endif @@ -230,6 +230,9 @@ static void do_boot(struct boot_rsp *rsp) #if CONFIG_MCUBOOT_NRF_CLEANUP_PERIPHERAL nrf_cleanup_peripheral(); #endif +#if CONFIG_MCUBOOT_NRF_CLEANUP_NONSECURE_RAM && defined(PM_SRAM_NONSECURE_NAME) + nrf_cleanup_ns_ram(); +#endif #if CONFIG_MCUBOOT_CLEANUP_ARM_CORE cleanup_arm_interrupts(); /* Disable and acknowledge all interrupts */ diff --git a/boot/zephyr/nrf_cleanup.c b/boot/zephyr/nrf_cleanup.c index 5bab26b24..051705ec9 100644 --- a/boot/zephyr/nrf_cleanup.c +++ b/boot/zephyr/nrf_cleanup.c @@ -5,9 +5,8 @@ */ #include -#if defined(NRF_UARTE0) || defined(NRF_UARTE1) - #include -#endif +#include +#include #if defined(NRF_RTC0) || defined(NRF_RTC1) || defined(NRF_RTC2) #include #endif @@ -20,6 +19,15 @@ #include +#if USE_PARTITION_MANAGER +#include +#endif + +#if defined(NRF_UARTE0) || defined(NRF_UARTE1) || defined(NRF_UARTE20) || \ + defined(NRF_UARTE30) +#define NRF_UARTE_CLEANUP +#endif + #define NRF_UARTE_SUBSCRIBE_CONF_OFFS offsetof(NRF_UARTE_Type, SUBSCRIBE_STARTRX) #define NRF_UARTE_SUBSCRIBE_CONF_SIZE (offsetof(NRF_UARTE_Type, EVENTS_CTS) -\ NRF_UARTE_SUBSCRIBE_CONF_OFFS) @@ -37,6 +45,23 @@ static inline void nrf_cleanup_rtc(NRF_RTC_Type * rtc_reg) } #endif +#if defined(NRF_UARTE_CLEANUP) +static NRF_UARTE_Type *nrf_uarte_to_clean[] = { +#if defined(NRF_UARTE0) + NRF_UARTE0, +#endif +#if defined(NRF_UARTE1) + NRF_UARTE1, +#endif +#if defined(NRF_UARTE20) + NRF_UARTE20, +#endif +#if defined(NRF_UARTE30) + NRF_UARTE30, +#endif +}; +#endif + static void nrf_cleanup_clock(void) { nrf_clock_int_disable(NRF_CLOCK, 0xFFFFFFFF); @@ -53,26 +78,31 @@ void nrf_cleanup_peripheral(void) #if defined(NRF_RTC2) nrf_cleanup_rtc(NRF_RTC2); #endif -#if defined(NRF_UARTE0) - nrf_uarte_disable(NRF_UARTE0); - nrf_uarte_int_disable(NRF_UARTE0, 0xFFFFFFFF); -#if defined(NRF_DPPIC) - /* Clear all SUBSCRIBE configurations. */ - memset((uint8_t *)NRF_UARTE0 + NRF_UARTE_SUBSCRIBE_CONF_OFFS, 0, NRF_UARTE_SUBSCRIBE_CONF_SIZE); - /* Clear all PUBLISH configurations. */ - memset((uint8_t *)NRF_UARTE0 + NRF_UARTE_PUBLISH_CONF_OFFS, 0, NRF_UARTE_PUBLISH_CONF_SIZE); -#endif -#endif -#if defined(NRF_UARTE1) - nrf_uarte_disable(NRF_UARTE1); - nrf_uarte_int_disable(NRF_UARTE1, 0xFFFFFFFF); + +#if defined(NRF_UARTE_CLEANUP) + for (int i = 0; i < sizeof(nrf_uarte_to_clean) / sizeof(nrf_uarte_to_clean[0]); ++i) { + NRF_UARTE_Type *current = nrf_uarte_to_clean[i]; + + nrfy_uarte_int_disable(current, 0xFFFFFFFF); + nrfy_uarte_int_uninit(current); + nrfy_uarte_task_trigger(current, NRF_UARTE_TASK_STOPRX); + + nrfy_uarte_event_clear(current, NRF_UARTE_EVENT_RXSTARTED); + nrfy_uarte_event_clear(current, NRF_UARTE_EVENT_ENDRX); + nrfy_uarte_event_clear(current, NRF_UARTE_EVENT_RXTO); + nrfy_uarte_disable(current); + #if defined(NRF_DPPIC) - /* Clear all SUBSCRIBE configurations. */ - memset((uint8_t *)NRF_UARTE1 + NRF_UARTE_SUBSCRIBE_CONF_OFFS, 0, NRF_UARTE_SUBSCRIBE_CONF_SIZE); - /* Clear all PUBLISH configurations. */ - memset((uint8_t *)NRF_UARTE1 + NRF_UARTE_PUBLISH_CONF_OFFS, 0, NRF_UARTE_PUBLISH_CONF_SIZE); + /* Clear all SUBSCRIBE configurations. */ + memset((uint8_t *)current + NRF_UARTE_SUBSCRIBE_CONF_OFFS, 0, + NRF_UARTE_SUBSCRIBE_CONF_SIZE); + /* Clear all PUBLISH configurations. */ + memset((uint8_t *)current + NRF_UARTE_PUBLISH_CONF_OFFS, 0, + NRF_UARTE_PUBLISH_CONF_SIZE); #endif + } #endif + #if defined(NRF_PPI) nrf_ppi_channels_disable_all(NRF_PPI); #endif @@ -81,3 +111,12 @@ void nrf_cleanup_peripheral(void) #endif nrf_cleanup_clock(); } + +#if USE_PARTITION_MANAGER \ + && defined(CONFIG_ARM_TRUSTZONE_M) \ + && defined(PM_SRAM_NONSECURE_NAME) +void nrf_cleanup_ns_ram(void) +{ + memset((void *) PM_SRAM_NONSECURE_ADDRESS, 0, PM_SRAM_NONSECURE_SIZE); +} +#endif From f239be93f8ac5b71ea65140a30207b8923ffe606 Mon Sep 17 00:00:00 2001 From: Christian Taedcke Date: Thu, 10 Feb 2022 15:37:49 +0100 Subject: [PATCH 293/420] [nrf noup] loader: Fix reading reset addr to support ext flash MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit When mcuboot_secondary is on external flash, the image header cannot dircetly be accessed via secondary_fa->fa_off. Instead the provided function boot_img_hdr() is used now. Additionally a similar issue is present when trying to read the address of the reset handler. For this flash_area_read() is used now. With this patch is possible to have the update partiton mcuboot_secondary on external flash and update a updatable bootloader (mcuboot) in s0 and/or s1. Signed-off-by: Christian Taedcke Signed-off-by: Ole Sæther Signed-off-by: Sigvart Hovland Signed-off-by: Dominik Ermel (cherry picked from commit c1cf5e424057fea8a317bccd88dff62888453ccf) --- boot/bootutil/src/loader.c | 25 +++++++++++++++---------- 1 file changed, 15 insertions(+), 10 deletions(-) diff --git a/boot/bootutil/src/loader.c b/boot/bootutil/src/loader.c index 8938c387a..52bd1bfa0 100644 --- a/boot/bootutil/src/loader.c +++ b/boot/bootutil/src/loader.c @@ -1130,10 +1130,9 @@ boot_validated_swap_type(struct boot_loader_state *state, #if defined(PM_S1_ADDRESS) || defined(CONFIG_SOC_NRF5340_CPUAPP) const struct flash_area *secondary_fa = BOOT_IMG_AREA(state, BOOT_SECONDARY_SLOT); - struct image_header *hdr = (struct image_header *)secondary_fa->fa_off; - uint32_t vtable_addr = 0; - uint32_t *vtable = 0; + struct image_header *hdr = boot_img_hdr(state, BOOT_SECONDARY_SLOT); uint32_t reset_addr = 0; + int rc = 0; /* Patch needed for NCS. Since image 0 (the app) and image 1 (the other * B1 slot S0 or S1) share the same secondary slot, we need to check * whether the update candidate in the secondary slot is intended for @@ -1143,16 +1142,19 @@ boot_validated_swap_type(struct boot_loader_state *state, */ if (hdr->ih_magic == IMAGE_MAGIC) { - vtable_addr = (uint32_t)hdr + hdr->ih_hdr_size; - vtable = (uint32_t *)(vtable_addr); - reset_addr = vtable[1]; + rc = flash_area_read(secondary_fa, hdr->ih_hdr_size + + sizeof(uint32_t), &reset_addr, + sizeof(reset_addr)); + if (rc != 0) { + return BOOT_SWAP_TYPE_FAIL; + } #ifdef PM_S1_ADDRESS #ifdef PM_CPUNET_B0N_ADDRESS if(reset_addr < PM_CPUNET_B0N_ADDRESS) #endif { const struct flash_area *primary_fa; - int rc = flash_area_open(flash_area_id_from_multi_image_slot( + rc = flash_area_open(flash_area_id_from_multi_image_slot( BOOT_CURR_IMG(state), BOOT_PRIMARY_SLOT), &primary_fa); @@ -1188,16 +1190,19 @@ boot_validated_swap_type(struct boot_loader_state *state, upgrade_valid = true; } -#if defined(CONFIG_SOC_NRF5340_CPUAPP) && defined(PM_CPUNET_B0N_ADDRESS) +#if defined(CONFIG_SOC_NRF5340_CPUAPP) && defined(PM_CPUNET_B0N_ADDRESS) \ + && !defined(CONFIG_NRF53_MULTI_IMAGE_UPDATE) /* If the update is valid, and it targets the network core: perform the * update and indicate to the caller of this function that no update is * available */ if (upgrade_valid && reset_addr > PM_CPUNET_B0N_ADDRESS) { + struct image_header *hdr = (struct image_header *)secondary_fa->fa_off; + uint32_t vtable_addr = (uint32_t)hdr + hdr->ih_hdr_size; + uint32_t *net_core_fw_addr = (uint32_t *)(vtable_addr); uint32_t fw_size = hdr->ih_img_size; - BOOT_LOG_INF("Starting network core update"); - int rc = pcd_network_core_update(vtable, fw_size); + rc = pcd_network_core_update(net_core_fw_addr, fw_size); if (rc != 0) { swap_type = BOOT_SWAP_TYPE_FAIL; From 99de74982aaef827e0fb0e8179f2f74d02230d8a Mon Sep 17 00:00:00 2001 From: Dominik Ermel Date: Fri, 22 Sep 2023 21:31:08 +0000 Subject: [PATCH 294/420] [nrf noup] loader: Do not check reset vector for XIP image The XIP image, 2, does not have reset vector. Signed-off-by: Dominik Ermel (cherry picked from commit 1e991723c85e8ef8d6df432f196ec75c89caf78c) (cherry picked from commit 1ec17e963cb21d6978792e2aaf504838f20b52d8) --- boot/bootutil/src/loader.c | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/boot/bootutil/src/loader.c b/boot/bootutil/src/loader.c index 52bd1bfa0..a34401961 100644 --- a/boot/bootutil/src/loader.c +++ b/boot/bootutil/src/loader.c @@ -1021,8 +1021,18 @@ boot_validate_slot(struct boot_loader_state *state, int slot, * overwriting an application written to the incorrect slot. * This feature is only supported by ARM platforms. */ - if (fap == BOOT_IMG_AREA(state, BOOT_SLOT_SECONDARY)) { - const struct flash_area *pri_fa = BOOT_IMG_AREA(state, BOOT_SLOT_PRIMARY); +#if MCUBOOT_IMAGE_NUMBER >= 3 + /* Currently the MCUboot can be configured for up to 3 image, where image number 2 is + * designated for XIP, where it is the second part of image stored in slots of image + * 0. This part of image is not bootable, as the XIP setup is done by the app in + * image 0 slot, and it does not carry the reset vector. + */ + if (fap == state->imgs[2][BOOT_SECONDARY_SLOT].area) { + goto out; + } +#endif + if (fap == BOOT_IMG_AREA(state, BOOT_SECONDARY_SLOT)) { + const struct flash_area *pri_fa = BOOT_IMG_AREA(state, BOOT_PRIMARY_SLOT); struct image_header *secondary_hdr = boot_img_hdr(state, slot); uint32_t reset_value = 0; uint32_t reset_addr = secondary_hdr->ih_hdr_size + sizeof(reset_value); From 6512a0366e3d68a3a59fbc3ccd943e85dc98ae2a Mon Sep 17 00:00:00 2001 From: Jamie McCrae Date: Mon, 18 Sep 2023 13:47:00 +0100 Subject: [PATCH 295/420] [nrf noup] zephyr: Add RAM flash configuration to cache for sysbuild Puts the flash simulation configurtion into cache variables that can be used by other applications and CMake code to know specifics on the simulated flash details Signed-off-by: Jamie McCrae (cherry picked from commit c8d8f5a48cf1f17bad6cbc41dfd83a5f584ab005) --- boot/zephyr/CMakeLists.txt | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/boot/zephyr/CMakeLists.txt b/boot/zephyr/CMakeLists.txt index a9a869921..f781da7ef 100644 --- a/boot/zephyr/CMakeLists.txt +++ b/boot/zephyr/CMakeLists.txt @@ -740,3 +740,14 @@ zephyr_library_sources( ${BOOT_DIR}/zephyr/nrf_cleanup.c ) endif() + +if(SYSBUILD AND CONFIG_PCD_APP) + # Sysbuild requires details of the RAM flash device are stored to the cache of MCUboot so + # that they can be read when running partition manager + dt_nodelabel(ram_flash_dev NODELABEL flash_sim0) + dt_reg_addr(ram_flash_addr PATH ${ram_flash_dev}) + dt_reg_size(ram_flash_size PATH ${ram_flash_dev}) + + set(RAM_FLASH_ADDR "${ram_flash_addr}" CACHE STRING "" FORCE) + set(RAM_FLASH_SIZE "${ram_flash_size}" CACHE STRING "" FORCE) +endif() From 0f20d8ef9909c6c508024d9ea04bcfaaf4929dc5 Mon Sep 17 00:00:00 2001 From: Sigvart Hovland Date: Tue, 17 Oct 2023 11:28:09 +0200 Subject: [PATCH 296/420] [nrf noup] zephyr: Boot even if EXT_ABI is not provided This removes the `return;` to ensure that the application is booted even if EXT_ABI is not provided to the application because it does not include `FW_INFO`. Added a bit more description to the error messages when FW_INFO is not found and EXT_ABI is not able to be provided to the next image. Ref. NCSDK-24132 Signed-off-by: Sigvart Hovland (cherry picked from commit d07555bf0439aeec7c15609c46a85a06fa9be807) --- boot/zephyr/main.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/boot/zephyr/main.c b/boot/zephyr/main.c index 71ec93775..bbc7abe97 100644 --- a/boot/zephyr/main.c +++ b/boot/zephyr/main.c @@ -217,13 +217,16 @@ static void do_boot(struct boot_rsp *rsp) #endif #if defined(CONFIG_FW_INFO) && !defined(CONFIG_EXT_API_PROVIDE_EXT_API_UNUSED) - bool provided = fw_info_ext_api_provide(fw_info_find((uint32_t)vt), true); + const struct fw_info *firmware_info = fw_info_find((uint32_t) vt); + bool provided = fw_info_ext_api_provide(firmware_info, true); #ifdef PM_S0_ADDRESS /* Only fail if the immutable bootloader is present. */ if (!provided) { - BOOT_LOG_ERR("Failed to provide EXT_APIs\n"); - return; + if (firmware_info == NULL) { + BOOT_LOG_WRN("Unable to find firmware info structure in %p", vt); + } + BOOT_LOG_ERR("Failed to provide EXT_APIs to %p", vt); } #endif #endif From d1c8f64803b71430c49329cbf6171a76c545ff6d Mon Sep 17 00:00:00 2001 From: Sigvart Hovland Date: Wed, 27 Sep 2023 15:18:04 +0200 Subject: [PATCH 297/420] =?UTF-8?q?[nrf=20noup]=C2=A0loader:=20Add=20firmw?= =?UTF-8?q?are=20version=20check=20downgrade=20prevention?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit For nRF53, the only existing version number metadata is stored in the `firmware_info` structure in the network core. This utilizes PCD to read out the version number and compares it against the version number found in the secondary slot for the network core. Ref. NCSDK-21379 Signed-off-by: Sigvart Hovland (cherry picked from commit 42e8551d6bdcb50388ab7aac51d44aa12cf8ef55) (cherry picked from commit 420ac794db054e9a3bae31c6627d5b08920de0ed) --- boot/bootutil/src/loader.c | 24 ++++++++++++++++++++---- 1 file changed, 20 insertions(+), 4 deletions(-) diff --git a/boot/bootutil/src/loader.c b/boot/bootutil/src/loader.c index a34401961..f2c016399 100644 --- a/boot/bootutil/src/loader.c +++ b/boot/bootutil/src/loader.c @@ -52,6 +52,10 @@ #if defined(CONFIG_SOC_NRF5340_CPUAPP) && defined(PM_CPUNET_B0N_ADDRESS) && defined(CONFIG_PCD_APP) #include +#ifdef CONFIG_PCD_READ_NETCORE_APP_VERSION +#include +int pcd_version_cmp_net(const struct flash_area *fap, struct image_header *hdr); +#endif #endif #ifdef MCUBOOT_ENC_IMAGES @@ -974,10 +978,22 @@ boot_validate_slot(struct boot_loader_state *state, int slot, int rc; /* Check if version of secondary slot is sufficient */ - rc = boot_version_cmp( - &boot_img_hdr(state, BOOT_SLOT_SECONDARY)->ih_ver, - &boot_img_hdr(state, BOOT_SLOT_PRIMARY)->ih_ver); - if (rc < 0 && boot_check_header_erased(state, BOOT_SLOT_PRIMARY)) { + +#if defined(CONFIG_SOC_NRF5340_CPUAPP) && defined(CONFIG_NRF53_MULTI_IMAGE_UPDATE) \ + && defined(CONFIG_PCD_APP) && defined(CONFIG_PCD_READ_NETCORE_APP_VERSION) + if (BOOT_CURR_IMG(state) == 1) { + rc = pcd_version_cmp_net(fap, boot_img_hdr(state, BOOT_SECONDARY_SLOT)); + } else { + rc = boot_version_cmp( + &boot_img_hdr(state, BOOT_SECONDARY_SLOT)->ih_ver, + &boot_img_hdr(state, BOOT_PRIMARY_SLOT)->ih_ver); + } +#else + rc = boot_version_cmp( + &boot_img_hdr(state, BOOT_SECONDARY_SLOT)->ih_ver, + &boot_img_hdr(state, BOOT_PRIMARY_SLOT)->ih_ver); +#endif + if (rc < 0 && boot_check_header_erased(state, BOOT_PRIMARY_SLOT)) { BOOT_LOG_ERR("insufficient version in secondary slot"); boot_scramble_slot(fap, slot); /* Image in the secondary slot does not satisfy version requirement. From 2c695f49eec83510b9d3df473b20089497491185 Mon Sep 17 00:00:00 2001 From: Nikodem Kastelik Date: Mon, 9 Oct 2023 09:55:57 +0200 Subject: [PATCH 298/420] [nrf noup] boards: thingy53: disable GPIO ISR support Change disables GPIO interrupt support in Zephyr GPIO driver, which is not obligatory for MCUboot. This is needed to reduce memory footprint. Signed-off-by: Nikodem Kastelik (cherry picked from commit 937e0f6d566c43d7b2445bd74b586ef28fb64aff) --- boot/zephyr/boards/thingy53_nrf5340_cpuapp.conf | 1 + 1 file changed, 1 insertion(+) diff --git a/boot/zephyr/boards/thingy53_nrf5340_cpuapp.conf b/boot/zephyr/boards/thingy53_nrf5340_cpuapp.conf index 93be36738..d68509786 100644 --- a/boot/zephyr/boards/thingy53_nrf5340_cpuapp.conf +++ b/boot/zephyr/boards/thingy53_nrf5340_cpuapp.conf @@ -21,6 +21,7 @@ CONFIG_UART_LINE_CTRL=y # MCUBoot serial CONFIG_GPIO=y +CONFIG_GPIO_NRFX_INTERRUPT=n CONFIG_MCUBOOT_SERIAL=y CONFIG_MCUBOOT_SERIAL_DIRECT_IMAGE_UPLOAD=y CONFIG_BOOT_SERIAL_CDC_ACM=y From 9a33626249ce5e852e9ec3458f1912a20032aa11 Mon Sep 17 00:00:00 2001 From: Sigvart Hovland Date: Tue, 30 Mar 2021 22:45:17 +0200 Subject: [PATCH 299/420] [nrf noup] loader: work-around for multi-image builds Seems multi-image dependencies are not supported for multi-image in NCS yet. This is a workaround which reverts some lines to restore previous MCUboot behavior, so that Immutable bootloader + MCUBoot type builds will work. Ref. NCSDK-8681 Signed-off-by: Sigvart Hovland (cherry picked from commit 470e7cb53980087f835c81eedd2b4c11180fde41) --- boot/bootutil/src/loader.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/boot/bootutil/src/loader.c b/boot/bootutil/src/loader.c index f2c016399..5766ccf28 100644 --- a/boot/bootutil/src/loader.c +++ b/boot/bootutil/src/loader.c @@ -440,7 +440,7 @@ boot_verify_dependencies(struct boot_loader_state *state) if (rc == 0) { /* All dependencies've been satisfied, continue with next image. */ BOOT_CURR_IMG(state)++; - } else { + } else if (rc == BOOT_EBADIMAGE) { /* Cannot upgrade due to non-met dependencies, so disable all * image upgrades. */ @@ -449,7 +449,10 @@ boot_verify_dependencies(struct boot_loader_state *state) BOOT_SWAP_TYPE(state) = BOOT_SWAP_TYPE_NONE; } break; - } + } else { + /* Other error happened, images are inconsistent */ + return rc; + } } return rc; } From a23ae31a24f2f9f0bfda39386aa2cf8c364c135f Mon Sep 17 00:00:00 2001 From: Jamie McCrae Date: Thu, 31 Aug 2023 08:58:31 +0100 Subject: [PATCH 300/420] [nrf noup] loader: Fix missing PCD define check Fixes a missing PCD define check, an image might have the network core partition layout set but if PCD support is not enabled then it should not assume that PCD support is part of mcuboot. Signed-off-by: Jamie McCrae (cherry picked from commit 1ca64e93ce9f7484e9033989ff7dbfcacab0864b) --- boot/bootutil/src/loader.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/boot/bootutil/src/loader.c b/boot/bootutil/src/loader.c index 5766ccf28..9ab1aab98 100644 --- a/boot/bootutil/src/loader.c +++ b/boot/bootutil/src/loader.c @@ -1220,7 +1220,7 @@ boot_validated_swap_type(struct boot_loader_state *state, } #if defined(CONFIG_SOC_NRF5340_CPUAPP) && defined(PM_CPUNET_B0N_ADDRESS) \ - && !defined(CONFIG_NRF53_MULTI_IMAGE_UPDATE) + && !defined(CONFIG_NRF53_MULTI_IMAGE_UPDATE) && defined(CONFIG_PCD_APP) /* If the update is valid, and it targets the network core: perform the * update and indicate to the caller of this function that no update is * available @@ -1248,7 +1248,8 @@ boot_validated_swap_type(struct boot_loader_state *state, swap_type = BOOT_SWAP_TYPE_NONE; } } -#endif /* CONFIG_SOC_NRF5340_CPUAPP */ +#endif /* CONFIG_SOC_NRF5340_CPUAPP && PM_CPUNET_B0N_ADDRESS && + !CONFIG_NRF53_MULTI_IMAGE_UPDATE && CONFIG_PCD_APP */ } return swap_type; From 5cb4e7420b182677f120d302e71e3bd8c75f6646 Mon Sep 17 00:00:00 2001 From: Sigvart Hovland Date: Wed, 31 May 2023 14:41:13 +0200 Subject: [PATCH 301/420] [nrf noup] boot: Add support for NSIB and multi-image This adds support for using both NSIB and the multi-image configuration in MCUboot. Before this was not possible due to upgradable bootloader support through NSIB was using the `UPDATEABLE_IMAGE_NUMBER` configuration to update the updateable bootloader. In this commit we change from using `FLASH_AREA_IMAGE_PRIMARY` to get the flash area ID to using the bootloader state where we set the flash area ID of the free updatable bootloader slot if the image is intended for this slot. Ref. NCSDK-19223 Ref. NCSDK-23305 Signed-off-by: Sigvart Hovland (cherry picked from commit 75073fd88eca232c350c9a0af3c859815cb1ca4e) --- boot/bootutil/src/loader.c | 42 +++++++++++++++++++------ boot/zephyr/include/sysflash/sysflash.h | 19 +++++++++-- 2 files changed, 50 insertions(+), 11 deletions(-) diff --git a/boot/bootutil/src/loader.c b/boot/bootutil/src/loader.c index 9ab1aab98..71ecdfd37 100644 --- a/boot/bootutil/src/loader.c +++ b/boot/bootutil/src/loader.c @@ -1071,6 +1071,11 @@ boot_validate_slot(struct boot_loader_state *state, int slot, if (BOOT_CURR_IMG(state) == 1) { min_addr = PM_CPUNET_APP_ADDRESS; max_addr = PM_CPUNET_APP_ADDRESS + PM_CPUNET_APP_SIZE; +#ifdef PM_S1_ADDRESS + } else if (BOOT_CURR_IMG(state) == 0) { + min_addr = PM_S0_ADDRESS; + max_addr = pri_fa->fa_off + pri_fa->fa_size; +#endif } else #endif { @@ -1184,18 +1189,37 @@ boot_validated_swap_type(struct boot_loader_state *state, { const struct flash_area *primary_fa; rc = flash_area_open(flash_area_id_from_multi_image_slot( - BOOT_CURR_IMG(state), - BOOT_PRIMARY_SLOT), - &primary_fa); - + BOOT_CURR_IMG(state), BOOT_PRIMARY_SLOT), + &primary_fa); if (rc != 0) { return BOOT_SWAP_TYPE_FAIL; } - /* Get start and end of primary slot for current image */ - if (reset_addr < primary_fa->fa_off || - reset_addr > (primary_fa->fa_off + primary_fa->fa_size)) { - /* The image in the secondary slot is not intended for this image - */ + + /* Check start and end of primary slot for current image */ + if (reset_addr < primary_fa->fa_off) { +#if defined(CONFIG_SOC_NRF5340_CPUAPP) && defined(CONFIG_NRF53_MULTI_IMAGE_UPDATE) + const struct flash_area *nsib_fa; + + /* NSIB upgrade slot */ + rc = flash_area_open((uint32_t)_image_1_primary_slot_id, + &nsib_fa); + + if (rc != 0) { + return BOOT_SWAP_TYPE_FAIL; + } + + /* Image is placed before Primary and within the NSIB slot */ + if (reset_addr > nsib_fa->fa_off + && reset_addr < (nsib_fa->fa_off + nsib_fa->fa_size)) { + /* Set primary to be NSIB upgrade slot */ + BOOT_IMG_AREA(state, 0) = nsib_fa; + } +#else + return BOOT_SWAP_TYPE_NONE; +#endif + + } else if (reset_addr > (primary_fa->fa_off + primary_fa->fa_size)) { + /* The image in the secondary slot is not intended for any */ return BOOT_SWAP_TYPE_NONE; } } diff --git a/boot/zephyr/include/sysflash/sysflash.h b/boot/zephyr/include/sysflash/sysflash.h index 7112f9baa..f1ef4100e 100644 --- a/boot/zephyr/include/sysflash/sysflash.h +++ b/boot/zephyr/include/sysflash/sysflash.h @@ -23,9 +23,24 @@ /* If B0 is present then two bootloaders are present, and we must use * a single secondary slot for both primary slots. */ -#ifdef PM_B0_ADDRESS - +#if defined(PM_B0_ADDRESS) extern uint32_t _image_1_primary_slot_id[]; +#endif +#if defined(PM_B0_ADDRESS) && defined(CONFIG_NRF53_MULTI_IMAGE_UPDATE) +#define FLASH_AREA_IMAGE_PRIMARY(x) \ + ((x == 0) ? \ + PM_MCUBOOT_PRIMARY_ID : \ + (x == 1) ? \ + PM_MCUBOOT_PRIMARY_1_ID : \ + 255 ) + +#define FLASH_AREA_IMAGE_SECONDARY(x) \ + ((x == 0) ? \ + PM_MCUBOOT_SECONDARY_ID: \ + (x == 1) ? \ + PM_MCUBOOT_SECONDARY_1_ID: \ + 255 ) +#elif defined(PM_B0_ADDRESS) #define FLASH_AREA_IMAGE_PRIMARY(x) \ ((x == 0) ? \ From 2c2c2e559f4ae27ca4d3de06815b0e649405b27d Mon Sep 17 00:00:00 2001 From: Dominik Ermel Date: Thu, 10 Aug 2023 17:32:48 +0000 Subject: [PATCH 302/420] [nrf noup] sysflash: Move partition manager definitions to pm_sysflash.h Making sysflash.h and pm_sysflash.h more readable. Signed-off-by: Dominik Ermel (cherry picked from commit bc86df639008e27e8296b9253079944c689eacad) --- boot/zephyr/include/sysflash/pm_sysflash.h | 92 ++++++++++++++++++++++ boot/zephyr/include/sysflash/sysflash.h | 90 ++------------------- 2 files changed, 97 insertions(+), 85 deletions(-) create mode 100644 boot/zephyr/include/sysflash/pm_sysflash.h diff --git a/boot/zephyr/include/sysflash/pm_sysflash.h b/boot/zephyr/include/sysflash/pm_sysflash.h new file mode 100644 index 000000000..377291e8b --- /dev/null +++ b/boot/zephyr/include/sysflash/pm_sysflash.h @@ -0,0 +1,92 @@ +/* + * Copyright (c) 2023 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: LicenseRef-Nordic-5-Clause + */ + +#ifndef __PM_SYSFLASH_H__ +#define __PM_SYSFLASH_H__ +/* Blocking the __SYSFLASH_H__ */ +#define __SYSFLASH_H__ + +#include +#include + +#ifndef CONFIG_SINGLE_APPLICATION_SLOT + +#if (MCUBOOT_IMAGE_NUMBER == 1) + +#define FLASH_AREA_IMAGE_PRIMARY(x) PM_MCUBOOT_PRIMARY_ID +#define FLASH_AREA_IMAGE_SECONDARY(x) PM_MCUBOOT_SECONDARY_ID + +#elif (MCUBOOT_IMAGE_NUMBER == 2) + +/* If B0 is present then two bootloaders are present, and we must use + * a single secondary slot for both primary slots. + */ +#if defined(PM_B0_ADDRESS) +extern uint32_t _image_1_primary_slot_id[]; +#endif +#if defined(PM_B0_ADDRESS) && defined(CONFIG_NRF53_MULTI_IMAGE_UPDATE) +#define FLASH_AREA_IMAGE_PRIMARY(x) \ + ((x == 0) ? \ + PM_MCUBOOT_PRIMARY_ID : \ + (x == 1) ? \ + PM_MCUBOOT_PRIMARY_1_ID : \ + 255 ) + +#define FLASH_AREA_IMAGE_SECONDARY(x) \ + ((x == 0) ? \ + PM_MCUBOOT_SECONDARY_ID: \ + (x == 1) ? \ + PM_MCUBOOT_SECONDARY_1_ID: \ + 255 ) +#elif defined(PM_B0_ADDRESS) + +#define FLASH_AREA_IMAGE_PRIMARY(x) \ + ((x == 0) ? \ + PM_MCUBOOT_PRIMARY_ID : \ + (x == 1) ? \ + (uint32_t)_image_1_primary_slot_id : \ + 255 ) + +#define FLASH_AREA_IMAGE_SECONDARY(x) \ + ((x == 0) ? \ + PM_MCUBOOT_SECONDARY_ID: \ + (x == 1) ? \ + PM_MCUBOOT_SECONDARY_ID: \ + 255 ) +#else + +#define FLASH_AREA_IMAGE_PRIMARY(x) \ + ((x == 0) ? \ + PM_MCUBOOT_PRIMARY_ID : \ + (x == 1) ? \ + PM_MCUBOOT_PRIMARY_1_ID : \ + 255 ) + +#define FLASH_AREA_IMAGE_SECONDARY(x) \ + ((x == 0) ? \ + PM_MCUBOOT_SECONDARY_ID: \ + (x == 1) ? \ + PM_MCUBOOT_SECONDARY_1_ID: \ + 255 ) + +#endif /* PM_B0_ADDRESS */ + +#endif +#define FLASH_AREA_IMAGE_SCRATCH PM_MCUBOOT_SCRATCH_ID + +#else /* CONFIG_SINGLE_APPLICATION_SLOT */ + +#define FLASH_AREA_IMAGE_PRIMARY(x) PM_MCUBOOT_PRIMARY_ID +#define FLASH_AREA_IMAGE_SECONDARY(x) PM_MCUBOOT_PRIMARY_ID +/* NOTE: Scratch parition is not used by single image DFU but some of + * functions in common files reference it, so the definitions has been + * provided to allow compilation of common units. + */ +#define FLASH_AREA_IMAGE_SCRATCH 0 + +#endif /* CONFIG_SINGLE_APPLICATION_SLOT */ + +#endif /* __PM_SYSFLASH_H__ */ diff --git a/boot/zephyr/include/sysflash/sysflash.h b/boot/zephyr/include/sysflash/sysflash.h index f1ef4100e..3c3638d7f 100644 --- a/boot/zephyr/include/sysflash/sysflash.h +++ b/boot/zephyr/include/sysflash/sysflash.h @@ -4,93 +4,15 @@ * SPDX-License-Identifier: Apache-2.0 */ -#ifndef __SYSFLASH_H__ -#define __SYSFLASH_H__ - #if USE_PARTITION_MANAGER -#include -#include - -#ifndef CONFIG_SINGLE_APPLICATION_SLOT - -#if (MCUBOOT_IMAGE_NUMBER == 1) - -#define FLASH_AREA_IMAGE_PRIMARY(x) PM_MCUBOOT_PRIMARY_ID -#define FLASH_AREA_IMAGE_SECONDARY(x) PM_MCUBOOT_SECONDARY_ID - -#elif (MCUBOOT_IMAGE_NUMBER == 2) - -/* If B0 is present then two bootloaders are present, and we must use - * a single secondary slot for both primary slots. - */ -#if defined(PM_B0_ADDRESS) -extern uint32_t _image_1_primary_slot_id[]; -#endif -#if defined(PM_B0_ADDRESS) && defined(CONFIG_NRF53_MULTI_IMAGE_UPDATE) -#define FLASH_AREA_IMAGE_PRIMARY(x) \ - ((x == 0) ? \ - PM_MCUBOOT_PRIMARY_ID : \ - (x == 1) ? \ - PM_MCUBOOT_PRIMARY_1_ID : \ - 255 ) - -#define FLASH_AREA_IMAGE_SECONDARY(x) \ - ((x == 0) ? \ - PM_MCUBOOT_SECONDARY_ID: \ - (x == 1) ? \ - PM_MCUBOOT_SECONDARY_1_ID: \ - 255 ) -#elif defined(PM_B0_ADDRESS) - -#define FLASH_AREA_IMAGE_PRIMARY(x) \ - ((x == 0) ? \ - PM_MCUBOOT_PRIMARY_ID : \ - (x == 1) ? \ - (uint32_t)_image_1_primary_slot_id : \ - 255 ) - -#define FLASH_AREA_IMAGE_SECONDARY(x) \ - ((x == 0) ? \ - PM_MCUBOOT_SECONDARY_ID: \ - (x == 1) ? \ - PM_MCUBOOT_SECONDARY_ID: \ - 255 ) -#else - -#define FLASH_AREA_IMAGE_PRIMARY(x) \ - ((x == 0) ? \ - PM_MCUBOOT_PRIMARY_ID : \ - (x == 1) ? \ - PM_MCUBOOT_PRIMARY_1_ID : \ - 255 ) - -#define FLASH_AREA_IMAGE_SECONDARY(x) \ - ((x == 0) ? \ - PM_MCUBOOT_SECONDARY_ID: \ - (x == 1) ? \ - PM_MCUBOOT_SECONDARY_1_ID: \ - 255 ) - -#endif /* PM_B0_ADDRESS */ - +/* Blocking the rest of the file */ +#define __SYSFLASH_H__ +#include #endif -#define FLASH_AREA_IMAGE_SCRATCH PM_MCUBOOT_SCRATCH_ID - -#else /* CONFIG_SINGLE_APPLICATION_SLOT */ - -#define FLASH_AREA_IMAGE_PRIMARY(x) PM_MCUBOOT_PRIMARY_ID -#define FLASH_AREA_IMAGE_SECONDARY(x) PM_MCUBOOT_PRIMARY_ID -/* NOTE: Scratch parition is not used by single image DFU but some of - * functions in common files reference it, so the definitions has been - * provided to allow compilation of common units. - */ -#define FLASH_AREA_IMAGE_SCRATCH 0 -#endif /* CONFIG_SINGLE_APPLICATION_SLOT */ - -#else +#ifndef __SYSFLASH_H__ +#define __SYSFLASH_H__ -#include #include #include #include @@ -149,6 +71,4 @@ static inline uint32_t __flash_area_ids_for_slot(int img, int slot) #endif /* CONFIG_SINGLE_APPLICATION_SLOT */ -#endif /* USE_PARTITION_MANAGER */ - #endif /* __SYSFLASH_H__ */ From 7025efda58de8c60794c1622bb76338ad0342eac Mon Sep 17 00:00:00 2001 From: Dominik Ermel Date: Fri, 11 Aug 2023 12:29:13 +0000 Subject: [PATCH 303/420] [nrf noup] sysflash: Add support for three images The commit modifies pm_sysflash.h to add support for three application images. Ref. NCSDK-19223 Signed-off-by: Dominik Ermel Signed-off-by: Sigvart Hovland (cherry picked from commit 3b3298de5dae0055bf95c2bf62a7f45a8c36b950) --- boot/zephyr/include/sysflash/pm_sysflash.h | 82 ++++++++++++---------- 1 file changed, 45 insertions(+), 37 deletions(-) diff --git a/boot/zephyr/include/sysflash/pm_sysflash.h b/boot/zephyr/include/sysflash/pm_sysflash.h index 377291e8b..db60ddd03 100644 --- a/boot/zephyr/include/sysflash/pm_sysflash.h +++ b/boot/zephyr/include/sysflash/pm_sysflash.h @@ -11,37 +11,19 @@ #include #include +#include #ifndef CONFIG_SINGLE_APPLICATION_SLOT -#if (MCUBOOT_IMAGE_NUMBER == 1) - -#define FLASH_AREA_IMAGE_PRIMARY(x) PM_MCUBOOT_PRIMARY_ID -#define FLASH_AREA_IMAGE_SECONDARY(x) PM_MCUBOOT_SECONDARY_ID - -#elif (MCUBOOT_IMAGE_NUMBER == 2) - +#if (MCUBOOT_IMAGE_NUMBER == 2) && defined(PM_B0_ADDRESS) /* If B0 is present then two bootloaders are present, and we must use * a single secondary slot for both primary slots. */ -#if defined(PM_B0_ADDRESS) extern uint32_t _image_1_primary_slot_id[]; -#endif -#if defined(PM_B0_ADDRESS) && defined(CONFIG_NRF53_MULTI_IMAGE_UPDATE) -#define FLASH_AREA_IMAGE_PRIMARY(x) \ - ((x == 0) ? \ - PM_MCUBOOT_PRIMARY_ID : \ - (x == 1) ? \ - PM_MCUBOOT_PRIMARY_1_ID : \ - 255 ) +#endif /* (MCUBOOT_IMAGE_NUMBER == 2 && defined(PM_B0_ADDRESS) */ -#define FLASH_AREA_IMAGE_SECONDARY(x) \ - ((x == 0) ? \ - PM_MCUBOOT_SECONDARY_ID: \ - (x == 1) ? \ - PM_MCUBOOT_SECONDARY_1_ID: \ - 255 ) -#elif defined(PM_B0_ADDRESS) +#if (MCUBOOT_IMAGE_NUMBER == 2) && defined(PM_B0_ADDRESS) && \ + !defined(CONFIG_NRF53_MULTI_IMAGE_UPDATE) #define FLASH_AREA_IMAGE_PRIMARY(x) \ ((x == 0) ? \ @@ -56,26 +38,52 @@ extern uint32_t _image_1_primary_slot_id[]; (x == 1) ? \ PM_MCUBOOT_SECONDARY_ID: \ 255 ) + +#else /* MCUBOOT_IMAGE_NUMBER == 2) && defined(PM_B0_ADDRESS) && \ + * !defined(CONFIG_NRF53_MULTI_IMAGE_UPDATE) + */ + +/* Each pair of slots is separated by , and there is no terminating character */ +#define FLASH_AREA_IMAGE_0_SLOTS PM_MCUBOOT_PRIMARY_ID, PM_MCUBOOT_SECONDARY_ID +#define FLASH_AREA_IMAGE_1_SLOTS PM_MCUBOOT_PRIMARY_1_ID, PM_MCUBOOT_SECONDARY_1_ID +#define FLASH_AREA_IMAGE_2_SLOTS PM_MCUBOOT_PRIMARY_2_ID, PM_MCUBOOT_SECONDARY_2_ID + +#if (MCUBOOT_IMAGE_NUMBER == 1) +#define ALL_AVAILABLE_SLOTS FLASH_AREA_IMAGE_0_SLOTS +#elif (MCUBOOT_IMAGE_NUMBER == 2) +#define ALL_AVAILABLE_SLOTS FLASH_AREA_IMAGE_0_SLOTS, \ + FLASH_AREA_IMAGE_1_SLOTS +#elif (MCUBOOT_IMAGE_NUMBER == 3) +#define ALL_AVAILABLE_SLOTS FLASH_AREA_IMAGE_0_SLOTS, \ + FLASH_AREA_IMAGE_1_SLOTS, \ + FLASH_AREA_IMAGE_2_SLOTS #else +#error Unsupported number of images +#endif -#define FLASH_AREA_IMAGE_PRIMARY(x) \ - ((x == 0) ? \ - PM_MCUBOOT_PRIMARY_ID : \ - (x == 1) ? \ - PM_MCUBOOT_PRIMARY_1_ID : \ - 255 ) +static inline uint32_t __flash_area_ids_for_slot(int img, int slot) +{ + static const int all_slots[] = { + ALL_AVAILABLE_SLOTS + }; + return all_slots[img * 2 + slot]; +}; -#define FLASH_AREA_IMAGE_SECONDARY(x) \ - ((x == 0) ? \ - PM_MCUBOOT_SECONDARY_ID: \ - (x == 1) ? \ - PM_MCUBOOT_SECONDARY_1_ID: \ - 255 ) +#undef FLASH_AREA_IMAGE_0_SLOTS +#undef FLASH_AREA_IMAGE_1_SLOTS +#undef FLASH_AREA_IMAGE_2_SLOTS +#undef ALL_AVAILABLE_SLOTS -#endif /* PM_B0_ADDRESS */ +#define FLASH_AREA_IMAGE_PRIMARY(x) __flash_area_ids_for_slot(x, 0) +#define FLASH_AREA_IMAGE_SECONDARY(x) __flash_area_ids_for_slot(x, 1) +#if !defined(CONFIG_BOOT_SWAP_USING_MOVE) +#define FLASH_AREA_IMAGE_SCRATCH PM_MCUBOOT_SCRATCH_ID #endif -#define FLASH_AREA_IMAGE_SCRATCH PM_MCUBOOT_SCRATCH_ID + +#endif /* MCUBOOT_IMAGE_NUMBER == 2) && defined(PM_B0_ADDRESS) && \ + * !defined(CONFIG_NRF53_MULTI_IMAGE_UPDATE) + */ #else /* CONFIG_SINGLE_APPLICATION_SLOT */ From 1e13c43c8faa7eff93ebd0ef85bf7d6bf7595000 Mon Sep 17 00:00:00 2001 From: Andrzej Puzdrowski Date: Thu, 15 Feb 2024 16:47:25 +0100 Subject: [PATCH 304/420] [nrf noup] loader: introduced cleanup of unusable secondary slot Added procedure which clean-up content of all the secondary slot which contains valid header but couldn't be assigned to any of supported primary images. This behavior is needed when configuration allows to use one secondary slot for collecting image for multiple primary slots. Signed-off-by: Andrzej Puzdrowski (cherry picked from commit bd97f58190446c2a6e6a6e1a273b38a0ae848273) --- boot/bootutil/src/loader.c | 90 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 90 insertions(+) diff --git a/boot/bootutil/src/loader.c b/boot/bootutil/src/loader.c index 71ecdfd37..ff542b401 100644 --- a/boot/bootutil/src/loader.c +++ b/boot/bootutil/src/loader.c @@ -1144,6 +1144,87 @@ boot_update_security_counter(struct boot_loader_state *state, int slot, int hdr_ } #endif /* MCUBOOT_HW_ROLLBACK_PROT */ +#if defined(CONFIG_MCUBOOT_CLEANUP_UNUSABLE_SECONDARY) &&\ +(defined(PM_S1_ADDRESS) || defined(CONFIG_SOC_NRF5340_CPUAPP)) + +#define SEC_SLOT_VIRGIN 0 +#define SEC_SLOT_TOUCHED 1 +#define SEC_SLOT_ASSIGNED 2 + +#if (MCUBOOT_IMAGE_NUMBER == 2) && defined(PM_B0_ADDRESS) && \ + !defined(CONFIG_NRF53_MULTI_IMAGE_UPDATE) +/* This configuration is peculiar - the one physical secondary slot is + * mocking two logical secondary + */ +#define SEC_SLOT_PHYSICAL_CNT 1 +#else +#define SEC_SLOT_PHYSICAL_CNT MCUBOOT_IMAGE_NUMBER +#endif + +static uint8_t sec_slot_assignmnet[SEC_SLOT_PHYSICAL_CNT] = {0}; + +static inline void sec_slot_touch(struct boot_loader_state *state) +{ + uint8_t idx = (SEC_SLOT_PHYSICAL_CNT == 1) ? 0 : BOOT_CURR_IMG(state); + + if (SEC_SLOT_VIRGIN == sec_slot_assignmnet[idx]) { + sec_slot_assignmnet[idx] = SEC_SLOT_TOUCHED; + } +} + +static inline void sec_slot_mark_assigned(struct boot_loader_state *state) +{ + uint8_t idx = (SEC_SLOT_PHYSICAL_CNT == 1) ? 0 : BOOT_CURR_IMG(state); + + sec_slot_assignmnet[idx] = SEC_SLOT_ASSIGNED; +} + +/** + * Cleanu up all secondary slot which couldn't be assigned to any primary slot. + * + * This function erases content of each secondary slot which contains valid + * header but couldn't be assigned to any of supported primary images. + * + * This function is supposed to be called after boot_validated_swap_type() + * iterates over all the images in context_boot_go(). + */ +static void sec_slot_cleanup_if_unusable(void) +{ + uint8_t idx; + + for (idx = 0; idx < SEC_SLOT_PHYSICAL_CNT; idx++) { + if (SEC_SLOT_TOUCHED == sec_slot_assignmnet[idx]) { + const struct flash_area *secondary_fa; + int rc; + + rc = flash_area_open(flash_area_id_from_multi_image_slot(idx, BOOT_SECONDARY_SLOT), + &secondary_fa); + if (!rc) { + rc = flash_area_erase(secondary_fa, 0, secondary_fa->fa_size); + if (!rc) { + BOOT_LOG_ERR("Cleaned-up secondary slot of %d. image.", idx); + } + } + + if (rc) { + BOOT_LOG_ERR("Can not cleanup secondary slot of %d. image.", idx); + } + } + } +} +#else +static inline void sec_slot_touch(struct boot_loader_state *state) +{ +} +static inline void sec_slot_mark_assigned(struct boot_loader_state *state) +{ +} +static inline void sec_slot_cleanup_if_unusable(void) +{ +} +#endif /* defined(CONFIG_MCUBOOT_CLEANUP_UNUSABLE_SECONDARY) &&\ + defined(PM_S1_ADDRESS) || defined(CONFIG_SOC_NRF5340_CPUAPP) */ + #if !defined(MCUBOOT_DIRECT_XIP) && !defined(MCUBOOT_RAM_LOAD) /** * Determines which swap operation to perform, if any. If it is determined @@ -1182,6 +1263,9 @@ boot_validated_swap_type(struct boot_loader_state *state, if (rc != 0) { return BOOT_SWAP_TYPE_FAIL; } + + sec_slot_touch(state); + #ifdef PM_S1_ADDRESS #ifdef PM_CPUNET_B0N_ADDRESS if(reset_addr < PM_CPUNET_B0N_ADDRESS) @@ -1216,6 +1300,7 @@ boot_validated_swap_type(struct boot_loader_state *state, } #else return BOOT_SWAP_TYPE_NONE; + #endif } else if (reset_addr > (primary_fa->fa_off + primary_fa->fa_size)) { @@ -1224,7 +1309,9 @@ boot_validated_swap_type(struct boot_loader_state *state, } } #endif /* PM_S1_ADDRESS */ + sec_slot_mark_assigned(state); } + #endif /* PM_S1_ADDRESS || CONFIG_SOC_NRF5340_CPUAPP */ swap_type = boot_swap_type_multi(BOOT_CURR_IMG(state)); @@ -2434,6 +2521,9 @@ context_boot_go(struct boot_loader_state *state, struct boot_rsp *rsp) } } + /* cleanup secondary slots which were recognized unusable*/ + sec_slot_cleanup_if_unusable(); + #if (BOOT_IMAGE_NUMBER > 1) if (has_upgrade) { /* Iterate over all the images and verify whether the image dependencies From 210289dfff728925f2e56ffaacfea95aec49d575 Mon Sep 17 00:00:00 2001 From: Grzegorz Chwierut Date: Fri, 17 May 2024 18:25:07 +0200 Subject: [PATCH 305/420] [nrf noup] loader: remove cleanup for direct xip mode Move ifdefs just to not add code for cleanup unusable slot when direct xip mode is enabled to avoid warnings. Signed-off-by: Grzegorz Chwierut (cherry picked from commit 271e50509bfb6d9625f25b4b6f8ccd991799e93e) --- boot/bootutil/src/loader.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/boot/bootutil/src/loader.c b/boot/bootutil/src/loader.c index ff542b401..4b4882b7d 100644 --- a/boot/bootutil/src/loader.c +++ b/boot/bootutil/src/loader.c @@ -1144,6 +1144,8 @@ boot_update_security_counter(struct boot_loader_state *state, int slot, int hdr_ } #endif /* MCUBOOT_HW_ROLLBACK_PROT */ +#if !defined(MCUBOOT_DIRECT_XIP) && !defined(MCUBOOT_RAM_LOAD) + #if defined(CONFIG_MCUBOOT_CLEANUP_UNUSABLE_SECONDARY) &&\ (defined(PM_S1_ADDRESS) || defined(CONFIG_SOC_NRF5340_CPUAPP)) @@ -1225,7 +1227,6 @@ static inline void sec_slot_cleanup_if_unusable(void) #endif /* defined(CONFIG_MCUBOOT_CLEANUP_UNUSABLE_SECONDARY) &&\ defined(PM_S1_ADDRESS) || defined(CONFIG_SOC_NRF5340_CPUAPP) */ -#if !defined(MCUBOOT_DIRECT_XIP) && !defined(MCUBOOT_RAM_LOAD) /** * Determines which swap operation to perform, if any. If it is determined * that a swap operation is required, the image in the secondary slot is checked From 8a1a4c98646d8d84acb73cbf0d4bd7c7efa56fdd Mon Sep 17 00:00:00 2001 From: Maximilian Deubel Date: Tue, 12 Mar 2024 12:30:52 +0100 Subject: [PATCH 306/420] [nrf noup] boards: thingy91x: enable serial recovery This patch disbales MCUBoot logging and enables serial recovery for the Thingy:91. Signed-off-by: Maximilian Deubel Signed-off-by: Bernt Johan Damslora (cherry picked from commit f5f382f4fe888e560e0db125fded0ef49ba6e7a7) --- boot/zephyr/boards/thingy91x_nrf5340_cpuapp.conf | 10 ++++++++-- boot/zephyr/boards/thingy91x_nrf9151.conf | 9 +++++++++ 2 files changed, 17 insertions(+), 2 deletions(-) diff --git a/boot/zephyr/boards/thingy91x_nrf5340_cpuapp.conf b/boot/zephyr/boards/thingy91x_nrf5340_cpuapp.conf index 72dfa7fca..37c7e95b1 100644 --- a/boot/zephyr/boards/thingy91x_nrf5340_cpuapp.conf +++ b/boot/zephyr/boards/thingy91x_nrf5340_cpuapp.conf @@ -32,7 +32,7 @@ CONFIG_USB_COMPOSITE_DEVICE=y CONFIG_USB_MASS_STORAGE=n CONFIG_USB_DEVICE_MANUFACTURER="Nordic Semiconductor" CONFIG_USB_DEVICE_VID=0x1915 -CONFIG_USB_DEVICE_PID=0x520F +CONFIG_USB_DEVICE_PID=0x910A CONFIG_BOOT_SERIAL_BOOT_MODE=y @@ -49,6 +49,12 @@ CONFIG_FLASH_SIMULATOR_DOUBLE_WRITES=y CONFIG_FLASH_SIMULATOR_STATS=n CONFIG_BOOT_IMAGE_ACCESS_HOOKS=y -CONFIG_MCUBOOT_SERIAL_DIRECT_IMAGE_UPLOAD=y +# Makes it possible to update the network core using the flash simulator CONFIG_NRF53_RECOVERY_NETWORK_CORE=y + +CONFIG_MCUBOOT_SERIAL_DIRECT_IMAGE_UPLOAD=y +CONFIG_BOOT_SERIAL_IMG_GRP_IMAGE_STATE=y + +# Skip checks on the secondary image to make it possible to update MCUBoot on S1/S0 +CONFIG_MCUBOOT_VERIFY_IMG_ADDRESS=n diff --git a/boot/zephyr/boards/thingy91x_nrf9151.conf b/boot/zephyr/boards/thingy91x_nrf9151.conf index 33cd3301c..2efe1e170 100644 --- a/boot/zephyr/boards/thingy91x_nrf9151.conf +++ b/boot/zephyr/boards/thingy91x_nrf9151.conf @@ -6,3 +6,12 @@ CONFIG_SPI_NOR=y CONFIG_SPI_NOR_FLASH_LAYOUT_PAGE_SIZE=4096 CONFIG_SPI_NOR_SFDP_DEVICETREE=y CONFIG_MULTITHREADING=y + +# Disable Zephyr console and use UART for MCUboot serial recovery instead +CONFIG_CONSOLE=n +CONFIG_CONSOLE_HANDLER=n +CONFIG_UART_CONSOLE=n +CONFIG_MCUBOOT_SERIAL=y + +CONFIG_MCUBOOT_SERIAL_DIRECT_IMAGE_UPLOAD=y +CONFIG_BOOT_SERIAL_IMG_GRP_IMAGE_STATE=y From cc0b66feed6f6f9dd1145d04f588dc7fac898f04 Mon Sep 17 00:00:00 2001 From: Robert Lubos Date: Fri, 17 May 2024 14:14:54 +0200 Subject: [PATCH 307/420] [nrf noup] boot: zephyr: Disable boot banner if NCS_BOOT_BANNER is used Mcuboot's boot banner should not be used if NCS boot banner is enabled. Signed-off-by: Robert Lubos (cherry picked from commit b8f6a06206675d1c51009215aeb9c7b1b348d45f) --- boot/zephyr/Kconfig | 1 + 1 file changed, 1 insertion(+) diff --git a/boot/zephyr/Kconfig b/boot/zephyr/Kconfig index bf9b4d511..6b3a1288a 100644 --- a/boot/zephyr/Kconfig +++ b/boot/zephyr/Kconfig @@ -1157,6 +1157,7 @@ config BOOT_DISABLE_CACHES config MCUBOOT_BOOT_BANNER bool "Use MCUboot boot banner" depends on BOOT_BANNER + depends on !NCS_BOOT_BANNER depends on "$(APP_VERSION_EXTENDED_STRING)" != "" default y help From b054302ac43ccf433f887ff441e28fcfa01a20a2 Mon Sep 17 00:00:00 2001 From: Andrzej Puzdrowski Date: Mon, 27 May 2024 13:59:49 +0200 Subject: [PATCH 308/420] [nrf noup] boot/zephyr: fix fw_info search By the upstream patch the vt get now the pointer to the copy of the arm_vector instead of original. This patch fixes address of the firmware which is to be taken by the fw_info_find. Signed-off-by: Andrzej Puzdrowski (cherry picked from commit 8949a6a34d4522447069a6630866f136132e3ac3) --- boot/zephyr/main.c | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/boot/zephyr/main.c b/boot/zephyr/main.c index bbc7abe97..d192f52d1 100644 --- a/boot/zephyr/main.c +++ b/boot/zephyr/main.c @@ -217,7 +217,14 @@ static void do_boot(struct boot_rsp *rsp) #endif #if defined(CONFIG_FW_INFO) && !defined(CONFIG_EXT_API_PROVIDE_EXT_API_UNUSED) - const struct fw_info *firmware_info = fw_info_find((uint32_t) vt); + uintptr_t fw_start_addr; + + rc = flash_device_base(rsp->br_flash_dev_id, &fw_start_addr); + assert(rc == 0); + + fw_start_addr += rsp->br_image_off + rsp->br_hdr->ih_hdr_size; + + const struct fw_info *firmware_info = fw_info_find(fw_start_addr); bool provided = fw_info_ext_api_provide(firmware_info, true); #ifdef PM_S0_ADDRESS From 6ccfff81eb5f6d2573e8147f0a14ec80afddade8 Mon Sep 17 00:00:00 2001 From: Andrzej Puzdrowski Date: Thu, 13 Jun 2024 16:34:55 +0200 Subject: [PATCH 309/420] [nrf noup] boot/../loader: skip downgrade prevention for s1/s0 This patch introduces skip on checking downgrade for s1/s0 upgrade image (chain-loaded by NSIB). which is used for upgrade MCUboot instance itself. Reason is that sdk-mcuboot has not access to semantic version of its own image. I also shouldn't touch HW counter used for hardware downgrade prevention for the application image (which was the case). HW counters for s0/s1 image are owned by NSIB because its role is to prevnt dongrades of s0/s1 MCUboot. Signed-off-by: Andrzej Puzdrowski (cherry picked from commit bf143850d06f24d83c51bc904034e3ccdf22290c) --- boot/bootutil/include/bootutil/security_cnt.h | 9 ++ boot/bootutil/src/image_validate.c | 20 +++++ boot/bootutil/src/loader.c | 83 +++++++++++++++++++ 3 files changed, 112 insertions(+) diff --git a/boot/bootutil/include/bootutil/security_cnt.h b/boot/bootutil/include/bootutil/security_cnt.h index 228ada8dc..ff3a7371c 100644 --- a/boot/bootutil/include/bootutil/security_cnt.h +++ b/boot/bootutil/include/bootutil/security_cnt.h @@ -39,6 +39,15 @@ extern "C" { */ fih_ret boot_nv_security_counter_init(void); +/** + * Checks if the specified image should have a security counter present on it or not + * + * @param image_index Index of the image to check (from 0). + * + * @return FIH_SUCCESS if security counter should be present; FIH_FAILURE if otherwise + */ +fih_ret boot_nv_image_should_have_security_counter(uint32_t image_index); + /** * Reads the stored value of a given image's security counter. * diff --git a/boot/bootutil/src/image_validate.c b/boot/bootutil/src/image_validate.c index f40667866..cb9ce3466 100644 --- a/boot/bootutil/src/image_validate.c +++ b/boot/bootutil/src/image_validate.c @@ -241,6 +241,15 @@ bootutil_img_validate(struct boot_loader_state *state, fih_int security_cnt = fih_int_encode(INT_MAX); uint32_t img_security_cnt = 0; FIH_DECLARE(security_counter_valid, FIH_FAILURE); + FIH_DECLARE(security_counter_should_be_present, FIH_FAILURE); + + FIH_CALL(boot_nv_image_should_have_security_counter, security_counter_should_be_present, + image_index); + if (FIH_NOT_EQ(security_counter_should_be_present, FIH_SUCCESS) && + FIH_NOT_EQ(security_counter_should_be_present, FIH_FAILURE)) { + rc = -1; + goto out; + } #endif #ifdef MCUBOOT_UUID_VID struct image_uuid img_uuid_vid = {0x00}; @@ -445,6 +454,10 @@ bootutil_img_validate(struct boot_loader_state *state, goto out; } + if (FIH_EQ(security_counter_should_be_present, FIH_FAILURE)) { + goto skip_security_counter_read; + } + FIH_CALL(boot_nv_security_counter_get, fih_rc, image_index, &security_cnt); if (FIH_NOT_EQ(fih_rc, FIH_SUCCESS)) { @@ -479,6 +492,7 @@ bootutil_img_validate(struct boot_loader_state *state, /* The image's security counter has been successfully verified. */ security_counter_valid = fih_rc; +skip_security_counter_read: break; } #endif /* MCUBOOT_HW_ROLLBACK_PROT */ @@ -556,10 +570,16 @@ bootutil_img_validate(struct boot_loader_state *state, FIH_SET(fih_rc, valid_signature); #endif #ifdef MCUBOOT_HW_ROLLBACK_PROT + if (FIH_EQ(security_counter_should_be_present, FIH_FAILURE)) { + goto skip_security_counter_check; + } + if (FIH_NOT_EQ(security_counter_valid, FIH_SUCCESS)) { rc = -1; goto out; } + +skip_security_counter_check: #endif #ifdef MCUBOOT_UUID_VID diff --git a/boot/bootutil/src/loader.c b/boot/bootutil/src/loader.c index 4b4882b7d..690857375 100644 --- a/boot/bootutil/src/loader.c +++ b/boot/bootutil/src/loader.c @@ -71,6 +71,9 @@ int pcd_version_cmp_net(const struct flash_area *fap, struct image_header *hdr); BOOT_LOG_MODULE_DECLARE(mcuboot); static struct boot_loader_state boot_data; +#ifdef PM_S1_ADDRESS +static bool owner_nsib[BOOT_IMAGE_NUMBER] = {false}; +#endif #if defined(MCUBOOT_SERIAL_IMG_GRP_SLOT_INFO) || defined(MCUBOOT_DATA_SHARING) static struct image_max_size image_max_sizes[BOOT_IMAGE_NUMBER] = {0}; @@ -1105,6 +1108,38 @@ boot_validate_slot(struct boot_loader_state *state, int slot, } #ifdef MCUBOOT_HW_ROLLBACK_PROT +/** + * Checks if the specified image should have a security counter present on it or not + * + * @param image_index Index of the image to check. + * + * @return true if security counter should be present; false if otherwise + */ +fih_ret boot_nv_image_should_have_security_counter(uint32_t image_index) +{ +#if defined(PM_S1_ADDRESS) + if (owner_nsib[image_index]) { + /* + * Downgrade prevention on S0/S1 image is managed by NSIB, which is a software (not + * hardware) check + */ + return FIH_FAILURE; + } +#endif + +#if defined(CONFIG_SOC_NRF5340_CPUAPP) && CONFIG_MCUBOOT_NETWORK_CORE_IMAGE_NUMBER != -1 + if (image_index == CONFIG_MCUBOOT_NETWORK_CORE_IMAGE_NUMBER) { + /* + * Downgrade prevention on network core image is managed by NSIB which is a software (not + * hardware) check + */ + return FIH_FAILURE; + } +#endif + + return FIH_SUCCESS; +} + /** * Updates the stored security counter value with the image's security counter * value which resides in the given slot, only if it's greater than the stored @@ -1126,6 +1161,26 @@ boot_update_security_counter(struct boot_loader_state *state, int slot, int hdr_ uint32_t img_security_cnt; int rc; +#if defined(PM_S1_ADDRESS) + if (owner_nsib[BOOT_CURR_IMG(state)]) { + /* + * Downgrade prevention on S0/S1 image is managed by NSIB which is a software (not + * hardware) check + */ + return 0; + } +#endif + +#if defined(CONFIG_SOC_NRF5340_CPUAPP) && CONFIG_MCUBOOT_NETWORK_CORE_IMAGE_NUMBER != -1 + if (BOOT_CURR_IMG(state) == CONFIG_MCUBOOT_NETWORK_CORE_IMAGE_NUMBER) { + /* + * Downgrade prevention on network core image is managed by NSIB which is a software (not + * hardware) check + */ + return 0; + } +#endif + fap = BOOT_IMG_AREA(state, slot); assert(fap != NULL); @@ -1242,6 +1297,9 @@ boot_validated_swap_type(struct boot_loader_state *state, int swap_type; FIH_DECLARE(fih_rc, FIH_FAILURE); bool upgrade_valid = false; +#if defined(PM_S1_ADDRESS) + owner_nsib[BOOT_CURR_IMG(state)] = false; +#endif #if defined(PM_S1_ADDRESS) || defined(CONFIG_SOC_NRF5340_CPUAPP) const struct flash_area *secondary_fa = @@ -1298,6 +1356,7 @@ boot_validated_swap_type(struct boot_loader_state *state, && reset_addr < (nsib_fa->fa_off + nsib_fa->fa_size)) { /* Set primary to be NSIB upgrade slot */ BOOT_IMG_AREA(state, 0) = nsib_fa; + owner_nsib[BOOT_CURR_IMG(state)] = true; } #else return BOOT_SWAP_TYPE_NONE; @@ -1308,6 +1367,10 @@ boot_validated_swap_type(struct boot_loader_state *state, /* The image in the secondary slot is not intended for any */ return BOOT_SWAP_TYPE_NONE; } + + if ((primary_fa->fa_off == PM_S0_ADDRESS) || (primary_fa->fa_off == PM_S1_ADDRESS)) { + owner_nsib[BOOT_CURR_IMG(state)] = true; + } } #endif /* PM_S1_ADDRESS */ sec_slot_mark_assigned(state); @@ -2416,6 +2479,26 @@ check_downgrade_prevention(struct boot_loader_state *state) uint32_t security_counter[2]; int rc; +#if defined(PM_S1_ADDRESS) + if (owner_nsib[BOOT_CURR_IMG(state)]) { + /* + * Downgrade prevention on S0/S1 image is managed by NSIB which is a software (not + * hardware) check + */ + return 0; + } +#endif + +#if defined(CONFIG_SOC_NRF5340_CPUAPP) && CONFIG_MCUBOOT_NETWORK_CORE_IMAGE_NUMBER != -1 + if (BOOT_CURR_IMG(state) == CONFIG_MCUBOOT_NETWORK_CORE_IMAGE_NUMBER) { + /* + * Downgrade prevention on network core image is managed by NSIB which is a software (not + * hardware) check + */ + return 0; + } +#endif + if (MCUBOOT_DOWNGRADE_PREVENTION_SECURITY_COUNTER) { /* If there was security no counter in slot 0, allow swap */ rc = bootutil_get_img_security_cnt(state, BOOT_SLOT_PRIMARY, From 7e0d80253cf5396ae5bf5f86a8735b3d7532a90f Mon Sep 17 00:00:00 2001 From: Andrzej Puzdrowski Date: Tue, 18 Jun 2024 17:35:41 +0200 Subject: [PATCH 310/420] [nrf noup] boot/../loader: reboot after updating s0/s1 As this is MCUboot updating itself, it should reboot the device so NSIB will chainload the update MCUboot Signed-off-by: Andrzej Puzdrowski (cherry picked from commit 674adc7d3f6508c9bfeb5f8af93ac489f93d25ce) --- boot/bootutil/src/loader.c | 10 ++++++++++ boot/zephyr/Kconfig | 1 + 2 files changed, 11 insertions(+) diff --git a/boot/bootutil/src/loader.c b/boot/bootutil/src/loader.c index 690857375..3a3c2bb15 100644 --- a/boot/bootutil/src/loader.c +++ b/boot/bootutil/src/loader.c @@ -50,6 +50,10 @@ #include "bootutil/boot_hooks.h" #include "bootutil/mcuboot_status.h" +#ifdef __ZEPHYR__ +#include +#endif + #if defined(CONFIG_SOC_NRF5340_CPUAPP) && defined(PM_CPUNET_B0N_ADDRESS) && defined(CONFIG_PCD_APP) #include #ifdef CONFIG_PCD_READ_NETCORE_APP_VERSION @@ -2678,6 +2682,12 @@ context_boot_go(struct boot_loader_state *state, struct boot_rsp *rsp) rc = boot_perform_update(state, &bs); } assert(rc == 0); +#if defined(PM_S1_ADDRESS) && defined(CONFIG_REBOOT) + if (owner_nsib[BOOT_CURR_IMG(state)]) { + sys_reboot(SYS_REBOOT_COLD); + + } +#endif break; case BOOT_SWAP_TYPE_FAIL: diff --git a/boot/zephyr/Kconfig b/boot/zephyr/Kconfig index 6b3a1288a..03c591346 100644 --- a/boot/zephyr/Kconfig +++ b/boot/zephyr/Kconfig @@ -18,6 +18,7 @@ config MCUBOOT select MPU_ALLOW_FLASH_WRITE if ARM_MPU select USE_DT_CODE_PARTITION if HAS_FLASH_LOAD_OFFSET select MCUBOOT_BOOTUTIL_LIB + select REBOOT if SECURE_BOOT config BOOT_USE_MBEDTLS bool From 919ecf064763a75085bd35f9e5066756f03fb053 Mon Sep 17 00:00:00 2001 From: Jamie McCrae Date: Thu, 29 Aug 2024 12:41:37 +0100 Subject: [PATCH 311/420] [nrf noup] bootutil: loader: Fix netcore address checking Fixes an issues with wrongly checking the network core reset address Signed-off-by: Jamie McCrae (cherry picked from commit 1f364bf2105226a6a12eb51ef25bce2a7fe1219b) --- boot/bootutil/src/loader.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/boot/bootutil/src/loader.c b/boot/bootutil/src/loader.c index 3a3c2bb15..79f7e8d4b 100644 --- a/boot/bootutil/src/loader.c +++ b/boot/bootutil/src/loader.c @@ -1331,7 +1331,7 @@ boot_validated_swap_type(struct boot_loader_state *state, #ifdef PM_S1_ADDRESS #ifdef PM_CPUNET_B0N_ADDRESS - if(reset_addr < PM_CPUNET_B0N_ADDRESS) + if(!(reset_addr >= PM_CPUNET_APP_ADDRESS && reset_addr < PM_CPUNET_APP_END_ADDRESS)) #endif { const struct flash_area *primary_fa; @@ -1404,7 +1404,8 @@ boot_validated_swap_type(struct boot_loader_state *state, * update and indicate to the caller of this function that no update is * available */ - if (upgrade_valid && reset_addr > PM_CPUNET_B0N_ADDRESS) { + if (upgrade_valid && reset_addr >= PM_CPUNET_APP_ADDRESS && + reset_addr < PM_CPUNET_APP_END_ADDRESS) { struct image_header *hdr = (struct image_header *)secondary_fa->fa_off; uint32_t vtable_addr = (uint32_t)hdr + hdr->ih_hdr_size; uint32_t *net_core_fw_addr = (uint32_t *)(vtable_addr); From 3de4115d4b1bae5668ec9453f4c0ba7e2897de6a Mon Sep 17 00:00:00 2001 From: Andrzej Puzdrowski Date: Wed, 18 Sep 2024 12:28:37 +0200 Subject: [PATCH 312/420] [nrf noup] boards: nrf54l15dk: Disable FPROTECT FPROTECT is not suppored for nrf54l15dk. Signed-off-by: Andrzej Puzdrowski (cherry picked from commit 62ddef300f7567b43014e8d8e71ca94e6bd4ef5c) --- boot/zephyr/boards/nrf54l15dk_nrf54l15_cpuapp.conf | 3 +++ 1 file changed, 3 insertions(+) diff --git a/boot/zephyr/boards/nrf54l15dk_nrf54l15_cpuapp.conf b/boot/zephyr/boards/nrf54l15dk_nrf54l15_cpuapp.conf index c8fcd32c3..1dbd7c1ab 100644 --- a/boot/zephyr/boards/nrf54l15dk_nrf54l15_cpuapp.conf +++ b/boot/zephyr/boards/nrf54l15dk_nrf54l15_cpuapp.conf @@ -7,6 +7,9 @@ CONFIG_BOOT_MAX_IMG_SECTORS=256 # Ensure that the SPI NOR driver is disabled by default CONFIG_SPI_NOR=n +# TODO: below are not yet supported and need fixing +CONFIG_FPROTECT=n + CONFIG_BOOT_WATCHDOG_FEED=n # Ensure the fastest RRAM write operations From 5015e54ed88b7d13d7d6107c2a0b8790f9cd2b10 Mon Sep 17 00:00:00 2001 From: Sigvart Hovland Date: Thu, 14 Feb 2019 13:20:34 +0100 Subject: [PATCH 313/420] [nrf noup] boot: Add shared crypto for ECDSA and SHA MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Add functions for ecdsa_verify_secp256r1 and sha256 to use the shared crypto API * Add Kconfig and CMake variables for selecting shared crypto when using ecdsa * Add custom section to project for placing the API section in the correct location in flash * Add kconfig fragment for using external crypto Signed-off-by: Sigvart Hovland Signed-off-by: Martí Bolívar Signed-off-by: Emil Obalski Signed-off-by: Andrzej Puzdrowski Signed-off-by: Håkon Øye Amundsen Signed-off-by: Ioannis Glaropoulos Signed-off-by: Trond Einar Snekvik Signed-off-by: Georgios Vasilakis Signed-off-by: Johann Fischer Signed-off-by: Torsten Rasmussen Signed-off-by: Jamie McCrae Signed-off-by: Dominik Ermel Signed-off-by: Artur Hadasz (cherry picked from commit 2c64b71cf0f060786b0e821a6b94128d9f8e35e1) --- boot/bootutil/include/bootutil/crypto/ecdsa.h | 66 +++++++++++++++++-- boot/bootutil/include/bootutil/crypto/sha.h | 32 +++++++++ boot/zephyr/CMakeLists.txt | 2 + boot/zephyr/external_crypto.conf | 20 ++++++ .../include/mcuboot_config/mcuboot_config.h | 2 + 5 files changed, 116 insertions(+), 6 deletions(-) create mode 100644 boot/zephyr/external_crypto.conf diff --git a/boot/bootutil/include/bootutil/crypto/ecdsa.h b/boot/bootutil/include/bootutil/crypto/ecdsa.h index 8a1463e57..cbbff1783 100644 --- a/boot/bootutil/include/bootutil/crypto/ecdsa.h +++ b/boot/bootutil/include/bootutil/crypto/ecdsa.h @@ -34,6 +34,7 @@ #if (defined(MCUBOOT_USE_TINYCRYPT) + \ defined(MCUBOOT_USE_CC310) + \ + defined(MCUBOOT_USE_NRF_EXTERNAL_CRYPTO) + \ defined(MCUBOOT_USE_PSA_OR_MBED_TLS)) != 1 #error "One crypto backend must be defined: either CC310/TINYCRYPT/MBED_TLS/PSA_CRYPTO" #endif @@ -72,12 +73,18 @@ #include "bootutil/crypto/common.h" #endif +#if defined(MCUBOOT_USE_NRF_EXTERNAL_CRYPTO) + #include + #define NUM_ECC_BYTES (256 / 8) +#endif /* MCUBOOT_USE_NRF_EXTERNAL_CRYPTO */ + #ifdef __cplusplus extern "C" { #endif #if (defined(MCUBOOT_USE_TINYCRYPT) || defined(MCUBOOT_USE_MBED_TLS) || \ - defined(MCUBOOT_USE_CC310)) && !defined(MCUBOOT_USE_PSA_CRYPTO) + defined(MCUBOOT_USE_CC310) || defined(MCUBOOT_USE_NRF_EXTERNAL_CRYPTO)) \ + && !defined(MCUBOOT_USE_PSA_CRYPTO) /* * Declaring these like this adds NULL termination. */ @@ -129,8 +136,7 @@ static int bootutil_import_key(uint8_t **cp, uint8_t *end) } #endif /* (MCUBOOT_USE_TINYCRYPT || MCUBOOT_USE_MBED_TLS || MCUBOOT_USE_CC310) && !MCUBOOT_USE_PSA_CRYPTO */ -#if defined(MCUBOOT_USE_TINYCRYPT) -#ifndef MCUBOOT_ECDSA_NEED_ASN1_SIG +#ifndef MCUBOOT_USE_PSA_CRYPTO /* * cp points to ASN1 string containing an integer. * Verify the tag, and that the length is 32 bytes. Helper function. @@ -180,8 +186,9 @@ static int bootutil_decode_sig(uint8_t signature[NUM_ECC_BYTES * 2], uint8_t *cp } return 0; } -#endif /* not MCUBOOT_ECDSA_NEED_ASN1_SIG */ +#endif /* !MCUBOOT_USE_PSA_CRYPTO */ +#if defined(MCUBOOT_USE_TINYCRYPT) typedef uintptr_t bootutil_ecdsa_context; static inline void bootutil_ecdsa_init(bootutil_ecdsa_context *ctx) { @@ -250,8 +257,12 @@ static inline int bootutil_ecdsa_verify(bootutil_ecdsa_context *ctx, { (void)ctx; (void)pk_len; - (void)sig_len; (void)hash_len; + uint8_t dsig[2 * NUM_ECC_BYTES]; + + if (bootutil_decode_sig(dsig, sig, sig + sig_len)) { + return -1; + } /* Only support uncompressed keys. */ if (pk[0] != 0x04) { @@ -259,7 +270,7 @@ static inline int bootutil_ecdsa_verify(bootutil_ecdsa_context *ctx, } pk++; - return cc310_ecdsa_verify_secp256r1(hash, pk, sig, BOOTUTIL_CRYPTO_ECDSA_P256_HASH_SIZE); + return cc310_ecdsa_verify_secp256r1(hash, pk, dsig, BOOTUTIL_CRYPTO_ECDSA_P256_HASH_SIZE); } static inline int bootutil_ecdsa_parse_public_key(bootutil_ecdsa_context *ctx, @@ -615,6 +626,49 @@ static inline int bootutil_ecdsa_parse_public_key(bootutil_ecdsa_context *ctx, #endif /* MCUBOOT_USE_MBED_TLS */ +#if defined(MCUBOOT_USE_NRF_EXTERNAL_CRYPTO) +typedef uintptr_t bootutil_ecdsa_context; +static inline void bootutil_ecdsa_init(bootutil_ecdsa_context *ctx) +{ + (void)ctx; +} + +static inline void bootutil_ecdsa_drop(bootutil_ecdsa_context *ctx) +{ + (void)ctx; +} + +static inline int bootutil_ecdsa_verify(bootutil_ecdsa_context *ctx, + uint8_t *pk, size_t pk_len, + uint8_t *hash, size_t hash_len, + uint8_t *sig, size_t sig_len) +{ + (void)ctx; + (void)pk_len; + (void)hash_len; + uint8_t dsig[2 * NUM_ECC_BYTES]; + + if (bootutil_decode_sig(dsig, sig, sig + sig_len)) { + return -1; + } + + /* Only support uncompressed keys. */ + if (pk[0] != 0x04) { + return -1; + } + pk++; + + return bl_secp256r1_validate(hash, BOOTUTIL_CRYPTO_ECDSA_P256_HASH_SIZE, pk, dsig); +} + +static inline int bootutil_ecdsa_parse_public_key(bootutil_ecdsa_context *ctx, + uint8_t **cp,uint8_t *end) +{ + (void)ctx; + return bootutil_import_key(cp, end); +} +#endif /* MCUBOOT_USE_NRF_EXTERNAL_CRYPTO */ + #ifdef __cplusplus } #endif diff --git a/boot/bootutil/include/bootutil/crypto/sha.h b/boot/bootutil/include/bootutil/crypto/sha.h index 6a009ff95..b83a3ec40 100644 --- a/boot/bootutil/include/bootutil/crypto/sha.h +++ b/boot/bootutil/include/bootutil/crypto/sha.h @@ -30,6 +30,7 @@ #if (defined(MCUBOOT_USE_PSA_OR_MBED_TLS) + \ defined(MCUBOOT_USE_TINYCRYPT) + \ + defined(MCUBOOT_USE_NRF_EXTERNAL_CRYPTO) + \ defined(MCUBOOT_USE_CC310)) != 1 #error "One crypto backend must be defined: either CC310/MBED_TLS/TINYCRYPT/PSA_CRYPTO" #endif @@ -270,6 +271,37 @@ static inline int bootutil_sha_finish(bootutil_sha_context *ctx, } #endif /* MCUBOOT_USE_CC310 */ +#if defined(MCUBOOT_USE_NRF_EXTERNAL_CRYPTO) + +#include + +typedef bl_sha256_ctx_t bootutil_sha_context; + +static inline void bootutil_sha_init(bootutil_sha_context *ctx) +{ + bl_sha256_init(ctx); +} + +static inline void bootutil_sha_drop(bootutil_sha_context *ctx) +{ + (void)ctx; +} + +static inline int bootutil_sha_update(bootutil_sha_context *ctx, + const void *data, + uint32_t data_len) +{ + return bl_sha256_update(ctx, data, data_len); +} + +static inline int bootutil_sha_finish(bootutil_sha_context *ctx, + uint8_t *output) +{ + bl_sha256_finalize(ctx, output); + return 0; +} +#endif /* MCUBOOT_USE_NRF_EXTERNAL_CRYPTO */ + #ifdef __cplusplus } #endif diff --git a/boot/zephyr/CMakeLists.txt b/boot/zephyr/CMakeLists.txt index f781da7ef..86d2bd5a2 100644 --- a/boot/zephyr/CMakeLists.txt +++ b/boot/zephyr/CMakeLists.txt @@ -213,6 +213,8 @@ if(CONFIG_BOOT_SIGNATURE_TYPE_ECDSA_P256 OR CONFIG_BOOT_ENCRYPT_EC256) zephyr_library_sources(${NRF_DIR}/cc310_glue.c) zephyr_library_include_directories(${NRF_DIR}) zephyr_link_libraries(nrfxlib_crypto) + elseif(CONFIG_BOOT_USE_NRF_EXTERNAL_CRYPTO) + zephyr_include_directories(${BL_CRYPTO_DIR}/../include) endif() if(CONFIG_MBEDTLS_CFG_FILE) diff --git a/boot/zephyr/external_crypto.conf b/boot/zephyr/external_crypto.conf new file mode 100644 index 000000000..8181ad51c --- /dev/null +++ b/boot/zephyr/external_crypto.conf @@ -0,0 +1,20 @@ +# +# Copyright (c) 2021 Nordic Semiconductor ASA +# +# SPDX-License-Identifier: LicenseRef-Nordic-5-Clause +# + +# These configurations should be used when using nrf/samples/bootloader +# as the immutable bootloader (B0), and MCUBoot as the second stage updateable +# bootloader. + +# Set ECDSA as signing mechanism +CONFIG_BOOT_SIGNATURE_TYPE_ECDSA_P256=y + +# Use crypto backend from B0 +CONFIG_BOOT_NRF_EXTERNAL_CRYPTO=y +CONFIG_SECURE_BOOT_CRYPTO=y +CONFIG_SB_CRYPTO_CLIENT_ECDSA_SECP256R1=y +CONFIG_SB_CRYPTO_CLIENT_SHA256=y +CONFIG_BL_SHA256_EXT_API_REQUIRED=y +CONFIG_BL_SECP256R1_EXT_API_REQUIRED=y diff --git a/boot/zephyr/include/mcuboot_config/mcuboot_config.h b/boot/zephyr/include/mcuboot_config/mcuboot_config.h index 8df98ede6..d82fc57f3 100644 --- a/boot/zephyr/include/mcuboot_config/mcuboot_config.h +++ b/boot/zephyr/include/mcuboot_config/mcuboot_config.h @@ -49,6 +49,8 @@ #endif #elif defined(CONFIG_BOOT_USE_PSA_CRYPTO) #define MCUBOOT_USE_PSA_CRYPTO +#elif defined(CONFIG_BOOT_USE_NRF_EXTERNAL_CRYPTO) +#define MCUBOOT_USE_NRF_EXTERNAL_CRYPTO #endif #ifdef CONFIG_BOOT_IMG_HASH_ALG_SHA512 From 2e29ea662c45ef1bc07dbf36315abe3a35a7eec0 Mon Sep 17 00:00:00 2001 From: Markus Lassila Date: Fri, 30 Aug 2024 13:10:05 +0300 Subject: [PATCH 314/420] [nrf noup] boot: zephyr: Do not lock PCD region with TF-M Previously PCD memory was locked as read-only, non-secure in MCUboot. Given that TF-M also needs write to PCD to communicate with b0n, the memory is left unlocked and locked to read-only, non-secure in TF-M. Signed-off-by: Markus Lassila (cherry picked from commit 599a1b9b55e61e17e1f9f95e1d8b136d0d5a3751) --- boot/zephyr/main.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/boot/zephyr/main.c b/boot/zephyr/main.c index d192f52d1..bdc264d94 100644 --- a/boot/zephyr/main.c +++ b/boot/zephyr/main.c @@ -754,7 +754,11 @@ int main(void) } #if defined(CONFIG_SOC_NRF5340_CPUAPP) && defined(PM_CPUNET_B0N_ADDRESS) && defined(CONFIG_PCD_APP) - pcd_lock_ram(); +#if defined(PM_TFM_SECURE_ADDRESS) + pcd_lock_ram(false); +#else + pcd_lock_ram(true); +#endif #endif #endif /* USE_PARTITION_MANAGER && CONFIG_FPROTECT */ From 8a76fc264125264aca061c138548cd199a33ae8d Mon Sep 17 00:00:00 2001 From: Jamie McCrae Date: Tue, 10 Sep 2024 13:41:30 +0100 Subject: [PATCH 315/420] [nrf noup] treewide: Add support for sysbuild assigned images Adds support for image IDs that are assigned by sysbuild, which allows for dynamically supporting different configurations without needing dummy images to support different modes. Also fixes multiple deficiencies with the previous code where things were not properly accounted for e.g. using the swap algorithm including all swap status parts when updating s0/s1 MCUboot image which could overwrite and corrupt the image data in the other slot Adds support for getting the maximum allowable image size for NSIB Signed-off-by: Jamie McCrae Signed-off-by: Dominik Ermel (cherry picked from commit 352b2a4a9cdd531cb3a1401f100e7d82e7434958) --- boot/bootutil/src/bootutil_misc.c | 12 ++ boot/bootutil/src/loader.c | 181 +++++++++++++-------- boot/bootutil/src/swap_nsib.c | 70 ++++++++ boot/bootutil/src/swap_priv.h | 8 + boot/zephyr/CMakeLists.txt | 6 + boot/zephyr/include/sysflash/pm_sysflash.h | 69 ++++---- 6 files changed, 241 insertions(+), 105 deletions(-) create mode 100644 boot/bootutil/src/swap_nsib.c diff --git a/boot/bootutil/src/bootutil_misc.c b/boot/bootutil/src/bootutil_misc.c index 4fc9e8279..396381437 100644 --- a/boot/bootutil/src/bootutil_misc.c +++ b/boot/bootutil/src/bootutil_misc.c @@ -432,6 +432,18 @@ boot_write_enc_key(const struct flash_area *fap, uint8_t slot, uint32_t bootutil_max_image_size(struct boot_loader_state *state, const struct flash_area *fap) { +#if defined(CONFIG_MCUBOOT_MCUBOOT_IMAGE_NUMBER) && CONFIG_MCUBOOT_MCUBOOT_IMAGE_NUMBER != -1 + if (BOOT_CURR_IMG(state) == CONFIG_MCUBOOT_MCUBOOT_IMAGE_NUMBER) { + /* NSIB is a direct upgrade without any status or trailer, get the full size of the + * primary slot. + */ + const struct flash_area *fap_nsib = BOOT_IMG_AREA(state, 0); + assert(fap_nsib != NULL); + + return flash_area_get_size(fap_nsib); + } +#endif /* CONFIG_MCUBOOT_MCUBOOT_IMAGE_NUMBER != -1 */ + #if defined(MCUBOOT_SINGLE_APPLICATION_SLOT) || \ defined(MCUBOOT_FIRMWARE_LOADER) || \ defined(MCUBOOT_SINGLE_APPLICATION_SLOT_RAM_LOAD) diff --git a/boot/bootutil/src/loader.c b/boot/bootutil/src/loader.c index 79f7e8d4b..7b3f8ebac 100644 --- a/boot/bootutil/src/loader.c +++ b/boot/bootutil/src/loader.c @@ -144,15 +144,15 @@ boot_read_image_headers(struct boot_loader_state *state, bool require_all, * * Failure to read any headers is a fatal error. */ -#ifdef PM_S1_ADDRESS +#if CONFIG_MCUBOOT_MCUBOOT_IMAGE_NUMBER != -1 /* Patch needed for NCS. The primary slot of the second image * (image 1) will not contain a valid image header until an upgrade * of mcuboot has happened (filling S1 with the new version). */ - if (BOOT_CURR_IMG(state) == 1 && i == 0) { + if (BOOT_CURR_IMG(state) == CONFIG_MCUBOOT_MCUBOOT_IMAGE_NUMBER && i == 0) { continue; } -#endif /* PM_S1_ADDRESS */ +#endif /* CONFIG_MCUBOOT_MCUBOOT_IMAGE_NUMBER != -1 */ if (i > 0 && !require_all) { return 0; } else { @@ -991,7 +991,7 @@ boot_validate_slot(struct boot_loader_state *state, int slot, #if defined(CONFIG_SOC_NRF5340_CPUAPP) && defined(CONFIG_NRF53_MULTI_IMAGE_UPDATE) \ && defined(CONFIG_PCD_APP) && defined(CONFIG_PCD_READ_NETCORE_APP_VERSION) - if (BOOT_CURR_IMG(state) == 1) { + if (BOOT_CURR_IMG(state) == CONFIG_MCUBOOT_NETWORK_CORE_IMAGE_NUMBER) { rc = pcd_version_cmp_net(fap, boot_img_hdr(state, BOOT_SECONDARY_SLOT)); } else { rc = boot_version_cmp( @@ -1062,35 +1062,54 @@ boot_validate_slot(struct boot_loader_state *state, int slot, struct image_header *secondary_hdr = boot_img_hdr(state, slot); uint32_t reset_value = 0; uint32_t reset_addr = secondary_hdr->ih_hdr_size + sizeof(reset_value); + uint32_t min_addr, max_addr; + bool check_addresses = false; if (flash_area_read(fap, reset_addr, &reset_value, sizeof(reset_value)) != 0) { fih_rc = FIH_NO_BOOTABLE_IMAGE; goto out; } - uint32_t min_addr, max_addr; - #ifdef PM_CPUNET_APP_ADDRESS /* The primary slot for the network core is emulated in RAM. * Its flash_area hasn't got relevant boundaries. * Therfore need to override its boundaries for the check. */ - if (BOOT_CURR_IMG(state) == 1) { + if (BOOT_CURR_IMG(state) == CONFIG_MCUBOOT_NETWORK_CORE_IMAGE_NUMBER) { min_addr = PM_CPUNET_APP_ADDRESS; max_addr = PM_CPUNET_APP_ADDRESS + PM_CPUNET_APP_SIZE; -#ifdef PM_S1_ADDRESS - } else if (BOOT_CURR_IMG(state) == 0) { + check_addresses = true; + } else +#endif +#if CONFIG_MCUBOOT_MCUBOOT_IMAGE_NUMBER != -1 + if (BOOT_CURR_IMG(state) == CONFIG_MCUBOOT_MCUBOOT_IMAGE_NUMBER) { +#if (CONFIG_NCS_IS_VARIANT_IMAGE) min_addr = PM_S0_ADDRESS; - max_addr = pri_fa->fa_off + pri_fa->fa_size; + max_addr = (PM_S0_ADDRESS + PM_S0_SIZE); +#else + min_addr = PM_S1_ADDRESS; + max_addr = (PM_S1_ADDRESS + PM_S1_SIZE); #endif + check_addresses = true; } else #endif - { + if (BOOT_CURR_IMG(state) == CONFIG_MCUBOOT_APPLICATION_IMAGE_NUMBER) { +#if CONFIG_MCUBOOT_MCUBOOT_IMAGE_NUMBER != -1 +#if (CONFIG_NCS_IS_VARIANT_IMAGE) + min_addr = MIN(pri_fa->fa_off, PM_S0_ADDRESS); + max_addr = MAX((pri_fa->fa_off + pri_fa->fa_size), (PM_S0_ADDRESS + PM_S0_SIZE)); +#else + min_addr = MIN(pri_fa->fa_off, PM_S1_ADDRESS); + max_addr = MAX((pri_fa->fa_off + pri_fa->fa_size), (PM_S1_ADDRESS + PM_S1_SIZE)); +#endif +#else min_addr = pri_fa->fa_off; max_addr = pri_fa->fa_off + pri_fa->fa_size; +#endif + check_addresses = true; } - if (reset_value < min_addr || reset_value> (max_addr)) { + if (check_addresses == true && (reset_value < min_addr || reset_value > max_addr)) { BOOT_LOG_ERR("Reset address of image in secondary slot is not in the primary slot"); BOOT_LOG_ERR("Erasing image from secondary slot"); @@ -1212,36 +1231,54 @@ boot_update_security_counter(struct boot_loader_state *state, int slot, int hdr_ #define SEC_SLOT_TOUCHED 1 #define SEC_SLOT_ASSIGNED 2 -#if (MCUBOOT_IMAGE_NUMBER == 2) && defined(PM_B0_ADDRESS) && \ - !defined(CONFIG_NRF53_MULTI_IMAGE_UPDATE) -/* This configuration is peculiar - the one physical secondary slot is - * mocking two logical secondary - */ -#define SEC_SLOT_PHYSICAL_CNT 1 +static uint8_t sec_slot_assignment[MCUBOOT_IMAGE_NUMBER] = {0}; + +#if CONFIG_MCUBOOT_MCUBOOT_IMAGE_NUMBER != -1 +static inline void sec_slot_untouch(struct boot_loader_state *state) +{ + sec_slot_assignment[CONFIG_MCUBOOT_APPLICATION_IMAGE_NUMBER] = SEC_SLOT_VIRGIN; + sec_slot_assignment[CONFIG_MCUBOOT_MCUBOOT_IMAGE_NUMBER] = SEC_SLOT_VIRGIN; +} #else -#define SEC_SLOT_PHYSICAL_CNT MCUBOOT_IMAGE_NUMBER +static inline void sec_slot_untouch(struct boot_loader_state *state) +{ +} #endif -static uint8_t sec_slot_assignmnet[SEC_SLOT_PHYSICAL_CNT] = {0}; - static inline void sec_slot_touch(struct boot_loader_state *state) { - uint8_t idx = (SEC_SLOT_PHYSICAL_CNT == 1) ? 0 : BOOT_CURR_IMG(state); +#if CONFIG_MCUBOOT_MCUBOOT_IMAGE_NUMBER != -1 + if (BOOT_CURR_IMG(state) == CONFIG_MCUBOOT_MCUBOOT_IMAGE_NUMBER) { + if (sec_slot_assignment[CONFIG_MCUBOOT_APPLICATION_IMAGE_NUMBER] == SEC_SLOT_VIRGIN) { + sec_slot_assignment[CONFIG_MCUBOOT_APPLICATION_IMAGE_NUMBER] = SEC_SLOT_TOUCHED; + } + } else if (BOOT_CURR_IMG(state) == CONFIG_MCUBOOT_APPLICATION_IMAGE_NUMBER) { + if (sec_slot_assignment[CONFIG_MCUBOOT_MCUBOOT_IMAGE_NUMBER] == SEC_SLOT_VIRGIN) { + sec_slot_assignment[CONFIG_MCUBOOT_MCUBOOT_IMAGE_NUMBER] = SEC_SLOT_TOUCHED; + } + } +#endif - if (SEC_SLOT_VIRGIN == sec_slot_assignmnet[idx]) { - sec_slot_assignmnet[idx] = SEC_SLOT_TOUCHED; + if (sec_slot_assignment[BOOT_CURR_IMG(state)] == SEC_SLOT_VIRGIN) { + sec_slot_assignment[BOOT_CURR_IMG(state)] = SEC_SLOT_TOUCHED; } } static inline void sec_slot_mark_assigned(struct boot_loader_state *state) { - uint8_t idx = (SEC_SLOT_PHYSICAL_CNT == 1) ? 0 : BOOT_CURR_IMG(state); +#if CONFIG_MCUBOOT_MCUBOOT_IMAGE_NUMBER != -1 + if (BOOT_CURR_IMG(state) == CONFIG_MCUBOOT_MCUBOOT_IMAGE_NUMBER) { + sec_slot_assignment[CONFIG_MCUBOOT_APPLICATION_IMAGE_NUMBER] = SEC_SLOT_ASSIGNED; + } else if (BOOT_CURR_IMG(state) == CONFIG_MCUBOOT_APPLICATION_IMAGE_NUMBER) { + sec_slot_assignment[CONFIG_MCUBOOT_MCUBOOT_IMAGE_NUMBER] = SEC_SLOT_ASSIGNED; + } +#endif - sec_slot_assignmnet[idx] = SEC_SLOT_ASSIGNED; + sec_slot_assignment[BOOT_CURR_IMG(state)] = SEC_SLOT_ASSIGNED; } /** - * Cleanu up all secondary slot which couldn't be assigned to any primary slot. + * Cleanup up all secondary slot which couldn't be assigned to any primary slot. * * This function erases content of each secondary slot which contains valid * header but couldn't be assigned to any of supported primary images. @@ -1253,8 +1290,8 @@ static void sec_slot_cleanup_if_unusable(void) { uint8_t idx; - for (idx = 0; idx < SEC_SLOT_PHYSICAL_CNT; idx++) { - if (SEC_SLOT_TOUCHED == sec_slot_assignmnet[idx]) { + for (idx = 0; idx < MCUBOOT_IMAGE_NUMBER; idx++) { + if (SEC_SLOT_TOUCHED == sec_slot_assignment[idx]) { const struct flash_area *secondary_fa; int rc; @@ -1263,17 +1300,20 @@ static void sec_slot_cleanup_if_unusable(void) if (!rc) { rc = flash_area_erase(secondary_fa, 0, secondary_fa->fa_size); if (!rc) { - BOOT_LOG_ERR("Cleaned-up secondary slot of %d. image.", idx); + BOOT_LOG_ERR("Cleaned-up secondary slot of image %d", idx); } } if (rc) { - BOOT_LOG_ERR("Can not cleanup secondary slot of %d. image.", idx); + BOOT_LOG_ERR("Failed to clean-up secondary slot of image %d: %d", idx, rc); } } } } #else +static inline void sec_slot_untouch(struct boot_loader_state *state) +{ +} static inline void sec_slot_touch(struct boot_loader_state *state) { } @@ -1305,7 +1345,7 @@ boot_validated_swap_type(struct boot_loader_state *state, owner_nsib[BOOT_CURR_IMG(state)] = false; #endif -#if defined(PM_S1_ADDRESS) || defined(CONFIG_SOC_NRF5340_CPUAPP) +#if defined(PM_S1_ADDRESS) || defined(PM_CPUNET_B0N_ADDRESS) const struct flash_area *secondary_fa = BOOT_IMG_AREA(state, BOOT_SECONDARY_SLOT); struct image_header *hdr = boot_img_hdr(state, BOOT_SECONDARY_SLOT); @@ -1343,31 +1383,31 @@ boot_validated_swap_type(struct boot_loader_state *state, } /* Check start and end of primary slot for current image */ - if (reset_addr < primary_fa->fa_off) { -#if defined(CONFIG_SOC_NRF5340_CPUAPP) && defined(CONFIG_NRF53_MULTI_IMAGE_UPDATE) - const struct flash_area *nsib_fa; - - /* NSIB upgrade slot */ - rc = flash_area_open((uint32_t)_image_1_primary_slot_id, - &nsib_fa); - - if (rc != 0) { - return BOOT_SWAP_TYPE_FAIL; - } - - /* Image is placed before Primary and within the NSIB slot */ - if (reset_addr > nsib_fa->fa_off - && reset_addr < (nsib_fa->fa_off + nsib_fa->fa_size)) { - /* Set primary to be NSIB upgrade slot */ - BOOT_IMG_AREA(state, 0) = nsib_fa; - owner_nsib[BOOT_CURR_IMG(state)] = true; - } +#if (CONFIG_NCS_IS_VARIANT_IMAGE) + if (reset_addr >= PM_S0_ADDRESS && reset_addr <= (PM_S0_ADDRESS + PM_S0_SIZE)) { #else - return BOOT_SWAP_TYPE_NONE; - + if (reset_addr >= PM_S1_ADDRESS && reset_addr <= (PM_S1_ADDRESS + PM_S1_SIZE)) { #endif + if (BOOT_CURR_IMG(state) == CONFIG_MCUBOOT_APPLICATION_IMAGE_NUMBER) { + /* This is not the s0/s1 upgrade image but the application image, pretend + * there is no image so the NSIB update can be loaded + */ + return BOOT_SWAP_TYPE_NONE; + } - } else if (reset_addr > (primary_fa->fa_off + primary_fa->fa_size)) { + owner_nsib[BOOT_CURR_IMG(state)] = true; +#if (CONFIG_NCS_IS_VARIANT_IMAGE) + } else if (reset_addr >= PM_S1_ADDRESS && reset_addr <= (PM_S1_ADDRESS + PM_S1_SIZE)) { +#else + } else if (reset_addr >= PM_S0_ADDRESS && reset_addr <= (PM_S0_ADDRESS + PM_S0_SIZE)) { +#endif + /* NSIB upgrade but for the wrong slot, must be erased */ + BOOT_LOG_ERR("Image in slot is for wrong s0/s1 image"); + flash_area_erase(secondary_fa, 0, secondary_fa->fa_size); + sec_slot_untouch(state); + BOOT_LOG_ERR("Cleaned-up secondary slot of image %d", BOOT_CURR_IMG(state)); + return BOOT_SWAP_TYPE_FAIL; + } else if (reset_addr < primary_fa->fa_off || reset_addr > (primary_fa->fa_off + primary_fa->fa_size)) { /* The image in the secondary slot is not intended for any */ return BOOT_SWAP_TYPE_NONE; } @@ -1380,7 +1420,7 @@ boot_validated_swap_type(struct boot_loader_state *state, sec_slot_mark_assigned(state); } -#endif /* PM_S1_ADDRESS || CONFIG_SOC_NRF5340_CPUAPP */ +#endif /* PM_S1_ADDRESS || PM_CPUNET_B0N_ADDRESS */ swap_type = boot_swap_type_multi(BOOT_CURR_IMG(state)); if (BOOT_IS_UPGRADE(swap_type)) { @@ -2038,7 +2078,22 @@ boot_swap_image(struct boot_loader_state *state, struct boot_status *bs) flash_area_close(fap); } - swap_run(state, bs, copy_size); +#if defined(PM_S1_ADDRESS) && CONFIG_MCUBOOT_MCUBOOT_IMAGE_NUMBER != -1 + if (owner_nsib[BOOT_CURR_IMG(state)]) { + if (BOOT_CURR_IMG(state) == CONFIG_MCUBOOT_MCUBOOT_IMAGE_NUMBER) { + /* For NSIB, move the image instead of swapping it */ + nsib_swap_run(state, bs); + +#if defined(CONFIG_REBOOT) + /* Should also reboot at this point so the new S0/S1 update is applied */ + sys_reboot(SYS_REBOOT_COLD); +#endif + } + } else +#endif + { + swap_run(state, bs, copy_size); + } #ifdef MCUBOOT_VALIDATE_PRIMARY_SLOT extern int boot_status_fails; @@ -2683,12 +2738,6 @@ context_boot_go(struct boot_loader_state *state, struct boot_rsp *rsp) rc = boot_perform_update(state, &bs); } assert(rc == 0); -#if defined(PM_S1_ADDRESS) && defined(CONFIG_REBOOT) - if (owner_nsib[BOOT_CURR_IMG(state)]) { - sys_reboot(SYS_REBOOT_COLD); - - } -#endif break; case BOOT_SWAP_TYPE_FAIL: @@ -2756,13 +2805,17 @@ context_boot_go(struct boot_loader_state *state, struct boot_rsp *rsp) */ } -#ifdef MCUBOOT_VALIDATE_PRIMARY_SLOT #ifdef PM_S1_ADDRESS /* Patch needed for NCS. Image 1 primary is the currently * executing MCUBoot image, and is therefore already validated by NSIB and * does not need to also be validated by MCUBoot. */ - bool image_validated_by_nsib = BOOT_CURR_IMG(state) == 1; + bool image_validated_by_nsib = BOOT_CURR_IMG(state) == + CONFIG_MCUBOOT_MCUBOOT_IMAGE_NUMBER; +#endif + +#ifdef MCUBOOT_VALIDATE_PRIMARY_SLOT +#ifdef PM_S1_ADDRESS if (!image_validated_by_nsib) #endif { diff --git a/boot/bootutil/src/swap_nsib.c b/boot/bootutil/src/swap_nsib.c new file mode 100644 index 000000000..079e193d5 --- /dev/null +++ b/boot/bootutil/src/swap_nsib.c @@ -0,0 +1,70 @@ +/* + * SPDX-License-Identifier: Apache-2.0 + * + * Copyright (c) 2024 Nordic Semiconductor ASA + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include +#include +#include +#include +#include "bootutil/bootutil.h" +#include "bootutil_priv.h" +#include "swap_priv.h" +#include "bootutil/bootutil_log.h" + +#include "mcuboot_config/mcuboot_config.h" + +BOOT_LOG_MODULE_DECLARE(mcuboot); + +void nsib_swap_run(struct boot_loader_state *state, struct boot_status *bs) +{ + uint32_t sector_sz; + uint8_t image_index; + const struct flash_area *fap_pri; + const struct flash_area *fap_sec; + int rc; + + BOOT_LOG_INF("Starting swap using nsib algorithm."); + + sector_sz = boot_img_sector_size(state, BOOT_SECONDARY_SLOT, 0); + +#if (CONFIG_NCS_IS_VARIANT_IMAGE) + rc = flash_area_open(PM_S0_ID, &fap_pri); +#else + rc = flash_area_open(PM_S1_ID, &fap_pri); +#endif + assert (rc == 0); + image_index = BOOT_CURR_IMG(state); + + rc = flash_area_open(FLASH_AREA_IMAGE_SECONDARY(image_index), &fap_sec); + assert (rc == 0); + + rc = boot_erase_region(fap_pri, 0, fap_pri->fa_size, false); + assert(rc == 0); + + rc = boot_copy_region(state, fap_sec, fap_pri, 0, 0, fap_pri->fa_size); + assert(rc == 0); + + rc = swap_scramble_trailer_sectors(state, fap_sec); + assert(rc == 0); + + rc = boot_scramble_region(fap_sec, 0, MIN((fap_pri->fa_size + sector_sz), fap_sec->fa_size), false); + assert(rc == 0); + + flash_area_close(fap_pri); + flash_area_close(fap_sec); +} diff --git a/boot/bootutil/src/swap_priv.h b/boot/bootutil/src/swap_priv.h index b564ea99e..90e0b3742 100644 --- a/boot/bootutil/src/swap_priv.h +++ b/boot/bootutil/src/swap_priv.h @@ -130,4 +130,12 @@ bool swap_write_block_size_check(struct boot_loader_state *state); */ int app_max_size(struct boot_loader_state *state); +#if defined(PM_S1_ADDRESS) && !defined(MCUBOOT_OVERWRITE_ONLY) && \ +(CONFIG_MCUBOOT_MCUBOOT_IMAGE_NUMBER != -1 || defined(LEGACY_CHILD_PARENT_S0_S1_UPDATE_ENABLED)) +/** + * Performs an NSIB update + */ +void nsib_swap_run(struct boot_loader_state *state, struct boot_status *bs); +#endif + #endif /* H_SWAP_PRIV_ */ diff --git a/boot/zephyr/CMakeLists.txt b/boot/zephyr/CMakeLists.txt index 86d2bd5a2..918de1041 100644 --- a/boot/zephyr/CMakeLists.txt +++ b/boot/zephyr/CMakeLists.txt @@ -179,6 +179,12 @@ else() ) endif() endif() + + if(NOT CONFIG_MCUBOOT_MCUBOOT_IMAGE_NUMBER EQUAL "-1" AND NOT CONFIG_BOOT_UPGRADE_ONLY) + zephyr_library_sources( + ${BOOT_DIR}/bootutil/src/swap_nsib.c + ) + endif() endif() if(CONFIG_BOOT_SIGNATURE_TYPE_ECDSA_P256 OR CONFIG_BOOT_ENCRYPT_EC256) diff --git a/boot/zephyr/include/sysflash/pm_sysflash.h b/boot/zephyr/include/sysflash/pm_sysflash.h index db60ddd03..42f25182e 100644 --- a/boot/zephyr/include/sysflash/pm_sysflash.h +++ b/boot/zephyr/include/sysflash/pm_sysflash.h @@ -15,48 +15,36 @@ #ifndef CONFIG_SINGLE_APPLICATION_SLOT -#if (MCUBOOT_IMAGE_NUMBER == 2) && defined(PM_B0_ADDRESS) -/* If B0 is present then two bootloaders are present, and we must use - * a single secondary slot for both primary slots. - */ -extern uint32_t _image_1_primary_slot_id[]; -#endif /* (MCUBOOT_IMAGE_NUMBER == 2 && defined(PM_B0_ADDRESS) */ - -#if (MCUBOOT_IMAGE_NUMBER == 2) && defined(PM_B0_ADDRESS) && \ - !defined(CONFIG_NRF53_MULTI_IMAGE_UPDATE) - -#define FLASH_AREA_IMAGE_PRIMARY(x) \ - ((x == 0) ? \ - PM_MCUBOOT_PRIMARY_ID : \ - (x == 1) ? \ - (uint32_t)_image_1_primary_slot_id : \ - 255 ) - -#define FLASH_AREA_IMAGE_SECONDARY(x) \ - ((x == 0) ? \ - PM_MCUBOOT_SECONDARY_ID: \ - (x == 1) ? \ - PM_MCUBOOT_SECONDARY_ID: \ - 255 ) - -#else /* MCUBOOT_IMAGE_NUMBER == 2) && defined(PM_B0_ADDRESS) && \ - * !defined(CONFIG_NRF53_MULTI_IMAGE_UPDATE) - */ - /* Each pair of slots is separated by , and there is no terminating character */ -#define FLASH_AREA_IMAGE_0_SLOTS PM_MCUBOOT_PRIMARY_ID, PM_MCUBOOT_SECONDARY_ID -#define FLASH_AREA_IMAGE_1_SLOTS PM_MCUBOOT_PRIMARY_1_ID, PM_MCUBOOT_SECONDARY_1_ID -#define FLASH_AREA_IMAGE_2_SLOTS PM_MCUBOOT_PRIMARY_2_ID, PM_MCUBOOT_SECONDARY_2_ID +#define FLASH_AREA_IMAGE_0_SLOTS PM_MCUBOOT_PRIMARY_ID, PM_MCUBOOT_SECONDARY_ID, +#define FLASH_AREA_IMAGE_1_SLOTS PM_MCUBOOT_PRIMARY_1_ID, PM_MCUBOOT_SECONDARY_1_ID, +#define FLASH_AREA_IMAGE_2_SLOTS PM_MCUBOOT_PRIMARY_2_ID, PM_MCUBOOT_SECONDARY_2_ID, +#define FLASH_AREA_IMAGE_3_SLOTS PM_MCUBOOT_PRIMARY_3_ID, PM_MCUBOOT_SECONDARY_3_ID, + +#if CONFIG_MCUBOOT_MCUBOOT_IMAGE_NUMBER != -1 +#ifdef CONFIG_NCS_IS_VARIANT_IMAGE +#define MCUBOOT_S0_S1_SLOTS PM_S0_ID, PM_MCUBOOT_SECONDARY_ID, +#else +#define MCUBOOT_S0_S1_SLOTS PM_S1_ID, PM_MCUBOOT_SECONDARY_ID, +#endif +#else +#define MCUBOOT_S0_S1_SLOTS +#endif -#if (MCUBOOT_IMAGE_NUMBER == 1) +#if (MCUBOOT_IMAGE_NUMBER == 1) || (MCUBOOT_IMAGE_NUMBER == 2 && CONFIG_MCUBOOT_MCUBOOT_IMAGE_NUMBER != -1) #define ALL_AVAILABLE_SLOTS FLASH_AREA_IMAGE_0_SLOTS -#elif (MCUBOOT_IMAGE_NUMBER == 2) -#define ALL_AVAILABLE_SLOTS FLASH_AREA_IMAGE_0_SLOTS, \ +#elif (MCUBOOT_IMAGE_NUMBER == 2) || (MCUBOOT_IMAGE_NUMBER == 3 && CONFIG_MCUBOOT_MCUBOOT_IMAGE_NUMBER != -1) +#define ALL_AVAILABLE_SLOTS FLASH_AREA_IMAGE_0_SLOTS \ FLASH_AREA_IMAGE_1_SLOTS -#elif (MCUBOOT_IMAGE_NUMBER == 3) -#define ALL_AVAILABLE_SLOTS FLASH_AREA_IMAGE_0_SLOTS, \ - FLASH_AREA_IMAGE_1_SLOTS, \ +#elif (MCUBOOT_IMAGE_NUMBER == 3) || (MCUBOOT_IMAGE_NUMBER == 4 && CONFIG_MCUBOOT_MCUBOOT_IMAGE_NUMBER != -1) +#define ALL_AVAILABLE_SLOTS FLASH_AREA_IMAGE_0_SLOTS \ + FLASH_AREA_IMAGE_1_SLOTS \ FLASH_AREA_IMAGE_2_SLOTS +#elif (MCUBOOT_IMAGE_NUMBER == 4) +#define ALL_AVAILABLE_SLOTS FLASH_AREA_IMAGE_0_SLOTS \ + FLASH_AREA_IMAGE_1_SLOTS \ + FLASH_AREA_IMAGE_2_SLOTS \ + FLASH_AREA_IMAGE_3_SLOTS #else #error Unsupported number of images #endif @@ -65,6 +53,7 @@ static inline uint32_t __flash_area_ids_for_slot(int img, int slot) { static const int all_slots[] = { ALL_AVAILABLE_SLOTS + MCUBOOT_S0_S1_SLOTS }; return all_slots[img * 2 + slot]; }; @@ -72,6 +61,8 @@ static inline uint32_t __flash_area_ids_for_slot(int img, int slot) #undef FLASH_AREA_IMAGE_0_SLOTS #undef FLASH_AREA_IMAGE_1_SLOTS #undef FLASH_AREA_IMAGE_2_SLOTS +#undef FLASH_AREA_IMAGE_3_SLOTS +#undef MCUBOOT_S0_S1_SLOTS #undef ALL_AVAILABLE_SLOTS #define FLASH_AREA_IMAGE_PRIMARY(x) __flash_area_ids_for_slot(x, 0) @@ -81,10 +72,6 @@ static inline uint32_t __flash_area_ids_for_slot(int img, int slot) #define FLASH_AREA_IMAGE_SCRATCH PM_MCUBOOT_SCRATCH_ID #endif -#endif /* MCUBOOT_IMAGE_NUMBER == 2) && defined(PM_B0_ADDRESS) && \ - * !defined(CONFIG_NRF53_MULTI_IMAGE_UPDATE) - */ - #else /* CONFIG_SINGLE_APPLICATION_SLOT */ #define FLASH_AREA_IMAGE_PRIMARY(x) PM_MCUBOOT_PRIMARY_ID From 4aba01c40bc3983d3d341b802b1769670b6f9d43 Mon Sep 17 00:00:00 2001 From: Jamie McCrae Date: Tue, 15 Oct 2024 11:31:20 +0100 Subject: [PATCH 316/420] [nrf noup] boot: bootutil: loader: Add s0/s1 checking of MCUboot image Adds a check that will also check the s0/s1 package version of the currently running MCUboot against a MCUboot update image to ensure that an older version of MCUboot isn't loaded to the opposite slot Signed-off-by: Jamie McCrae (cherry picked from commit 9c834622b023e321350fca2aedb15a8a9570c63a) (cherry picked from commit d5f373adeb1c296c8d312ca8484f5f73414d7f48) --- boot/bootutil/src/loader.c | 68 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 68 insertions(+) diff --git a/boot/bootutil/src/loader.c b/boot/bootutil/src/loader.c index 7b3f8ebac..c22450076 100644 --- a/boot/bootutil/src/loader.c +++ b/boot/bootutil/src/loader.c @@ -83,6 +83,40 @@ static bool owner_nsib[BOOT_IMAGE_NUMBER] = {false}; static struct image_max_size image_max_sizes[BOOT_IMAGE_NUMBER] = {0}; #endif +#if (!defined(MCUBOOT_DIRECT_XIP) && !defined(MCUBOOT_RAM_LOAD)) || \ +defined(MCUBOOT_SERIAL_IMG_GRP_SLOT_INFO) +#if !defined(__BOOTSIM__) +/* Used for holding static buffers in multiple functions to work around issues + * in older versions of gcc (e.g. 4.8.4) + */ +struct sector_buffer_t { + boot_sector_t primary[BOOT_IMAGE_NUMBER][BOOT_MAX_IMG_SECTORS]; + boot_sector_t secondary[BOOT_IMAGE_NUMBER][BOOT_MAX_IMG_SECTORS]; +#if MCUBOOT_SWAP_USING_SCRATCH + boot_sector_t scratch[BOOT_MAX_IMG_SECTORS]; +#endif +}; + +#endif +#endif + +#if CONFIG_MCUBOOT_MCUBOOT_IMAGE_NUMBER != -1 && defined(MCUBOOT_OVERWRITE_ONLY) && \ + defined(MCUBOOT_DOWNGRADE_PREVENTION) +/* s0/s1 package version of the current MCUboot image */ +static const struct image_version mcuboot_s0_s1_image_version = { + .iv_major = CONFIG_MCUBOOT_MCUBOOT_S0_S1_VERSION_MAJOR, + .iv_minor = CONFIG_MCUBOOT_MCUBOOT_S0_S1_VERSION_MINOR, + .iv_revision = CONFIG_MCUBOOT_MCUBOOT_S0_S1_VERSION_REVISION, + .iv_build_num = CONFIG_MCUBOOT_MCUBOOT_S0_S1_VERSION_BUILD_NUMBER, +}; +#endif + +#if (BOOT_IMAGE_NUMBER > 1) +#define IMAGES_ITER(x) for ((x) = 0; (x) < BOOT_IMAGE_NUMBER; ++(x)) +#else +#define IMAGES_ITER(x) +#endif + /* * This macro allows some control on the allocation of local variables. * When running natively on a target, we don't want to allocated huge @@ -997,11 +1031,45 @@ boot_validate_slot(struct boot_loader_state *state, int slot, rc = boot_version_cmp( &boot_img_hdr(state, BOOT_SECONDARY_SLOT)->ih_ver, &boot_img_hdr(state, BOOT_PRIMARY_SLOT)->ih_ver); + +#if CONFIG_MCUBOOT_MCUBOOT_IMAGE_NUMBER != -1 + if (rc >= 0 && BOOT_CURR_IMG(state) == CONFIG_MCUBOOT_MCUBOOT_IMAGE_NUMBER) { + /* Also check the new version of MCUboot against that of the current s0/s1 MCUboot + * trailer version to prevent downgrades + */ + int version_check; + + version_check = boot_version_cmp(&boot_img_hdr(state, BOOT_SECONDARY_SLOT)->ih_ver, + &mcuboot_s0_s1_image_version); + + /* Only update rc if the currently running version is newer */ + if (version_check < rc) { + rc = version_check; + } + } +#endif } #else rc = boot_version_cmp( &boot_img_hdr(state, BOOT_SECONDARY_SLOT)->ih_ver, &boot_img_hdr(state, BOOT_PRIMARY_SLOT)->ih_ver); + +#if CONFIG_MCUBOOT_MCUBOOT_IMAGE_NUMBER != -1 + if (rc >= 0 && BOOT_CURR_IMG(state) == CONFIG_MCUBOOT_MCUBOOT_IMAGE_NUMBER) { + /* Also check the new version of MCUboot against that of the current s0/s1 MCUboot + * trailer version to prevent downgrades + */ + int version_check; + + version_check = boot_version_cmp(&boot_img_hdr(state, BOOT_SECONDARY_SLOT)->ih_ver, + &mcuboot_s0_s1_image_version); + + /* Only update rc if the currently running version is newer */ + if (version_check < rc) { + rc = version_check; + } + } +#endif #endif if (rc < 0 && boot_check_header_erased(state, BOOT_PRIMARY_SLOT)) { BOOT_LOG_ERR("insufficient version in secondary slot"); From 2847335a42f33a49e0f3d4977824a0bd28b1dd83 Mon Sep 17 00:00:00 2001 From: Maximilian Deubel Date: Wed, 23 Oct 2024 16:48:13 +0200 Subject: [PATCH 317/420] [nrf noup] boards: Thingy:91 X release config Update the configuration files for the Thingy:91 X targets to the ones used in production. Signed-off-by: Maximilian Deubel Signed-off-by: Michal Kozikowski (cherry picked from commit be6d73eca89a94e990f57eac4acd8a6c60858a84) --- boot/zephyr/boards/thingy91x_nrf5340_cpuapp.conf | 3 +++ boot/zephyr/boards/thingy91x_nrf9151.conf | 7 +++++-- boot/zephyr/boards/thingy91x_nrf9151.overlay | 4 ++++ 3 files changed, 12 insertions(+), 2 deletions(-) create mode 100644 boot/zephyr/boards/thingy91x_nrf9151.overlay diff --git a/boot/zephyr/boards/thingy91x_nrf5340_cpuapp.conf b/boot/zephyr/boards/thingy91x_nrf5340_cpuapp.conf index 37c7e95b1..d3e253b65 100644 --- a/boot/zephyr/boards/thingy91x_nrf5340_cpuapp.conf +++ b/boot/zephyr/boards/thingy91x_nrf5340_cpuapp.conf @@ -58,3 +58,6 @@ CONFIG_BOOT_SERIAL_IMG_GRP_IMAGE_STATE=y # Skip checks on the secondary image to make it possible to update MCUBoot on S1/S0 CONFIG_MCUBOOT_VERIFY_IMG_ADDRESS=n + +CONFIG_BOOT_SERIAL_NO_APPLICATION=y +CONFIG_FW_INFO_FIRMWARE_VERSION=2 diff --git a/boot/zephyr/boards/thingy91x_nrf9151.conf b/boot/zephyr/boards/thingy91x_nrf9151.conf index 2efe1e170..8088686e0 100644 --- a/boot/zephyr/boards/thingy91x_nrf9151.conf +++ b/boot/zephyr/boards/thingy91x_nrf9151.conf @@ -5,13 +5,16 @@ CONFIG_SPI=y CONFIG_SPI_NOR=y CONFIG_SPI_NOR_FLASH_LAYOUT_PAGE_SIZE=4096 CONFIG_SPI_NOR_SFDP_DEVICETREE=y -CONFIG_MULTITHREADING=y # Disable Zephyr console and use UART for MCUboot serial recovery instead CONFIG_CONSOLE=n CONFIG_CONSOLE_HANDLER=n CONFIG_UART_CONSOLE=n CONFIG_MCUBOOT_SERIAL=y - CONFIG_MCUBOOT_SERIAL_DIRECT_IMAGE_UPLOAD=y CONFIG_BOOT_SERIAL_IMG_GRP_IMAGE_STATE=y + +CONFIG_PM_EXTERNAL_FLASH_MCUBOOT_SECONDARY=y +CONFIG_PM_OVERRIDE_EXTERNAL_DRIVER_CHECK=y + +CONFIG_FW_INFO_FIRMWARE_VERSION=2 diff --git a/boot/zephyr/boards/thingy91x_nrf9151.overlay b/boot/zephyr/boards/thingy91x_nrf9151.overlay new file mode 100644 index 000000000..7f2818c0d --- /dev/null +++ b/boot/zephyr/boards/thingy91x_nrf9151.overlay @@ -0,0 +1,4 @@ +&uart0 { + status = "okay"; + current-speed = < 1000000 >; +}; From 6ac98445b02bd0795b4e0dfd10544032592fafd8 Mon Sep 17 00:00:00 2001 From: Carles Cufi Date: Fri, 25 Oct 2024 09:37:44 +0200 Subject: [PATCH 318/420] [nrf noup] workflows: Add a backport workflow Enable backporting of PRs. Signed-off-by: Carles Cufi (cherry picked from commit e40684941b5d29b21d9ae4d4afb56841b685f177) --- .github/workflows/backport.yml | 31 +++++++++++++++++++++++++++++++ 1 file changed, 31 insertions(+) create mode 100644 .github/workflows/backport.yml diff --git a/.github/workflows/backport.yml b/.github/workflows/backport.yml new file mode 100644 index 000000000..e986738ff --- /dev/null +++ b/.github/workflows/backport.yml @@ -0,0 +1,31 @@ +name: Backport +on: + pull_request_target: + types: + - closed + - labeled + branches: + - main + +jobs: + backport: + name: Backport + runs-on: ubuntu-22.04 + # Only react to merged PRs for security reasons. + # See https://docs.github.com/en/actions/using-workflows/events-that-trigger-workflows#pull_request_target. + if: > + github.event.pull_request.merged && + ( + github.event.action == 'closed' || + ( + github.event.action == 'labeled' && + contains(github.event.label.name, 'backport') + ) + ) + steps: + - name: Backport + uses: zephyrproject-rtos/action-backport@v2.0.3-3 + with: + github_token: ${{ secrets.NCS_GITHUB_TOKEN }} + issue_labels: Backport + labels_template: '["Backport"]' From 5ef6baed45e914285714c0ff5058e2a19cd43c31 Mon Sep 17 00:00:00 2001 From: Mateusz Michalek Date: Thu, 7 Nov 2024 11:09:18 +0100 Subject: [PATCH 319/420] [nrf noup] boot/zephyr: add nrf54l15dk ext flash configs Moved configs from nrf54l15pdk. Turn protection on fprotect by default. Signed-off-by: Andrzej Puzdrowski Signed-off-by: Mateusz Michalek Signed-off-by: Michal Kozikowski Signed-off-by: Jamie McCrae (cherry picked from commit 835b63f3a179634b5c265aa1f39f4834b54bd9cc) --- .../boards/nrf54l15dk_nrf54l15_cpuapp.conf | 16 ------- .../nrf54l15dk_nrf54l15_cpuapp_ext_flash.conf | 9 ++++ ...f54l15dk_nrf54l15_cpuapp_ext_flash.overlay | 48 +++++++++++++++++++ boot/zephyr/prj.conf | 1 - .../nrf54l05_cpuapp.conf} | 0 .../nrf54l10_cpuapp.conf} | 0 boot/zephyr/socs/nrf54l15_cpuapp.conf | 14 ++++++ 7 files changed, 71 insertions(+), 17 deletions(-) delete mode 100644 boot/zephyr/boards/nrf54l15dk_nrf54l15_cpuapp.conf create mode 100644 boot/zephyr/boards/nrf54l15dk_nrf54l15_cpuapp_ext_flash.conf create mode 100644 boot/zephyr/boards/nrf54l15dk_nrf54l15_cpuapp_ext_flash.overlay rename boot/zephyr/{boards/nrf54l15dk_nrf54l05_cpuapp.conf => socs/nrf54l05_cpuapp.conf} (100%) rename boot/zephyr/{boards/nrf54l15dk_nrf54l10_cpuapp.conf => socs/nrf54l10_cpuapp.conf} (100%) diff --git a/boot/zephyr/boards/nrf54l15dk_nrf54l15_cpuapp.conf b/boot/zephyr/boards/nrf54l15dk_nrf54l15_cpuapp.conf deleted file mode 100644 index 1dbd7c1ab..000000000 --- a/boot/zephyr/boards/nrf54l15dk_nrf54l15_cpuapp.conf +++ /dev/null @@ -1,16 +0,0 @@ -# Copyright (c) 2024 Nordic Semiconductor ASA -# -# SPDX-License-Identifier: Apache-2.0 -# -CONFIG_BOOT_MAX_IMG_SECTORS=256 - -# Ensure that the SPI NOR driver is disabled by default -CONFIG_SPI_NOR=n - -# TODO: below are not yet supported and need fixing -CONFIG_FPROTECT=n - -CONFIG_BOOT_WATCHDOG_FEED=n - -# Ensure the fastest RRAM write operations -CONFIG_NRF_RRAM_WRITE_BUFFER_SIZE=32 diff --git a/boot/zephyr/boards/nrf54l15dk_nrf54l15_cpuapp_ext_flash.conf b/boot/zephyr/boards/nrf54l15dk_nrf54l15_cpuapp_ext_flash.conf new file mode 100644 index 000000000..ec944f828 --- /dev/null +++ b/boot/zephyr/boards/nrf54l15dk_nrf54l15_cpuapp_ext_flash.conf @@ -0,0 +1,9 @@ +CONFIG_SPI=y +CONFIG_SPI_NOR=y +CONFIG_FLASH=y +CONFIG_PM_PARTITION_SIZE_MCUBOOT=0x14000 +CONFIG_MAIN_STACK_SIZE=20480 +CONFIG_BOOT_MAX_IMG_SECTORS=512 +CONFIG_SPI_NOR_FLASH_LAYOUT_PAGE_SIZE=4096 +# Ensure that the qspi driver is disabled by default +CONFIG_NORDIC_QSPI_NOR=n diff --git a/boot/zephyr/boards/nrf54l15dk_nrf54l15_cpuapp_ext_flash.overlay b/boot/zephyr/boards/nrf54l15dk_nrf54l15_cpuapp_ext_flash.overlay new file mode 100644 index 000000000..ba6274221 --- /dev/null +++ b/boot/zephyr/boards/nrf54l15dk_nrf54l15_cpuapp_ext_flash.overlay @@ -0,0 +1,48 @@ +/ { + chosen { + nordic,pm-ext-flash = &mx25r64; + zephyr,code-partition = &boot_partition; + }; +}; + +/delete-node/ &boot_partition; +/delete-node/ &slot0_partition; +/delete-node/ &slot1_partition; + +/delete-node/ &storage_partition; + +&cpuapp_rram { + reg = < 0x0 DT_SIZE_K(1524) >; + + partitions { + boot_partition: partition@0 { + label = "mcuboot"; + reg = <0x000000000 0x00014000>; + }; + + slot0_partition: partition@14000 { + label = "image-0"; + reg = <0x000014000 0x0015A000>; + }; + + storage_partition: partition@16E000 { + label = "storage"; + reg = < 0x16E000 0x9000 >; + }; + }; +}; + +&mx25r64 { + status = "okay"; + + partitions { + compatible = "fixed-partitions"; + #address-cells = <1>; + #size-cells = <1>; + + slot1_partition: partition@0 { + label = "image-1"; + reg = <0x000000000 0x0015A000>; + }; + }; +}; diff --git a/boot/zephyr/prj.conf b/boot/zephyr/prj.conf index 615daf599..b824ca1b1 100644 --- a/boot/zephyr/prj.conf +++ b/boot/zephyr/prj.conf @@ -12,7 +12,6 @@ CONFIG_BOOT_BOOTSTRAP=n # CONFIG_HEAP_MEM_POOL_SIZE is not set CONFIG_FLASH=y -CONFIG_FPROTECT=y ### Various Zephyr boards enable features that we don't want. # CONFIG_BT is not set diff --git a/boot/zephyr/boards/nrf54l15dk_nrf54l05_cpuapp.conf b/boot/zephyr/socs/nrf54l05_cpuapp.conf similarity index 100% rename from boot/zephyr/boards/nrf54l15dk_nrf54l05_cpuapp.conf rename to boot/zephyr/socs/nrf54l05_cpuapp.conf diff --git a/boot/zephyr/boards/nrf54l15dk_nrf54l10_cpuapp.conf b/boot/zephyr/socs/nrf54l10_cpuapp.conf similarity index 100% rename from boot/zephyr/boards/nrf54l15dk_nrf54l10_cpuapp.conf rename to boot/zephyr/socs/nrf54l10_cpuapp.conf diff --git a/boot/zephyr/socs/nrf54l15_cpuapp.conf b/boot/zephyr/socs/nrf54l15_cpuapp.conf index 8db9d2d23..645325513 100644 --- a/boot/zephyr/socs/nrf54l15_cpuapp.conf +++ b/boot/zephyr/socs/nrf54l15_cpuapp.conf @@ -1,3 +1,17 @@ +# Copyright (c) 2024 Nordic Semiconductor ASA +# +# SPDX-License-Identifier: Apache-2.0 +# +CONFIG_BOOT_MAX_IMG_SECTORS=256 + +# Ensure that the SPI NOR driver is disabled by default +CONFIG_SPI_NOR=n + +CONFIG_BOOT_WATCHDOG_FEED=n + +# Ensure the fastest RRAM write operations +CONFIG_NRF_RRAM_WRITE_BUFFER_SIZE=32 + # Link Time Optimizations CONFIG_ISR_TABLES_LOCAL_DECLARATION=y CONFIG_LTO=y From 232924ad3a61cec7989c5253cc6f2c9fa181f3f8 Mon Sep 17 00:00:00 2001 From: Andrzej Puzdrowski Date: Thu, 19 Sep 2024 14:32:37 +0200 Subject: [PATCH 320/420] [nrf noup] boot/zephyr/Kconfig: conditionally disable BOOT_MAX_IMG_SECTORS_AUTO Automatic calculation are based on DTS data which are no the right source on partition layout in case Partition manager does the partitioning. Signed-off-by: Andrzej Puzdrowski Signed-off-by: Dominik Ermel (cherry picked from commit a4457ac3dd0a734fb7ff2122fef2eadc3dc5b2ad) --- boot/zephyr/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/boot/zephyr/Kconfig b/boot/zephyr/Kconfig index 03c591346..e17f35106 100644 --- a/boot/zephyr/Kconfig +++ b/boot/zephyr/Kconfig @@ -758,7 +758,7 @@ config BOOT_ENCRYPTION_KEY_FILE config BOOT_MAX_IMG_SECTORS_AUTO bool "Calculate maximum sectors automatically" - default y + default y if !PARTITION_MANAGER_ENABLED help If this option is enabled then the maximum number of supported sectors per image will be calculated automatically from the flash erase sizes and size of each partition for From c2358e0ff06fa1c063e65d3952b5fc73fdf0665f Mon Sep 17 00:00:00 2001 From: Jamie McCrae Date: Mon, 9 Dec 2024 12:27:38 +0000 Subject: [PATCH 321/420] [nrf noup] boot: zephyr: serial_recovery: Add nRF5340 Kconfig override Adds additional conditions that lets the direct upload option to be selected on nRF5340 to allow for uploading network core updates directly to the network core with the flash simulator Signed-off-by: Jamie McCrae (cherry picked from commit 2f3b28c09ebc156310732cc991d2c5995e62aed2) --- boot/zephyr/Kconfig.serial_recovery | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/boot/zephyr/Kconfig.serial_recovery b/boot/zephyr/Kconfig.serial_recovery index 45d252408..5b4ba3e11 100644 --- a/boot/zephyr/Kconfig.serial_recovery +++ b/boot/zephyr/Kconfig.serial_recovery @@ -46,9 +46,14 @@ config BOOT_SERIAL_CDC_ACM endchoice +DT_COMPAT_SIM_FLASH:= zephyr,sim-flash +DT_SIM_FLASH_PATH := $(dt_nodelabel_path,flash_sim0) + config MCUBOOT_SERIAL_DIRECT_IMAGE_UPLOAD bool "Allow to select image number for DFU" - depends on !SINGLE_APPLICATION_SLOT + # Allow this option to be selected in cases where support for direct uploading to nRF5340 + # network core should be supported + depends on !SINGLE_APPLICATION_SLOT || (SINGLE_APPLICATION_SLOT && SOC_NRF5340_CPUAPP && BOOT_IMAGE_ACCESS_HOOK_NRF5340 && FLASH_SIMULATOR && $(dt_compat_enabled,$(DT_COMPAT_SIM_FLASH))) help With the option enabled, the mcuboot serial recovery will respect the "image" field in mcumgr image update frame From eb8734740049d42334fadafd312347204c60c351 Mon Sep 17 00:00:00 2001 From: Jamie McCrae Date: Thu, 5 Dec 2024 10:20:19 +0000 Subject: [PATCH 322/420] [nrf noup] boot: Remove child/parent references Removes stray child/parent references Signed-off-by: Jamie McCrae (cherry picked from commit 9e2bba9806b33af0d52e1f62774de55a48d2538d) --- boot/bootutil/src/swap_priv.h | 2 +- boot/zephyr/pm.yml | 2 -- 2 files changed, 1 insertion(+), 3 deletions(-) diff --git a/boot/bootutil/src/swap_priv.h b/boot/bootutil/src/swap_priv.h index 90e0b3742..10473a9cc 100644 --- a/boot/bootutil/src/swap_priv.h +++ b/boot/bootutil/src/swap_priv.h @@ -131,7 +131,7 @@ bool swap_write_block_size_check(struct boot_loader_state *state); int app_max_size(struct boot_loader_state *state); #if defined(PM_S1_ADDRESS) && !defined(MCUBOOT_OVERWRITE_ONLY) && \ -(CONFIG_MCUBOOT_MCUBOOT_IMAGE_NUMBER != -1 || defined(LEGACY_CHILD_PARENT_S0_S1_UPDATE_ENABLED)) +CONFIG_MCUBOOT_MCUBOOT_IMAGE_NUMBER != -1 /** * Performs an NSIB update */ diff --git a/boot/zephyr/pm.yml b/boot/zephyr/pm.yml index 13ffc44aa..ab8f6d1c3 100644 --- a/boot/zephyr/pm.yml +++ b/boot/zephyr/pm.yml @@ -4,9 +4,7 @@ mcuboot: size: CONFIG_PM_PARTITION_SIZE_MCUBOOT placement: before: [mcuboot_primary] -#if defined(CONFIG_HIDE_CHILD_PARENT_CONFIG) align: {end: 0x1000} -#endif mcuboot_primary_app: # All images to be placed in MCUboot's slot 0 should be placed in this From dbbf3fd5ed430df4c573bab4870ad6bbc044c960 Mon Sep 17 00:00:00 2001 From: Dominik Ermel Date: Wed, 15 Jan 2025 15:09:55 +0000 Subject: [PATCH 323/420] [nrf noup] sysflash: Add missing _FLASH_0_ID definitions MCUboot uses SOC_FLASH_0_ID and SPI_FLASH_0_ID to distinguish between internal and external boot device. These IDs are provided by sysflash.h, but the pm_sysflash.h overrides entire file, and was lacking that definitions. Signed-off-by: Dominik Ermel (cherry picked from commit 60dcc0d468fde468f36637a5603204a8ea972b9b) --- boot/zephyr/include/sysflash/pm_sysflash.h | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/boot/zephyr/include/sysflash/pm_sysflash.h b/boot/zephyr/include/sysflash/pm_sysflash.h index 42f25182e..0cb16292f 100644 --- a/boot/zephyr/include/sysflash/pm_sysflash.h +++ b/boot/zephyr/include/sysflash/pm_sysflash.h @@ -84,4 +84,12 @@ static inline uint32_t __flash_area_ids_for_slot(int img, int slot) #endif /* CONFIG_SINGLE_APPLICATION_SLOT */ +#ifndef SOC_FLASH_0_ID +#define SOC_FLASH_0_ID 0 +#endif + +#ifndef SPI_FLASH_0_ID +#define SPI_FLASH_0_ID 1 +#endif + #endif /* __PM_SYSFLASH_H__ */ From 19e8300332439b8d71e4aada5b90db4625ae6910 Mon Sep 17 00:00:00 2001 From: Kamil Kasperczyk Date: Fri, 24 Jan 2025 08:59:31 +0100 Subject: [PATCH 324/420] [nrf noup] boot: zephyr: boards: Disabled NCS boot banner for thingy 53 Disabled NCS BOOT BANNER to save some flash, as Thingy:53 stopped to fit in the mcuboot partition. The boot banner is not used anyway, as logs are disabled. Signed-off-by: Kamil Kasperczyk (cherry picked from commit fd3ccd378677d6cd27df57dcb774698fa5adbdd9) --- boot/zephyr/boards/thingy53_nrf5340_cpuapp.conf | 1 + 1 file changed, 1 insertion(+) diff --git a/boot/zephyr/boards/thingy53_nrf5340_cpuapp.conf b/boot/zephyr/boards/thingy53_nrf5340_cpuapp.conf index d68509786..bbef18460 100644 --- a/boot/zephyr/boards/thingy53_nrf5340_cpuapp.conf +++ b/boot/zephyr/boards/thingy53_nrf5340_cpuapp.conf @@ -47,6 +47,7 @@ CONFIG_USB_CDC_ACM=y CONFIG_CBPRINTF_NANO=y CONFIG_TIMESLICING=n CONFIG_BOOT_BANNER=n +CONFIG_NCS_BOOT_BANNER=n CONFIG_CONSOLE=n CONFIG_CONSOLE_HANDLER=n CONFIG_UART_CONSOLE=n From 4185e97573e4ab34e501cf8dc7904d09e5c67507 Mon Sep 17 00:00:00 2001 From: Sigurd Hellesvik Date: Thu, 6 Feb 2025 08:47:39 +0100 Subject: [PATCH 325/420] [nrf noup] partition_manager: Add support for internal flash netcore DFU Adds check to region of mcuboot_secondary_1 to put it in external flash only if CONFIG_PM_EXTERNAL_FLASH_MCUBOOT_SECONDARY is set. This should allow for DFU from internal flash on the nRF5340 with dynamic partitioning. Also fixing a typo. Signed-off-by: Sigurd Hellesvik (cherry picked from commit 1f1b7be6c9500a53f9e55fe30a6b22898d5d478f) --- boot/zephyr/pm.yml | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/boot/zephyr/pm.yml b/boot/zephyr/pm.yml index ab8f6d1c3..eec62473c 100644 --- a/boot/zephyr/pm.yml +++ b/boot/zephyr/pm.yml @@ -78,11 +78,17 @@ mcuboot_pad: mcuboot_primary_1: region: ram_flash size: CONFIG_NRF53_RAM_FLASH_SIZE -#endif /* CONFIG_NRF53_MULTI_IMAGE_UPDATE */ +#endif /* CONFIG_NRF53_MCUBOOT_PRIMARY_1_RAM_FLASH */ #if (CONFIG_NRF53_MULTI_IMAGE_UPDATE) mcuboot_secondary_1: +#if defined(CONFIG_PM_EXTERNAL_FLASH_MCUBOOT_SECONDARY) region: external_flash +#else + placement: + align: {start: CONFIG_FPROTECT_BLOCK_SIZE} + after: mcuboot_secondary +#endif size: CONFIG_NRF53_RAM_FLASH_SIZE #endif /* CONFIG_NRF53_MULTI_IMAGE_UPDATE */ From 0918e210c4d427fc3f8b077680f710b4a6453379 Mon Sep 17 00:00:00 2001 From: Dominik Ermel Date: Tue, 4 Mar 2025 17:31:33 +0000 Subject: [PATCH 326/420] [nrf noup] zephyr: sdk-nrf specific overrides on PSA Kconfigs Select proper configuration and disable mbedTLS selection, as we are using NRF Security enabled Oberon. Signed-off-by: Dominik Ermel Signed-off-by: Artur Hadasz (cherry picked from commit f471000c9946cbd678b25ce9b63427550d525450) --- boot/bootutil/zephyr/CMakeLists.txt | 2 +- boot/zephyr/Kconfig | 18 +++++++++++------- 2 files changed, 12 insertions(+), 8 deletions(-) diff --git a/boot/bootutil/zephyr/CMakeLists.txt b/boot/bootutil/zephyr/CMakeLists.txt index f6d37441c..44f78f395 100644 --- a/boot/bootutil/zephyr/CMakeLists.txt +++ b/boot/bootutil/zephyr/CMakeLists.txt @@ -40,7 +40,7 @@ if(CONFIG_BOOT_USE_PSA_CRYPTO) ) endif() -if(CONFIG_BOOT_USE_MBEDTLS OR CONFIG_BOOT_USE_PSA_CRYPTO) +if(CONFIG_BOOT_USE_MBEDTLS OR CONFIG_BOOT_USE_PSA_CRYPTO AND NOT CONFIG_NRF_SECURITY) zephyr_link_libraries(mbedTLS) endif() endif() diff --git a/boot/zephyr/Kconfig b/boot/zephyr/Kconfig index e17f35106..45e2623fb 100644 --- a/boot/zephyr/Kconfig +++ b/boot/zephyr/Kconfig @@ -88,8 +88,7 @@ config BOOT_PSA_IMG_HASH_ALG_SHA512_DEPENDENCIES config BOOT_ED25519_PSA_DEPENDENCIES bool select PSA_WANT_ALG_PURE_EDDSA - # Seems that upstream mbedTLS does not have TE - #select PSA_WANT_ECC_TWISTED_EDWARDS_255 + select PSA_WANT_ECC_TWISTED_EDWARDS_255 select PSA_WANT_ECC_MONTGOMERY_255 select PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_IMPORT help @@ -119,7 +118,7 @@ endif # BOOT_ENCRYPT_IMAGE config BOOT_ECDSA_PSA_DEPENDENCIES bool select PSA_WANT_ALG_ECDSA - select PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_IMPORT + select PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_IMPORT if !PSA_CORE_LITE select PSA_WANT_ECC_SECP_R1_256 help Dependencies for ECDSA signature @@ -248,7 +247,8 @@ choice BOOT_SIGNATURE_TYPE config BOOT_SIGNATURE_TYPE_NONE bool "No signature; use only hash check" - select BOOT_USE_TINYCRYPT + select BOOT_USE_TINYCRYPT if !SOC_SERIES_NRF54LX + select BOOT_USE_PSA_CRYPTO if SOC_SERIES_NRF54LX select BOOT_IMG_HASH_ALG_SHA256_ALLOW config BOOT_SIGNATURE_TYPE_RSA @@ -280,6 +280,7 @@ config BOOT_SIGNATURE_TYPE_ECDSA_P256 if BOOT_SIGNATURE_TYPE_ECDSA_P256 choice BOOT_ECDSA_IMPLEMENTATION prompt "Ecdsa implementation" + default BOOT_ECDSA_PSA if NRF_SECURITY default BOOT_ECDSA_TINYCRYPT config BOOT_ECDSA_TINYCRYPT @@ -296,11 +297,12 @@ config BOOT_ECDSA_CC310 config BOOT_ECDSA_PSA bool "Use psa cryptoo" + depends on NRF_SECURITY select BOOT_USE_PSA_CRYPTO select PSA_CRYPTO_CLIENT select PSA_CRYPTO_C - select BOOT_IMG_HASH_ALG_SHA256_ALLOW - select BOOT_IMG_HASH_ALG_SHA512_ALLOW + select BOOT_IMG_HASH_ALG_SHA256_ALLOW if !PSA_CORE_LITE + select BOOT_IMG_HASH_ALG_SHA512_ALLOW if !PSA_CORE_LITE select BOOT_ECDSA_PSA_DEPENDENCIES endchoice # Ecdsa implementation @@ -332,6 +334,7 @@ config BOOT_SIGNATURE_TYPE_PURE choice BOOT_ED25519_IMPLEMENTATION prompt "Ecdsa implementation" + default BOOT_ED25519_PSA if NRF_SECURITY default BOOT_ED25519_TINYCRYPT config BOOT_ED25519_TINYCRYPT @@ -352,7 +355,7 @@ config BOOT_ED25519_MBEDTLS config BOOT_ED25519_PSA bool "Use PSA crypto" - select MBEDTLS + depends on NRF_SECURITY select BOOT_USE_PSA_CRYPTO select PSA_CRYPTO_CLIENT select PSA_CRYPTO_C @@ -442,6 +445,7 @@ config MBEDTLS_CFG_FILE # is used, but the fact is that Mbed TLS' ASN1 parse module is used # also when TinyCrypt is used as crypto backend. default "mcuboot-mbedtls-cfg.h" if BOOT_USE_TINYCRYPT + default "config-tls-generic.h" if NRF_SECURITY && (MBEDTLS_BUILTIN || BOOT_USE_PSA_CRYPTO) default "mcuboot-mbedtls-cfg.h" if BOOT_USE_MBEDTLS && !MBEDTLS_BUILTIN config BOOT_HW_KEY From 306a2496d9149b30fb85cb5fa3fc28ffb6ff21d3 Mon Sep 17 00:00:00 2001 From: Jamie McCrae Date: Tue, 11 Jul 2023 08:42:49 +0100 Subject: [PATCH 327/420] [nrf noup] zephyr: Fix path variables Fixes path variables to use the proper Zephyr module variables Signed-off-by: Jamie McCrae Signed-off-by: Dominik Ermel (cherry picked from commit 791dd599386c95e464c6958927fb98a88dd61e3e) --- boot/zephyr/CMakeLists.txt | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/boot/zephyr/CMakeLists.txt b/boot/zephyr/CMakeLists.txt index 918de1041..6563f79d9 100644 --- a/boot/zephyr/CMakeLists.txt +++ b/boot/zephyr/CMakeLists.txt @@ -35,21 +35,20 @@ if(NOT CONFIG_MBEDTLS_BUILTIN AND NOT CONFIG_BOOT_KEY_IMPORT_BYPASS_ASN) set(MBEDTLS_ASN1_DIR "${MCUBOOT_DIR}/ext/mbedtls-asn1") assert_exists(MBEDTLS_ASN1_DIR) endif() -set(NRF_DIR "${MCUBOOT_DIR}/ext/nrf") +set(MCUBOOT_NRF_EXT_DIR "${MCUBOOT_DIR}/ext/nrf") if(CONFIG_BOOT_USE_NRF_CC310_BL) -set(NRFXLIB_DIR ${ZEPHYR_BASE}/../nrfxlib) -if(NOT EXISTS ${NRFXLIB_DIR}) - message(FATAL_ERROR " + if(NOT EXISTS ${ZEPHYR_NRFXLIB_MODULE_DIR}) + message(FATAL_ERROR " ------------------------------------------------------------------------ - No such file or directory: ${NRFXLIB_DIR} + No such file or directory: ${ZEPHYR_NRFXLIB_MODULE_DIR} The current configuration enables nRF CC310 crypto accelerator hardware with the `CONFIG_BOOT_USE_NRF_CC310_BL` option. Please follow `ext/nrf/README.md` guide to fix your setup or use tinycrypt instead of the HW accelerator. To use the tinycrypt set `CONFIG_BOOT_ECDSA_TINYCRYPT` to y. ------------------------------------------------------------------------") -endif() + endif() endif() zephyr_library_include_directories( @@ -216,8 +215,8 @@ if(CONFIG_BOOT_SIGNATURE_TYPE_ECDSA_P256 OR CONFIG_BOOT_ENCRYPT_EC256) ${TINYCRYPT_DIR}/source/utils.c ) elseif(CONFIG_BOOT_USE_NRF_CC310_BL) - zephyr_library_sources(${NRF_DIR}/cc310_glue.c) - zephyr_library_include_directories(${NRF_DIR}) + zephyr_library_sources(${MCUBOOT_NRF_EXT_DIR}/cc310_glue.c) + zephyr_library_include_directories(${MCUBOOT_NRF_EXT_DIR}) zephyr_link_libraries(nrfxlib_crypto) elseif(CONFIG_BOOT_USE_NRF_EXTERNAL_CRYPTO) zephyr_include_directories(${BL_CRYPTO_DIR}/../include) From ce02ebecac971f6821c1fbc940054df472d1deed Mon Sep 17 00:00:00 2001 From: Dominik Ermel Date: Fri, 14 Mar 2025 17:51:23 +0000 Subject: [PATCH 328/420] [nrf noup] zephyr: Use mbedTLS specific C functions with RSA Use snprinf, alloc, calloc and free from mbedTLS rather than from Zephyr. Signed-off-by: Dominik Ermel (cherry picked from commit 7f674d9817e30c458a33af49211a34f21bb023da) --- boot/zephyr/Kconfig | 2 ++ 1 file changed, 2 insertions(+) diff --git a/boot/zephyr/Kconfig b/boot/zephyr/Kconfig index 45e2623fb..8d37e2bad 100644 --- a/boot/zephyr/Kconfig +++ b/boot/zephyr/Kconfig @@ -261,6 +261,8 @@ config BOOT_SIGNATURE_TYPE_RSA select MBEDTLS_PKCS1_V15 if MBEDTLS_BUILTIN select MBEDTLS_PKCS1_V21 if MBEDTLS_BUILTIN select MBEDTLS_KEY_EXCHANGE_RSA_ENABLED if MBEDTLS_BUILTIN + select MBEDTLS_PLATFORM_NO_STD_FUNCTIONS if MBEDTLS_BUILTIN + select MBEDTLS_PLATFORM_SNPRINTF_ALT if MBEDTLS_BUILTIN select BOOT_ENCRYPTION_SUPPORT select BOOT_IMG_HASH_ALG_SHA256_ALLOW select BOOT_AES_MBEDTLS_DEPENDENCIES if MBEDTLS_BUILTIN && BOOT_ENCRYPT_IMAGE From 1bb784582fbfea8da55fb8242a3f05c72ebd0666 Mon Sep 17 00:00:00 2001 From: Michal Kozikowski Date: Mon, 10 Mar 2025 17:23:37 +0100 Subject: [PATCH 329/420] [nrf noup] boot/zephyr: nrf54h20dk board support Added basic support for nrf54h20dk_nrf54h20_cpuapp_iron board. This commit turns off CONFIG_FPROTECT for this board build. Signed-off-by: Michal Kozikowski (cherry picked from commit c872f6ab7bd026fe779543f24ede6d2b343202f3) --- boot/zephyr/boards/nrf54h20dk_nrf54h20_cpuapp.conf | 3 +++ 1 file changed, 3 insertions(+) diff --git a/boot/zephyr/boards/nrf54h20dk_nrf54h20_cpuapp.conf b/boot/zephyr/boards/nrf54h20dk_nrf54h20_cpuapp.conf index 30594ff39..cddf7b646 100644 --- a/boot/zephyr/boards/nrf54h20dk_nrf54h20_cpuapp.conf +++ b/boot/zephyr/boards/nrf54h20dk_nrf54h20_cpuapp.conf @@ -6,6 +6,9 @@ # Ensure that the SPI NOR driver is disabled by default CONFIG_SPI_NOR=n +# TODO: below are not yet supported and need fixing +CONFIG_FPROTECT=n + CONFIG_BOOT_WATCHDOG_FEED=n # Power domains forced on by default on boot, no need From a5e4aeb25130206c786632e593f28a0625c39d4e Mon Sep 17 00:00:00 2001 From: Michal Kozikowski Date: Fri, 28 Mar 2025 17:46:28 +0100 Subject: [PATCH 330/420] [nrf noup] boot/zephyr: nrf54h20dk cleanup adaptations This commit removes NRF_CLOCK cleanup for this board build - for Lillium, there is no clock peripheral access from the app domain. Signed-off-by: Michal Kozikowski (cherry picked from commit 31766fcae89baee588d1ac49802ce5b1fd7b544d) --- boot/zephyr/nrf_cleanup.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/boot/zephyr/nrf_cleanup.c b/boot/zephyr/nrf_cleanup.c index 051705ec9..72c601db3 100644 --- a/boot/zephyr/nrf_cleanup.c +++ b/boot/zephyr/nrf_cleanup.c @@ -4,7 +4,9 @@ * SPDX-License-Identifier: LicenseRef-Nordic-5-Clause */ +#if !defined(CONFIG_SOC_SERIES_NRF54HX) #include +#endif #include #include #if defined(NRF_RTC0) || defined(NRF_RTC1) || defined(NRF_RTC2) @@ -62,10 +64,12 @@ static NRF_UARTE_Type *nrf_uarte_to_clean[] = { }; #endif +#if !defined(CONFIG_SOC_SERIES_NRF54HX) static void nrf_cleanup_clock(void) { nrf_clock_int_disable(NRF_CLOCK, 0xFFFFFFFF); } +#endif void nrf_cleanup_peripheral(void) { @@ -109,7 +113,10 @@ void nrf_cleanup_peripheral(void) #if defined(NRF_DPPIC) nrf_dppi_channels_disable_all(NRF_DPPIC); #endif + +#if !defined(CONFIG_SOC_SERIES_NRF54HX) nrf_cleanup_clock(); +#endif } #if USE_PARTITION_MANAGER \ From a9918fab45fb9fd0a0ee705ffbc20037152696f6 Mon Sep 17 00:00:00 2001 From: Andrzej Puzdrowski Date: Tue, 5 Mar 2024 18:44:13 +0100 Subject: [PATCH 331/420] [nrf noup] boot/zephyr/nrf_cleanup: cleanup uarte pins Added procedure which does configure UARTE pins to the default states. This allows to reduce power consumption if pin is floating. clean-up UARTE only if its driver was enabled Signed-off-by: Andrzej Puzdrowski (cherry picked from commit fac7ac4990fe9f28348bfb3e0e52ac4bf51c757a) --- boot/zephyr/nrf_cleanup.c | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/boot/zephyr/nrf_cleanup.c b/boot/zephyr/nrf_cleanup.c index 72c601db3..1252334ca 100644 --- a/boot/zephyr/nrf_cleanup.c +++ b/boot/zephyr/nrf_cleanup.c @@ -9,6 +9,7 @@ #endif #include #include +#include #if defined(NRF_RTC0) || defined(NRF_RTC1) || defined(NRF_RTC2) #include #endif @@ -96,6 +97,21 @@ void nrf_cleanup_peripheral(void) nrfy_uarte_event_clear(current, NRF_UARTE_EVENT_RXTO); nrfy_uarte_disable(current); + uint32_t pin[4]; + + pin[0] = nrfy_uarte_tx_pin_get(current); + pin[1] = nrfy_uarte_rx_pin_get(current); + pin[2] = nrfy_uarte_rts_pin_get(current); + pin[3] = nrfy_uarte_cts_pin_get(current); + + nrfy_uarte_pins_disconnect(current); + + for (int j = 0; j < 4; j++) { + if (pin[j] != NRF_UARTE_PSEL_DISCONNECTED) { + nrfy_gpio_cfg_default(pin[i]); + } + } + #if defined(NRF_DPPIC) /* Clear all SUBSCRIBE configurations. */ memset((uint8_t *)current + NRF_UARTE_SUBSCRIBE_CONF_OFFS, 0, From a6105787d1d906b8c362bfc6f6bef36555e7821f Mon Sep 17 00:00:00 2001 From: Andrzej Puzdrowski Date: Tue, 1 Apr 2025 19:30:57 +0200 Subject: [PATCH 332/420] [nrf noup] boot/zephyr/Kconfig: fix MBEDTLS_CFG_FILE value Zephyr provides "mcuboot-mbedtls-cfg.h" as glue interface for configure mbedts. "config-tls-generic.h" default value was erroneously introduced during a meta codebase synchronization. Signed-off-by: Andrzej Puzdrowski (cherry picked from commit c6e2585f8e382a3bc6f1700d892d3636a3155af5) --- boot/zephyr/Kconfig | 1 - 1 file changed, 1 deletion(-) diff --git a/boot/zephyr/Kconfig b/boot/zephyr/Kconfig index 8d37e2bad..cefec0021 100644 --- a/boot/zephyr/Kconfig +++ b/boot/zephyr/Kconfig @@ -447,7 +447,6 @@ config MBEDTLS_CFG_FILE # is used, but the fact is that Mbed TLS' ASN1 parse module is used # also when TinyCrypt is used as crypto backend. default "mcuboot-mbedtls-cfg.h" if BOOT_USE_TINYCRYPT - default "config-tls-generic.h" if NRF_SECURITY && (MBEDTLS_BUILTIN || BOOT_USE_PSA_CRYPTO) default "mcuboot-mbedtls-cfg.h" if BOOT_USE_MBEDTLS && !MBEDTLS_BUILTIN config BOOT_HW_KEY From 5b586d4920f22e1eb28e661694a7d322e749500d Mon Sep 17 00:00:00 2001 From: Andrzej Puzdrowski Date: Fri, 11 Apr 2025 12:55:00 +0200 Subject: [PATCH 333/420] [nrf noup] nrf_cleanup: nRF54l: disable cleanup on UARTE pins Compile out code which does cleanup on UARTE pins as this cause issues on for some applications. ref.: NCSDK-33039 Signed-off-by: Andrzej Puzdrowski (cherry picked from commit 5f6e119a726d9f17b3f65139540db838f2286bde) --- boot/zephyr/nrf_cleanup.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/boot/zephyr/nrf_cleanup.c b/boot/zephyr/nrf_cleanup.c index 1252334ca..f90a46af1 100644 --- a/boot/zephyr/nrf_cleanup.c +++ b/boot/zephyr/nrf_cleanup.c @@ -97,6 +97,12 @@ void nrf_cleanup_peripheral(void) nrfy_uarte_event_clear(current, NRF_UARTE_EVENT_RXTO); nrfy_uarte_disable(current); +#ifndef CONFIG_SOC_SERIES_NRF54LX + /* Disconnect pins UARTE pins + * causes issues on nRF54l SoCs, + * could be enabled once fix to NCSDK-33039 will be implemented. + */ + uint32_t pin[4]; pin[0] = nrfy_uarte_tx_pin_get(current); @@ -111,6 +117,7 @@ void nrf_cleanup_peripheral(void) nrfy_gpio_cfg_default(pin[i]); } } +#endif #if defined(NRF_DPPIC) /* Clear all SUBSCRIBE configurations. */ From 97fcfdce12d3c497cd9b36fb402b8eff1ce6257b Mon Sep 17 00:00:00 2001 From: Mateusz Michalek Date: Wed, 23 Apr 2025 09:05:24 +0200 Subject: [PATCH 334/420] [nrf noup] boot: zephyr: boards: nrf54lm20pdk adding default configs. Signed-off-by: Mateusz Michalek (cherry picked from commit 1aa8af0eae8d67f21cdccd81588f37cebde536c8) --- .../boards/nrf54lm20pdk_nrf54lm20a_cpuapp.conf | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) create mode 100644 boot/zephyr/boards/nrf54lm20pdk_nrf54lm20a_cpuapp.conf diff --git a/boot/zephyr/boards/nrf54lm20pdk_nrf54lm20a_cpuapp.conf b/boot/zephyr/boards/nrf54lm20pdk_nrf54lm20a_cpuapp.conf new file mode 100644 index 000000000..4944f7b13 --- /dev/null +++ b/boot/zephyr/boards/nrf54lm20pdk_nrf54lm20a_cpuapp.conf @@ -0,0 +1,16 @@ +# Copyright (c) 2025 Nordic Semiconductor ASA +# +# SPDX-License-Identifier: Apache-2.0 +# +CONFIG_BOOT_MAX_IMG_SECTORS=256 + +# Ensure that the SPI NOR driver is disabled by default +CONFIG_SPI_NOR=n + +# TODO: below are not yet supported and need fixing +CONFIG_FPROTECT=n + +CONFIG_BOOT_WATCHDOG_FEED=n + +CONFIG_PSA_CRYPTO_DRIVER_CRACEN=n +CONFIG_PSA_CRYPTO_DRIVER_OBERON=y From 4509cebd992d40f7636a518cc7af3e67562b31b0 Mon Sep 17 00:00:00 2001 From: Artur Hadasz Date: Mon, 28 Apr 2025 14:17:35 +0200 Subject: [PATCH 335/420] [nrf noup] nrf_cleanup: nRF54h: fix missing peripheral cleanup This commit adds cleanup for GRTC and UARTE peripherals. ref: NCSDK-32966 Signed-off-by: Artur Hadasz (cherry picked from commit b6c992e20c51fd77c1761450aaae118fee3f097d) --- boot/zephyr/nrf_cleanup.c | 23 ++++++++++++++++++++--- 1 file changed, 20 insertions(+), 3 deletions(-) diff --git a/boot/zephyr/nrf_cleanup.c b/boot/zephyr/nrf_cleanup.c index f90a46af1..39dfcbc41 100644 --- a/boot/zephyr/nrf_cleanup.c +++ b/boot/zephyr/nrf_cleanup.c @@ -4,7 +4,7 @@ * SPDX-License-Identifier: LicenseRef-Nordic-5-Clause */ -#if !defined(CONFIG_SOC_SERIES_NRF54HX) +#if defined(CONFIG_NRFX_CLOCK) #include #endif #include @@ -13,6 +13,9 @@ #if defined(NRF_RTC0) || defined(NRF_RTC1) || defined(NRF_RTC2) #include #endif +#if defined(CONFIG_NRF_GRTC_TIMER) + #include +#endif #if defined(NRF_PPI) #include #endif @@ -48,6 +51,13 @@ static inline void nrf_cleanup_rtc(NRF_RTC_Type * rtc_reg) } #endif +#if defined(CONFIG_NRF_GRTC_TIMER) +static inline void nrf_cleanup_grtc(void) +{ + nrfx_grtc_uninit(); +} +#endif + #if defined(NRF_UARTE_CLEANUP) static NRF_UARTE_Type *nrf_uarte_to_clean[] = { #if defined(NRF_UARTE0) @@ -62,10 +72,13 @@ static NRF_UARTE_Type *nrf_uarte_to_clean[] = { #if defined(NRF_UARTE30) NRF_UARTE30, #endif +#if defined(NRF_UARTE136) + NRF_UARTE136, +#endif }; #endif -#if !defined(CONFIG_SOC_SERIES_NRF54HX) +#if defined(CONFIG_NRFX_CLOCK) static void nrf_cleanup_clock(void) { nrf_clock_int_disable(NRF_CLOCK, 0xFFFFFFFF); @@ -84,6 +97,10 @@ void nrf_cleanup_peripheral(void) nrf_cleanup_rtc(NRF_RTC2); #endif +#if defined(CONFIG_NRF_GRTC_TIMER) + nrf_cleanup_grtc(); +#endif + #if defined(NRF_UARTE_CLEANUP) for (int i = 0; i < sizeof(nrf_uarte_to_clean) / sizeof(nrf_uarte_to_clean[0]); ++i) { NRF_UARTE_Type *current = nrf_uarte_to_clean[i]; @@ -137,7 +154,7 @@ void nrf_cleanup_peripheral(void) nrf_dppi_channels_disable_all(NRF_DPPIC); #endif -#if !defined(CONFIG_SOC_SERIES_NRF54HX) +#if defined(CONFIG_NRFX_CLOCK) nrf_cleanup_clock(); #endif } From d3ee58375b3ae4b421987047cd60e34fab921a89 Mon Sep 17 00:00:00 2001 From: Jamie McCrae Date: Thu, 12 Jun 2025 08:38:15 +0100 Subject: [PATCH 336/420] [nrf noup] boot: zephyr: Add bm firmware loader code Adds firmware loader code for use in baremetal mode Signed-off-by: Jamie McCrae (cherry picked from commit 9200785d3284a15f6a469a86efb79d95b68cce1c) --- boot/zephyr/CMakeLists.txt | 19 ++- boot/zephyr/firmware_loader_bm.c | 283 +++++++++++++++++++++++++++++++ boot/zephyr/io_bm.c | 198 +++++++++++++++++++++ 3 files changed, 496 insertions(+), 4 deletions(-) create mode 100644 boot/zephyr/firmware_loader_bm.c create mode 100644 boot/zephyr/io_bm.c diff --git a/boot/zephyr/CMakeLists.txt b/boot/zephyr/CMakeLists.txt index 6563f79d9..839381d58 100644 --- a/boot/zephyr/CMakeLists.txt +++ b/boot/zephyr/CMakeLists.txt @@ -64,12 +64,17 @@ endif() # Zephyr port-specific sources. zephyr_library_sources( main.c - io.c flash_map_extended.c os.c keys.c ) +if(CONFIG_NCS_BM) + zephyr_library_sources(io_bm.c) +else() + zephyr_library_sources(io.c) +endif() + if(DEFINED CONFIG_ENABLE_MGMT_PERUSER) zephyr_library_sources( boot_serial_extensions.c @@ -148,9 +153,15 @@ elseif(CONFIG_SINGLE_APPLICATION_SLOT) ) zephyr_library_include_directories(${BOOT_DIR}/bootutil/src) elseif(CONFIG_BOOT_FIRMWARE_LOADER) - zephyr_library_sources( - ${BOOT_DIR}/zephyr/firmware_loader.c - ) + if(CONFIG_NCS_BM) + zephyr_library_sources( + ${BOOT_DIR}/zephyr/firmware_loader_bm.c + ) + else() + zephyr_library_sources( + ${BOOT_DIR}/zephyr/firmware_loader.c + ) + endif() zephyr_library_include_directories(${BOOT_DIR}/bootutil/src) else() zephyr_library_sources( diff --git a/boot/zephyr/firmware_loader_bm.c b/boot/zephyr/firmware_loader_bm.c new file mode 100644 index 000000000..14d5c96bd --- /dev/null +++ b/boot/zephyr/firmware_loader_bm.c @@ -0,0 +1,283 @@ +/* + * Copyright (c) 2025 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +#include +#include +#include +#include "bootutil/image.h" +#include "bootutil_priv.h" +#include "bootutil/bootutil_log.h" +#include "bootutil/bootutil_public.h" +#include "bootutil/fault_injection_hardening.h" +#include + +#include "io/io.h" +#include "mcuboot_config/mcuboot_config.h" + +#define IMAGE_TLV_INSTALLER_IMAGE 0xa0 + +BOOT_LOG_MODULE_DECLARE(mcuboot); + +static struct flash_area fa_app_installer = { + .fa_id = 1, + .fa_off = FIXED_PARTITION_OFFSET(slot0_partition), + .fa_size = FIXED_PARTITION_SIZE(slot0_partition), + .fa_dev = DEVICE_DT_GET(DT_CHOSEN(zephyr_flash_controller)), +}; + +static struct image_header hdr_app_installer = { 0 }; + +static struct flash_area fa_softdevice = { + .fa_id = 2, + .fa_dev = DEVICE_DT_GET(DT_CHOSEN(zephyr_flash_controller)), +}; + +static struct image_header hdr_softdevice = { 0 }; + +#ifdef CONFIG_BOOT_FIRMWARE_LOADER +static struct flash_area fa_firmware_loader = { + .fa_id = 3, + .fa_dev = DEVICE_DT_GET(DT_CHOSEN(zephyr_flash_controller)), +}; + +static struct image_header hdr_firmware_loader = { 0 }; +#endif + +/** + * Validate hash of a primary boot image. + * + * @param[in] fa_p flash area pointer + * @param[in] hdr boot image header pointer + * + * @return FIH_SUCCESS on success, error code otherwise + */ +static fih_ret validate_image(const struct flash_area *fap, struct image_header *hdr) +{ + static uint8_t tmpbuf[BOOT_TMPBUF_SZ]; + FIH_DECLARE(fih_rc, FIH_FAILURE); + + FIH_CALL(bootutil_img_validate, fih_rc, NULL, hdr, fap, tmpbuf, BOOT_TMPBUF_SZ, NULL, 0, NULL); + FIH_RET(fih_rc); +} + +/** + * Gather information on image and prepare for booting. Will boot from main + * image if none of the enabled entrance modes for the firmware loader are set, + * otherwise will boot the firmware loader. Note: firmware loader must be a + * valid signed image with the same signing key as the application image. + * + * @param[out] rsp Parameters for booting image, on success + * + * @return FIH_SUCCESS on success; non-zero on failure. + */ +fih_ret +boot_go(struct boot_rsp *rsp) +{ + bool boot_firmware_loader = false; + FIH_DECLARE(fih_rc, FIH_FAILURE); + bool softdevice_area_valid = false; + bool firmware_loader_area_valid = false; + int rc; + bool app_installer_image_valid = false; + bool softdevice_image_valid = false; + bool firmware_loader_image_valid = false; + bool app_installer_is_installer_image = false; + + bm_installs_init(); + + if (bm_installs_is_valid()) { + off_t start_address = 0; + size_t image_size = 0; + + rc = bm_installs_get_image_data(BM_INSTALLS_IMAGE_INDEX_SOFTDEVICE, &start_address, + &image_size); + + if (!rc) { + fa_softdevice.fa_off = start_address; + fa_softdevice.fa_size = image_size; + + if (start_address < fa_app_installer.fa_off) { + /* Invalid start address for SoftDevice */ + goto invalid_softdevice; + } + + fa_app_installer.fa_size = start_address - fa_app_installer.fa_off; + + rc = boot_image_load_header(&fa_softdevice, &hdr_softdevice); + + if (!rc) { + softdevice_area_valid = true; + } + } + +invalid_softdevice: +#ifdef CONFIG_BOOT_FIRMWARE_LOADER + start_address = 0; + image_size = 0; + rc = bm_installs_get_image_data(BM_INSTALLS_IMAGE_INDEX_FIRMWARE_LOADER, &start_address, + &image_size); + + if (!rc) { + fa_firmware_loader.fa_off = start_address; + fa_firmware_loader.fa_size = image_size; + + if (start_address < fa_app_installer.fa_off) { + /* Invalid start address for firmware loader */ + goto invalid_firmware_loader; + } + + fa_app_installer.fa_size = start_address - fa_app_installer.fa_off; + + rc = boot_image_load_header(&fa_firmware_loader, &hdr_softdevice); + + if (!rc) { + firmware_loader_area_valid = true; + } + } +#endif + } + +invalid_firmware_loader: + rc = boot_image_load_header(&fa_app_installer, &hdr_app_installer); + + if (rc) { + BOOT_LOG_ERR("Failed loading application/installer image header: %d", rc); + } else { + FIH_CALL(validate_image, fih_rc, &fa_app_installer, &hdr_app_installer); + + if (FIH_EQ(fih_rc, FIH_SUCCESS)) { + struct image_tlv_iter it; + uint32_t off2; + uint16_t len2; + + app_installer_image_valid = true; + + if (hdr_app_installer.ih_protect_tlv_size > 0) { + rc = bootutil_tlv_iter_begin(&it, &hdr_app_installer, &fa_app_installer, + IMAGE_TLV_INSTALLER_IMAGE, true); + + if (rc == 0) { + rc = bootutil_tlv_iter_next(&it, &off2, &len2, NULL); + + if (rc == 0 && len2 == sizeof(app_installer_is_installer_image)) { + rc = LOAD_IMAGE_DATA(&hdr_app_installer, &fa_app_installer, off2, + &app_installer_is_installer_image, len2); + + if (rc != 0) { + app_installer_is_installer_image = false; + } + } + } + } + } + } + + if (softdevice_area_valid) { + fih_rc = FIH_FAILURE; + rc = boot_image_load_header(&fa_softdevice, &hdr_softdevice); + + if (rc) { + BOOT_LOG_ERR("Failed loading SoftDevice image header: %d", rc); + } else { + FIH_CALL(validate_image, fih_rc, &fa_softdevice, &hdr_softdevice); + + if (FIH_EQ(fih_rc, FIH_SUCCESS)) { + softdevice_image_valid = true; + } + } + } + +#ifdef CONFIG_BOOT_FIRMWARE_LOADER + if (firmware_loader_area_valid) { + fih_rc = FIH_FAILURE; + rc = boot_image_load_header(&fa_firmware_loader, &hdr_firmware_loader); + + if (rc) { + BOOT_LOG_ERR("Failed loading firmware loader image header: %d", rc); + } else { + FIH_CALL(validate_image, fih_rc, &fa_firmware_loader, &hdr_firmware_loader); + + if (FIH_EQ(fih_rc, FIH_SUCCESS)) { + firmware_loader_image_valid = true; + } + } + } +#endif + + BOOT_LOG_DBG("Application/installer partition offset: 0x%lx, size: 0x%x, type: %d", + fa_app_installer.fa_off, fa_app_installer.fa_size, + app_installer_is_installer_image); + BOOT_LOG_DBG("SoftDevice partition offset: 0x%lx, size: 0x%x", fa_softdevice.fa_off, + fa_softdevice.fa_size); +#ifdef CONFIG_BOOT_FIRMWARE_LOADER + BOOT_LOG_DBG("Firmware loader off: 0x%lx, size: 0x%x", fa_firmware_loader.fa_off, + fa_firmware_loader.fa_size); + BOOT_LOG_DBG("SoftDevice area valid: %d, Firmware loader area valid: %d, " + "Application/installer image valid: %d, SoftDevice image valid: %d, " + "Firmware loader image valid: %d", softdevice_area_valid, + firmware_loader_area_valid, app_installer_image_valid, softdevice_image_valid, + firmware_loader_image_valid); +#else + BOOT_LOG_DBG("SoftDevice area valid: %d, Application/installer image valid: %d, " + "SoftDevice image valid: %d", softdevice_area_valid, app_installer_image_valid, + softdevice_image_valid); +#endif + +#ifdef CONFIG_BOOT_FIRMWARE_LOADER_ENTRANCE_GPIO + if (io_detect_pin() && !io_boot_skip_serial_recovery()) { + BOOT_LOG_DBG("GPIO detected for firmware loader mode"); + boot_firmware_loader = true; + } +#endif + +#ifdef CONFIG_BOOT_FIRMWARE_LOADER_PIN_RESET + if (io_detect_pin_reset()) { + BOOT_LOG_DBG("Pin reset detected for firmware loader mode"); + boot_firmware_loader = true; + } +#endif + +#ifdef CONFIG_BOOT_FIRMWARE_LOADER_BOOT_MODE + if (io_detect_boot_mode()) { + BOOT_LOG_DBG("Boot mode detected for firmware loader mode"); + boot_firmware_loader = true; + } +#endif + + if (app_installer_image_valid == true && app_installer_is_installer_image == true) { + /* Installer image is present, this gets priority */ + BOOT_LOG_DBG("Booting installer"); + rsp->br_image_off = flash_area_get_off(&fa_app_installer); + rsp->br_hdr = &hdr_app_installer; + } else if (boot_firmware_loader == true && softdevice_image_valid == true && + firmware_loader_image_valid == true) { + /* Boot firmware loader */ + BOOT_LOG_INF("Booting firmware loader"); + rsp->br_image_off = flash_area_get_off(&fa_firmware_loader); + rsp->br_hdr = &hdr_firmware_loader; + } else if (app_installer_image_valid == true && softdevice_image_valid == true) { + /* Boot main application */ + BOOT_LOG_INF("Booting main application"); + rsp->br_image_off = flash_area_get_off(&fa_app_installer); + rsp->br_hdr = &hdr_app_installer; + } else if (app_installer_image_valid == false && softdevice_image_valid == true && + firmware_loader_image_valid == true) { + /* Boot firmware loader due to missing main image */ + BOOT_LOG_INF("Booting firmware loader due to missing application image"); + rsp->br_image_off = flash_area_get_off(&fa_firmware_loader); + rsp->br_hdr = &hdr_firmware_loader; + } else { + /* Cannot boot in this configuration */ + BOOT_LOG_ERR("Error: no bootable configuration found"); + return -1; + } + + rsp->br_flash_dev_id = flash_area_get_device_id(&fa_app_installer); + + return 0; +} diff --git a/boot/zephyr/io_bm.c b/boot/zephyr/io_bm.c new file mode 100644 index 000000000..3f65a5d0e --- /dev/null +++ b/boot/zephyr/io_bm.c @@ -0,0 +1,198 @@ +/* + * Copyright (c) 2012-2014 Wind River Systems, Inc. + * Copyright (c) 2020 Arm Limited + * Copyright (c) 2021-2025 Nordic Semiconductor ASA + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "target.h" +#include "bootutil/bootutil_log.h" + +#include +#include + +#if defined(CONFIG_BOOT_SERIAL_PIN_RESET) || defined(CONFIG_BOOT_FIRMWARE_LOADER_PIN_RESET) +#include +#endif + +#if defined(CONFIG_BOOT_SERIAL_BOOT_MODE) || defined(CONFIG_BOOT_FIRMWARE_LOADER_BOOT_MODE) +#include +#endif + +/* Validate serial recovery configuration */ +#ifdef CONFIG_MCUBOOT_SERIAL +#if !defined(CONFIG_BOOT_SERIAL_ENTRANCE_GPIO) && \ + !defined(CONFIG_BOOT_SERIAL_WAIT_FOR_DFU) && \ + !defined(CONFIG_BOOT_SERIAL_BOOT_MODE) && \ + !defined(CONFIG_BOOT_SERIAL_NO_APPLICATION) && \ + !defined(CONFIG_BOOT_SERIAL_PIN_RESET) +#error "Serial recovery selected without an entrance mode set" +#endif +#endif + +/* Validate firmware loader configuration */ +#ifdef CONFIG_BOOT_FIRMWARE_LOADER +#if !defined(CONFIG_BOOT_FIRMWARE_LOADER_ENTRANCE_GPIO) && \ + !defined(CONFIG_BOOT_FIRMWARE_LOADER_BOOT_MODE) && \ + !defined(CONFIG_BOOT_FIRMWARE_LOADER_NO_APPLICATION) && \ + !defined(CONFIG_BOOT_FIRMWARE_LOADER_PIN_RESET) +#error "Firmware loader selected without an entrance mode set" +#endif +#endif + +BOOT_LOG_MODULE_DECLARE(mcuboot); + +#ifdef CONFIG_MCUBOOT_INDICATION_LED + +void io_led_init(void) +{ + nrf_gpio_cfg_output(BOARD_PIN_LED_0); + nrf_gpio_pin_write(BOARD_PIN_LED_0, BOARD_LED_ACTIVE_STATE); +} + +void io_led_set(int value) +{ + nrf_gpio_pin_write(BOARD_PIN_LED_0, (value == 0 ? !BOARD_LED_ACTIVE_STATE : BOARD_LED_ACTIVE_STATE)); +} +#endif /* CONFIG_MCUBOOT_INDICATION_LED */ + +#if defined(CONFIG_BOOT_SERIAL_ENTRANCE_GPIO) || defined(CONFIG_BOOT_USB_DFU_GPIO) || \ + defined(CONFIG_BOOT_FIRMWARE_LOADER_ENTRANCE_GPIO) + +#if defined(CONFIG_MCUBOOT_SERIAL) +#define BUTTON_0_DETECT_DELAY CONFIG_BOOT_SERIAL_DETECT_DELAY +#elif defined(CONFIG_BOOT_FIRMWARE_LOADER) +#define BUTTON_0_DETECT_DELAY CONFIG_BOOT_FIRMWARE_LOADER_DETECT_DELAY +#else +#define BUTTON_0_DETECT_DELAY CONFIG_BOOT_USB_DFU_DETECT_DELAY +#endif + +bool io_detect_pin(void) +{ + int rc; + bool pin_active; + + rc = bm_buttons_init( + &(struct bm_buttons_config){ + .pin_number = BOARD_PIN_BTN_0, + .active_state = BM_BUTTONS_ACTIVE_LOW, + .pull_config = BM_BUTTONS_PIN_PULLUP, + }, + 1, + BM_BUTTONS_DETECTION_DELAY_MIN_US); + if (rc) { + BOOT_LOG_ERR("Failed to initialize buttons: %d", rc); + return false; + } + + rc = bm_buttons_enable(); + if (rc) { + BOOT_LOG_ERR("Failed to enable button detection: %d", rc); + return false; + } + + pin_active = bm_buttons_is_pressed(BOARD_PIN_BTN_0); + + if (pin_active) { + if (BUTTON_0_DETECT_DELAY > 0) { +#ifdef CONFIG_MULTITHREADING + k_sleep(K_MSEC(50)); +#else + k_busy_wait(50000); +#endif + + /* Get the uptime for debounce purposes. */ + int64_t timestamp = k_uptime_get(); + + for(;;) { + pin_active = bm_buttons_is_pressed(BOARD_PIN_BTN_0); + + /* Get delta from when this started */ + uint32_t delta = k_uptime_get() - timestamp; + + /* If not pressed OR if pressed > debounce period, stop. */ + if (delta >= BUTTON_0_DETECT_DELAY || !pin_active) { + break; + } + + /* Delay 1 ms */ +#ifdef CONFIG_MULTITHREADING + k_sleep(K_MSEC(1)); +#else + k_busy_wait(1000); +#endif + } + } + } + + rc = bm_buttons_disable(); + + if (rc) { + BOOT_LOG_ERR("Failed to disable buttons: %d", rc); + } + + rc = bm_buttons_deinit(); + if (rc) { + BOOT_LOG_ERR("Failed to de-initialize buttons: %d", rc); + } + + return (bool)pin_active; +} +#endif + +#if defined(CONFIG_BOOT_SERIAL_PIN_RESET) || defined(CONFIG_BOOT_FIRMWARE_LOADER_PIN_RESET) +bool io_detect_pin_reset(void) +{ + uint32_t reset_cause; + int rc; + + rc = hwinfo_get_reset_cause(&reset_cause); + + if (rc == 0 && (reset_cause & RESET_PIN)) { + (void)hwinfo_clear_reset_cause(); + return true; + } + + return false; +} +#endif + +#if defined(CONFIG_BOOT_SERIAL_BOOT_MODE) || defined(CONFIG_BOOT_FIRMWARE_LOADER_BOOT_MODE) +bool io_detect_boot_mode(void) +{ + int32_t boot_mode; + + boot_mode = bootmode_check(BOOT_MODE_TYPE_BOOTLOADER); + + if (boot_mode == 1) { + /* Boot mode to stay in bootloader, clear status and enter serial + * recovery mode + */ + bootmode_clear(); + + return true; + } + + return false; +} +#endif From 2b13bcea10e8f91bd2400696c8a8c48f50e35525 Mon Sep 17 00:00:00 2001 From: Tomasz Chyrowicz Date: Thu, 3 Jul 2025 12:52:05 +0200 Subject: [PATCH 337/420] [nrf noup] boot: Provide default configuration for nRF54H20 Enable ed25519 signature as well as direct hashing while building for nRF54H20DK. Ref: NCSDK-34304 Signed-off-by: Tomasz Chyrowicz (cherry picked from commit 068718ae281e70cc5c771d51320f1f8707d8ea59) --- boot/zephyr/Kconfig | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/boot/zephyr/Kconfig b/boot/zephyr/Kconfig index cefec0021..24f115afc 100644 --- a/boot/zephyr/Kconfig +++ b/boot/zephyr/Kconfig @@ -185,6 +185,7 @@ config BOOT_IMG_HASH_ALG_SHA512_ALLOW config BOOT_IMG_HASH_DIRECTLY_ON_STORAGE bool "Hash calculation functions access storage through address space" + default y if NRF_SECURITY && SOC_NRF54H20 depends on !BOOT_ENCRYPT_IMAGE help When possible to map storage device, at least for read operations, @@ -242,7 +243,7 @@ config BOOT_SIGNATURE_TYPE_PURE_ALLOW choice BOOT_SIGNATURE_TYPE prompt "Signature type" - default BOOT_SIGNATURE_TYPE_ED25519 if SOC_NRF54L15_CPUAPP + default BOOT_SIGNATURE_TYPE_ED25519 if SOC_NRF54L15_CPUAPP || SOC_NRF54H20_CPUAPP default BOOT_SIGNATURE_TYPE_RSA config BOOT_SIGNATURE_TYPE_NONE From d29c5a5bee2f14560e0d5f2be9f2045ef206aaa4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Adam=20Szczygie=C5=82?= Date: Tue, 8 Jul 2025 09:05:18 +0200 Subject: [PATCH 338/420] [nrf noup] boot: Add retry for image verification MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Intended mainly for direct-xip mode. Allows to control: - number of image validation attempts performed before considering the image invalid - time before next attempt is made Signed-off-by: Adam Szczygieł (cherry picked from commit 25346815646625708b3269c46fe45089885da551) (cherry picked from commit a9e70e43fa548c86bec946dc06210b8a2ba2b860) --- boot/bootutil/src/loader.c | 40 ++++++++++++++++++++++++++++++++++++-- boot/zephyr/Kconfig | 17 ++++++++++++++++ 2 files changed, 55 insertions(+), 2 deletions(-) diff --git a/boot/bootutil/src/loader.c b/boot/bootutil/src/loader.c index c22450076..1333c6b81 100644 --- a/boot/bootutil/src/loader.c +++ b/boot/bootutil/src/loader.c @@ -52,6 +52,9 @@ #ifdef __ZEPHYR__ #include +#if defined(CONFIG_NRF_MCUBOOT_IMG_VALIDATE_ATTEMPT_WAIT_MS) +#include +#endif /* CONFIG_NRF_MCUBOOT_IMG_VALIDATE_ATTEMPT_WAIT_MS */ #endif #if defined(CONFIG_SOC_NRF5340_CPUAPP) && defined(PM_CPUNET_B0N_ADDRESS) && defined(CONFIG_PCD_APP) @@ -756,9 +759,42 @@ boot_image_check(struct boot_loader_state *state, struct image_header *hdr, } #endif - FIH_CALL(bootutil_img_validate, fih_rc, state, hdr, fap, tmpbuf, BOOT_TMPBUF_SZ, - NULL, 0, NULL); + for (int i = 1; i <= CONFIG_NRF_MCUBOOT_IMG_VALIDATE_ATTEMPT_COUNT; i++ ) { +#if CONFIG_NRF_MCUBOOT_IMG_VALIDATE_ATTEMPT_COUNT > 1 + BOOT_LOG_DBG("Image validation attempt %d/%d", i, CONFIG_NRF_MCUBOOT_IMG_VALIDATE_ATTEMPT_COUNT); +#endif /* CONFIG_NRF_MCUBOOT_IMG_VALIDATE_ATTEMPT_COUNT > 1 */ +#if defined(MCUBOOT_SWAP_USING_OFFSET) && defined(MCUBOOT_SERIAL_RECOVERY) + FIH_CALL(bootutil_img_validate, fih_rc, state, hdr, fap, tmpbuf, BOOT_TMPBUF_SZ, + NULL, 0, NULL, 0); +#else + FIH_CALL(bootutil_img_validate, fih_rc, state, hdr, fap, tmpbuf, BOOT_TMPBUF_SZ, + NULL, 0, NULL); +#endif + + if (FIH_EQ(fih_rc, FIH_SUCCESS)) { +#if CONFIG_NRF_MCUBOOT_IMG_VALIDATE_ATTEMPT_COUNT > 1 + BOOT_LOG_DBG("Image validation attempt %d/%d success", i, CONFIG_NRF_MCUBOOT_IMG_VALIDATE_ATTEMPT_COUNT); +#endif /* CONFIG_NRF_MCUBOOT_IMG_VALIDATE_ATTEMPT_COUNT > 1 */ + break; + } else { +#if CONFIG_NRF_MCUBOOT_IMG_VALIDATE_ATTEMPT_COUNT > 1 + BOOT_LOG_WRN("Image validation attempt %d/%d failure: %d", + i, + CONFIG_NRF_MCUBOOT_IMG_VALIDATE_ATTEMPT_COUNT, fih_rc); +#endif /* CONFIG_NRF_MCUBOOT_IMG_VALIDATE_ATTEMPT_COUNT > 1 */ + + if (i < CONFIG_NRF_MCUBOOT_IMG_VALIDATE_ATTEMPT_COUNT) { +#if defined(CONFIG_NRF_MCUBOOT_IMG_VALIDATE_ATTEMPT_WAIT_MS) +#if CONFIG_NRF_MCUBOOT_IMG_VALIDATE_ATTEMPT_COUNT > 1 + BOOT_LOG_DBG("Waiting %d ms before next attempt", + CONFIG_NRF_MCUBOOT_IMG_VALIDATE_ATTEMPT_WAIT_MS); +#endif /* CONFIG_NRF_MCUBOOT_IMG_VALIDATE_ATTEMPT_COUNT > 1 */ + k_busy_wait(CONFIG_NRF_MCUBOOT_IMG_VALIDATE_ATTEMPT_WAIT_MS * 1000); +#endif /* CONFIG_NRF_MCUBOOT_IMG_VALIDATE_ATTEMPT_WAIT_MS */ + } + } + } FIH_RET(fih_rc); } diff --git a/boot/zephyr/Kconfig b/boot/zephyr/Kconfig index 24f115afc..9bf615867 100644 --- a/boot/zephyr/Kconfig +++ b/boot/zephyr/Kconfig @@ -1336,4 +1336,21 @@ config MCUBOOT_VERIFY_IMG_ADDRESS also be useful when BOOT_DIRECT_XIP is enabled, to ensure that the image linked at the correct address is loaded. +config NRF_MCUBOOT_IMG_VALIDATE_ATTEMPT_COUNT + int "Number of image validation attempts" + default 1 + help + Number of image validation attempts performed before an image is considered invalid. + A wait is done between each attempt to allow for recovery from a temporary disruption. + This can prevent erasing an image when initial validation fails. + Wait time is controlled by MCUBOOT_IMG_VALIDATE_ATTEMPT_WAIT_MS. + +config NRF_MCUBOOT_IMG_VALIDATE_ATTEMPT_WAIT_MS + int "Time between image validation attempts" + depends on NRF_MCUBOOT_IMG_VALIDATE_ATTEMPT_COUNT > 1 + default 5000 + help + Time between image validation attempts, in milliseconds. + Allows for recovery from transient bit flips or similar situations. + source "Kconfig.zephyr" From 47d8a1cf30e626cae93cf0e0e5a93cdc8678e4f3 Mon Sep 17 00:00:00 2001 From: Mateusz Michalek Date: Wed, 28 May 2025 15:09:33 +0200 Subject: [PATCH 339/420] [nrf noup] boot: zephyr: Kconfig dependencies for PSA LITE exclude certain crypto parts when PSA_CORE_LITE is selected. Signed-off-by: Mateusz Michalek Signed-off-by: Dominik Ermel (cherry picked from commit 2f7059edfa0140851289651fd9b69069a31051e2) --- boot/zephyr/Kconfig | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/boot/zephyr/Kconfig b/boot/zephyr/Kconfig index 9bf615867..5f2337d29 100644 --- a/boot/zephyr/Kconfig +++ b/boot/zephyr/Kconfig @@ -74,14 +74,14 @@ if BOOT_USE_PSA_CRYPTO config BOOT_PSA_IMG_HASH_ALG_SHA256_DEPENDENCIES bool default y if BOOT_SOMETHING_USES_SHA256 - select PSA_WANT_ALG_SHA_256 + select PSA_WANT_ALG_SHA_256 if !PSA_CORE_LITE help Dependencies for hashing with SHA256 config BOOT_PSA_IMG_HASH_ALG_SHA512_DEPENDENCIES bool default y if BOOT_SOMETHING_USES_SHA512 - select PSA_WANT_ALG_SHA_512 + select PSA_WANT_ALG_SHA_512 if !PSA_CORE_LITE help Dependencies for hashing with SHA512 @@ -90,7 +90,7 @@ config BOOT_ED25519_PSA_DEPENDENCIES select PSA_WANT_ALG_PURE_EDDSA select PSA_WANT_ECC_TWISTED_EDWARDS_255 select PSA_WANT_ECC_MONTGOMERY_255 - select PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_IMPORT + select PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_IMPORT if !PSA_CORE_LITE help Dependencies for ed25519 signature @@ -364,9 +364,9 @@ config BOOT_ED25519_PSA select PSA_CRYPTO_C select MBEDTLS_PSA_CRYPTO_C select MBEDTLS_ASN1_PARSE_C if MBEDTLS_BUILTIN - select MBEDTLS_ENABLE_HEAP - select BOOT_IMG_HASH_ALG_SHA256_ALLOW - select BOOT_IMG_HASH_ALG_SHA512_ALLOW + select MBEDTLS_ENABLE_HEAP if !PSA_CORE_LITE + select BOOT_IMG_HASH_ALG_SHA256_ALLOW if !PSA_CORE_LITE + select BOOT_IMG_HASH_ALG_SHA512_ALLOW if !PSA_CORE_LITE select BOOT_ED25519_PSA_DEPENDENCIES select BOOT_X25519_PSA_DEPENDENCIES if BOOT_ENCRYPT_IMAGE From 54d2fdaca8ca55881f6c5b88efecde0e42b91802 Mon Sep 17 00:00:00 2001 From: Dominik Ermel Date: Wed, 30 Jul 2025 14:09:32 +0000 Subject: [PATCH 340/420] [nrf noup] zephyr: Enforce HMAC-SHA512 for NRF54L with X25519 ECIES-X25519 key exchange on NRF54L will be using HMAC-SHA512 for MAC tagging encryption key. Signed-off-by: Dominik Ermel (cherry picked from commit 8b2d04cba336b40f97b1c5edbef80f4e58fa1a90) --- boot/zephyr/Kconfig | 1 + 1 file changed, 1 insertion(+) diff --git a/boot/zephyr/Kconfig b/boot/zephyr/Kconfig index 5f2337d29..da4dc7a70 100644 --- a/boot/zephyr/Kconfig +++ b/boot/zephyr/Kconfig @@ -720,6 +720,7 @@ if BOOT_ENCRYPT_X25519 && BOOT_USE_PSA_CRYPTO choice BOOT_HMAC_SHA prompt "SHA used for HMAC and HKDF in encryption key exchange" + default BOOT_HMAC_SHA512 if BOOT_ENCRYPT_X25519 && (SOC_NRF54L15_CPUAPP || SOC_NRF54LM20A_ENGA_CPUAPP) default BOOT_HMAC_SHA256 help HMAC/HKDF sha algorithm may be selected to synchronize sha From 9126c5a1865fc1dea050859bc111cc4731613846 Mon Sep 17 00:00:00 2001 From: Dominik Ermel Date: Thu, 31 Jul 2025 12:01:43 +0000 Subject: [PATCH 341/420] [nrf noup] boot: Use NCS_ prefix for sdk-nrf specific Kconfigs nrf-squash! [nrf noup] boot: Add retry for image verification Use NCS_ prefix, for Kconfigs added in noups, to avoid collisions. The NRF_ prefix will remain reserved for Kconfigs related to products or sdk-nrf subsystems. Signed-off-by: Dominik Ermel (cherry picked from commit 30e7326a49a20df7326d3996bec73cf3802745e2) --- boot/bootutil/src/loader.c | 38 +++++++++++++++++++------------------- boot/zephyr/Kconfig | 6 +++--- 2 files changed, 22 insertions(+), 22 deletions(-) diff --git a/boot/bootutil/src/loader.c b/boot/bootutil/src/loader.c index 1333c6b81..aaea24942 100644 --- a/boot/bootutil/src/loader.c +++ b/boot/bootutil/src/loader.c @@ -52,9 +52,9 @@ #ifdef __ZEPHYR__ #include -#if defined(CONFIG_NRF_MCUBOOT_IMG_VALIDATE_ATTEMPT_WAIT_MS) +#if defined(CONFIG_NCS_MCUBOOT_IMG_VALIDATE_ATTEMPT_WAIT_MS) #include -#endif /* CONFIG_NRF_MCUBOOT_IMG_VALIDATE_ATTEMPT_WAIT_MS */ +#endif /* CONFIG_NCS_MCUBOOT_IMG_VALIDATE_ATTEMPT_WAIT_MS */ #endif #if defined(CONFIG_SOC_NRF5340_CPUAPP) && defined(PM_CPUNET_B0N_ADDRESS) && defined(CONFIG_PCD_APP) @@ -759,10 +759,10 @@ boot_image_check(struct boot_loader_state *state, struct image_header *hdr, } #endif - for (int i = 1; i <= CONFIG_NRF_MCUBOOT_IMG_VALIDATE_ATTEMPT_COUNT; i++ ) { -#if CONFIG_NRF_MCUBOOT_IMG_VALIDATE_ATTEMPT_COUNT > 1 - BOOT_LOG_DBG("Image validation attempt %d/%d", i, CONFIG_NRF_MCUBOOT_IMG_VALIDATE_ATTEMPT_COUNT); -#endif /* CONFIG_NRF_MCUBOOT_IMG_VALIDATE_ATTEMPT_COUNT > 1 */ + for (int i = 1; i <= CONFIG_NCS_MCUBOOT_IMG_VALIDATE_ATTEMPT_COUNT; i++ ) { +#if CONFIG_NCS_MCUBOOT_IMG_VALIDATE_ATTEMPT_COUNT > 1 + BOOT_LOG_DBG("Image validation attempt %d/%d", i, CONFIG_NCS_MCUBOOT_IMG_VALIDATE_ATTEMPT_COUNT); +#endif /* CONFIG_NCS_MCUBOOT_IMG_VALIDATE_ATTEMPT_COUNT > 1 */ #if defined(MCUBOOT_SWAP_USING_OFFSET) && defined(MCUBOOT_SERIAL_RECOVERY) FIH_CALL(bootutil_img_validate, fih_rc, state, hdr, fap, tmpbuf, BOOT_TMPBUF_SZ, @@ -773,25 +773,25 @@ boot_image_check(struct boot_loader_state *state, struct image_header *hdr, #endif if (FIH_EQ(fih_rc, FIH_SUCCESS)) { -#if CONFIG_NRF_MCUBOOT_IMG_VALIDATE_ATTEMPT_COUNT > 1 - BOOT_LOG_DBG("Image validation attempt %d/%d success", i, CONFIG_NRF_MCUBOOT_IMG_VALIDATE_ATTEMPT_COUNT); -#endif /* CONFIG_NRF_MCUBOOT_IMG_VALIDATE_ATTEMPT_COUNT > 1 */ +#if CONFIG_NCS_MCUBOOT_IMG_VALIDATE_ATTEMPT_COUNT > 1 + BOOT_LOG_DBG("Image validation attempt %d/%d success", i, CONFIG_NCS_MCUBOOT_IMG_VALIDATE_ATTEMPT_COUNT); +#endif /* CONFIG_NCS_MCUBOOT_IMG_VALIDATE_ATTEMPT_COUNT > 1 */ break; } else { -#if CONFIG_NRF_MCUBOOT_IMG_VALIDATE_ATTEMPT_COUNT > 1 +#if CONFIG_NCS_MCUBOOT_IMG_VALIDATE_ATTEMPT_COUNT > 1 BOOT_LOG_WRN("Image validation attempt %d/%d failure: %d", i, - CONFIG_NRF_MCUBOOT_IMG_VALIDATE_ATTEMPT_COUNT, fih_rc); -#endif /* CONFIG_NRF_MCUBOOT_IMG_VALIDATE_ATTEMPT_COUNT > 1 */ + CONFIG_NCS_MCUBOOT_IMG_VALIDATE_ATTEMPT_COUNT, fih_rc); +#endif /* CONFIG_NCS_MCUBOOT_IMG_VALIDATE_ATTEMPT_COUNT > 1 */ - if (i < CONFIG_NRF_MCUBOOT_IMG_VALIDATE_ATTEMPT_COUNT) { -#if defined(CONFIG_NRF_MCUBOOT_IMG_VALIDATE_ATTEMPT_WAIT_MS) -#if CONFIG_NRF_MCUBOOT_IMG_VALIDATE_ATTEMPT_COUNT > 1 + if (i < CONFIG_NCS_MCUBOOT_IMG_VALIDATE_ATTEMPT_COUNT) { +#if defined(CONFIG_NCS_MCUBOOT_IMG_VALIDATE_ATTEMPT_WAIT_MS) +#if CONFIG_NCS_MCUBOOT_IMG_VALIDATE_ATTEMPT_COUNT > 1 BOOT_LOG_DBG("Waiting %d ms before next attempt", - CONFIG_NRF_MCUBOOT_IMG_VALIDATE_ATTEMPT_WAIT_MS); -#endif /* CONFIG_NRF_MCUBOOT_IMG_VALIDATE_ATTEMPT_COUNT > 1 */ - k_busy_wait(CONFIG_NRF_MCUBOOT_IMG_VALIDATE_ATTEMPT_WAIT_MS * 1000); -#endif /* CONFIG_NRF_MCUBOOT_IMG_VALIDATE_ATTEMPT_WAIT_MS */ + CONFIG_NCS_MCUBOOT_IMG_VALIDATE_ATTEMPT_WAIT_MS); +#endif /* CONFIG_NCS_MCUBOOT_IMG_VALIDATE_ATTEMPT_COUNT > 1 */ + k_busy_wait(CONFIG_NCS_MCUBOOT_IMG_VALIDATE_ATTEMPT_WAIT_MS * 1000); +#endif /* CONFIG_NCS_MCUBOOT_IMG_VALIDATE_ATTEMPT_WAIT_MS */ } } } diff --git a/boot/zephyr/Kconfig b/boot/zephyr/Kconfig index da4dc7a70..26c0f1a79 100644 --- a/boot/zephyr/Kconfig +++ b/boot/zephyr/Kconfig @@ -1337,7 +1337,7 @@ config MCUBOOT_VERIFY_IMG_ADDRESS also be useful when BOOT_DIRECT_XIP is enabled, to ensure that the image linked at the correct address is loaded. -config NRF_MCUBOOT_IMG_VALIDATE_ATTEMPT_COUNT +config NCS_MCUBOOT_IMG_VALIDATE_ATTEMPT_COUNT int "Number of image validation attempts" default 1 help @@ -1346,9 +1346,9 @@ config NRF_MCUBOOT_IMG_VALIDATE_ATTEMPT_COUNT This can prevent erasing an image when initial validation fails. Wait time is controlled by MCUBOOT_IMG_VALIDATE_ATTEMPT_WAIT_MS. -config NRF_MCUBOOT_IMG_VALIDATE_ATTEMPT_WAIT_MS +config NCS_MCUBOOT_IMG_VALIDATE_ATTEMPT_WAIT_MS int "Time between image validation attempts" - depends on NRF_MCUBOOT_IMG_VALIDATE_ATTEMPT_COUNT > 1 + depends on NCS_MCUBOOT_IMG_VALIDATE_ATTEMPT_COUNT > 1 default 5000 help Time between image validation attempts, in milliseconds. From e2bd60731db5b7e07bebc0297c8bf71dfbd005f8 Mon Sep 17 00:00:00 2001 From: Audun Korneliussen Date: Mon, 4 Aug 2025 15:50:33 +0200 Subject: [PATCH 342/420] [nrf noup] boot/zephyr/nrf_cleanup: fix index error nrf-squash! [nrf noup] boot/zephyr/nrf_cleanup: cleanup uarte pins Fix indexing variable mismatch. Signed-off-by: Audun Korneliussen (cherry picked from commit 58175b6f71bdae10e1d10896c1c858520ab583ec) --- boot/zephyr/nrf_cleanup.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/boot/zephyr/nrf_cleanup.c b/boot/zephyr/nrf_cleanup.c index 39dfcbc41..e261d1914 100644 --- a/boot/zephyr/nrf_cleanup.c +++ b/boot/zephyr/nrf_cleanup.c @@ -131,7 +131,7 @@ void nrf_cleanup_peripheral(void) for (int j = 0; j < 4; j++) { if (pin[j] != NRF_UARTE_PSEL_DISCONNECTED) { - nrfy_gpio_cfg_default(pin[i]); + nrfy_gpio_cfg_default(pin[j]); } } #endif From 9d16a63458920394f9692150701c33a691cb5a16 Mon Sep 17 00:00:00 2001 From: Kari Hamalainen Date: Fri, 8 Aug 2025 09:32:03 +0300 Subject: [PATCH 343/420] [nrf noup] workflows: Add manifest PRs creation Adding action to create manifest PRs automatically. Signed-off-by: Kari Hamalainen (cherry picked from commit 37486f508fd7bc760732a67eab650d76590ebe86) --- .github/workflows/manifest-PR.yml | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) create mode 100644 .github/workflows/manifest-PR.yml diff --git a/.github/workflows/manifest-PR.yml b/.github/workflows/manifest-PR.yml new file mode 100644 index 000000000..a871aa381 --- /dev/null +++ b/.github/workflows/manifest-PR.yml @@ -0,0 +1,17 @@ +name: handle manifest PR +on: + pull_request_target: + types: [opened, synchronize, closed] + branches: + - main + + +jobs: + call-manifest-pr-action: + runs-on: ubuntu-latest + steps: + - name: handle manifest PR + uses: nrfconnect/action-manifest-pr@main + with: + token: ${{ secrets.NCS_GITHUB_TOKEN }} + manifest-pr-title-details: ${{ github.event.pull_request.title }} From d8357faaa8c94351bbffdfeb3dcb1c569fbe560b Mon Sep 17 00:00:00 2001 From: Jamie McCrae Date: Thu, 7 Aug 2025 11:58:29 +0100 Subject: [PATCH 344/420] [nrf noup] boot: zephyr: Fix bm IO button check nrf-squash! [nrf noup] boot: zephyr: Add bm firmware loader code Fixes IO in BM mode to use the hal directly rather than a library that increases the build size by 2.5KiB for a simple button check Signed-off-by: Jamie McCrae (cherry picked from commit a184e32064cb04efdd49951088f8b2e802990e7e) --- boot/zephyr/io_bm.c | 45 +++++++++------------------------------------ 1 file changed, 9 insertions(+), 36 deletions(-) diff --git a/boot/zephyr/io_bm.c b/boot/zephyr/io_bm.c index 3f65a5d0e..798cf7a3f 100644 --- a/boot/zephyr/io_bm.c +++ b/boot/zephyr/io_bm.c @@ -89,31 +89,13 @@ void io_led_set(int value) bool io_detect_pin(void) { - int rc; bool pin_active; - rc = bm_buttons_init( - &(struct bm_buttons_config){ - .pin_number = BOARD_PIN_BTN_0, - .active_state = BM_BUTTONS_ACTIVE_LOW, - .pull_config = BM_BUTTONS_PIN_PULLUP, - }, - 1, - BM_BUTTONS_DETECTION_DELAY_MIN_US); - if (rc) { - BOOT_LOG_ERR("Failed to initialize buttons: %d", rc); - return false; - } + nrf_gpio_cfg_input(BOARD_PIN_BTN_0, BM_BUTTONS_PIN_PULLUP); - rc = bm_buttons_enable(); - if (rc) { - BOOT_LOG_ERR("Failed to enable button detection: %d", rc); - return false; - } + pin_active = (bool)nrf_gpio_pin_read(BOARD_PIN_BTN_0); - pin_active = bm_buttons_is_pressed(BOARD_PIN_BTN_0); - - if (pin_active) { + if (!pin_active) { if (BUTTON_0_DETECT_DELAY > 0) { #ifdef CONFIG_MULTITHREADING k_sleep(K_MSEC(50)); @@ -125,13 +107,15 @@ bool io_detect_pin(void) int64_t timestamp = k_uptime_get(); for(;;) { - pin_active = bm_buttons_is_pressed(BOARD_PIN_BTN_0); + uint32_t delta; + + pin_active = (bool)nrf_gpio_pin_read(BOARD_PIN_BTN_0); /* Get delta from when this started */ - uint32_t delta = k_uptime_get() - timestamp; + delta = k_uptime_get() - timestamp; /* If not pressed OR if pressed > debounce period, stop. */ - if (delta >= BUTTON_0_DETECT_DELAY || !pin_active) { + if (delta >= BUTTON_0_DETECT_DELAY || pin_active) { break; } @@ -145,18 +129,7 @@ bool io_detect_pin(void) } } - rc = bm_buttons_disable(); - - if (rc) { - BOOT_LOG_ERR("Failed to disable buttons: %d", rc); - } - - rc = bm_buttons_deinit(); - if (rc) { - BOOT_LOG_ERR("Failed to de-initialize buttons: %d", rc); - } - - return (bool)pin_active; + return (bool)!pin_active; } #endif From 9508e94abcf1f7167c396d4285a66ab9540b8f1c Mon Sep 17 00:00:00 2001 From: Georgios Vasilakis Date: Fri, 8 Aug 2025 12:52:24 +0200 Subject: [PATCH 345/420] [nrf noup] boot: zephyr: Adjust PSA requirements for PSA_CORE_LITE nrf-squash! [nrf noup] boot: zephyr: Kconfig dependencies for PSA LITE The PSA core lite now requires the PSA_WANTs for the hashing functions to be set in order to be used so select them as normal. Signed-off-by: Georgios Vasilakis (cherry picked from commit 6c096b8ed7bfddf044b20dfb512c4c1fd06c2ef6) --- boot/zephyr/Kconfig | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/boot/zephyr/Kconfig b/boot/zephyr/Kconfig index 26c0f1a79..56af8fc7a 100644 --- a/boot/zephyr/Kconfig +++ b/boot/zephyr/Kconfig @@ -74,14 +74,14 @@ if BOOT_USE_PSA_CRYPTO config BOOT_PSA_IMG_HASH_ALG_SHA256_DEPENDENCIES bool default y if BOOT_SOMETHING_USES_SHA256 - select PSA_WANT_ALG_SHA_256 if !PSA_CORE_LITE + select PSA_WANT_ALG_SHA_256 help Dependencies for hashing with SHA256 config BOOT_PSA_IMG_HASH_ALG_SHA512_DEPENDENCIES bool default y if BOOT_SOMETHING_USES_SHA512 - select PSA_WANT_ALG_SHA_512 if !PSA_CORE_LITE + select PSA_WANT_ALG_SHA_512 help Dependencies for hashing with SHA512 From f5d42e946607b72f5ce51821542a7f62a27a3264 Mon Sep 17 00:00:00 2001 From: Artur Hadasz Date: Mon, 11 Aug 2025 14:23:04 +0200 Subject: [PATCH 346/420] [nrf noup] zephyr: hw security counter limited set by default This commit sets the MCUBOOT_HW_DOWNGRADE_PREVENTION_COUNTER_LIMITED by default for platforms which support the security counter. Signed-off-by: Artur Hadasz (cherry picked from commit 0fadab126d9ba51365b3db1cdb6d55ed892c62b4) --- boot/zephyr/Kconfig | 1 + 1 file changed, 1 insertion(+) diff --git a/boot/zephyr/Kconfig b/boot/zephyr/Kconfig index 56af8fc7a..a765830c5 100644 --- a/boot/zephyr/Kconfig +++ b/boot/zephyr/Kconfig @@ -1071,6 +1071,7 @@ config MCUBOOT_HW_DOWNGRADE_PREVENTION config MCUBOOT_HW_DOWNGRADE_PREVENTION_COUNTER_LIMITED bool "HW based downgrade prevention counter has limited number of updates" depends on MCUBOOT_HW_DOWNGRADE_PREVENTION + default y if SOC_NRF5340_CPUAPP || SOC_SERIES_NRF91X || SOC_SERIES_NRF54LX help When this option is set, the hardware downgrade prevention counter has limited number of updates. This option will enable checking From 4adc4f628cdbf0a65e09737d7c297f7080f6922e Mon Sep 17 00:00:00 2001 From: Mateusz Michalek Date: Tue, 19 Aug 2025 12:37:42 +0200 Subject: [PATCH 347/420] [nrf noup] boot: zephyr: remove nonsecure ram cleanup nrf-squash! [nrf noup] zephyr: Clean up non-secure RAM if enabled This leads to stack corruption. Signed-off-by: Mateusz Michalek (cherry picked from commit 3adc1f232221dc8a6d77c378aa0d97fa24c9c0cb) --- boot/zephyr/CMakeLists.txt | 2 +- boot/zephyr/main.c | 5 +---- boot/zephyr/nrf_cleanup.c | 9 --------- 3 files changed, 2 insertions(+), 14 deletions(-) diff --git a/boot/zephyr/CMakeLists.txt b/boot/zephyr/CMakeLists.txt index 839381d58..c1820df76 100644 --- a/boot/zephyr/CMakeLists.txt +++ b/boot/zephyr/CMakeLists.txt @@ -753,7 +753,7 @@ if(SYSBUILD) set(mcuboot_image_upgrade_footer_size ${required_upgrade_size} CACHE INTERNAL "Estimated MCUboot update image trailer size" FORCE) endif() -if(CONFIG_MCUBOOT_NRF_CLEANUP_PERIPHERAL OR CONFIG_MCUBOOT_CLEANUP_NONSECURE_RAM) +if(CONFIG_MCUBOOT_NRF_CLEANUP_PERIPHERAL) zephyr_library_sources( ${BOOT_DIR}/zephyr/nrf_cleanup.c ) diff --git a/boot/zephyr/main.c b/boot/zephyr/main.c index bdc264d94..8b39963a9 100644 --- a/boot/zephyr/main.c +++ b/boot/zephyr/main.c @@ -149,7 +149,7 @@ K_SEM_DEFINE(boot_log_sem, 1, 1); #include #endif -#if CONFIG_MCUBOOT_NRF_CLEANUP_PERIPHERAL || CONFIG_MCUBOOT_NRF_CLEANUP_NONSECURE_RAM +#if CONFIG_MCUBOOT_NRF_CLEANUP_PERIPHERAL #include #endif @@ -240,9 +240,6 @@ static void do_boot(struct boot_rsp *rsp) #if CONFIG_MCUBOOT_NRF_CLEANUP_PERIPHERAL nrf_cleanup_peripheral(); #endif -#if CONFIG_MCUBOOT_NRF_CLEANUP_NONSECURE_RAM && defined(PM_SRAM_NONSECURE_NAME) - nrf_cleanup_ns_ram(); -#endif #if CONFIG_MCUBOOT_CLEANUP_ARM_CORE cleanup_arm_interrupts(); /* Disable and acknowledge all interrupts */ diff --git a/boot/zephyr/nrf_cleanup.c b/boot/zephyr/nrf_cleanup.c index e261d1914..5ddc74a64 100644 --- a/boot/zephyr/nrf_cleanup.c +++ b/boot/zephyr/nrf_cleanup.c @@ -158,12 +158,3 @@ void nrf_cleanup_peripheral(void) nrf_cleanup_clock(); #endif } - -#if USE_PARTITION_MANAGER \ - && defined(CONFIG_ARM_TRUSTZONE_M) \ - && defined(PM_SRAM_NONSECURE_NAME) -void nrf_cleanup_ns_ram(void) -{ - memset((void *) PM_SRAM_NONSECURE_ADDRESS, 0, PM_SRAM_NONSECURE_SIZE); -} -#endif From f2a6ad28febf1cb73ecb816d52052739837b4600 Mon Sep 17 00:00:00 2001 From: Jamie McCrae Date: Tue, 19 Aug 2025 12:29:54 +0100 Subject: [PATCH 348/420] [nrf noup] boot: zephyr: Delay bm IO button check nrf-squash! [nrf noup] boot: zephyr: Add bm firmware loader code Delays checking IO button state by 5us after pull-up has been applied to allow time for it to be applied Signed-off-by: Jamie McCrae (cherry picked from commit 1b1a37fb7abf8b6e5f7d1e05daacd0081ce2844e) --- boot/zephyr/io_bm.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/boot/zephyr/io_bm.c b/boot/zephyr/io_bm.c index 798cf7a3f..788bfab9e 100644 --- a/boot/zephyr/io_bm.c +++ b/boot/zephyr/io_bm.c @@ -93,6 +93,9 @@ bool io_detect_pin(void) nrf_gpio_cfg_input(BOARD_PIN_BTN_0, BM_BUTTONS_PIN_PULLUP); + /* Delay 5 us for pull-up to be applied */ + k_busy_wait(5); + pin_active = (bool)nrf_gpio_pin_read(BOARD_PIN_BTN_0); if (!pin_active) { From 25f21d2b1b7834e6439c28d0fb73dc049a1985c1 Mon Sep 17 00:00:00 2001 From: Jamie McCrae Date: Tue, 11 Jun 2024 12:32:51 +0100 Subject: [PATCH 349/420] [nrf noup] boot: zephyr: Add NCS boot banner Adds a boot banner which shows as MCUboot Signed-off-by: Jamie McCrae (cherry picked from commit c85960801ddb83ca6cc2125bd5342139d3befa2c) --- boot/zephyr/prj.conf | 3 +++ 1 file changed, 3 insertions(+) diff --git a/boot/zephyr/prj.conf b/boot/zephyr/prj.conf index b824ca1b1..df37b82fb 100644 --- a/boot/zephyr/prj.conf +++ b/boot/zephyr/prj.conf @@ -29,3 +29,6 @@ CONFIG_CBPRINTF_NANO=y CONFIG_PICOLIBC=y ### Disable malloc arena because we don't need it CONFIG_COMMON_LIBC_MALLOC_ARENA_SIZE=0 + +# NCS boot banner +CONFIG_NCS_APPLICATION_BOOT_BANNER_STRING="MCUboot" From 07b4cb68b20e9c88523142802aaec2895fc20aa9 Mon Sep 17 00:00:00 2001 From: Jamie McCrae Date: Tue, 26 Aug 2025 10:22:04 +0100 Subject: [PATCH 350/420] [nrf noup] boot: zephyr: firmware_loader: Allow GPIO usage in BM Allows GPIO entrance mode when bare metal is used, this is needed because the zephyr GPIO drivers are not used, therefore the Kconfig will not be enabled Signed-off-by: Jamie McCrae (cherry picked from commit ecc13ac1b0336c5ff39fc00075d34b55ab619752) --- boot/zephyr/Kconfig.firmware_loader | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/boot/zephyr/Kconfig.firmware_loader b/boot/zephyr/Kconfig.firmware_loader index 1ba223949..036da98eb 100644 --- a/boot/zephyr/Kconfig.firmware_loader +++ b/boot/zephyr/Kconfig.firmware_loader @@ -8,7 +8,7 @@ menu "Firmware loader entrance methods" menuconfig BOOT_FIRMWARE_LOADER_ENTRANCE_GPIO bool "GPIO" - depends on GPIO + depends on GPIO || NCS_BM help Use a GPIO to enter firmware loader mode. From 211da1bf19b4dc5b8078ffbc143f02caca88bb9f Mon Sep 17 00:00:00 2001 From: Mateusz Michalek Date: Tue, 5 Aug 2025 15:55:31 +0200 Subject: [PATCH 351/420] [nrf noup] boot: zephyr: Disable self RWX Disables read write and execute on mcuboots NVM at the end of execution. Signed-off-by: Mateusz Michalek (cherry picked from commit 285fd59f4386a0317e476da5484f67b906073296) --- boot/zephyr/Kconfig | 7 +++ boot/zephyr/main.c | 140 +++++++++++++++++++++++++++++++------------- 2 files changed, 105 insertions(+), 42 deletions(-) diff --git a/boot/zephyr/Kconfig b/boot/zephyr/Kconfig index a765830c5..cc265de0a 100644 --- a/boot/zephyr/Kconfig +++ b/boot/zephyr/Kconfig @@ -436,6 +436,13 @@ config MCUBOOT_CLEANUP_RAM help Sets contents of memory to 0 before jumping to application. +config NCS_MCUBOOT_DISABLE_SELF_RWX + bool "Disable read and execution on self NVM" + depends on (SOC_NRF54L15_CPUAPP || SOC_NRF54L10_CPUAPP || SOC_NRF54L05_CPUAPP) && !FPROTECT + help + Sets RRAMC's region no.4 protection before jumping to application. + It disables reads writes and execution memory area which holds MCUBOOT. + config MCUBOOT_INFINITE_LOOP_AFTER_RAM_CLEANUP bool "Infinite loop after RAM cleanup" depends on MCUBOOT_CLEANUP_RAM diff --git a/boot/zephyr/main.c b/boot/zephyr/main.c index 8b39963a9..6fb27c7ca 100644 --- a/boot/zephyr/main.c +++ b/boot/zephyr/main.c @@ -153,6 +153,25 @@ K_SEM_DEFINE(boot_log_sem, 1, 1); #include #endif +#include +#define CLEANUP_RAM_GAP_START ((int)__ramfunc_region_start) +#define CLEANUP_RAM_GAP_SIZE ((int) (__ramfunc_end - __ramfunc_region_start)) + +#if defined(CONFIG_NCS_MCUBOOT_DISABLE_SELF_RWX) +/* Disabling R_X has to be done while running from RAM for obvious reasons. + * Moreover as a last step before jumping to application it must work even after + * RAM has been cleared, therefore these operations are performed while executing from RAM. + * RAM cleanup ommits portion of the memory where code lives. + */ +#include + +#define RRAMC_REGION_RWX_LSB 0 +#define RRAMC_REGION_RWX_WIDTH 3 +#define RRAMC_REGION_TO_LOCK_ADDR NRF_RRAMC->REGION[4].CONFIG +#define RRAMC_REGION_TO_LOCK_ADDR_H (((uint32_t)(&(RRAMC_REGION_TO_LOCK_ADDR))) >> 16) +#define RRAMC_REGION_TO_LOCK_ADDR_L (((uint32_t)(&(RRAMC_REGION_TO_LOCK_ADDR))) & 0x0000fffful) +#endif /* CONFIG_NCS_MCUBOOT_DISABLE_SELF_RWX */ + BOOT_LOG_MODULE_REGISTER(mcuboot); void os_heap_init(void); @@ -179,6 +198,84 @@ struct arm_vector_table { #endif }; +static void __ramfunc jump_in(uint32_t reset) +{ + __asm__ volatile ( + /* reset -> r0 */ + " mov r0, %0\n" +#ifdef CONFIG_MCUBOOT_CLEANUP_RAM + /* Base to write -> r1 */ + " mov r1, %1\n" + /* Size to write -> r2 */ + " mov r2, %2\n" + /* Value to write -> r3 */ + " movw r3, %5\n" + /* gap start */ + " mov r4, %3\n" + /* gap size */ + " mov r5, %4\n" + "clear:\n" + " subs r6, r4, r1\n" + " cbnz r6, skip_gap\n" + " add r1, r5\n" + "skip_gap:\n" + " str r3, [r1]\n" + " add r1, r1, #1\n" + " sub r2, r2, #1\n" + " cbz r2, clear_end\n" + " b clear\n" + "clear_end:\n" + " dsb\n" +#ifdef CONFIG_MCUBOOT_INFINITE_LOOP_AFTER_RAM_CLEANUP + " b clear_end\n" +#endif /* CONFIG_MCUBOOT_INFINITE_LOOP_AFTER_RAM_CLEANUP */ +#endif /* CONFIG_MCUBOOT_CLEANUP_RAM */ + +#ifdef CONFIG_NCS_MCUBOOT_DISABLE_SELF_RWX + ".thumb_func\n" + "region_disable_rwx:\n" + " movw r1, %6\n" + " movt r1, %7\n" + " ldr r2, [r1]\n" + /* Size of the region should be set at this point + * by NSIB's DISABLE_NEXT_W. + * If not, set it according partition size. + */ + " ands r4, r2, %12\n" + " cbnz r4, clear_rwx\n" + " movt r2, %8\n" + "clear_rwx:\n" + " bfc r2, %9, %10\n" + /* Disallow further modifications */ + " orr r2, %11\n" + " str r2, [r1]\n" + " dsb\n" + /* Next assembly line is important for current function */ + + #endif /* CONFIG_NCS_MCUBOOT_DISABLE_SELF_RWX */ + + /* Jump to reset vector of an app */ + " bx r0\n" + : + : "r" (reset), + "r" (CONFIG_SRAM_BASE_ADDRESS), + "i" (CONFIG_SRAM_SIZE * 1024), + "r" (CLEANUP_RAM_GAP_START), + "r" (CLEANUP_RAM_GAP_SIZE), + "i" (0) +#ifdef CONFIG_NCS_MCUBOOT_DISABLE_SELF_RWX + , "i" (RRAMC_REGION_TO_LOCK_ADDR_L), + "i" (RRAMC_REGION_TO_LOCK_ADDR_H), + "i" (CONFIG_PM_PARTITION_SIZE_B0_IMAGE / 1024), + "i" (RRAMC_REGION_RWX_LSB), + "i" (RRAMC_REGION_RWX_WIDTH), + "i" (RRAMC_REGION_CONFIG_LOCK_Msk), + "i" (RRAMC_REGION_CONFIG_SIZE_Msk) +#endif /* CONFIG_NCS_MCUBOOT_DISABLE_SELF_RWX */ + : "r0", "r1", "r2", "r3", "r4", "r5", "r6", "memory" + ); +} + static void do_boot(struct boot_rsp *rsp) { /* vt is static as it shall not land on the stack, @@ -310,48 +407,7 @@ static void do_boot(struct boot_rsp *rsp) #endif /* CONFIG_CPU_CORTEX_M */ #endif -#if CONFIG_MCUBOOT_CLEANUP_RAM - __asm__ volatile ( - /* vt->reset -> r0 */ - " mov r0, %0\n" - /* base to write -> r1 */ - " mov r1, %1\n" - /* size to write -> r2 */ - " mov r2, %2\n" - /* value to write -> r3 */ - " mov r3, %3\n" - "clear:\n" - " str r3, [r1]\n" - " add r1, r1, #4\n" - " sub r2, r2, #4\n" - " cbz r2, out\n" - " b clear\n" - "out:\n" - " dsb\n" -#if CONFIG_MCUBOOT_INFINITE_LOOP_AFTER_RAM_CLEANUP - " b out\n" -#endif /*CONFIG_MCUBOOT_INFINITE_LOOP_AFTER_RAM_CLEANUP */ - /* jump to reset vector of an app */ - " bx r0\n" - : - : "r" (vt->reset), "i" (CONFIG_SRAM_BASE_ADDRESS), - "i" (CONFIG_SRAM_SIZE * 1024), "i" (0) - : "r0", "r1", "r2", "r3", "memory" - ); -#else - -#ifdef CONFIG_CPU_CORTEX_M - ((void (*)(void))vt->reset)(); -#else - /* Some ARM CPUs like the Cortex-R5 can run in thumb mode but reset into ARM - * mode (depending on a CPU signal configurations). To do the switch into ARM - * mode, if needed, an explicit branch with exchange instruction set - * instruction is needed - */ - __asm__("bx %0\n" : : "r" (&vt->reset)); -#endif - -#endif + jump_in(vt->reset); } #elif defined(CONFIG_XTENSA) || defined(CONFIG_RISCV) From c54198b86aec6a39746047240daee59cd4643831 Mon Sep 17 00:00:00 2001 From: Mateusz Michalek Date: Tue, 26 Aug 2025 12:42:56 +0200 Subject: [PATCH 352/420] [nrf noup] zephyr: boards: nrf54lm20dk_nrf54lm20a_cpuapp.conf adding DK default configuration and fixing PDK configuration. Signed-off-by: Mateusz Michalek (cherry picked from commit d8a2e457f25f4d8b3924e3da69b54965e1690678) --- .../boards/nrf54lm20dk_nrf54lm20a_cpuapp.conf | 13 +++++++++++++ .../boards/nrf54lm20pdk_nrf54lm20a_cpuapp.conf | 3 --- 2 files changed, 13 insertions(+), 3 deletions(-) create mode 100644 boot/zephyr/boards/nrf54lm20dk_nrf54lm20a_cpuapp.conf diff --git a/boot/zephyr/boards/nrf54lm20dk_nrf54lm20a_cpuapp.conf b/boot/zephyr/boards/nrf54lm20dk_nrf54lm20a_cpuapp.conf new file mode 100644 index 000000000..816560405 --- /dev/null +++ b/boot/zephyr/boards/nrf54lm20dk_nrf54lm20a_cpuapp.conf @@ -0,0 +1,13 @@ +# Copyright (c) 2025 Nordic Semiconductor ASA +# +# SPDX-License-Identifier: Apache-2.0 +# +CONFIG_BOOT_MAX_IMG_SECTORS=256 + +# Ensure that the SPI NOR driver is disabled by default +CONFIG_SPI_NOR=n + +# TODO: below are not yet supported and need fixing +CONFIG_FPROTECT=n + +CONFIG_BOOT_WATCHDOG_FEED=n diff --git a/boot/zephyr/boards/nrf54lm20pdk_nrf54lm20a_cpuapp.conf b/boot/zephyr/boards/nrf54lm20pdk_nrf54lm20a_cpuapp.conf index 4944f7b13..816560405 100644 --- a/boot/zephyr/boards/nrf54lm20pdk_nrf54lm20a_cpuapp.conf +++ b/boot/zephyr/boards/nrf54lm20pdk_nrf54lm20a_cpuapp.conf @@ -11,6 +11,3 @@ CONFIG_SPI_NOR=n CONFIG_FPROTECT=n CONFIG_BOOT_WATCHDOG_FEED=n - -CONFIG_PSA_CRYPTO_DRIVER_CRACEN=n -CONFIG_PSA_CRYPTO_DRIVER_OBERON=y From cc558efbb2e06ef1a195a3a0e3e83ecd182c8946 Mon Sep 17 00:00:00 2001 From: Tomasz Chyrowicz Date: Mon, 28 Jul 2025 12:46:20 +0200 Subject: [PATCH 353/420] [nrf noup] bootloader: Add bootloader requests Add a capability inside the Zephyr bootloader to handle memory-based bootloader requests to: - Boot recovery firmware - Boot firmware loader - Confirm an image - Set the slot preference Ref: NCSDK-34429 Signed-off-by: Tomasz Chyrowicz (cherry picked from commit 09ce751132d4a7b48ec110c3f8ea2e6256601731) --- boot/bootutil/include/bootutil/boot_request.h | 105 ++++++ boot/bootutil/src/bootutil_public.c | 84 ++++- boot/bootutil/zephyr/CMakeLists.txt | 5 + .../zephyr/src/boot_request_retention.c | 346 ++++++++++++++++++ boot/zephyr/Kconfig | 4 + boot/zephyr/Kconfig.firmware_loader | 6 + boot/zephyr/Kconfig.serial_recovery | 6 + boot/zephyr/firmware_loader.c | 9 + boot/zephyr/main.c | 53 +++ 9 files changed, 613 insertions(+), 5 deletions(-) create mode 100644 boot/bootutil/include/bootutil/boot_request.h create mode 100644 boot/bootutil/zephyr/src/boot_request_retention.c diff --git a/boot/bootutil/include/bootutil/boot_request.h b/boot/bootutil/include/bootutil/boot_request.h new file mode 100644 index 000000000..b1e8f891e --- /dev/null +++ b/boot/bootutil/include/bootutil/boot_request.h @@ -0,0 +1,105 @@ +/* + * SPDX-License-Identifier: Apache-2.0 + * + * Copyright (c) 2025 Nordic Semiconductor ASA + */ + +#ifndef __BOOT_REQUEST_H__ +#define __BOOT_REQUEST_H__ + +#ifdef __cplusplus +extern "C" { +#endif + +#include +#include + +/** Special value, indicating that there is no preferred slot. */ +#define BOOT_REQUEST_NO_PREFERRED_SLOT UINT32_MAX + +/** + * @brief Request a bootloader to confirm the specified slot of an image. + * + * @param[in] image Image number. + * @param[in] slot Slot number. + * + * @return 0 if requested, negative error code otherwise. + */ +int boot_request_confirm_slot(uint8_t image, uint32_t slot); + +/** + * @brief Request a bootloader to boot the specified slot of an image. + * + * @param[in] image Image number. + * @param[in] slot Slot number. + * + * @return 0 if requested, negative error code otherwise. + */ +int boot_request_set_preferred_slot(uint8_t image, uint32_t slot); + +/** + * @brief Request a bootloader to boot recovery image. + * + * @return 0 if requested, negative error code otherwise. + */ +int boot_request_enter_recovery(void); + +/** + * @brief Request a bootloader to boot firmware loader image. + * + * @return 0 if requested, negative error code otherwise. + */ +int boot_request_enter_firmware_loader(void); + +/** + * @brief Check if there is a request to confirm the specified slot of an image. + * + * @param[in] image Image number. + * @param[in] slot Slot number. + * + * @return true if requested, false otherwise. + */ +bool boot_request_check_confirmed_slot(uint8_t image, uint32_t slot); + +/** + * @brief Find if there is a request to boot certain slot of the specified image. + * + * @param[in] image Image number. + * + * @return slot number if requested, BOOT_REQUEST_NO_PREFERRED_SLOT otherwise. + */ +uint32_t boot_request_get_preferred_slot(uint8_t image); + +/** + * @brief Check if there is a request to boot recovery image. + * + * @return true if requested, false otherwise. + */ +bool boot_request_detect_recovery(void); + +/** + * @brief Check if there is a request to boot firmware loader image. + * + * @return true if requested, false otherwise. + */ +bool boot_request_detect_firmware_loader(void); + +/** + * @brief Initialize boot requests module. + * + * @return 0 if successful, negative error code otherwise. + */ +int boot_request_init(void); + +/** + * @brief Clear/drop all requests. + * + * @return 0 if successful, negative error code otherwise. + */ +int boot_request_clear(void); + +#ifdef __cplusplus +} +#endif + +#endif /* __BOOT_REQUEST_H__ */ diff --git a/boot/bootutil/src/bootutil_public.c b/boot/bootutil/src/bootutil_public.c index cb689be3b..5299a9cba 100644 --- a/boot/bootutil/src/bootutil_public.c +++ b/boot/bootutil/src/bootutil_public.c @@ -51,6 +51,11 @@ #include "bootutil_priv.h" #include "bootutil_misc.h" +#if defined(CONFIG_NRF_MCUBOOT_BOOT_REQUEST) && !defined(CONFIG_MCUBOOT) +#include +#define SEND_BOOT_REQUEST +#endif /* CONFIG_NRF_MCUBOOT_BOOT_REQUEST && !CONFIG_MCUBOOT */ + #ifdef CONFIG_MCUBOOT BOOT_LOG_MODULE_DECLARE(mcuboot); #else @@ -503,16 +508,47 @@ boot_write_copy_done(const struct flash_area *fap) return boot_write_trailer_flag(fap, off, BOOT_FLAG_SET); } -#ifndef MCUBOOT_BOOTUTIL_LIB_FOR_DIRECT_XIP +#ifdef SEND_BOOT_REQUEST +static int +send_boot_request(uint8_t magic, bool confirm, int image_id, uint32_t slot_id) +{ + int rc = BOOT_EBADIMAGE; -static int flash_area_to_image(const struct flash_area *fa) + /* Handle write-protected active image. */ + if ((magic == BOOT_MAGIC_GOOD) || (magic == BOOT_MAGIC_UNSET)) { + if (confirm) { + BOOT_LOG_DBG("Confirm image: %d, %d", image_id, slot_id); + rc = boot_request_confirm_slot(image_id, slot_id); + } else { + BOOT_LOG_DBG("Set image preference: %d, %d", image_id, slot_id); + rc = boot_request_set_preferred_slot(image_id, slot_id); + } + if (rc != 0) { + rc = BOOT_EBADIMAGE; + } + } + + return rc; +} +#endif /* SEND_BOOT_REQUEST */ + +#if defined(SEND_BOOT_REQUEST) || (!defined(MCUBOOT_BOOTUTIL_LIB_FOR_DIRECT_XIP)) +static int flash_area_to_image_slot(const struct flash_area *fa, uint32_t *slot) { + int id = flash_area_get_id(fa); #if BOOT_IMAGE_NUMBER > 1 uint8_t i = 0; - int id = flash_area_get_id(fa); while (i < BOOT_IMAGE_NUMBER) { - if (FLASH_AREA_IMAGE_PRIMARY(i) == id || (FLASH_AREA_IMAGE_SECONDARY(i) == id)) { + if (FLASH_AREA_IMAGE_PRIMARY(i) == id) { + if (slot != NULL) { + *slot = 0; + } + return i; + } else if (FLASH_AREA_IMAGE_SECONDARY(i) == id) { + if (slot != NULL) { + *slot = 1; + } return i; } @@ -520,15 +556,31 @@ static int flash_area_to_image(const struct flash_area *fa) } #else (void)fa; + if (slot != NULL) { + if (FLASH_AREA_IMAGE_PRIMARY(0) == id) { + *slot = 0; + } else if (FLASH_AREA_IMAGE_SECONDARY(0) == id) { + *slot = 1; + } else { + *slot = UINT32_MAX; + } + } #endif return 0; } +#endif /* defined(SEND_BOOT_REQUEST) || (!defined(MCUBOOT_BOOTUTIL_LIB_FOR_DIRECT_XIP)) */ +#ifndef MCUBOOT_BOOTUTIL_LIB_FOR_DIRECT_XIP int boot_set_next(const struct flash_area *fa, bool active, bool confirm) { struct boot_swap_state slot_state; int rc; + int image_id; + uint32_t slot_id; + + BOOT_LOG_DBG("boot_set_next: fa %p active == %d, confirm == %d", + fa, (int)active, (int)confirm); if (active) { confirm = true; @@ -539,6 +591,15 @@ boot_set_next(const struct flash_area *fa, bool active, bool confirm) return rc; } + image_id = flash_area_to_image_slot(fa, &slot_id); + +#ifdef SEND_BOOT_REQUEST + rc = send_boot_request(slot_state.magic, confirm, image_id, slot_id); + if ((rc != 0) || active) { + return rc; + } +#endif + switch (slot_state.magic) { case BOOT_MAGIC_GOOD: /* If non-active then swap already scheduled, else confirm needed.*/ @@ -569,7 +630,7 @@ boot_set_next(const struct flash_area *fa, bool active, bool confirm) } else { swap_type = BOOT_SWAP_TYPE_TEST; } - rc = boot_write_swap_info(fa, swap_type, flash_area_to_image(fa)); + rc = boot_write_swap_info(fa, swap_type, image_id); } } break; @@ -597,6 +658,10 @@ boot_set_next(const struct flash_area *fa, bool active, bool confirm) { struct boot_swap_state slot_state; int rc; +#ifdef SEND_BOOT_REQUEST + int image_id; + uint32_t slot_id; +#endif BOOT_LOG_DBG("boot_set_next: fa %p active == %d, confirm == %d", fa, (int)active, (int)confirm); @@ -615,6 +680,15 @@ boot_set_next(const struct flash_area *fa, bool active, bool confirm) return rc; } +#ifdef SEND_BOOT_REQUEST + image_id = flash_area_to_image_slot(fa, &slot_id); + + rc = send_boot_request(slot_state.magic, confirm, image_id, slot_id); + if ((rc != 0) || active) { + return rc; + } +#endif + switch (slot_state.magic) { case BOOT_MAGIC_UNSET: /* Magic is needed for MCUboot to even consider booting an image */ diff --git a/boot/bootutil/zephyr/CMakeLists.txt b/boot/bootutil/zephyr/CMakeLists.txt index 44f78f395..111cf4f1d 100644 --- a/boot/bootutil/zephyr/CMakeLists.txt +++ b/boot/bootutil/zephyr/CMakeLists.txt @@ -16,6 +16,11 @@ zephyr_library_named(mcuboot_util) zephyr_library_sources( ../src/bootutil_public.c ) +if(CONFIG_NRF_MCUBOOT_BOOT_REQUEST) + zephyr_library_sources_ifdef(CONFIG_NRF_MCUBOOT_BOOT_REQUEST_IMPL_RETENTION + src/boot_request_retention.c + ) +endif() # Sensitivity to the TEST_BOOT_IMAGE_ACCESS_HOOKS define is implemented for # allowing the test-build with the hooks feature enabled. diff --git a/boot/bootutil/zephyr/src/boot_request_retention.c b/boot/bootutil/zephyr/src/boot_request_retention.c new file mode 100644 index 000000000..023f5af5e --- /dev/null +++ b/boot/bootutil/zephyr/src/boot_request_retention.c @@ -0,0 +1,346 @@ +/* + * SPDX-License-Identifier: Apache-2.0 + * + * Copyright (c) 2025 Nordic Semiconductor ASA + */ +#include + +#include "bootutil/bootutil_log.h" +#include + +/** Special value of image number, indicating a request to the bootloader. */ +#define BOOT_REQUEST_IMG_BOOTLOADER 0xFF + +/** Additional memory used by the retention subsystem (2B - prefix, 4B - CRC).*/ +#define BOOT_REQUEST_ENTRY_METADATA_SIZE (2 + 4) + +MCUBOOT_LOG_MODULE_REGISTER(bootloader_request); + +static const struct device *bootloader_request_dev = + DEVICE_DT_GET(DT_CHOSEN(nrf_bootloader_request)); + +enum boot_request_type { + /** Invalid request. */ + BOOT_REQUEST_INVALID = 0, + + /** Request a change in the bootloader boot mode. + * + * @details Use @p boot_request_mode as argument. + * @p BOOT_REQUEST_IMG_BOOTLOADER as image number. + * + * @note Used to trigger recovery through i.e. retention sybsystem. + */ + BOOT_REQUEST_BOOT_MODE = 1, + + /** Select the preferred image to be selected during boot or update. + * + * @details Use @p boot_request_slot_t as argument. + * + * @note Used in the Direct XIP mode. + */ + BOOT_REQUEST_IMG_PREFERENCE = 2, + + /** Request a confirmation of an image. + * + * @details Use @p boot_request_slot_t as argument. + * + * @note Used if the code cannot modify the image trailer directly. + */ + BOOT_REQUEST_IMG_CONFIRM = 3, +}; + +/* Entries inside the boot request shared memory. */ +enum boot_request_entry { + BOOT_REQUEST_ENTRY_BOOT_MODE = 0, + BOOT_REQUEST_ENTRY_IMAGE_0_PREFERENCE = 1, + BOOT_REQUEST_ENTRY_IMAGE_0_CONFIRM = 2, + BOOT_REQUEST_ENTRY_IMAGE_1_PREFERENCE = 3, + BOOT_REQUEST_ENTRY_IMAGE_1_CONFIRM = 4, + BOOT_REQUEST_ENTRY_MAX = 5, +}; + +/* Assert that all requests will fit within the retention area. */ +BUILD_ASSERT((BOOT_REQUEST_ENTRY_METADATA_SIZE + BOOT_REQUEST_ENTRY_MAX * sizeof(uint8_t)) < + DT_REG_SIZE_BY_IDX(DT_CHOSEN(nrf_bootloader_request), 0), + "nrf,bootloader-request area is too small for bootloader request struct"); + +enum boot_request_slot { + /** Unsupported value. */ + BOOT_REQUEST_SLOT_INVALID = 0, + /** Primary slot. */ + BOOT_REQUEST_SLOT_PRIMARY = 1, + /** Secondary slot. */ + BOOT_REQUEST_SLOT_SECONDARY = 2, +}; + +/** Alias type for the image and number. */ +typedef uint8_t boot_request_slot_t; + +enum boot_request_mode { + /** Execute a regular boot logic. */ + BOOT_REQUEST_MODE_REGULAR = 0, + /** Execute the recovery boot logic. */ + BOOT_REQUEST_MODE_RECOVERY = 1, + /** Execute the firmware loader logic. */ + BOOT_REQUEST_MODE_FIRMWARE_LOADER = 2, + /** Unsupported value. */ + BOOT_REQUEST_MODE_INVALID = 0xFF, +}; + +/** Alias type for the image number. */ +typedef uint8_t boot_request_img_t; + +/** + * @brief Find an entry for a given request. + * + * @param[in] type Type of request. + * @param[in] image Image number. Use @p BOOT_REQUEST_IMG_BOOTLOADER for generic requests. + * @param[out] entry Entry to use. + * + * @return 0 on success; nonzero on failure. + */ +static int boot_request_entry_find(enum boot_request_type type, boot_request_img_t image, + size_t *entry) +{ + if (entry == NULL) { + return -EINVAL; + } + + switch (type) { + case BOOT_REQUEST_BOOT_MODE: + *entry = BOOT_REQUEST_ENTRY_BOOT_MODE; + break; + case BOOT_REQUEST_IMG_PREFERENCE: + switch (image) { + case 0: + *entry = BOOT_REQUEST_ENTRY_IMAGE_0_PREFERENCE; + break; + case 1: + *entry = BOOT_REQUEST_ENTRY_IMAGE_1_PREFERENCE; + break; + default: + return -EINVAL; + } + break; + case BOOT_REQUEST_IMG_CONFIRM: + switch (image) { + case 0: + *entry = BOOT_REQUEST_ENTRY_IMAGE_0_CONFIRM; + break; + case 1: + *entry = BOOT_REQUEST_ENTRY_IMAGE_1_CONFIRM; + break; + default: + return -EINVAL; + } + break; + default: + return -EINVAL; + } + + return 0; +} + +int boot_request_init(void) +{ + if (!device_is_ready(bootloader_request_dev)) { + return -EIO; + } + + return 0; +} + +int boot_request_clear(void) +{ + return retention_clear(bootloader_request_dev); +} + +int boot_request_confirm_slot(uint8_t image, uint32_t slot) +{ + uint8_t value = BOOT_REQUEST_SLOT_INVALID; + size_t req_entry; + int ret; + + ret = boot_request_entry_find(BOOT_REQUEST_IMG_CONFIRM, image, &req_entry); + if (ret != 0) { + return ret; + } + + switch (slot) { + case 0: + value = BOOT_REQUEST_SLOT_PRIMARY; + break; + case 1: + value = BOOT_REQUEST_SLOT_SECONDARY; + break; + default: + return -EINVAL; + } + + return retention_write(bootloader_request_dev, req_entry * sizeof(value), (void *)&value, + sizeof(value)); +} + +bool boot_request_check_confirmed_slot(uint8_t image, uint32_t slot) +{ + uint8_t value = BOOT_REQUEST_SLOT_INVALID; + size_t req_entry; + int ret; + + ret = boot_request_entry_find(BOOT_REQUEST_IMG_CONFIRM, image, &req_entry); + if (ret != 0) { + return false; + } + + ret = retention_read(bootloader_request_dev, req_entry * sizeof(value), (void *)&value, + sizeof(value)); + if (ret != 0) { + return false; + } + + switch (value) { + case BOOT_REQUEST_SLOT_PRIMARY: + return (slot == 0); + case BOOT_REQUEST_SLOT_SECONDARY: + return (slot == 1); + default: + break; + } + + return false; +} + +int boot_request_set_preferred_slot(uint8_t image, uint32_t slot) +{ + uint8_t value = BOOT_REQUEST_SLOT_INVALID; + size_t req_entry; + int ret; + + ret = boot_request_entry_find(BOOT_REQUEST_IMG_PREFERENCE, image, &req_entry); + if (ret != 0) { + return ret; + } + + switch (slot) { + case 0: + value = BOOT_REQUEST_SLOT_PRIMARY; + break; + case 1: + value = BOOT_REQUEST_SLOT_SECONDARY; + break; + default: + return -EINVAL; + } + + return retention_write(bootloader_request_dev, req_entry * sizeof(value), (void *)&value, + sizeof(value)); +} + +#ifdef CONFIG_FIND_NEXT_SLOT_HOOKS +uint32_t boot_request_get_preferred_slot(uint8_t image) +{ + uint8_t value = BOOT_REQUEST_SLOT_INVALID; + size_t req_entry; + int ret; + + ret = boot_request_entry_find(BOOT_REQUEST_IMG_PREFERENCE, image, &req_entry); + if (ret != 0) { + return BOOT_REQUEST_NO_PREFERRED_SLOT; + } + + ret = retention_read(bootloader_request_dev, req_entry * sizeof(value), (void *)&value, + sizeof(value)); + if (ret != 0) { + return BOOT_REQUEST_NO_PREFERRED_SLOT; + } + + switch (value) { + case BOOT_REQUEST_SLOT_PRIMARY: + return 0; + case BOOT_REQUEST_SLOT_SECONDARY: + return 1; + default: + break; + } + + return BOOT_REQUEST_NO_PREFERRED_SLOT; +} +#endif /* CONFIG_FIND_NEXT_SLOT_HOOKS */ + +int boot_request_enter_recovery(void) +{ + uint8_t value = BOOT_REQUEST_MODE_RECOVERY; + size_t req_entry; + int ret; + + ret = boot_request_entry_find(BOOT_REQUEST_BOOT_MODE, BOOT_REQUEST_IMG_BOOTLOADER, + &req_entry); + if (ret != 0) { + return ret; + } + + return retention_write(bootloader_request_dev, req_entry * sizeof(value), (void *)&value, + sizeof(value)); +} + +#ifdef CONFIG_NRF_BOOT_SERIAL_BOOT_REQ +bool boot_request_detect_recovery(void) +{ + uint8_t value = BOOT_REQUEST_MODE_INVALID; + size_t req_entry; + int ret; + + ret = boot_request_entry_find(BOOT_REQUEST_BOOT_MODE, BOOT_REQUEST_IMG_BOOTLOADER, + &req_entry); + if (ret != 0) { + return false; + } + + ret = retention_read(bootloader_request_dev, req_entry * sizeof(value), (void *)&value, + sizeof(value)); + if ((ret == 0) && (value == BOOT_REQUEST_MODE_RECOVERY)) { + return true; + } + + return false; +} +#endif /* CONFIG_NRF_BOOT_SERIAL_BOOT_REQ */ + +int boot_request_enter_firmware_loader(void) +{ + uint8_t value = BOOT_REQUEST_MODE_FIRMWARE_LOADER; + size_t req_entry; + int ret; + + ret = boot_request_entry_find(BOOT_REQUEST_BOOT_MODE, BOOT_REQUEST_IMG_BOOTLOADER, + &req_entry); + if (ret != 0) { + return ret; + } + + return retention_write(bootloader_request_dev, req_entry * sizeof(value), (void *)&value, + sizeof(value)); +} + +#ifdef CONFIG_NRF_BOOT_FIRMWARE_LOADER_BOOT_REQ +bool boot_request_detect_firmware_loader(void) +{ + uint8_t value = BOOT_REQUEST_MODE_INVALID; + size_t req_entry; + int ret; + + ret = boot_request_entry_find(BOOT_REQUEST_BOOT_MODE, BOOT_REQUEST_IMG_BOOTLOADER, + &req_entry); + if (ret != 0) { + return false; + } + + ret = retention_read(bootloader_request_dev, req_entry * sizeof(value), (void *)&value, + sizeof(value)); + if ((ret == 0) && (value == BOOT_REQUEST_MODE_FIRMWARE_LOADER)) { + return true; + } + + return false; +} +#endif /* CONFIG_NRF_BOOT_FIRMWARE_LOADER_BOOT_REQ */ diff --git a/boot/zephyr/Kconfig b/boot/zephyr/Kconfig index cc265de0a..0685baefb 100644 --- a/boot/zephyr/Kconfig +++ b/boot/zephyr/Kconfig @@ -1327,6 +1327,10 @@ config USB_DEVICE_PRODUCT config MCUBOOT_BOOTUTIL_LIB_OWN_LOG bool +config NRF_MCUBOOT_BOOT_REQUEST + bool + imply FIND_NEXT_SLOT_HOOKS if BOOT_DIRECT_XIP || BOOT_RAM_LOAD + config MCUBOOT_VERIFY_IMG_ADDRESS bool "Verify reset address of image in secondary slot" depends on UPDATEABLE_IMAGE_NUMBER > 1 diff --git a/boot/zephyr/Kconfig.firmware_loader b/boot/zephyr/Kconfig.firmware_loader index 036da98eb..376dc06f7 100644 --- a/boot/zephyr/Kconfig.firmware_loader +++ b/boot/zephyr/Kconfig.firmware_loader @@ -42,6 +42,12 @@ config BOOT_FIRMWARE_LOADER_PIN_RESET Checks if the module reset was caused by the reset pin and will remain in bootloader firmware loader mode if it was. +config NRF_BOOT_FIRMWARE_LOADER_BOOT_REQ + bool "Check boot mode via bootloader request" + depends on NRF_MCUBOOT_BOOT_REQUEST + help + Allows for entering firmware loader mode by using bootloader rquests. + endmenu endif diff --git a/boot/zephyr/Kconfig.serial_recovery b/boot/zephyr/Kconfig.serial_recovery index 5b4ba3e11..b6c71e5e0 100644 --- a/boot/zephyr/Kconfig.serial_recovery +++ b/boot/zephyr/Kconfig.serial_recovery @@ -191,6 +191,12 @@ config BOOT_SERIAL_PIN_RESET Checks if the module reset was caused by the reset pin and will remain in bootloader serial recovery mode if it was. +config NRF_BOOT_SERIAL_BOOT_REQ + bool "Check boot mode via bootloader request subsystem" + depends on NRF_MCUBOOT_BOOT_REQUEST + help + Allows for entering serial recovery mode by using bootloader requests. + endmenu config BOOT_SERIAL_IMG_GRP_HASH diff --git a/boot/zephyr/firmware_loader.c b/boot/zephyr/firmware_loader.c index 18070bc25..217336755 100644 --- a/boot/zephyr/firmware_loader.c +++ b/boot/zephyr/firmware_loader.c @@ -17,6 +17,9 @@ #include "io/io.h" #include "mcuboot_config/mcuboot_config.h" +#ifdef CONFIG_NRF_MCUBOOT_BOOT_REQUEST +#include +#endif /* CONFIG_NRF_MCUBOOT_BOOT_REQUEST */ BOOT_LOG_MODULE_DECLARE(mcuboot); @@ -183,6 +186,12 @@ boot_go(struct boot_rsp *rsp) } #endif +#ifdef CONFIG_NRF_BOOT_FIRMWARE_LOADER_BOOT_REQ + if (boot_request_detect_firmware_loader()) { + boot_firmware_loader = true; + } +#endif + /* Check if firmware loader button is pressed. TODO: check all entrance methods */ if (boot_firmware_loader == true) { FIH_CALL(validate_image_slot, fih_rc, FLASH_AREA_IMAGE_SECONDARY(0), rsp); diff --git a/boot/zephyr/main.c b/boot/zephyr/main.c index 6fb27c7ca..bc4fc314c 100644 --- a/boot/zephyr/main.c +++ b/boot/zephyr/main.c @@ -47,6 +47,12 @@ #include "bootutil/fault_injection_hardening.h" #include "bootutil/mcuboot_status.h" #include "flash_map_backend/flash_map_backend.h" +#ifdef CONFIG_NRF_MCUBOOT_BOOT_REQUEST +#include + +/** Number of image slots. */ +#define BOOT_REQUEST_NUM_SLOTS 2 +#endif /* CONFIG_NRF_MCUBOOT_BOOT_REQUEST */ #if defined(CONFIG_MCUBOOT_UUID_VID) || defined(CONFIG_MCUBOOT_UUID_CID) #include "bootutil/mcuboot_uuid.h" @@ -606,6 +612,37 @@ static void boot_serial_enter() } #endif +static int boot_prevalidate(void) +{ +#ifdef CONFIG_NRF_MCUBOOT_BOOT_REQUEST + uint8_t image_index; + uint32_t slot; + uint32_t area_id; + const struct flash_area *fap; + int rc = boot_request_init(); + + if (rc != 0) { + return rc; + } + + for (image_index = 0; image_index < BOOT_IMAGE_NUMBER; ++image_index) { + for (slot = 0; slot < BOOT_REQUEST_NUM_SLOTS; slot++) { + if (boot_request_check_confirmed_slot(image_index, slot)) { + BOOT_LOG_DBG("Confirm image: %d slot: %d due to bootloader request.", + image_index, slot); + + area_id = flash_area_id_from_multi_image_slot(image_index, slot); + rc = flash_area_open(area_id, &fap); + if (rc == 0) { + rc = boot_set_next(fap, true, true); + } + } + } + } +#endif + return 0; +} + int main(void) { struct boot_rsp rsp; @@ -645,6 +682,11 @@ int main(void) } #endif /* CONFIG_MCUBOOT_UUID_VID || CONFIG_MCUBOOT_UUID_CID */ + rc = boot_prevalidate(); + if (rc) { + BOOT_LOG_ERR("Failed to prevalidate the state: %d", rc); + } + #ifdef CONFIG_BOOT_SERIAL_ENTRANCE_GPIO BOOT_LOG_DBG("Checking GPIO for serial recovery"); if (io_detect_pin() && @@ -660,6 +702,13 @@ int main(void) } #endif +#ifdef CONFIG_NRF_BOOT_SERIAL_BOOT_REQ + if (boot_request_detect_recovery()) { + BOOT_LOG_DBG("Staying in serial recovery"); + boot_serial_enter(); + } +#endif + #if defined(CONFIG_BOOT_USB_DFU_GPIO) BOOT_LOG_DBG("Checking GPIO for USB DFU request"); if (io_detect_pin()) { @@ -720,6 +769,10 @@ int main(void) } BOOT_LOG_DBG("Left boot_go with success == %d", FIH_EQ(fih_rc, FIH_SUCCESS) ? 1 : 0); +#ifdef CONFIG_NRF_MCUBOOT_BOOT_REQUEST + (void)boot_request_clear(); +#endif + #ifdef CONFIG_BOOT_SERIAL_BOOT_MODE if (io_detect_boot_mode()) { /* Boot mode to stay in bootloader, clear status and enter serial From bb72623b1dfbebf95443562fe16baa4c73cf2121 Mon Sep 17 00:00:00 2001 From: Tomasz Chyrowicz Date: Thu, 4 Sep 2025 13:42:12 +0200 Subject: [PATCH 354/420] [nrf noup] boot: Improve bootloader request handling nrf-squash! [nrf noup] bootloader: Add bootloader requests Improve logic that handles sending bootloader requests as a result of issuing the MCUmgr commands. Signed-off-by: Tomasz Chyrowicz (cherry picked from commit 0b546656c3792bfe8e980fbde5eacdb27aa7eccd) --- boot/bootutil/src/bootutil_public.c | 17 +++++++++++++---- boot/zephyr/Kconfig | 11 +++++++++++ 2 files changed, 24 insertions(+), 4 deletions(-) diff --git a/boot/bootutil/src/bootutil_public.c b/boot/bootutil/src/bootutil_public.c index 5299a9cba..eac5beeeb 100644 --- a/boot/bootutil/src/bootutil_public.c +++ b/boot/bootutil/src/bootutil_public.c @@ -510,7 +510,8 @@ boot_write_copy_done(const struct flash_area *fap) #ifdef SEND_BOOT_REQUEST static int -send_boot_request(uint8_t magic, bool confirm, int image_id, uint32_t slot_id) +send_boot_request(uint8_t magic, uint8_t image_ok, bool confirm, int image_id, + uint32_t slot_id) { int rc = BOOT_EBADIMAGE; @@ -518,10 +519,16 @@ send_boot_request(uint8_t magic, bool confirm, int image_id, uint32_t slot_id) if ((magic == BOOT_MAGIC_GOOD) || (magic == BOOT_MAGIC_UNSET)) { if (confirm) { BOOT_LOG_DBG("Confirm image: %d, %d", image_id, slot_id); - rc = boot_request_confirm_slot(image_id, slot_id); + if ((image_ok != BOOT_FLAG_SET) || (magic != BOOT_MAGIC_GOOD)) { + rc = boot_request_confirm_slot(image_id, slot_id); + } else { + rc = 0; + } +#ifdef CONFIG_NCS_MCUBOOT_BOOT_REQUEST_TEST_SETS_BOOT_PREFERENCE } else { BOOT_LOG_DBG("Set image preference: %d, %d", image_id, slot_id); rc = boot_request_set_preferred_slot(image_id, slot_id); +#endif /* CONFIG_NCS_MCUBOOT_BOOT_REQUEST_TEST_SETS_BOOT_PREFERENCE */ } if (rc != 0) { rc = BOOT_EBADIMAGE; @@ -594,7 +601,8 @@ boot_set_next(const struct flash_area *fa, bool active, bool confirm) image_id = flash_area_to_image_slot(fa, &slot_id); #ifdef SEND_BOOT_REQUEST - rc = send_boot_request(slot_state.magic, confirm, image_id, slot_id); + rc = send_boot_request(slot_state.magic, slot_state.image_ok, confirm, + image_id, slot_id); if ((rc != 0) || active) { return rc; } @@ -683,7 +691,8 @@ boot_set_next(const struct flash_area *fa, bool active, bool confirm) #ifdef SEND_BOOT_REQUEST image_id = flash_area_to_image_slot(fa, &slot_id); - rc = send_boot_request(slot_state.magic, confirm, image_id, slot_id); + rc = send_boot_request(slot_state.magic, slot_state.image_ok, confirm, + image_id, slot_id); if ((rc != 0) || active) { return rc; } diff --git a/boot/zephyr/Kconfig b/boot/zephyr/Kconfig index 0685baefb..7c2ed030a 100644 --- a/boot/zephyr/Kconfig +++ b/boot/zephyr/Kconfig @@ -1366,4 +1366,15 @@ config NCS_MCUBOOT_IMG_VALIDATE_ATTEMPT_WAIT_MS Time between image validation attempts, in milliseconds. Allows for recovery from transient bit flips or similar situations. +config NCS_MCUBOOT_BOOT_REQUEST_TEST_SETS_BOOT_PREFERENCE + bool "Set boot preference if a slot is marked for test" + help + This option allows to verify boot preference requests through issuing + the image test. + Using this option is not recommended in production systems, because + it will boot any newly transferred image, even if it has a lower + version than the current one. + The rollback protection (using security counters) will still be + effective. + source "Kconfig.zephyr" From 90b22796b1a6f08705c79ddf5884f3a83a2563a0 Mon Sep 17 00:00:00 2001 From: Jamie McCrae Date: Thu, 22 Aug 2024 14:17:46 +0100 Subject: [PATCH 355/420] [nrf noup] zephyr: Add support for compressed image updates Adds support for LZMA-compressed firmware updates which also supports encrypted images and supports more than 1 updateable image Signed-off-by: Jamie McCrae Signed-off-by: Michal Kozikowski Signed-off-by: Dominik Ermel (cherry picked from commit 27758d7c440e5fbd284bd4e9b75e3e634562a718) (cherry picked from commit ce9d1d6bf1b26663195752ad137a315c1172c6cb) --- boot/bootutil/src/bootutil_misc.c | 80 +- boot/bootutil/src/image_validate.c | 223 ++- boot/bootutil/src/loader.c | 27 +- boot/zephyr/CMakeLists.txt | 6 + boot/zephyr/Kconfig | 9 +- boot/zephyr/decompression.c | 1505 +++++++++++++++++ .../include/compression/decompression.h | 103 ++ 7 files changed, 1927 insertions(+), 26 deletions(-) create mode 100644 boot/zephyr/decompression.c create mode 100644 boot/zephyr/include/compression/decompression.h diff --git a/boot/bootutil/src/bootutil_misc.c b/boot/bootutil/src/bootutil_misc.c index 396381437..ec61f6f9e 100644 --- a/boot/bootutil/src/bootutil_misc.c +++ b/boot/bootutil/src/bootutil_misc.c @@ -47,8 +47,9 @@ #include "swap_priv.h" #endif -#if defined(MCUBOOT_SERIAL_IMG_GRP_SLOT_INFO) || defined(MCUBOOT_SWAP_USING_SCRATCH) -#include "swap_priv.h" +#if defined(MCUBOOT_DECOMPRESS_IMAGES) +#include +#include #endif BOOT_LOG_MODULE_DECLARE(mcuboot); @@ -487,35 +488,76 @@ boot_read_image_size(struct boot_loader_state *state, int slot, uint32_t *size) fap = BOOT_IMG_AREA(state, slot); assert(fap != NULL); - off = BOOT_TLV_OFF(boot_img_hdr(state, slot)); +#ifdef MCUBOOT_DECOMPRESS_IMAGES + if (MUST_DECOMPRESS(fap, BOOT_CURR_IMG(state), boot_img_hdr(state, slot))) { + uint32_t tmp_size = 0; - if (flash_area_read(fap, off, &info, sizeof(info))) { - rc = BOOT_EFLASH; - goto done; - } + rc = bootutil_get_img_decomp_size(boot_img_hdr(state, slot), fap, &tmp_size); - protect_tlv_size = boot_img_hdr(state, slot)->ih_protect_tlv_size; - if (info.it_magic == IMAGE_TLV_PROT_INFO_MAGIC) { - if (protect_tlv_size != info.it_tlv_tot) { + if (rc) { rc = BOOT_EBADIMAGE; goto done; } - if (flash_area_read(fap, off + info.it_tlv_tot, &info, sizeof(info))) { + off = boot_img_hdr(state, slot)->ih_hdr_size + tmp_size; + + rc = boot_size_protected_tlvs(boot_img_hdr(state, slot), fap, &tmp_size); + + if (rc) { + rc = BOOT_EBADIMAGE; + goto done; + } + + off += tmp_size; + + if (flash_area_read(fap, (BOOT_TLV_OFF(boot_img_hdr(state, slot)) + + boot_img_hdr(state, slot)->ih_protect_tlv_size), &info, + sizeof(info))) { rc = BOOT_EFLASH; goto done; } - } else if (protect_tlv_size != 0) { - rc = BOOT_EBADIMAGE; - goto done; - } - if (info.it_magic != IMAGE_TLV_INFO_MAGIC) { - rc = BOOT_EBADIMAGE; - goto done; + if (info.it_magic != IMAGE_TLV_INFO_MAGIC) { + rc = BOOT_EBADIMAGE; + goto done; + } + + *size = off + info.it_tlv_tot; + } else { +#else + if (1) { +#endif + off = BOOT_TLV_OFF(boot_img_hdr(state, slot)); + + if (flash_area_read(fap, off, &info, sizeof(info))) { + rc = BOOT_EFLASH; + goto done; + } + + protect_tlv_size = boot_img_hdr(state, slot)->ih_protect_tlv_size; + if (info.it_magic == IMAGE_TLV_PROT_INFO_MAGIC) { + if (protect_tlv_size != info.it_tlv_tot) { + rc = BOOT_EBADIMAGE; + goto done; + } + + if (flash_area_read(fap, off + info.it_tlv_tot, &info, sizeof(info))) { + rc = BOOT_EFLASH; + goto done; + } + } else if (protect_tlv_size != 0) { + rc = BOOT_EBADIMAGE; + goto done; + } + + if (info.it_magic != IMAGE_TLV_INFO_MAGIC) { + rc = BOOT_EBADIMAGE; + goto done; + } + + *size = off + protect_tlv_size + info.it_tlv_tot; } - *size = off + protect_tlv_size + info.it_tlv_tot; rc = 0; done: diff --git a/boot/bootutil/src/image_validate.c b/boot/bootutil/src/image_validate.c index cb9ce3466..5d2efc98a 100644 --- a/boot/bootutil/src/image_validate.c +++ b/boot/bootutil/src/image_validate.c @@ -50,6 +50,11 @@ BOOT_LOG_MODULE_DECLARE(mcuboot); #include "bootutil/mcuboot_uuid.h" #endif /* MCUBOOT_UUID_VID || MCUBOOT_UUID_CID */ +#if defined(MCUBOOT_DECOMPRESS_IMAGES) +#include +#include +#endif + #ifdef MCUBOOT_ENC_IMAGES #include "bootutil/enc_key.h" #endif @@ -205,7 +210,7 @@ bootutil_img_validate(struct boot_loader_state *state, ) { #if (defined(EXPECTED_KEY_TLV) && defined(MCUBOOT_HW_KEY)) || defined(MCUBOOT_HW_ROLLBACK_PROT) \ - || defined(MCUBOOT_UUID_VID) || defined(MCUBOOT_UUID_CID) + || defined(MCUBOOT_UUID_VID) || defined(MCUBOOT_UUID_CID) || defined(MCUBOOT_DECOMPRESS_IMAGES) int image_index = (state == NULL ? 0 : BOOT_CURR_IMG(state)); #endif uint32_t off; @@ -261,6 +266,67 @@ bootutil_img_validate(struct boot_loader_state *state, #endif BOOT_LOG_DBG("bootutil_img_validate: flash area %p", fap); +#ifdef MCUBOOT_DECOMPRESS_IMAGES + /* If the image is compressed, the integrity of the image must also be validated */ + if (MUST_DECOMPRESS(fap, image_index, hdr)) { + bool found_decompressed_size = false; + bool found_decompressed_sha = false; + bool found_decompressed_signature = false; + + rc = bootutil_tlv_iter_begin(&it, hdr, fap, IMAGE_TLV_ANY, true); + if (rc) { + goto out; + } + + if (it.tlv_end > bootutil_max_image_size(state, fap)) { + rc = -1; + goto out; + } + + while (true) { + uint16_t expected_size = 0; + bool *found_flag = NULL; + + rc = bootutil_tlv_iter_next(&it, &off, &len, &type); + if (rc < 0) { + goto out; + } else if (rc > 0) { + break; + } + + switch (type) { + case IMAGE_TLV_DECOMP_SIZE: + expected_size = sizeof(size_t); + found_flag = &found_decompressed_size; + break; + case IMAGE_TLV_DECOMP_SHA: + expected_size = IMAGE_HASH_SIZE; + found_flag = &found_decompressed_sha; + break; + case IMAGE_TLV_DECOMP_SIGNATURE: + found_flag = &found_decompressed_signature; + break; + default: + continue; + }; + + if (type == IMAGE_TLV_DECOMP_SIGNATURE && !EXPECTED_SIG_LEN(len)) { + rc = -1; + goto out; + } else if (type != IMAGE_TLV_DECOMP_SIGNATURE && len != expected_size) { + rc = -1; + goto out; + } + + *found_flag = true; + } + + rc = (!found_decompressed_size || !found_decompressed_sha || !found_decompressed_signature); + if (rc) { + goto out; + } + } +#endif #if defined(EXPECTED_HASH_TLV) && !defined(MCUBOOT_SIGN_PURE) rc = bootutil_img_hash(state, hdr, fap, tmp_buf, tmp_buf_sz, hash, seed, seed_len); @@ -595,6 +661,161 @@ bootutil_img_validate(struct boot_loader_state *state, } #endif +#ifdef MCUBOOT_DECOMPRESS_IMAGES + /* Only after all previous verifications have passed, perform a dry-run of the decompression + * and ensure the image is valid + */ + if (!rc && MUST_DECOMPRESS(fap, image_index, hdr)) { + image_hash_valid = 0; + FIH_SET(valid_signature, FIH_FAILURE); + + rc = bootutil_img_hash_decompress(state, hdr, fap, tmp_buf, tmp_buf_sz, + hash, seed, seed_len); + if (rc) { + goto out; + } + + rc = bootutil_tlv_iter_begin(&it, hdr, fap, IMAGE_TLV_DECOMP_SHA, true); + if (rc) { + goto out; + } + + if (it.tlv_end > bootutil_max_image_size(state, fap)) { + rc = -1; + goto out; + } + + while (true) { + rc = bootutil_tlv_iter_next(&it, &off, &len, &type); + if (rc < 0) { + goto out; + } else if (rc > 0) { + break; + } + + if (type == IMAGE_TLV_DECOMP_SHA) { + /* Verify the image hash. This must always be present. */ + if (len != sizeof(hash)) { + rc = -1; + goto out; + } + rc = LOAD_IMAGE_DATA(hdr, fap, off, buf, sizeof(hash)); + if (rc) { + goto out; + } + + FIH_CALL(boot_fih_memequal, fih_rc, hash, buf, sizeof(hash)); + if (FIH_NOT_EQ(fih_rc, FIH_SUCCESS)) { + FIH_SET(fih_rc, FIH_FAILURE); + goto out; + } + + image_hash_valid = 1; + } + } + + rc = !image_hash_valid; + if (rc) { + goto out; + } + +#ifdef EXPECTED_SIG_TLV +#ifdef EXPECTED_KEY_TLV + rc = bootutil_tlv_iter_begin(&it, hdr, fap, EXPECTED_KEY_TLV, false); + if (rc) { + goto out; + } + + if (it.tlv_end > bootutil_max_image_size(state, fap)) { + rc = -1; + goto out; + } + + while (true) { + rc = bootutil_tlv_iter_next(&it, &off, &len, &type); + if (rc < 0) { + goto out; + } else if (rc > 0) { + break; + } + + if (type == EXPECTED_KEY_TLV) { + /* + * Determine which key we should be checking. + */ + if (len > KEY_BUF_SIZE) { + rc = -1; + goto out; + } +#ifndef MCUBOOT_HW_KEY + rc = LOAD_IMAGE_DATA(hdr, fap, off, buf, len); + if (rc) { + goto out; + } + key_id = bootutil_find_key(buf, len); +#else + rc = LOAD_IMAGE_DATA(hdr, fap, off, key_buf, len); + if (rc) { + goto out; + } + key_id = bootutil_find_key(image_index, key_buf, len); +#endif /* !MCUBOOT_HW_KEY */ + /* + * The key may not be found, which is acceptable. There + * can be multiple signatures, each preceded by a key. + */ + } + } +#endif /* EXPECTED_KEY_TLV */ + + rc = bootutil_tlv_iter_begin(&it, hdr, fap, IMAGE_TLV_DECOMP_SIGNATURE, true); + if (rc) { + goto out; + } + + if (it.tlv_end > bootutil_max_image_size(state, fap)) { + rc = -1; + goto out; + } + + while (true) { + rc = bootutil_tlv_iter_next(&it, &off, &len, &type); + if (rc < 0) { + goto out; + } else if (rc > 0) { + rc = 0; + break; + } + + if (type == IMAGE_TLV_DECOMP_SIGNATURE) { + /* Ignore this signature if it is out of bounds. */ + if (key_id < 0 || key_id >= bootutil_key_cnt) { + key_id = -1; + continue; + } + + if (!EXPECTED_SIG_LEN(len) || len > sizeof(buf)) { + rc = -1; + goto out; + } + rc = LOAD_IMAGE_DATA(hdr, fap, off, buf, len); + if (rc) { + goto out; + } + + FIH_CALL(bootutil_verify_sig, valid_signature, hash, sizeof(hash), + buf, len, key_id); + key_id = -1; + } + } +#endif /* EXPECTED_SIG_TLV */ + } +#endif + +#ifdef EXPECTED_SIG_TLV + FIH_SET(fih_rc, valid_signature); +#endif + out: if (rc) { FIH_SET(fih_rc, FIH_FAILURE); diff --git a/boot/bootutil/src/loader.c b/boot/bootutil/src/loader.c index aaea24942..9f2e6c868 100644 --- a/boot/bootutil/src/loader.c +++ b/boot/bootutil/src/loader.c @@ -50,6 +50,11 @@ #include "bootutil/boot_hooks.h" #include "bootutil/mcuboot_status.h" +#if defined(MCUBOOT_DECOMPRESS_IMAGES) +#include +#include +#endif + #ifdef __ZEPHYR__ #include #if defined(CONFIG_NCS_MCUBOOT_IMG_VALIDATE_ATTEMPT_WAIT_MS) @@ -886,10 +891,10 @@ boot_is_header_valid(const struct image_header *hdr, const struct flash_area *fa return false; } #else - if ((hdr->ih_flags & IMAGE_F_COMPRESSED_LZMA1) && - (hdr->ih_flags & IMAGE_F_COMPRESSED_LZMA2)) - { - return false; + if (MUST_DECOMPRESS(fap, BOOT_CURR_IMG(state), hdr)) { + if (!boot_is_compressed_header_valid(hdr, fap, state)) { + return false; + } } #endif @@ -1137,6 +1142,7 @@ boot_validate_slot(struct boot_loader_state *state, int slot, * attempts to validate and boot it. */ } + #if !defined(__BOOTSIM__) BOOT_LOG_ERR("Image in the %s slot is not valid!", (slot == BOOT_SLOT_PRIMARY) ? "primary" : "secondary"); @@ -1793,6 +1799,9 @@ boot_copy_region(struct boot_loader_state *state, #else (void)state; #endif +#if defined(MCUBOOT_DECOMPRESS_IMAGES) && !defined(MCUBOOT_ENC_IMAGES) + struct image_header *hdr; +#endif TARGET_STATIC uint8_t buf[BUF_SZ] __attribute__((aligned(4))); @@ -1818,6 +1827,16 @@ boot_copy_region(struct boot_loader_state *state, } #endif +#ifdef MCUBOOT_DECOMPRESS_IMAGES + hdr = boot_img_hdr(state, BOOT_SECONDARY_SLOT); + + if (MUST_DECOMPRESS(fap_src, BOOT_CURR_IMG(state), hdr)) { + /* Use alternative function for compressed images */ + return boot_copy_region_decompress(state, fap_src, fap_dst, off_src, off_dst, sz, buf, + BUF_SZ); + } +#endif + bytes_copied = 0; while (bytes_copied < sz) { if (sz - bytes_copied > sizeof buf) { diff --git a/boot/zephyr/CMakeLists.txt b/boot/zephyr/CMakeLists.txt index c1820df76..0ab3ebad4 100644 --- a/boot/zephyr/CMakeLists.txt +++ b/boot/zephyr/CMakeLists.txt @@ -331,6 +331,12 @@ if(CONFIG_BOOT_ENCRYPT_EC256 AND NOT CONFIG_BOOT_ECDSA_PSA) ) endif() +if(CONFIG_BOOT_DECOMPRESSION) + zephyr_library_sources( + decompression.c + ) +endif() + if(CONFIG_MCUBOOT_SERIAL) zephyr_sources(${BOOT_DIR}/zephyr/serial_adapter.c) zephyr_sources(${BOOT_DIR}/boot_serial/src/boot_serial.c) diff --git a/boot/zephyr/Kconfig b/boot/zephyr/Kconfig index 7c2ed030a..5cfc9b6c3 100644 --- a/boot/zephyr/Kconfig +++ b/boot/zephyr/Kconfig @@ -1202,6 +1202,9 @@ config MCUBOOT_USE_TLV_ALLOW_LIST config BOOT_DECOMPRESSION_SUPPORT bool + depends on NRF_COMPRESS && NRF_COMPRESS_DECOMPRESSION && (NRF_COMPRESS_LZMA_VERSION_LZMA1 || NRF_COMPRESS_LZMA_VERSION_LZMA2) + depends on !SINGLE_APPLICATION_SLOT && BOOT_UPGRADE_ONLY + default y help Hidden symbol which should be selected if a system provided decompression support. @@ -1209,6 +1212,8 @@ if BOOT_DECOMPRESSION_SUPPORT menuconfig BOOT_DECOMPRESSION bool "Decompression" + select NRF_COMPRESS_CLEANUP + select PM_USE_CONFIG_SRAM_SIZE if SOC_NRF54L15_CPUAPP help If enabled, will include support for compressed images being loaded to the secondary slot which then get decompressed into the primary slot. This mode allows the secondary slot to @@ -1217,9 +1222,9 @@ menuconfig BOOT_DECOMPRESSION if BOOT_DECOMPRESSION config BOOT_DECOMPRESSION_BUFFER_SIZE - int "Write buffer size" + int range 16 16384 - default 4096 + default NRF_COMPRESS_CHUNK_SIZE help The size of a secondary buffer used for writing decompressed data to the storage device. diff --git a/boot/zephyr/decompression.c b/boot/zephyr/decompression.c new file mode 100644 index 000000000..87e3d3763 --- /dev/null +++ b/boot/zephyr/decompression.c @@ -0,0 +1,1505 @@ +/* + * Copyright (c) 2024 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: LicenseRef-Nordic-5-Clause + */ + +#include +#include "compression/decompression.h" +#include "bootutil/crypto/sha.h" +#include "bootutil/bootutil_log.h" + +#if !defined(__BOOTSIM__) +#define TARGET_STATIC static +#else +#define TARGET_STATIC +#endif + +#if defined(MCUBOOT_SIGN_RSA) +#if MCUBOOT_SIGN_RSA_LEN == 2048 +#define EXPECTED_SIG_TLV IMAGE_TLV_RSA2048_PSS +#elif MCUBOOT_SIGN_RSA_LEN == 3072 +#define EXPECTED_SIG_TLV IMAGE_TLV_RSA3072_PSS +#endif +#elif defined(MCUBOOT_SIGN_EC256) || \ + defined(MCUBOOT_SIGN_EC384) || \ + defined(MCUBOOT_SIGN_EC) +#define EXPECTED_SIG_TLV IMAGE_TLV_ECDSA_SIG +#elif defined(MCUBOOT_SIGN_ED25519) +#define EXPECTED_SIG_TLV IMAGE_TLV_ED25519 +#endif + +#define DECOMP_BUF_SIZE CONFIG_BOOT_DECOMPRESSION_BUFFER_SIZE +#if defined(CONFIG_NRF_COMPRESS_ARM_THUMB) +/* Extra buffer space for being able to writeback ARM thumb decompression output, + * which may be of +2 bytes more size than its input. + */ +#define DECOMP_BUF_EXTRA_SIZE 2 +#else +#define DECOMP_BUF_EXTRA_SIZE 0 +#endif +#define DECOMP_BUF_ALLOC_SIZE (DECOMP_BUF_SIZE + DECOMP_BUF_EXTRA_SIZE) + +#define DECRYPTION_BLOCK_SIZE_AES128 16 +#define DECRYPTION_BLOCK_SIZE_AES256 32 + +/* Number of times that consumed data by decompression system can be 0 in a row before aborting */ +#define OFFSET_ZERO_CHECK_TIMES 3 + +BOOT_LOG_MODULE_DECLARE(mcuboot); + +static int boot_sha_protected_tlvs(const struct image_header *hdr, + const struct flash_area *fap_src, uint32_t protected_size, + uint8_t *buf, size_t buf_size, bootutil_sha_context *sha_ctx); + +bool boot_is_compressed_header_valid(const struct image_header *hdr, const struct flash_area *fap, + struct boot_loader_state *state) +{ + /* Image is compressed in secondary slot, need to check if fits into the primary slot */ + bool opened_flash_area = false; + int primary_fa_id; + int rc; + int size_check; + int size; + uint32_t protected_tlvs_size; + uint32_t decompressed_size; + + primary_fa_id = flash_area_id_from_multi_image_slot(BOOT_CURR_IMG(state), BOOT_PRIMARY_SLOT); + + if (primary_fa_id == fap->fa_id) { + BOOT_LOG_ERR("Primary slots cannot be compressed, image: %d", BOOT_CURR_IMG(state)); + return false; + } + + if (BOOT_IMG_AREA(state, BOOT_PRIMARY_SLOT) == NULL) { + opened_flash_area = true; + } + + rc = flash_area_open(primary_fa_id, &BOOT_IMG_AREA(state, BOOT_PRIMARY_SLOT)); + assert(rc == 0); + + size_check = flash_area_get_size(BOOT_IMG_AREA(state, BOOT_PRIMARY_SLOT)); + + if (opened_flash_area) { + (void)flash_area_close(BOOT_IMG_AREA(state, BOOT_PRIMARY_SLOT)); + } + + rc = bootutil_get_img_decomp_size(hdr, fap, &decompressed_size); + + if (rc) { + return false; + } + + if (!boot_u32_safe_add(&size, decompressed_size, hdr->ih_hdr_size)) { + return false; + } + + rc = boot_size_protected_tlvs(hdr, fap, &protected_tlvs_size); + + if (rc) { + return false; + } + + if (!boot_u32_safe_add(&size, size, protected_tlvs_size)) { + return false; + } + + if (size >= size_check) { + BOOT_LOG_ERR("Compressed image too large, decompressed image size: 0x%x, slot size: 0x%x", + size, size_check); + return false; + } + + return true; +} + +static bool is_compression_object_valid(struct nrf_compress_implementation *compression) +{ + if (compression == NULL || compression->init == NULL || compression->deinit == NULL || + compression->decompress_bytes_needed == NULL || compression->decompress == NULL) { + return false; + } + + return true; +} + +#ifdef MCUBOOT_ENC_IMAGES +int bootutil_get_img_decrypted_comp_size(const struct image_header *hdr, + const struct flash_area *fap, uint32_t *img_comp_size) +{ + if (hdr == NULL || fap == NULL || img_comp_size == NULL) { + return BOOT_EBADARGS; + } else if (hdr->ih_protect_tlv_size == 0) { + return BOOT_EBADIMAGE; + } + + if (!IS_ENCRYPTED(hdr)) { + /* Update is not encrypted so use size from header */ + *img_comp_size = hdr->ih_img_size; + } else { + struct image_tlv_iter it; + uint32_t off; + uint16_t len; + int32_t rc; + + rc = bootutil_tlv_iter_begin(&it, hdr, fap, IMAGE_TLV_COMP_DEC_SIZE, true); + + if (rc) { + return rc; + } + + rc = bootutil_tlv_iter_next(&it, &off, &len, NULL); + + if (rc != 0) { + return -1; + } + + if (len != sizeof(*img_comp_size)) { + BOOT_LOG_ERR("Invalid decompressed image size TLV: %d", len); + return BOOT_EBADIMAGE; + } + + rc = LOAD_IMAGE_DATA(hdr, fap, off, img_comp_size, len); + + if (rc) { + BOOT_LOG_ERR("Image data load failed at offset: 0x%x, size: 0x%x, area: %d, rc: %d", + off, len, fap->fa_id, rc); + return BOOT_EFLASH; + } + } + + return 0; +} +#endif + +int bootutil_img_hash_decompress(struct boot_loader_state *state, struct image_header *hdr, + const struct flash_area *fap, uint8_t *tmp_buf, + uint32_t tmp_buf_sz, uint8_t *hash_result, + uint8_t *seed, int seed_len) +{ + int rc; + uint32_t read_pos = 0; + uint32_t write_pos = 0; + uint32_t protected_tlv_size = 0; + uint32_t decompressed_image_size; + uint32_t output_size_total = 0; + struct nrf_compress_implementation *compression_lzma = NULL; + struct nrf_compress_implementation *compression_arm_thumb = NULL; + TARGET_STATIC struct image_header modified_hdr; + bootutil_sha_context sha_ctx; + +#ifdef MCUBOOT_ENC_IMAGES + struct enc_key_data *enc_state; + int image_index; + uint32_t comp_size = 0; + uint8_t decryption_block_size = 0; + + rc = bootutil_get_img_decrypted_comp_size(hdr, fap, &comp_size); + + if (rc) { + BOOT_LOG_ERR("Invalid/missing image decrypted compressed size value"); + rc = BOOT_EBADIMAGE; + goto finish_end; + } + + if (state == NULL) { + enc_state = NULL; + image_index = 0; + } else { + enc_state = BOOT_CURR_ENC(state); + image_index = BOOT_CURR_IMG(state); + } + + /* Encrypted images only exist in the secondary slot */ + if (MUST_DECRYPT(fap, image_index, hdr) && + !boot_enc_valid(enc_state, 1)) { + return -1; + } + + if (MUST_DECRYPT(fap, image_index, hdr)) { + if (hdr->ih_flags & IMAGE_F_ENCRYPTED_AES128) { + decryption_block_size = DECRYPTION_BLOCK_SIZE_AES128; + } else if (hdr->ih_flags & IMAGE_F_ENCRYPTED_AES256) { + decryption_block_size = DECRYPTION_BLOCK_SIZE_AES256; + } else { + LOG_ERR("Unknown decryption block size"); + rc = BOOT_EBADIMAGE; + goto finish_end; + } + } +#endif + + bootutil_sha_init(&sha_ctx); + + /* Setup decompression system */ +#if CONFIG_NRF_COMPRESS_LZMA_VERSION_LZMA1 + if (!(hdr->ih_flags & IMAGE_F_COMPRESSED_LZMA1)) { +#elif CONFIG_NRF_COMPRESS_LZMA_VERSION_LZMA2 + if (!(hdr->ih_flags & IMAGE_F_COMPRESSED_LZMA2)) { +#endif + /* Compressed image does not use the correct compression type which is supported by this + * build + */ + BOOT_LOG_ERR("Invalid image compression flags: no supported compression found"); + rc = BOOT_EBADIMAGE; + goto finish_without_clean; + } + + compression_lzma = nrf_compress_implementation_find(NRF_COMPRESS_TYPE_LZMA); + compression_arm_thumb = nrf_compress_implementation_find(NRF_COMPRESS_TYPE_ARM_THUMB); + + if (!is_compression_object_valid(compression_lzma) || + !is_compression_object_valid(compression_arm_thumb)) { + /* Compression library missing or missing required function pointer */ + BOOT_LOG_ERR("Decompression library fatal error"); + rc = BOOT_EBADSTATUS; + goto finish_without_clean; + } + + rc = compression_lzma->init(NULL); + rc = compression_arm_thumb->init(NULL); + + if (rc) { + BOOT_LOG_ERR("Decompression library fatal error"); + rc = BOOT_EBADSTATUS; + goto finish_without_clean; + } + + /* We need a modified header which has the updated sizes, start with the original header */ + memcpy(&modified_hdr, hdr, sizeof(modified_hdr)); + + /* Extract the decompressed image size from the protected TLV, set it and remove the + * compressed image flags + */ + rc = bootutil_get_img_decomp_size(hdr, fap, &decompressed_image_size); + + if (rc) { + BOOT_LOG_ERR("Unable to determine decompressed size of compressed image"); + rc = BOOT_EBADIMAGE; + goto finish; + } + + modified_hdr.ih_flags &= ~COMPRESSIONFLAGS; + modified_hdr.ih_img_size = decompressed_image_size; + + /* Calculate the protected TLV size, these will not include the decompressed + * sha/size/signature entries + */ + rc = boot_size_protected_tlvs(hdr, fap, &protected_tlv_size); + + if (rc) { + BOOT_LOG_ERR("Unable to determine protected TLV size of compressed image"); + rc = BOOT_EBADIMAGE; + goto finish; + } + + modified_hdr.ih_protect_tlv_size = protected_tlv_size; + bootutil_sha_update(&sha_ctx, &modified_hdr, sizeof(modified_hdr)); + read_pos = sizeof(modified_hdr); + + while (read_pos < modified_hdr.ih_hdr_size) { + uint32_t copy_size = tmp_buf_sz; + + if ((read_pos + copy_size) > modified_hdr.ih_hdr_size) { + copy_size = modified_hdr.ih_hdr_size - read_pos; + } + + rc = flash_area_read(fap, read_pos, tmp_buf, copy_size); + + if (rc != 0) { + BOOT_LOG_ERR("Flash read failed at offset: 0x%x, size: 0x%x, area: %d, rc: %d", + (hdr->ih_hdr_size + read_pos), copy_size, fap->fa_id, rc); + rc = BOOT_EFLASH; + goto finish; + } + + bootutil_sha_update(&sha_ctx, tmp_buf, copy_size); + read_pos += copy_size; + } + + /* Read in compressed data, decompress and add to hash calculation */ + read_pos = 0; + +#ifdef MCUBOOT_ENC_IMAGES + while (read_pos < comp_size) { + uint32_t copy_size = comp_size - read_pos; +#else + while (read_pos < hdr->ih_img_size) { + uint32_t copy_size = hdr->ih_img_size - read_pos; +#endif + uint32_t tmp_off = 0; + uint8_t offset_zero_check = 0; + + if (copy_size > tmp_buf_sz) { + copy_size = tmp_buf_sz; + } + + rc = flash_area_read(fap, (hdr->ih_hdr_size + read_pos), tmp_buf, copy_size); + + if (rc != 0) { + BOOT_LOG_ERR("Flash read failed at offset: 0x%x, size: 0x%x, area: %d, rc: %d", + (hdr->ih_hdr_size + read_pos), copy_size, fap->fa_id, rc); + rc = BOOT_EFLASH; + goto finish; + } + +#ifdef MCUBOOT_ENC_IMAGES + if (MUST_DECRYPT(fap, image_index, hdr)) { + uint8_t dummy_bytes = 0; + + if ((copy_size % decryption_block_size)) { + dummy_bytes = decryption_block_size - (copy_size % decryption_block_size); + memset(&tmp_buf[copy_size], 0x00, dummy_bytes); + } + + boot_enc_decrypt(enc_state, 1, read_pos, (copy_size + dummy_bytes), (read_pos & 0xf), + tmp_buf); + } +#endif + + /* Decompress data in chunks, writing it back with a larger write offset of the primary + * slot than read size of the secondary slot + */ + while (tmp_off < copy_size) { + uint32_t offset = 0; + uint8_t *output = NULL; + uint32_t output_size = 0; + uint32_t chunk_size; + bool last_packet = false; + + chunk_size = compression_lzma->decompress_bytes_needed(NULL); + + if (chunk_size > (copy_size - tmp_off)) { + chunk_size = (copy_size - tmp_off); + } + +#ifdef MCUBOOT_ENC_IMAGES + if ((read_pos + tmp_off + chunk_size) >= comp_size) { +#else + if ((read_pos + tmp_off + chunk_size) >= hdr->ih_img_size) { +#endif + last_packet = true; + } + + rc = compression_lzma->decompress(NULL, &tmp_buf[tmp_off], chunk_size, last_packet, + &offset, &output, &output_size); + + if (rc) { + BOOT_LOG_ERR("Decompression error: %d", rc); + rc = BOOT_EBADSTATUS; + goto finish; + } + + write_pos += output_size; + + if (write_pos > decompressed_image_size) { + BOOT_LOG_ERR("Decompressed image larger than claimed TLV size, at least: %d", + write_pos); + rc = BOOT_EBADIMAGE; + goto finish; + } + + /* Additional dry-run validity checks */ + if (last_packet == true && write_pos == 0) { + /* Last packet and we still have no output, this is a faulty update */ + BOOT_LOG_ERR("All compressed data consumed without any output, image not valid"); + rc = BOOT_EBADIMAGE; + goto finish; + } + + if (offset == 0) { + /* If the decompression system continually consumes 0 bytes, then there is a + * problem with this update image, abort and mark image as bad + */ + if (offset_zero_check >= OFFSET_ZERO_CHECK_TIMES) { + BOOT_LOG_ERR("Decompression system returning no output data, image not valid"); + rc = BOOT_EBADIMAGE; + goto finish; + } + + ++offset_zero_check; + + break; + } else { + offset_zero_check = 0; + } + + /* Copy data to secondary buffer for calculating hash */ + if (output_size > 0) { + if (hdr->ih_flags & IMAGE_F_COMPRESSED_ARM_THUMB_FLT) { + /* Run this through the ARM thumb filter */ + uint32_t offset_arm_thumb = 0; + uint8_t *output_arm_thumb = NULL; + uint32_t processed_size = 0; + uint32_t output_size_arm_thumb = 0; + + while (processed_size < output_size) { + uint32_t current_size = output_size - processed_size; + bool arm_thumb_last_packet = false; + + if (current_size > CONFIG_NRF_COMPRESS_CHUNK_SIZE) { + current_size = CONFIG_NRF_COMPRESS_CHUNK_SIZE; + } + + if (last_packet && (processed_size + current_size) == + output_size) { + arm_thumb_last_packet = true; + } + + rc = compression_arm_thumb->decompress(NULL, &output[processed_size], + current_size, arm_thumb_last_packet, + &offset_arm_thumb, + &output_arm_thumb, + &output_size_arm_thumb); + + if (rc) { + BOOT_LOG_ERR("Decompression error: %d", rc); + rc = BOOT_EBADSTATUS; + goto finish; + } + + bootutil_sha_update(&sha_ctx, output_arm_thumb, output_size_arm_thumb); + output_size_total += output_size_arm_thumb; + processed_size += current_size; + } + } else { + bootutil_sha_update(&sha_ctx, output, output_size); + output_size_total += output_size; + } + } + + tmp_off += offset; + } + + read_pos += copy_size; + } + + if (modified_hdr.ih_img_size != output_size_total) { + BOOT_LOG_ERR("Decompression expected output_size mismatch: %d vs %d", + modified_hdr.ih_img_size, output_size_total); + rc = BOOT_EBADSTATUS; + goto finish; + } + + /* If there are any protected TLVs present, add them after the main decompressed image */ + if (modified_hdr.ih_protect_tlv_size > 0) { + rc = boot_sha_protected_tlvs(hdr, fap, modified_hdr.ih_protect_tlv_size, tmp_buf, + tmp_buf_sz, &sha_ctx); + } + + bootutil_sha_finish(&sha_ctx, hash_result); + +finish: + /* Clean up decompression system */ + (void)compression_lzma->deinit(NULL); + (void)compression_arm_thumb->deinit(NULL); + +finish_without_clean: + bootutil_sha_drop(&sha_ctx); + +#ifdef MCUBOOT_ENC_IMAGES +finish_end: +#endif + return rc; +} + +static int boot_copy_protected_tlvs(const struct image_header *hdr, + const struct flash_area *fap_src, + const struct flash_area *fap_dst, uint32_t off_dst, + uint32_t protected_size, uint8_t *buf, size_t buf_size, + uint16_t *buf_pos, uint32_t *written) +{ + int rc; + uint32_t off; + uint32_t write_pos = 0; + uint16_t len; + uint16_t type; + struct image_tlv_iter it; + struct image_tlv tlv_header; + struct image_tlv_info tlv_info_header = { + .it_magic = IMAGE_TLV_PROT_INFO_MAGIC, + .it_tlv_tot = protected_size, + }; + uint16_t info_size_left = sizeof(tlv_info_header); + + while (info_size_left > 0) { + uint16_t copy_size = buf_size - *buf_pos; + + if (info_size_left > 0 && copy_size > 0) { + uint16_t single_copy_size = copy_size; + uint8_t *tlv_info_header_address = (uint8_t *)&tlv_info_header; + + if (single_copy_size > info_size_left) { + single_copy_size = info_size_left; + } + + memcpy(&buf[*buf_pos], &tlv_info_header_address[sizeof(tlv_info_header) - + info_size_left], single_copy_size); + *buf_pos += single_copy_size; + info_size_left -= single_copy_size; + } + + if (*buf_pos == buf_size) { + rc = flash_area_write(fap_dst, (off_dst + write_pos), buf, *buf_pos); + + if (rc != 0) { + BOOT_LOG_ERR("Flash write failed at offset: 0x%x, size: 0x%x, area: %d, rc: %d", + (off_dst + write_pos), *buf_pos, fap_dst->fa_id, rc); + rc = BOOT_EFLASH; + goto out; + } + + write_pos += *buf_pos; + *buf_pos = 0; + } + } + + rc = bootutil_tlv_iter_begin(&it, hdr, fap_src, IMAGE_TLV_ANY, true); + + if (rc) { + goto out; + } + + while (true) { + rc = bootutil_tlv_iter_next(&it, &off, &len, &type); + + if (rc < 0) { + goto out; + } else if (rc > 0) { + rc = 0; + break; + } + + if (type == IMAGE_TLV_DECOMP_SIZE || type == IMAGE_TLV_DECOMP_SHA || + type == IMAGE_TLV_DECOMP_SIGNATURE || type == IMAGE_TLV_COMP_DEC_SIZE) { + /* Skip these TLVs as they are not needed */ + continue; + } else { + uint16_t header_size_left = sizeof(tlv_header); + uint16_t data_size_left = len; + + tlv_header.it_type = type; + tlv_header.it_len = len; + + while (header_size_left > 0 || data_size_left > 0) { + uint16_t copy_size = buf_size - *buf_pos; + uint8_t *tlv_header_address = (uint8_t *)&tlv_header; + + if (header_size_left > 0 && copy_size > 0) { + uint16_t single_copy_size = copy_size; + + if (single_copy_size > header_size_left) { + single_copy_size = header_size_left; + } + + memcpy(&buf[*buf_pos], &tlv_header_address[sizeof(tlv_header) - + header_size_left], + single_copy_size); + *buf_pos += single_copy_size; + copy_size -= single_copy_size; + header_size_left -= single_copy_size; + } + + if (data_size_left > 0 && copy_size > 0) { + uint16_t single_copy_size = copy_size; + + if (single_copy_size > data_size_left) { + single_copy_size = data_size_left; + } + + rc = LOAD_IMAGE_DATA(hdr, fap_src, (off + (len - data_size_left)), + &buf[*buf_pos], single_copy_size); + + if (rc) { + BOOT_LOG_ERR( + "Image data load failed at offset: 0x%x, size: 0x%x, area: %d, rc: %d", + (off + (len - data_size_left)), single_copy_size, fap_src->fa_id, rc); + goto out; + } + + *buf_pos += single_copy_size; + data_size_left -= single_copy_size; + } + + if (*buf_pos == buf_size) { + rc = flash_area_write(fap_dst, (off_dst + write_pos), buf, *buf_pos); + + if (rc != 0) { + BOOT_LOG_ERR( + "Flash write failed at offset: 0x%x, size: 0x%x, area: %d, rc: %d", + (off_dst + write_pos), *buf_pos, fap_dst->fa_id, rc); + rc = BOOT_EFLASH; + goto out; + } + + write_pos += *buf_pos; + *buf_pos = 0; + } + } + } + } + + *written = write_pos; + +out: + return rc; +} + +static int boot_sha_protected_tlvs(const struct image_header *hdr, + const struct flash_area *fap_src, uint32_t protected_size, + uint8_t *buf, size_t buf_size, bootutil_sha_context *sha_ctx) +{ + int rc; + uint32_t off; + uint16_t len; + uint16_t type; + struct image_tlv_iter it; + struct image_tlv tlv_header; + struct image_tlv_info tlv_info_header = { + .it_magic = IMAGE_TLV_PROT_INFO_MAGIC, + .it_tlv_tot = protected_size, + }; + + bootutil_sha_update(sha_ctx, &tlv_info_header, sizeof(tlv_info_header)); + + rc = bootutil_tlv_iter_begin(&it, hdr, fap_src, IMAGE_TLV_ANY, true); + if (rc) { + goto out; + } + + while (true) { + uint32_t read_off = 0; + + rc = bootutil_tlv_iter_next(&it, &off, &len, &type); + + if (rc < 0) { + goto out; + } else if (rc > 0) { + rc = 0; + break; + } + + if (type == IMAGE_TLV_DECOMP_SIZE || type == IMAGE_TLV_DECOMP_SHA || + type == IMAGE_TLV_DECOMP_SIGNATURE || type == IMAGE_TLV_COMP_DEC_SIZE) { + /* Skip these TLVs as they are not needed */ + continue; + } + + tlv_header.it_type = type; + tlv_header.it_len = len; + + bootutil_sha_update(sha_ctx, &tlv_header, sizeof(tlv_header)); + + while (read_off < len) { + uint32_t copy_size = buf_size; + + if (copy_size > (len - read_off)) { + copy_size = len - read_off; + } + + rc = LOAD_IMAGE_DATA(hdr, fap_src, (off + read_off), buf, copy_size); + + if (rc) { + BOOT_LOG_ERR( + "Image data load failed at offset: 0x%x, size: 0x%x, area: %d, rc: %d", + (off + read_off), copy_size, fap_src->fa_id, rc); + goto out; + } + + bootutil_sha_update(sha_ctx, buf, copy_size); + read_off += copy_size; + } + } + +out: + return rc; +} + +int boot_size_protected_tlvs(const struct image_header *hdr, const struct flash_area *fap, + uint32_t *sz) +{ + int rc = 0; + uint32_t tlv_size; + uint32_t off; + uint16_t len; + uint16_t type; + struct image_tlv_iter it; + + *sz = 0; + tlv_size = hdr->ih_protect_tlv_size; + + rc = bootutil_tlv_iter_begin(&it, hdr, fap, IMAGE_TLV_ANY, true); + + if (rc) { + goto out; + } + + while (true) { + rc = bootutil_tlv_iter_next(&it, &off, &len, &type); + + if (rc < 0) { + goto out; + } else if (rc > 0) { + rc = 0; + break; + } + + if (type == IMAGE_TLV_DECOMP_SIZE || type == IMAGE_TLV_DECOMP_SHA || + type == IMAGE_TLV_DECOMP_SIGNATURE || type == IMAGE_TLV_COMP_DEC_SIZE) { + /* Exclude these TLVs as they will be copied to the unprotected area */ + tlv_size -= len + sizeof(struct image_tlv); + } + } + + if (!rc) { + if (tlv_size == sizeof(struct image_tlv_info)) { + /* If there are no entries then omit protected TLV section entirely */ + tlv_size = 0; + } + + *sz = tlv_size; + } + +out: + return rc; +} + +int boot_size_unprotected_tlvs(const struct image_header *hdr, const struct flash_area *fap, + uint32_t *sz) +{ + int rc = 0; + uint32_t tlv_size; + uint32_t off; + uint16_t len; + uint16_t type; + struct image_tlv_iter it; + + *sz = 0; + tlv_size = sizeof(struct image_tlv_info); + + rc = bootutil_tlv_iter_begin(&it, hdr, fap, IMAGE_TLV_ANY, false); + + if (rc) { + goto out; + } + + while (true) { + rc = bootutil_tlv_iter_next(&it, &off, &len, &type); + + if (rc < 0) { + goto out; + } else if (rc > 0) { + rc = 0; + break; + } else if (bootutil_tlv_iter_is_prot(&it, off) && type != IMAGE_TLV_DECOMP_SHA && + type != IMAGE_TLV_DECOMP_SIGNATURE) { + /* Include size of protected hash and signature as these will be replacing the + * original ones + */ + continue; + } else if (type == EXPECTED_HASH_TLV || type == EXPECTED_SIG_TLV || type == IMAGE_TLV_COMP_DEC_SIZE) { + /* Exclude the original unprotected TLVs for signature and hash, the length of the + * signature of the compressed data might not be the same size as the signaute of the + * decompressed data, as is the case when using ECDSA-P256 + */ + continue; + } + + tlv_size += len + sizeof(struct image_tlv); + } + + if (!rc) { + if (tlv_size == sizeof(struct image_tlv_info)) { + /* If there are no entries in the unprotected TLV section then there is something wrong + * with this image + */ + BOOT_LOG_ERR("No unprotected TLVs in post-decompressed image output, image is invalid"); + rc = BOOT_EBADIMAGE; + goto out; + } + + *sz = tlv_size; + } + +out: + return rc; +} + +static int boot_copy_unprotected_tlvs(const struct image_header *hdr, + const struct flash_area *fap_src, + const struct flash_area *fap_dst, uint32_t off_dst, + uint32_t unprotected_size, uint8_t *buf, size_t buf_size, + uint16_t *buf_pos, uint32_t *written) +{ + int rc; + uint32_t write_pos = 0; + uint32_t off; + uint16_t len; + uint16_t type; + struct image_tlv_iter it; + struct image_tlv_iter it_protected; + struct image_tlv tlv_header; + struct image_tlv_info tlv_info_header = { + .it_magic = IMAGE_TLV_INFO_MAGIC, + .it_tlv_tot = unprotected_size, + }; + uint16_t info_size_left = sizeof(tlv_info_header); + + while (info_size_left > 0) { + uint16_t copy_size = buf_size - *buf_pos; + + if (info_size_left > 0 && copy_size > 0) { + uint16_t single_copy_size = copy_size; + uint8_t *tlv_info_header_address = (uint8_t *)&tlv_info_header; + + if (single_copy_size > info_size_left) { + single_copy_size = info_size_left; + } + + memcpy(&buf[*buf_pos], &tlv_info_header_address[sizeof(tlv_info_header) - + info_size_left], single_copy_size); + *buf_pos += single_copy_size; + info_size_left -= single_copy_size; + } + + if (*buf_pos == buf_size) { + rc = flash_area_write(fap_dst, (off_dst + write_pos), buf, *buf_pos); + + if (rc != 0) { + BOOT_LOG_ERR("Flash write failed at offset: 0x%x, size: 0x%x, area: %d, rc: %d", + (off_dst + write_pos), *buf_pos, fap_dst->fa_id, rc); + rc = BOOT_EFLASH; + goto out; + } + + write_pos += *buf_pos; + *buf_pos = 0; + } + } + + rc = bootutil_tlv_iter_begin(&it, hdr, fap_src, IMAGE_TLV_ANY, false); + if (rc) { + goto out; + } + + while (true) { + uint16_t header_size_left = sizeof(tlv_header); + uint16_t data_size_left; + + rc = bootutil_tlv_iter_next(&it, &off, &len, &type); + if (rc < 0) { + goto out; + } else if (rc > 0) { + rc = 0; + break; + } else if (bootutil_tlv_iter_is_prot(&it, off)) { + /* Skip protected TLVs */ + continue; + } + + /* Change the values of these fields from having the data in the compressed image + * unprotected TLV (which is valid only for the compressed image data) to having the + * fields in the protected TLV section (which is valid for the decompressed image data). + * The compressed data is no longer needed + */ + if (type == EXPECTED_HASH_TLV || type == EXPECTED_SIG_TLV) { + rc = bootutil_tlv_iter_begin(&it_protected, hdr, fap_src, (type == EXPECTED_HASH_TLV ? + IMAGE_TLV_DECOMP_SHA : + IMAGE_TLV_DECOMP_SIGNATURE), + true); + + if (rc) { + goto out; + } + + while (true) { + rc = bootutil_tlv_iter_next(&it_protected, &off, &len, &type); + if (rc < 0) { + goto out; + } else if (rc > 0) { + rc = 0; + break; + } + } + + if (type == IMAGE_TLV_DECOMP_SHA) { + type = EXPECTED_HASH_TLV; + } else { + type = EXPECTED_SIG_TLV; + } + } + + data_size_left = len; + tlv_header.it_type = type; + tlv_header.it_len = len; + + while (header_size_left > 0 || data_size_left > 0) { + uint16_t copy_size = buf_size - *buf_pos; + + if (header_size_left > 0 && copy_size > 0) { + uint16_t single_copy_size = copy_size; + uint8_t *tlv_header_address = (uint8_t *)&tlv_header; + + if (single_copy_size > header_size_left) { + single_copy_size = header_size_left; + } + + memcpy(&buf[*buf_pos], &tlv_header_address[sizeof(tlv_header) - header_size_left], + single_copy_size); + *buf_pos += single_copy_size; + copy_size -= single_copy_size; + header_size_left -= single_copy_size; + } + + if (data_size_left > 0 && copy_size > 0) { + uint16_t single_copy_size = copy_size; + + if (single_copy_size > data_size_left) { + single_copy_size = data_size_left; + } + + rc = LOAD_IMAGE_DATA(hdr, fap_src, (off + len - data_size_left), + &buf[*buf_pos], single_copy_size); + + if (rc) { + BOOT_LOG_ERR( + "Image data load failed at offset: 0x%x, size: 0x%x, area: %d, rc: %d", + (off + (len - data_size_left)), single_copy_size, fap_src->fa_id, rc); + goto out; + } + + *buf_pos += single_copy_size; + data_size_left -= single_copy_size; + } + + if (*buf_pos == buf_size) { + rc = flash_area_write(fap_dst, (off_dst + write_pos), buf, *buf_pos); + + if (rc != 0) { + BOOT_LOG_ERR( + "Flash write failed at offset: 0x%x, size: 0x%x, area: %d, rc: %d", + (off_dst + write_pos), *buf_pos, fap_dst->fa_id, rc); + rc = BOOT_EFLASH; + goto out; + } + + write_pos += *buf_pos; + *buf_pos = 0; + } + } + } + + *written = write_pos; + +out: + return rc; +} + +#if defined(CONFIG_NRF_COMPRESS_ARM_THUMB) +/** + * @brief Helper function for in-place ARM Thumb filtering. + * This function places the decompressed data back into the same buffer + * at the beginning, overwriting the compressed data. WARNING: because + * ARM Thumb filtering can return +-2 more/less bytes than the input, + * the buffer provided needs to have free DECOMP_BUF_EXTRA_SIZE bytes at + * the beginning and provide valid data for filtering after these. + * + * @param[in] arm_thumb_impl Pointer to the ARM Thumb decompression implementation. + * @param[in,out] buf Pointer to the buffer containing the compressed data / filtered data. + * @param[in] buf_size Size of the buffer (including DECOMP_BUF_EXTRA_SIZE bytes at the beginning). + * @param[out] out_size Pointer to a variable where the size of the filtered data will be stored. + * @param[in] last_part Indicates if this is the last part of the data to be filtered. + * + * @return 0 on success, BOOT_EBADSTATUS on error. + */ +static int boot_arm_thumb_filter(struct nrf_compress_implementation * const arm_thumb_impl, + uint8_t *buf, size_t buf_size, size_t *out_size, bool last_part) { + + uint32_t filter_writeback_pos = 0; + uint32_t processed_size = 0; + int rc; + + while (processed_size < (buf_size - DECOMP_BUF_EXTRA_SIZE)) { + uint32_t offset_arm_thumb = 0; + uint32_t output_size_arm_thumb = 0; + uint8_t *output_arm_thumb = NULL; + uint32_t current_size = (buf_size - DECOMP_BUF_EXTRA_SIZE - processed_size); + bool arm_thumb_last_packet = false; + + if (current_size > CONFIG_NRF_COMPRESS_CHUNK_SIZE) { + current_size = CONFIG_NRF_COMPRESS_CHUNK_SIZE; + } + + if (last_part && (processed_size + current_size) == (buf_size - DECOMP_BUF_EXTRA_SIZE)) { + arm_thumb_last_packet = true; + } + + rc = arm_thumb_impl->decompress(NULL, + &buf[processed_size + + DECOMP_BUF_EXTRA_SIZE], + current_size, + arm_thumb_last_packet, + &offset_arm_thumb, + &output_arm_thumb, + &output_size_arm_thumb); + + if (rc) { + BOOT_LOG_ERR("Decompression error: %d", rc); + return BOOT_EBADSTATUS; + } + + if (output_size_arm_thumb > (buf_size - filter_writeback_pos)) { + BOOT_LOG_ERR("Filter writeback position exceeds buffer size"); + return BOOT_EBADSTATUS; + } + + memcpy(&buf[filter_writeback_pos], output_arm_thumb, + output_size_arm_thumb); + filter_writeback_pos += output_size_arm_thumb; + processed_size += offset_arm_thumb; + } + *out_size = filter_writeback_pos; + + return 0; +} +#endif /* CONFIG_NRF_COMPRESS_ARM_THUMB */ + +int boot_copy_region_decompress(struct boot_loader_state *state, const struct flash_area *fap_src, + const struct flash_area *fap_dst, uint32_t off_src, + uint32_t off_dst, uint32_t sz, uint8_t *buf, size_t buf_size) +{ + int rc; + uint32_t pos = 0; + uint16_t decomp_buf_size = 0; + uint16_t write_alignment; + uint32_t write_pos = 0; + uint32_t protected_tlv_size = 0; + uint32_t unprotected_tlv_size = 0; + uint32_t tlv_write_size = 0; + uint32_t decompressed_image_size; + struct nrf_compress_implementation *compression_lzma = NULL; + struct nrf_compress_implementation *compression_arm_thumb = NULL; + struct image_header *hdr; + TARGET_STATIC uint8_t decomp_buf[DECOMP_BUF_ALLOC_SIZE] __attribute__((aligned(4))); + TARGET_STATIC struct image_header modified_hdr; + uint16_t decomp_buf_max_size; + +#if defined(CONFIG_NRF_COMPRESS_ARM_THUMB) + uint8_t unaligned_data_length = 0; +#endif + +#ifdef MCUBOOT_ENC_IMAGES + uint32_t comp_size = 0; + uint8_t decryption_block_size = 0; +#endif + + hdr = boot_img_hdr(state, BOOT_SECONDARY_SLOT); + +#ifdef MCUBOOT_ENC_IMAGES + rc = bootutil_get_img_decrypted_comp_size(hdr, fap_src, &comp_size); + + if (rc) { + BOOT_LOG_ERR("Invalid/missing image decrypted compressed size value"); + rc = BOOT_EBADIMAGE; + goto finish; + } + + if (IS_ENCRYPTED(hdr)) { + if (hdr->ih_flags & IMAGE_F_ENCRYPTED_AES128) { + decryption_block_size = DECRYPTION_BLOCK_SIZE_AES128; + } else if (hdr->ih_flags & IMAGE_F_ENCRYPTED_AES256) { + decryption_block_size = DECRYPTION_BLOCK_SIZE_AES256; + } + } +#endif + + /* Setup decompression system */ +#if CONFIG_NRF_COMPRESS_LZMA_VERSION_LZMA1 + if (!(hdr->ih_flags & IMAGE_F_COMPRESSED_LZMA1)) { +#elif CONFIG_NRF_COMPRESS_LZMA_VERSION_LZMA2 + if (!(hdr->ih_flags & IMAGE_F_COMPRESSED_LZMA2)) { +#endif + /* Compressed image does not use the correct compression type which is supported by this + * build + */ + BOOT_LOG_ERR("Invalid image compression flags: no supported compression found"); + rc = BOOT_EBADIMAGE; + goto finish; + } + + compression_lzma = nrf_compress_implementation_find(NRF_COMPRESS_TYPE_LZMA); + compression_arm_thumb = nrf_compress_implementation_find(NRF_COMPRESS_TYPE_ARM_THUMB); + + if (!is_compression_object_valid(compression_lzma) || + !is_compression_object_valid(compression_arm_thumb)) { + /* Compression library missing or missing required function pointer */ + BOOT_LOG_ERR("Decompression library fatal error"); + rc = BOOT_EBADSTATUS; + goto finish; + } + + rc = compression_lzma->init(NULL); + rc = compression_arm_thumb->init(NULL); + + if (rc) { + BOOT_LOG_ERR("Decompression library fatal error"); + rc = BOOT_EBADSTATUS; + goto finish; + } + + write_alignment = flash_area_align(fap_dst); + + decomp_buf_max_size = DECOMP_BUF_SIZE - (DECOMP_BUF_SIZE % write_alignment); + + memcpy(&modified_hdr, hdr, sizeof(modified_hdr)); + + rc = bootutil_get_img_decomp_size(hdr, fap_src, &decompressed_image_size); + + if (rc) { + BOOT_LOG_ERR("Unable to determine decompressed size of compressed image"); + rc = BOOT_EBADIMAGE; + goto finish; + } + + modified_hdr.ih_flags &= ~COMPRESSIONFLAGS; + modified_hdr.ih_img_size = decompressed_image_size; + + /* Calculate protected TLV size for target image once items are removed */ + rc = boot_size_protected_tlvs(hdr, fap_src, &protected_tlv_size); + + if (rc) { + BOOT_LOG_ERR("Unable to determine protected TLV size of compressed image"); + rc = BOOT_EBADIMAGE; + goto finish; + } + + modified_hdr.ih_protect_tlv_size = protected_tlv_size; + + rc = boot_size_unprotected_tlvs(hdr, fap_src, &unprotected_tlv_size); + + if (rc) { + BOOT_LOG_ERR("Unable to determine unprotected TLV size of compressed image"); + rc = BOOT_EBADIMAGE; + goto finish; + } + + /* Write out the image header first, this should be a multiple of the write size */ + rc = flash_area_write(fap_dst, off_dst, &modified_hdr, sizeof(modified_hdr)); + + if (rc != 0) { + BOOT_LOG_ERR("Flash write failed at offset: 0x%x, size: 0x%x, area: %d, rc: %d", + off_dst, sizeof(modified_hdr), fap_dst->fa_id, rc); + rc = BOOT_EFLASH; + goto finish; + } + + /* Read in, decompress and write out data */ +#ifdef MCUBOOT_ENC_IMAGES + while (pos < comp_size) { + uint32_t copy_size = comp_size - pos; +#else + while (pos < hdr->ih_img_size) { + uint32_t copy_size = hdr->ih_img_size - pos; +#endif + uint32_t tmp_off = 0; + + if (copy_size > buf_size) { + copy_size = buf_size; + } + + rc = flash_area_read(fap_src, off_src + hdr->ih_hdr_size + pos, buf, copy_size); + + if (rc != 0) { + BOOT_LOG_ERR("Flash read failed at offset: 0x%x, size: 0x%x, area: %d, rc: %d", + (off_src + hdr->ih_hdr_size + pos), copy_size, fap_src->fa_id, rc); + rc = BOOT_EFLASH; + goto finish; + } + +#ifdef MCUBOOT_ENC_IMAGES + if (IS_ENCRYPTED(hdr)) { + uint8_t dummy_bytes = 0; + + if ((copy_size % decryption_block_size)) { + dummy_bytes = decryption_block_size - (copy_size % decryption_block_size); + memset(&buf[copy_size], 0x00, dummy_bytes); + } + + boot_enc_decrypt(BOOT_CURR_ENC(state), 1, pos, (copy_size + dummy_bytes), (pos & 0xf), buf); + } +#endif + + /* Decompress data in chunks, writing it back with a larger write offset of the primary + * slot than read size of the secondary slot + */ + while (tmp_off < copy_size) { + uint32_t offset = 0; + uint32_t output_size = 0; + uint32_t chunk_size; + uint32_t compression_buffer_pos = 0; + uint8_t *output = NULL; + bool last_packet = false; + + chunk_size = compression_lzma->decompress_bytes_needed(NULL); + + if (chunk_size > (copy_size - tmp_off)) { + chunk_size = (copy_size - tmp_off); + } + +#ifdef MCUBOOT_ENC_IMAGES + if ((pos + tmp_off + chunk_size) >= comp_size) { +#else + if ((pos + tmp_off + chunk_size) >= hdr->ih_img_size) { +#endif + last_packet = true; + } + + rc = compression_lzma->decompress(NULL, &buf[tmp_off], chunk_size, last_packet, + &offset, &output, &output_size); + + if (rc) { + BOOT_LOG_ERR("Decompression error: %d", rc); + rc = BOOT_EBADSTATUS; + goto finish; + } + + /* Copy data to secondary buffer for writing out */ + while (output_size > 0) { + uint32_t data_size = (decomp_buf_max_size - decomp_buf_size); + + if (data_size > output_size) { + data_size = output_size; + } + +#if defined(CONFIG_NRF_COMPRESS_ARM_THUMB) + if (hdr->ih_flags & IMAGE_F_COMPRESSED_ARM_THUMB_FLT) { + memcpy(&decomp_buf[decomp_buf_size + DECOMP_BUF_EXTRA_SIZE], + &output[compression_buffer_pos], data_size); + } else +#endif + { + memcpy(&decomp_buf[decomp_buf_size], &output[compression_buffer_pos], + data_size); + } + + compression_buffer_pos += data_size; + + decomp_buf_size += data_size; + output_size -= data_size; + + /* Write data out from secondary buffer when it is full */ + if (decomp_buf_size == decomp_buf_max_size) { +#if defined(CONFIG_NRF_COMPRESS_ARM_THUMB) + if (hdr->ih_flags & IMAGE_F_COMPRESSED_ARM_THUMB_FLT) { + + uint32_t filter_output_size; + + /* Run this through the ARM thumb filter */ + rc = boot_arm_thumb_filter(compression_arm_thumb, + &decomp_buf[unaligned_data_length], + decomp_buf_size - unaligned_data_length + DECOMP_BUF_EXTRA_SIZE, + &filter_output_size, + last_packet && output_size == 0); + + if (rc) { + goto finish; + } + + decomp_buf_size = filter_output_size + unaligned_data_length; + unaligned_data_length = decomp_buf_size % write_alignment; + + rc = flash_area_write(fap_dst, + (off_dst + hdr->ih_hdr_size + write_pos), + decomp_buf, + (decomp_buf_size - unaligned_data_length)); + + if (rc != 0) { + BOOT_LOG_ERR( + "Flash write failed at offset: 0x%x, size: 0x%x, area: %d, rc: %d", + (off_dst + hdr->ih_hdr_size + write_pos), + (decomp_buf_size - unaligned_data_length), + fap_dst->fa_id, rc); + rc = BOOT_EFLASH; + goto finish; + } + + memmove(decomp_buf, + &decomp_buf[decomp_buf_size - unaligned_data_length], + unaligned_data_length); + write_pos += decomp_buf_size - unaligned_data_length; + decomp_buf_size = unaligned_data_length; + } else +#endif + { + rc = flash_area_write(fap_dst, (off_dst + hdr->ih_hdr_size + write_pos), + decomp_buf, decomp_buf_max_size); + + if (rc != 0) { + BOOT_LOG_ERR( + "Flash write failed at offset: 0x%x, size: 0x%x, area: %d, rc: %d", + (off_dst + hdr->ih_hdr_size + write_pos), decomp_buf_max_size, + fap_dst->fa_id, rc); + rc = BOOT_EFLASH; + goto finish; + } + + write_pos += decomp_buf_max_size; + decomp_buf_size = 0; + } + } + } + + tmp_off += offset; + } + + pos += copy_size; + } + +#if defined(CONFIG_NRF_COMPRESS_ARM_THUMB) + if (hdr->ih_flags & IMAGE_F_COMPRESSED_ARM_THUMB_FLT && decomp_buf_size > 0) { + /* Extra data that has not been written out that needs ARM thumb filter applied */ + + uint32_t filter_output_size; + + rc = boot_arm_thumb_filter(compression_arm_thumb, + &decomp_buf[unaligned_data_length], + decomp_buf_size - unaligned_data_length + DECOMP_BUF_EXTRA_SIZE, + &filter_output_size, + true); + + if (rc) { + goto finish; + } + + decomp_buf_size = filter_output_size + unaligned_data_length; + + if (decomp_buf_size > decomp_buf_max_size) { + /* It can happen if ARM thumb decompression returned +2 bytes and we had near full + * decomp_buf. We still can hold these additional 2 bytes because of + * DECOMP_BUF_EXTRA_SIZE allocated. */ + + rc = flash_area_write(fap_dst, (off_dst + hdr->ih_hdr_size + write_pos), + decomp_buf, decomp_buf_max_size); + + if (rc != 0) { + BOOT_LOG_ERR("Flash write failed at offset: 0x%x, size: 0x%x, area: %d, rc: %d", + (off_dst + hdr->ih_hdr_size + write_pos), decomp_buf_max_size, + fap_dst->fa_id, rc); + rc = BOOT_EFLASH; + goto finish; + } + memmove(decomp_buf, &decomp_buf[decomp_buf_max_size], + (decomp_buf_size - decomp_buf_max_size)); + + decomp_buf_size = decomp_buf_size - decomp_buf_max_size; + write_pos += decomp_buf_max_size; + } + } +#endif + + /* Clean up decompression system */ + (void)compression_lzma->deinit(NULL); + (void)compression_arm_thumb->deinit(NULL); + + if (protected_tlv_size > 0) { + rc = boot_copy_protected_tlvs(hdr, fap_src, fap_dst, (off_dst + hdr->ih_hdr_size + + write_pos), protected_tlv_size, + decomp_buf, decomp_buf_max_size, &decomp_buf_size, + &tlv_write_size); + + if (rc) { + BOOT_LOG_ERR("Protected TLV copy failure: %d", rc); + goto finish; + } + + write_pos += tlv_write_size; + } + + tlv_write_size = 0; + rc = boot_copy_unprotected_tlvs(hdr, fap_src, fap_dst, (off_dst + hdr->ih_hdr_size + + write_pos), unprotected_tlv_size, + decomp_buf, decomp_buf_max_size, &decomp_buf_size, + &tlv_write_size); + + if (rc) { + BOOT_LOG_ERR("Protected TLV copy failure: %d", rc); + goto finish; + } + + write_pos += tlv_write_size; + + /* Check if we have unwritten data buffered up and, if so, write it out */ + if (decomp_buf_size > 0) { + uint32_t write_padding_size = write_alignment - (decomp_buf_size % write_alignment); + + /* Check if additional write padding should be applied to meet the minimum write size */ + if (write_alignment > 1 && write_padding_size) { + uint8_t flash_erased_value; + + flash_erased_value = flash_area_erased_val(fap_dst); + memset(&decomp_buf[decomp_buf_size], flash_erased_value, write_padding_size); + decomp_buf_size += write_padding_size; + } + + rc = flash_area_write(fap_dst, (off_dst + hdr->ih_hdr_size + write_pos), decomp_buf, + decomp_buf_size); + + if (rc != 0) { + BOOT_LOG_ERR("Flash write failed at offset: 0x%x, size: 0x%x, area: %d, rc: %d", + (off_dst + hdr->ih_hdr_size + write_pos), decomp_buf_size, + fap_dst->fa_id, rc); + rc = BOOT_EFLASH; + goto finish; + } + + write_pos += decomp_buf_size; + decomp_buf_size = 0; + } + +finish: + memset(decomp_buf, 0, sizeof(decomp_buf)); + + return rc; +} + +int bootutil_get_img_decomp_size(const struct image_header *hdr, const struct flash_area *fap, + uint32_t *img_decomp_size) +{ + struct image_tlv_iter it; + uint32_t off; + uint16_t len; + int32_t rc; + + if (hdr == NULL || fap == NULL || img_decomp_size == NULL) { + return BOOT_EBADARGS; + } else if (hdr->ih_protect_tlv_size == 0) { + return BOOT_EBADIMAGE; + } + + rc = bootutil_tlv_iter_begin(&it, hdr, fap, IMAGE_TLV_DECOMP_SIZE, true); + + if (rc) { + return rc; + } + + rc = bootutil_tlv_iter_next(&it, &off, &len, NULL); + + if (rc != 0) { + return -1; + } + + if (len != sizeof(*img_decomp_size)) { + BOOT_LOG_ERR("Invalid decompressed image size TLV: %d", len); + return BOOT_EBADIMAGE; + } + + rc = LOAD_IMAGE_DATA(hdr, fap, off, img_decomp_size, len); + + if (rc) { + BOOT_LOG_ERR("Image data load failed at offset: 0x%x, size: 0x%x, area: %d, rc: %d", + off, len, fap->fa_id, rc); + return BOOT_EFLASH; + } + + return 0; +} diff --git a/boot/zephyr/include/compression/decompression.h b/boot/zephyr/include/compression/decompression.h new file mode 100644 index 000000000..2104c4eb6 --- /dev/null +++ b/boot/zephyr/include/compression/decompression.h @@ -0,0 +1,103 @@ +/* + * Copyright (c) 2024 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: LicenseRef-Nordic-5-Clause + */ + +#ifndef H_DECOMPRESSION_ +#define H_DECOMPRESSION_ + +#include +#include +#include +#include "bootutil/bootutil.h" +#include "bootutil/bootutil_public.h" +#include "bootutil/image.h" +#include "../src/bootutil_priv.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * Checks if a compressed image header is valid. + * + * @param hdr Image header. + * @param fap Flash area of the slot. + * @param state Bootloader state object. + * + * @return true if valid; false if invalid. + */ +bool boot_is_compressed_header_valid(const struct image_header *hdr, const struct flash_area *fap, + struct boot_loader_state *state); + +/** + * Reads in compressed image data from a slot, decompresses it and writes it out to a destination + * slot, including corresponding image headers and TLVs. + * + * @param state Bootloader state object. + * @param fap_src Flash area of the source slot. + * @param fap_dst Flash area of the destination slot. + * @param off_src Offset of the source slot to read from (should be 0). + * @param off_dst Offset of the destination slot to write to (should be 0). + * @param sz Size of the source slot data. + * @param buf Temporary buffer for reading data from. + * @param buf_size Size of temporary buffer. + * + * @return 0 on success; nonzero on failure. + */ +int boot_copy_region_decompress(struct boot_loader_state *state, const struct flash_area *fap_src, + const struct flash_area *fap_dst, uint32_t off_src, + uint32_t off_dst, uint32_t sz, uint8_t *buf, size_t buf_size); + +/** + * Gets the total data size (excluding headers and TLVs) of a compressed image when it is + * decompressed. + * + * @param hdr Image header. + * @param fap Flash area of the slot. + * @param img_decomp_size Pointer to variable that will be updated with the decompressed image + * size. + * + * @return 0 on success; nonzero on failure. + */ +int bootutil_get_img_decomp_size(const struct image_header *hdr, const struct flash_area *fap, + uint32_t *img_decomp_size); + +/** + * Calculate MCUboot-compatible image hash of compressed image slot. + * + * @param state MCUboot state. + * @param hdr Image header. + * @param fap Flash area of the slot. + * @param tmp_buf Temporary buffer for reading data from. + * @param tmp_buf_sz Size of temporary buffer. + * @param hash_result Pointer to a variable that will be updated with the image hash. + * @param seed Not currently used, set to NULL. + * @param seed_len Not currently used, set to 0. + * + * @return 0 on success; nonzero on failure. + */ +int bootutil_img_hash_decompress(struct boot_loader_state *state, struct image_header *hdr, + const struct flash_area *fap, uint8_t *tmp_buf, + uint32_t tmp_buf_sz, uint8_t *hash_result, + uint8_t *seed, int seed_len); + +/** + * Calculates the size that the compressed image protected TLV section will occupy once the image + * has been decompressed. + * + * @param hdr Image header. + * @param fap Flash area of the slot. + * @param sz Pointer to variable that will be updated with the protected TLV size. + * + * @return 0 on success; nonzero on failure. + */ +int boot_size_protected_tlvs(const struct image_header *hdr, const struct flash_area *fap_src, + uint32_t *sz); + +#ifdef __cplusplus +} +#endif + +#endif /* H_DECOMPRESSION_ */ From 1efcec19d74e45296dc9a8c514c77873730d1a08 Mon Sep 17 00:00:00 2001 From: Michal Kozikowski Date: Tue, 13 May 2025 13:33:22 +0200 Subject: [PATCH 356/420] [nrf noup] decompression: Align to changes in nrfcompress API This commit aligns to the changes in the nrfcompress API, which now enables the caller to provide the expected size of the decompressed image. ref: NCSDK-32340 Signed-off-by: Michal Kozikowski Signed-off-by: Dominik Ermel (cherry picked from commit 8900bdaf1dd401b08748d4141f1196520579f4fd) --- boot/zephyr/decompression.c | 65 ++++++++++++++++++++++++------------- 1 file changed, 42 insertions(+), 23 deletions(-) diff --git a/boot/zephyr/decompression.c b/boot/zephyr/decompression.c index 87e3d3763..ce4fe0b2b 100644 --- a/boot/zephyr/decompression.c +++ b/boot/zephyr/decompression.c @@ -256,15 +256,6 @@ int bootutil_img_hash_decompress(struct boot_loader_state *state, struct image_h goto finish_without_clean; } - rc = compression_lzma->init(NULL); - rc = compression_arm_thumb->init(NULL); - - if (rc) { - BOOT_LOG_ERR("Decompression library fatal error"); - rc = BOOT_EBADSTATUS; - goto finish_without_clean; - } - /* We need a modified header which has the updated sizes, start with the original header */ memcpy(&modified_hdr, hdr, sizeof(modified_hdr)); @@ -276,12 +267,28 @@ int bootutil_img_hash_decompress(struct boot_loader_state *state, struct image_h if (rc) { BOOT_LOG_ERR("Unable to determine decompressed size of compressed image"); rc = BOOT_EBADIMAGE; - goto finish; + goto finish_without_clean; } modified_hdr.ih_flags &= ~COMPRESSIONFLAGS; modified_hdr.ih_img_size = decompressed_image_size; + rc = compression_lzma->init(NULL, decompressed_image_size); + + if (rc) { + BOOT_LOG_ERR("Decompression library fatal error"); + rc = BOOT_EBADSTATUS; + goto finish_without_clean; + } + + rc = compression_arm_thumb->init(NULL, decompressed_image_size); + + if (rc) { + BOOT_LOG_ERR("Decompression library fatal error"); + rc = BOOT_EBADSTATUS; + goto finish; + } + /* Calculate the protected TLV size, these will not include the decompressed * sha/size/signature entries */ @@ -1101,7 +1108,7 @@ int boot_copy_region_decompress(struct boot_loader_state *state, const struct fl if (rc) { BOOT_LOG_ERR("Invalid/missing image decrypted compressed size value"); rc = BOOT_EBADIMAGE; - goto finish; + goto finish_without_clean; } if (IS_ENCRYPTED(hdr)) { @@ -1124,7 +1131,7 @@ int boot_copy_region_decompress(struct boot_loader_state *state, const struct fl */ BOOT_LOG_ERR("Invalid image compression flags: no supported compression found"); rc = BOOT_EBADIMAGE; - goto finish; + goto finish_without_clean; } compression_lzma = nrf_compress_implementation_find(NRF_COMPRESS_TYPE_LZMA); @@ -1135,16 +1142,7 @@ int boot_copy_region_decompress(struct boot_loader_state *state, const struct fl /* Compression library missing or missing required function pointer */ BOOT_LOG_ERR("Decompression library fatal error"); rc = BOOT_EBADSTATUS; - goto finish; - } - - rc = compression_lzma->init(NULL); - rc = compression_arm_thumb->init(NULL); - - if (rc) { - BOOT_LOG_ERR("Decompression library fatal error"); - rc = BOOT_EBADSTATUS; - goto finish; + goto finish_without_clean; } write_alignment = flash_area_align(fap_dst); @@ -1158,12 +1156,28 @@ int boot_copy_region_decompress(struct boot_loader_state *state, const struct fl if (rc) { BOOT_LOG_ERR("Unable to determine decompressed size of compressed image"); rc = BOOT_EBADIMAGE; - goto finish; + goto finish_without_clean; } modified_hdr.ih_flags &= ~COMPRESSIONFLAGS; modified_hdr.ih_img_size = decompressed_image_size; + rc = compression_lzma->init(NULL, decompressed_image_size); + + if (rc) { + BOOT_LOG_ERR("Decompression library fatal error"); + rc = BOOT_EBADSTATUS; + goto finish_without_clean; + } + + rc = compression_arm_thumb->init(NULL, decompressed_image_size); + + if (rc) { + BOOT_LOG_ERR("Decompression library fatal error"); + rc = BOOT_EBADSTATUS; + goto finish; + } + /* Calculate protected TLV size for target image once items are removed */ rc = boot_size_protected_tlvs(hdr, fap_src, &protected_tlv_size); @@ -1457,6 +1471,11 @@ int boot_copy_region_decompress(struct boot_loader_state *state, const struct fl } finish: + /* Clean up decompression system */ + (void)compression_lzma->deinit(NULL); + (void)compression_arm_thumb->deinit(NULL); + +finish_without_clean: memset(decomp_buf, 0, sizeof(decomp_buf)); return rc; From 4d4123bb5a508c8bfbb39301cab0c53e6ecfb84c Mon Sep 17 00:00:00 2001 From: Jamie McCrae Date: Thu, 7 Nov 2024 10:53:06 +0000 Subject: [PATCH 357/420] [nrf noup] boot: zephyr: Add experimental selection to compression Adds selecting the experimental Kconfig when compession is in use Signed-off-by: Jamie McCrae Signed-off-by: Dominik Ermel (cherry picked from commit 4a528baa162b14d44a95892340aa299525ee1b8b) --- boot/zephyr/Kconfig | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/boot/zephyr/Kconfig b/boot/zephyr/Kconfig index 5cfc9b6c3..98cfade82 100644 --- a/boot/zephyr/Kconfig +++ b/boot/zephyr/Kconfig @@ -1211,9 +1211,10 @@ config BOOT_DECOMPRESSION_SUPPORT if BOOT_DECOMPRESSION_SUPPORT menuconfig BOOT_DECOMPRESSION - bool "Decompression" + bool "Decompression [EXPERIMENTAL]" select NRF_COMPRESS_CLEANUP select PM_USE_CONFIG_SRAM_SIZE if SOC_NRF54L15_CPUAPP + select EXPERIMENTAL help If enabled, will include support for compressed images being loaded to the secondary slot which then get decompressed into the primary slot. This mode allows the secondary slot to From d0cd58f1d7fceb6bbb7de0add810b652effb4b3b Mon Sep 17 00:00:00 2001 From: Dominik Ermel Date: Fri, 20 Sep 2024 16:34:00 +0000 Subject: [PATCH 358/420] [nrf noup] bootutil: Add support for KMU stored ED25519 signature key The commit adds verification of image using keys stored in KMU. Signed-off-by: Dominik Ermel (cherry picked from commit 26192ca1c9986dd9f50b9e5537bfc38fd2953128) (cherry picked from commit 6ba9587457e8b2b705528ffe6cc77435ae9df080) --- boot/bootutil/src/ed25519_psa.c | 51 +++++++++++++++++++ boot/bootutil/src/image_ed25519.c | 9 +++- boot/bootutil/src/image_validate.c | 80 +++++++++++++++++++++++++++++- boot/zephyr/CMakeLists.txt | 2 +- boot/zephyr/Kconfig | 26 ++++++++++ 5 files changed, 164 insertions(+), 4 deletions(-) diff --git a/boot/bootutil/src/ed25519_psa.c b/boot/bootutil/src/ed25519_psa.c index 5b8a4ed7c..cd016158b 100644 --- a/boot/bootutil/src/ed25519_psa.c +++ b/boot/bootutil/src/ed25519_psa.c @@ -12,6 +12,9 @@ #include #include +#if defined(CONFIG_BOOT_SIGNATURE_USING_KMU) +#include +#endif BOOT_LOG_MODULE_REGISTER(ed25519_psa); @@ -19,6 +22,18 @@ BOOT_LOG_MODULE_REGISTER(ed25519_psa); #define EDDSA_KEY_LENGTH 32 #define EDDSA_SIGNAGURE_LENGTH 64 +#if defined(CONFIG_BOOT_SIGNATURE_USING_KMU) +/* List of KMU stored key ids available for MCUboot */ +#define MAKE_PSA_KMU_KEY_ID(id) PSA_KEY_HANDLE_FROM_CRACEN_KMU_SLOT(CRACEN_KMU_KEY_USAGE_SCHEME_RAW, id) +static psa_key_id_t kmu_key_ids[3] = { + MAKE_PSA_KMU_KEY_ID(226), + MAKE_PSA_KMU_KEY_ID(228), + MAKE_PSA_KMU_KEY_ID(230) +}; +#define KMU_KEY_COUNT (sizeof(kmu_key_ids)/sizeof(kmu_key_ids[0])) +#endif + +#if !defined(CONFIG_BOOT_SIGNATURE_USING_KMU) int ED25519_verify(const uint8_t *message, size_t message_len, const uint8_t signature[EDDSA_SIGNAGURE_LENGTH], const uint8_t public_key[EDDSA_KEY_LENGTH]) @@ -71,3 +86,39 @@ int ED25519_verify(const uint8_t *message, size_t message_len, return ret; } +#else +int ED25519_verify(const uint8_t *message, size_t message_len, + const uint8_t signature[EDDSA_SIGNAGURE_LENGTH], + const uint8_t public_key[EDDSA_KEY_LENGTH]) +{ + ARG_UNUSED(public_key); + /* Set to any error */ + psa_status_t status = PSA_ERROR_BAD_STATE; + int ret = 0; /* Fail by default */ + + /* Initialize PSA Crypto */ + status = psa_crypto_init(); + if (status != PSA_SUCCESS) { + BOOT_LOG_ERR("PSA crypto init failed %d", status); + return 0; + } + + status = PSA_ERROR_BAD_STATE; + + for (int i = 0; i < KMU_KEY_COUNT; ++i) { + psa_key_id_t kid = kmu_key_ids[i]; + + status = psa_verify_message(kid, PSA_ALG_PURE_EDDSA, message, + message_len, signature, + EDDSA_SIGNAGURE_LENGTH); + if (status == PSA_SUCCESS) { + ret = 1; + break; + } + + BOOT_LOG_ERR("ED25519 signature verification failed %d", status); + } + + return ret; +} +#endif diff --git a/boot/bootutil/src/image_ed25519.c b/boot/bootutil/src/image_ed25519.c index 4d83bb3d7..1a02811e3 100644 --- a/boot/bootutil/src/image_ed25519.c +++ b/boot/bootutil/src/image_ed25519.c @@ -34,6 +34,7 @@ extern int ED25519_verify(const uint8_t *message, size_t message_len, const uint8_t signature[EDDSA_SIGNATURE_LENGTH], const uint8_t public_key[NUM_ED25519_BYTES]); +#if !defined(CONFIG_BOOT_SIGNATURE_USING_KMU) #if !defined(MCUBOOT_KEY_IMPORT_BYPASS_ASN) /* * Parse the public key used for signing. @@ -76,6 +77,7 @@ bootutil_import_key(uint8_t **cp, uint8_t *end) return 0; } #endif /* !defined(MCUBOOT_KEY_IMPORT_BYPASS_ASN) */ +#endif /* Signature verification base function. * The function takes buffer of specified length and tries to verify @@ -90,8 +92,10 @@ bootutil_verify(uint8_t *buf, uint32_t blen, { int rc; FIH_DECLARE(fih_rc, FIH_FAILURE); - uint8_t *pubkey; + uint8_t *pubkey = NULL; +#if !defined(CONFIG_BOOT_SIGNATURE_USING_KMU) uint8_t *end; +#endif BOOT_LOG_DBG("bootutil_verify: ED25519 key_id %d", (int)key_id); @@ -102,6 +106,7 @@ bootutil_verify(uint8_t *buf, uint32_t blen, goto out; } +#if !defined(CONFIG_BOOT_SIGNATURE_USING_KMU) pubkey = (uint8_t *)bootutil_keys[key_id].key; end = pubkey + *bootutil_keys[key_id].len; @@ -125,6 +130,8 @@ bootutil_verify(uint8_t *buf, uint32_t blen, } pubkey = end - NUM_ED25519_BYTES; +#endif + #endif rc = ED25519_verify(buf, blen, sig, pubkey); diff --git a/boot/bootutil/src/image_validate.c b/boot/bootutil/src/image_validate.c index 5d2efc98a..3f235e048 100644 --- a/boot/bootutil/src/image_validate.c +++ b/boot/bootutil/src/image_validate.c @@ -117,7 +117,77 @@ BOOT_LOG_MODULE_DECLARE(mcuboot); # define EXPECTED_KEY_TLV IMAGE_TLV_PUBKEY # define KEY_BUF_SIZE (SIG_BUF_SIZE + 24) #endif /* !MCUBOOT_HW_KEY */ + +#if !defined(CONFIG_BOOT_SIGNATURE_USING_KMU) +#if !defined(MCUBOOT_HW_KEY) +static int +bootutil_find_key(uint8_t *keyhash, uint8_t keyhash_len) +{ + bootutil_sha_context sha_ctx; + int i; + const struct bootutil_key *key; + uint8_t hash[IMAGE_HASH_SIZE]; + + BOOT_LOG_DBG("bootutil_find_key"); + + if (keyhash_len > IMAGE_HASH_SIZE) { + return -1; + } + + for (i = 0; i < bootutil_key_cnt; i++) { + key = &bootutil_keys[i]; + bootutil_sha_init(&sha_ctx); + bootutil_sha_update(&sha_ctx, key->key, *key->len); + bootutil_sha_finish(&sha_ctx, hash); + bootutil_sha_drop(&sha_ctx); + if (!memcmp(hash, keyhash, keyhash_len)) { + return i; + } + } + return -1; +} +#else /* !MCUBOOT_HW_KEY */ +extern unsigned int pub_key_len; +static int +bootutil_find_key(uint8_t image_index, uint8_t *key, uint16_t key_len) +{ + bootutil_sha_context sha_ctx; + uint8_t hash[IMAGE_HASH_SIZE]; + uint8_t key_hash[IMAGE_HASH_SIZE]; + size_t key_hash_size = sizeof(key_hash); + int rc; + FIH_DECLARE(fih_rc, FIH_FAILURE); + + BOOT_LOG_DBG("bootutil_find_key: image_index %d", image_index); + + bootutil_sha_init(&sha_ctx); + bootutil_sha_update(&sha_ctx, key, key_len); + bootutil_sha_finish(&sha_ctx, hash); + bootutil_sha_drop(&sha_ctx); + + rc = boot_retrieve_public_key_hash(image_index, key_hash, &key_hash_size); + if (rc) { + return -1; + } + + /* Adding hardening to avoid this potential attack: + * - Image is signed with an arbitrary key and the corresponding public + * key is added as a TLV field. + * - During public key validation (comparing against key-hash read from + * HW) a fault is injected to accept the public key as valid one. + */ + FIH_CALL(boot_fih_memequal, fih_rc, hash, key_hash, key_hash_size); + if (FIH_EQ(fih_rc, FIH_SUCCESS)) { + bootutil_keys[0].key = key; + pub_key_len = key_len; + return 0; + } + + return -1; +} +#endif /* !MCUBOOT_HW_KEY */ #endif /* !MCUBOOT_BUILTIN_KEY */ +#endif /* !defined(CONFIG_BOOT_SIGNATURE_USING_KMU) */ #endif /* EXPECTED_SIG_TLV */ #if defined(MCUBOOT_SIGN_PURE) @@ -433,6 +503,7 @@ bootutil_img_validate(struct boot_loader_state *state, break; } #endif /* defined(EXPECTED_HASH_TLV) && !defined(MCUBOOT_SIGN_PURE) */ +#if !defined(CONFIG_BOOT_SIGNATURE_USING_KMU) #ifdef EXPECTED_KEY_TLV case EXPECTED_KEY_TLV: { @@ -464,15 +535,18 @@ bootutil_img_validate(struct boot_loader_state *state, break; } #endif /* EXPECTED_KEY_TLV */ +#endif /* !defined(CONFIG_BOOT_SIGNATURE_USING_KMU) */ #ifdef EXPECTED_SIG_TLV case EXPECTED_SIG_TLV: { BOOT_LOG_DBG("bootutil_img_validate: EXPECTED_SIG_TLV == %d", EXPECTED_SIG_TLV); +#if !defined(CONFIG_BOOT_SIGNATURE_USING_KMU) /* Ignore this signature if it is out of bounds. */ if (key_id < 0 || key_id >= bootutil_key_cnt) { key_id = -1; continue; } +#endif /* !defined(CONFIG_BOOT_SIGNATURE_USING_KMU) */ if (!EXPECTED_SIG_LEN(len) || len > sizeof(buf)) { rc = -1; goto out; @@ -720,7 +794,7 @@ bootutil_img_validate(struct boot_loader_state *state, } #ifdef EXPECTED_SIG_TLV -#ifdef EXPECTED_KEY_TLV +#if !defined(CONFIG_BOOT_SIGNATURE_USING_KMU) && defined(EXPECTED_KEY_TLV) rc = bootutil_tlv_iter_begin(&it, hdr, fap, EXPECTED_KEY_TLV, false); if (rc) { goto out; @@ -766,7 +840,7 @@ bootutil_img_validate(struct boot_loader_state *state, */ } } -#endif /* EXPECTED_KEY_TLV */ +#endif /* !CONFIG_BOOT_SIGNATURE_USING_KMU && EXPECTED_KEY_TLV */ rc = bootutil_tlv_iter_begin(&it, hdr, fap, IMAGE_TLV_DECOMP_SIGNATURE, true); if (rc) { @@ -789,10 +863,12 @@ bootutil_img_validate(struct boot_loader_state *state, if (type == IMAGE_TLV_DECOMP_SIGNATURE) { /* Ignore this signature if it is out of bounds. */ +#if !defined(CONFIG_BOOT_SIGNATURE_USING_KMU) if (key_id < 0 || key_id >= bootutil_key_cnt) { key_id = -1; continue; } +#endif if (!EXPECTED_SIG_LEN(len) || len > sizeof(buf)) { rc = -1; diff --git a/boot/zephyr/CMakeLists.txt b/boot/zephyr/CMakeLists.txt index 0ab3ebad4..0c58f5529 100644 --- a/boot/zephyr/CMakeLists.txt +++ b/boot/zephyr/CMakeLists.txt @@ -358,7 +358,7 @@ if(CONFIG_MCUBOOT_SERIAL) endif() endif() -if(NOT CONFIG_BOOT_SIGNATURE_KEY_FILE STREQUAL "") +if(NOT CONFIG_BOOT_SIGNATURE_USING_KMU AND NOT CONFIG_BOOT_SIGNATURE_KEY_FILE STREQUAL "") # CONF_FILE points to the KConfig configuration files of the bootloader. foreach (filepath ${CONF_FILE}) file(READ ${filepath} temp_text) diff --git a/boot/zephyr/Kconfig b/boot/zephyr/Kconfig index 98cfade82..31a5fd556 100644 --- a/boot/zephyr/Kconfig +++ b/boot/zephyr/Kconfig @@ -397,6 +397,22 @@ config BOOT_BYPASS_KEY_MATCH Enabling this option turns off key matching, slightly reducing MCUboot code and boot time. +config BOOT_SIGNATURE_USING_KMU + bool "Use KMU stored keys for signature verification" + depends on NRF_SECURITY + depends on CRACEN_LIB_KMU + select PSA_WANT_ALG_GCM + select PSA_WANT_KEY_TYPE_AES + select PSA_WANT_AES_KEY_SIZE_256 + select PSA_WANT_ALG_SP800_108_COUNTER_CMAC + select PSA_WANT_ALG_CMAC + select PSA_WANT_ALG_ECB_NO_PADDING + help + MCUboot will use keys provisioned to the device key management unit for signature + verification instead of compiling in key data from a file. + +if !BOOT_SIGNATURE_USING_KMU + config BOOT_SIGNATURE_KEY_FILE string "PEM key file" default "root-ec-p256.pem" if BOOT_SIGNATURE_TYPE_ECDSA_P256 @@ -414,6 +430,8 @@ config BOOT_SIGNATURE_KEY_FILE with the public key information will be written in a format expected by MCUboot. +endif + config MCUBOOT_CLEANUP_ARM_CORE bool "Perform core cleanup before chain-load the application" depends on CPU_CORTEX_M || ARMV7_R @@ -450,6 +468,14 @@ config MCUBOOT_INFINITE_LOOP_AFTER_RAM_CLEANUP Verification option that keeps execution in infinite loop after RAM cleanup has been performed. +# Disable MBEDTLS from being selected if NRF_SECURITY is enabled, and use default NRF_SECURITY +# configuration file for MBEDTLS +config MBEDTLS + depends on !NRF_SECURITY + +config NRF_SECURITY + select MBEDTLS_PROMPTLESS + config MBEDTLS_CFG_FILE # It might be awkward to define an Mbed TLS header file when TinyCrypt # is used, but the fact is that Mbed TLS' ASN1 parse module is used From 37df88a122d6c12eaae322ba4ec9efca067741bf Mon Sep 17 00:00:00 2001 From: Jamie McCrae Date: Mon, 2 Dec 2024 10:51:41 +0000 Subject: [PATCH 359/420] [nrf noup] boot: bootutil: Allow configuring number of KMU keys Adds a new Kconfig CONFIG_BOOT_SIGNATURE_KMU_SLOTS which allows specifying how many KMU key IDs are supported, the default is set to 1 instead of 3 which was set before NCSDK-30743 Signed-off-by: Jamie McCrae Signed-off-by: Dominik Ermel (cherry picked from commit 83d1d959de612b8bc17dae56355b0ccc40cebde6) --- boot/bootutil/src/ed25519_psa.c | 7 +++++-- boot/zephyr/Kconfig | 12 ++++++++++++ 2 files changed, 17 insertions(+), 2 deletions(-) diff --git a/boot/bootutil/src/ed25519_psa.c b/boot/bootutil/src/ed25519_psa.c index cd016158b..7665e4067 100644 --- a/boot/bootutil/src/ed25519_psa.c +++ b/boot/bootutil/src/ed25519_psa.c @@ -12,6 +12,7 @@ #include #include +#include #if defined(CONFIG_BOOT_SIGNATURE_USING_KMU) #include #endif @@ -30,7 +31,9 @@ static psa_key_id_t kmu_key_ids[3] = { MAKE_PSA_KMU_KEY_ID(228), MAKE_PSA_KMU_KEY_ID(230) }; -#define KMU_KEY_COUNT (sizeof(kmu_key_ids)/sizeof(kmu_key_ids[0])) + +BUILD_ASSERT(CONFIG_BOOT_SIGNATURE_KMU_SLOTS <= ARRAY_SIZE(kmu_key_ids), + "Invalid number of KMU slots, up to 3 are supported on nRF54L15"); #endif #if !defined(CONFIG_BOOT_SIGNATURE_USING_KMU) @@ -105,7 +108,7 @@ int ED25519_verify(const uint8_t *message, size_t message_len, status = PSA_ERROR_BAD_STATE; - for (int i = 0; i < KMU_KEY_COUNT; ++i) { + for (int i = 0; i < CONFIG_BOOT_SIGNATURE_KMU_SLOTS; ++i) { psa_key_id_t kid = kmu_key_ids[i]; status = psa_verify_message(kid, PSA_ALG_PURE_EDDSA, message, diff --git a/boot/zephyr/Kconfig b/boot/zephyr/Kconfig index 31a5fd556..e5dca2ffe 100644 --- a/boot/zephyr/Kconfig +++ b/boot/zephyr/Kconfig @@ -411,6 +411,18 @@ config BOOT_SIGNATURE_USING_KMU MCUboot will use keys provisioned to the device key management unit for signature verification instead of compiling in key data from a file. +if BOOT_SIGNATURE_USING_KMU + +config BOOT_SIGNATURE_KMU_SLOTS + int "KMU key slots" + range 1 3 + default 1 + help + Selects the number of KMU key slots (also known as generations) to use when verifying + an image. + +endif + if !BOOT_SIGNATURE_USING_KMU config BOOT_SIGNATURE_KEY_FILE From 08e2009fbcdbcb8292cdb8bd62332f656443d170 Mon Sep 17 00:00:00 2001 From: Mateusz Michalek Date: Mon, 17 Mar 2025 21:25:41 +0100 Subject: [PATCH 360/420] [nrf noup] bootutil: key revocation Disable previous generation key when update comes with new valid key and application is confirmed. Signed-off-by: Mateusz Michalek Signed-off-by: Dominik Ermel (cherry picked from commit 51b0897bc30cf6cf5a33127bdd5501e59d051499) --- .../include/bootutil/key_revocation.h | 30 ++++++++++++++ boot/bootutil/src/ed25519_psa.c | 41 +++++++++++++++++++ boot/bootutil/src/key_revocation.c | 24 +++++++++++ boot/bootutil/src/loader.c | 16 ++++++++ boot/zephyr/CMakeLists.txt | 6 +++ boot/zephyr/Kconfig | 12 ++++++ 6 files changed, 129 insertions(+) create mode 100644 boot/bootutil/include/bootutil/key_revocation.h create mode 100644 boot/bootutil/src/key_revocation.c diff --git a/boot/bootutil/include/bootutil/key_revocation.h b/boot/bootutil/include/bootutil/key_revocation.h new file mode 100644 index 000000000..d184c9579 --- /dev/null +++ b/boot/bootutil/include/bootutil/key_revocation.h @@ -0,0 +1,30 @@ +/* + * Copyright (c) 2025 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: LicenseRef-Nordic-5-Clause + */ + +#ifndef H_KEY_REVOCATION_ +#define H_KEY_REVOCATION_ + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +#define BOOT_KEY_REVOKE_OK 0 +#define BOOT_KEY_REVOKE_NOT_READY 1 +#define BOOT_KEY_REVOKE_INVALID 2 +#define BOOT_KEY_REVOKE_FAILED 2 + + +void allow_revoke(void); + +int revoke(void); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/boot/bootutil/src/ed25519_psa.c b/boot/bootutil/src/ed25519_psa.c index 7665e4067..6393d996e 100644 --- a/boot/bootutil/src/ed25519_psa.c +++ b/boot/bootutil/src/ed25519_psa.c @@ -32,6 +32,11 @@ static psa_key_id_t kmu_key_ids[3] = { MAKE_PSA_KMU_KEY_ID(230) }; +#if defined(CONFIG_BOOT_KMU_KEYS_REVOCATION) +#include +static psa_key_id_t *validated_with = NULL; +#endif + BUILD_ASSERT(CONFIG_BOOT_SIGNATURE_KMU_SLOTS <= ARRAY_SIZE(kmu_key_ids), "Invalid number of KMU slots, up to 3 are supported on nRF54L15"); #endif @@ -116,6 +121,9 @@ int ED25519_verify(const uint8_t *message, size_t message_len, EDDSA_SIGNAGURE_LENGTH); if (status == PSA_SUCCESS) { ret = 1; +#if defined(CONFIG_BOOT_KMU_KEYS_REVOCATION) + validated_with = kmu_key_ids + i; +#endif break; } @@ -124,4 +132,37 @@ int ED25519_verify(const uint8_t *message, size_t message_len, return ret; } +#if defined(CONFIG_BOOT_KMU_KEYS_REVOCATION) +int exec_revoke(void) +{ + int ret = BOOT_KEY_REVOKE_OK; + psa_status_t status = psa_crypto_init(); + + if (!validated_with) { + ret = BOOT_KEY_REVOKE_INVALID; + goto out; + } + + if (status != PSA_SUCCESS) { + BOOT_LOG_ERR("PSA crypto init failed with error %d", status); + ret = BOOT_KEY_REVOKE_FAILED; + goto out; + } + for (int i = 0; i < CONFIG_BOOT_SIGNATURE_KMU_SLOTS; i++) { + if ((kmu_key_ids + i) == validated_with) { + break; + } + BOOT_LOG_DBG("Invalidating key ID %d", i); + + status = psa_destroy_key(kmu_key_ids[i]); + if (status == PSA_SUCCESS) { + BOOT_LOG_DBG("Success on key ID %d", i); + } else { + BOOT_LOG_ERR("Key invalidation failed with: %d", status); + } + } +out: + return ret; +} +#endif /* CONFIG_BOOT_KMU_KEYS_REVOCATION */ #endif diff --git a/boot/bootutil/src/key_revocation.c b/boot/bootutil/src/key_revocation.c new file mode 100644 index 000000000..0768a3188 --- /dev/null +++ b/boot/bootutil/src/key_revocation.c @@ -0,0 +1,24 @@ +/* + * Copyright (c) 2025 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: LicenseRef-Nordic-5-Clause + */ + +#include + +extern int exec_revoke(void); + +static uint8_t ready_to_revoke; + +void allow_revoke(void) +{ + ready_to_revoke = 1; +} + +int revoke(void) +{ + if (ready_to_revoke) { + return exec_revoke(); + } + return BOOT_KEY_REVOKE_NOT_READY; +} diff --git a/boot/bootutil/src/loader.c b/boot/bootutil/src/loader.c index 9f2e6c868..043d2cd0f 100644 --- a/boot/bootutil/src/loader.c +++ b/boot/bootutil/src/loader.c @@ -80,6 +80,10 @@ int pcd_version_cmp_net(const struct flash_area *fap, struct image_header *hdr); #include "mcuboot_config/mcuboot_config.h" +#if defined(CONFIG_BOOT_KEYS_REVOCATION) +#include "bootutil/key_revocation.h" +#endif + BOOT_LOG_MODULE_DECLARE(mcuboot); static struct boot_loader_state boot_data; @@ -2890,6 +2894,11 @@ context_boot_go(struct boot_loader_state *state, struct boot_rsp *rsp) } } +#if defined(CONFIG_BOOT_KEYS_REVOCATION) + if (BOOT_SWAP_TYPE(state) == BOOT_SWAP_TYPE_NONE) { + allow_revoke(); + } +#endif /* Iterate over all the images. At this point all required update operations * have finished. By the end of the loop each image in the primary slot will * have been re-validated. @@ -2998,6 +3007,13 @@ context_boot_go(struct boot_loader_state *state, struct boot_rsp *rsp) fill_rsp(state, rsp); fih_rc = FIH_SUCCESS; +#if defined(CONFIG_BOOT_KEYS_REVOCATION) + rc = revoke(); + if (rc != BOOT_KEY_REVOKE_OK && + rc != BOOT_KEY_REVOKE_NOT_READY) { + FIH_SET(fih_rc, FIH_FAILURE); + } +#endif /* CONFIG_BOOT_KEYS_REVOCATION */ out: /* * Since the boot_status struct stores plaintext encryption keys, reset diff --git a/boot/zephyr/CMakeLists.txt b/boot/zephyr/CMakeLists.txt index 0c58f5529..01da13a89 100644 --- a/boot/zephyr/CMakeLists.txt +++ b/boot/zephyr/CMakeLists.txt @@ -98,6 +98,12 @@ if(DEFINED CONFIG_BOOT_SHARE_BACKEND_RETENTION) ) endif() +if(DEFINED CONFIG_BOOT_KEYS_REVOCATION) + zephyr_library_sources( + ${BOOT_DIR}/bootutil/src/key_revocation.c +) +endif() + # Generic bootutil sources and includes. zephyr_library_include_directories(${BOOT_DIR}/bootutil/include) zephyr_library_sources( diff --git a/boot/zephyr/Kconfig b/boot/zephyr/Kconfig index e5dca2ffe..117f09a65 100644 --- a/boot/zephyr/Kconfig +++ b/boot/zephyr/Kconfig @@ -423,6 +423,18 @@ config BOOT_SIGNATURE_KMU_SLOTS endif +config BOOT_KEYS_REVOCATION + bool "Auto revoke previous gen key" + help + Automatically revoke previous generation key upon new valid key usage. + +config BOOT_KMU_KEYS_REVOCATION + bool + depends on BOOT_KEYS_REVOCATION + default y if BOOT_SIGNATURE_USING_KMU + help + Enabling KMU key revocation backend. + if !BOOT_SIGNATURE_USING_KMU config BOOT_SIGNATURE_KEY_FILE From e2bfd22d374aa91decc2d4d44b9dfde9bbb94213 Mon Sep 17 00:00:00 2001 From: Artur Hadasz Date: Thu, 24 Jul 2025 13:31:00 +0200 Subject: [PATCH 361/420] [nrf noup] Added BOOT_SIGNATURE_USING_ITS for ecdsa configuration This configuration has the purpose of using keys provisioned to the internal trusted storage (ITS). It makes use of the already existing parts of code for MCUBOOT_BUILTIN_KEY Signed-off-by: Artur Hadasz (cherry picked from commit 7ed49272a2f00e3e0936c333f2a0240e99226963) --- boot/bootutil/include/bootutil/crypto/ecdsa.h | 50 +++++++++++++++++++ boot/bootutil/src/image_validate.c | 3 +- boot/zephyr/Kconfig | 9 +++- .../include/mcuboot_config/mcuboot_config.h | 4 ++ 4 files changed, 64 insertions(+), 2 deletions(-) diff --git a/boot/bootutil/include/bootutil/crypto/ecdsa.h b/boot/bootutil/include/bootutil/crypto/ecdsa.h index cbbff1783..4fc7b7516 100644 --- a/boot/bootutil/include/bootutil/crypto/ecdsa.h +++ b/boot/bootutil/include/bootutil/crypto/ecdsa.h @@ -475,6 +475,7 @@ static int bootutil_ecdsa_parse_public_key(bootutil_ecdsa_context *ctx, } #endif /* !MCUBOOT_BUILTIN_KEY */ +#if !defined(CONFIG_NRF_BOOT_SIGNATURE_USING_ITS) /* Verify the signature against the provided hash. The signature gets parsed from * the encoding first, then PSA Crypto has a dedicated API for ECDSA verification */ @@ -493,6 +494,55 @@ static inline int bootutil_ecdsa_verify(bootutil_ecdsa_context *ctx, return (int) psa_verify_hash(ctx->key_id, PSA_ALG_ECDSA(ctx->required_algorithm), hash, hlen, reformatted_signature, 2*ctx->curve_byte_count); } +#else /* !CONFIG_NRF_BOOT_SIGNATURE_USING_ITS */ + +static const psa_key_id_t builtin_key_ids[] = { + 0x40022100, + 0x40022101, + 0x40022102, + 0x40022103 +}; + +#define BOOT_SIGNATURE_BUILTIN_KEY_SLOTS ARRAY_SIZE(builtin_key_ids) + +static inline int bootutil_ecdsa_verify(bootutil_ecdsa_context *ctx, + uint8_t *pk, size_t pk_len, + uint8_t *hash, size_t hlen, + uint8_t *sig, size_t slen) +{ + (void)pk; + (void)pk_len; + (void)slen; + psa_status_t status = PSA_ERROR_BAD_STATE; + + /* Initialize PSA Crypto */ + status = psa_crypto_init(); + if (status != PSA_SUCCESS) { + BOOT_LOG_ERR("PSA crypto init failed %d", status); + return 1; + } + + uint8_t reformatted_signature[96] = {0}; /* Enough for P-384 signature sizes */ + parse_signature_from_rfc5480_encoding(sig, ctx->curve_byte_count, reformatted_signature); + + status = PSA_ERROR_BAD_STATE; + + for (int i = 0; i < BOOT_SIGNATURE_BUILTIN_KEY_SLOTS; ++i) { + psa_key_id_t kid = builtin_key_ids[i]; + + status = psa_verify_hash(kid, PSA_ALG_ECDSA(ctx->required_algorithm), + hash, hlen, reformatted_signature, 2*ctx->curve_byte_count); + if (status == PSA_SUCCESS) { + break; + } + BOOT_LOG_ERR("ECDSA signature verification failed %d", status); + } + + return status == PSA_SUCCESS ? 0 : 2; +} + +#endif /* !CONFIG_NRF_BOOT_SIGNATURE_USING_ITS */ + #elif defined(MCUBOOT_USE_MBED_TLS) typedef mbedtls_ecdsa_context bootutil_ecdsa_context; diff --git a/boot/bootutil/src/image_validate.c b/boot/bootutil/src/image_validate.c index 3f235e048..fd1a6a925 100644 --- a/boot/bootutil/src/image_validate.c +++ b/boot/bootutil/src/image_validate.c @@ -280,7 +280,8 @@ bootutil_img_validate(struct boot_loader_state *state, ) { #if (defined(EXPECTED_KEY_TLV) && defined(MCUBOOT_HW_KEY)) || defined(MCUBOOT_HW_ROLLBACK_PROT) \ - || defined(MCUBOOT_UUID_VID) || defined(MCUBOOT_UUID_CID) || defined(MCUBOOT_DECOMPRESS_IMAGES) + || defined(MCUBOOT_UUID_VID) || defined(MCUBOOT_UUID_CID) || defined(MCUBOOT_DECOMPRESS_IMAGES) \ + || defined(MCUBOOT_BUILTIN_KEY) int image_index = (state == NULL ? 0 : BOOT_CURR_IMG(state)); #endif uint32_t off; diff --git a/boot/zephyr/Kconfig b/boot/zephyr/Kconfig index 117f09a65..5aa3f0cd8 100644 --- a/boot/zephyr/Kconfig +++ b/boot/zephyr/Kconfig @@ -435,7 +435,14 @@ config BOOT_KMU_KEYS_REVOCATION help Enabling KMU key revocation backend. -if !BOOT_SIGNATURE_USING_KMU +config NRF_BOOT_SIGNATURE_USING_ITS + bool "Use ITS stored keys for signature verification" + depends on NRF_SECURITY + help + MCUboot will use keys provisioned to the internal trusted storage for signature + verification instead of compiling in key data from a file. + +if !BOOT_SIGNATURE_USING_KMU && !NRF_BOOT_SIGNATURE_USING_ITS config BOOT_SIGNATURE_KEY_FILE string "PEM key file" diff --git a/boot/zephyr/include/mcuboot_config/mcuboot_config.h b/boot/zephyr/include/mcuboot_config/mcuboot_config.h index d82fc57f3..6b5784c86 100644 --- a/boot/zephyr/include/mcuboot_config/mcuboot_config.h +++ b/boot/zephyr/include/mcuboot_config/mcuboot_config.h @@ -68,6 +68,10 @@ #define MCUBOOT_HW_KEY #endif +#ifdef CONFIG_NRF_BOOT_SIGNATURE_USING_ITS +#define MCUBOOT_BUILTIN_KEY +#endif + #ifdef CONFIG_BOOT_VALIDATE_SLOT0 #define MCUBOOT_VALIDATE_PRIMARY_SLOT #endif From 7047d540c2d890d62513763dd963705bbea3e4b6 Mon Sep 17 00:00:00 2001 From: Dominik Ermel Date: Fri, 1 Aug 2025 10:36:12 +0000 Subject: [PATCH 362/420] [nrf noup] boot: Use NCS_ prefix for sdk-nrf specific Kconfigs nrf-squash! [nrf noup] Added BOOT_SIGNATURE_USING_ITS for ecdsa configuration Replace NRF_BOOT_SIGNATURE_USING_ITS with NCS_BOOT_SIGNATURE_USING_ITS prefix. Signed-off-by: Dominik Ermel (cherry picked from commit a4bae1322e51d086c454aa5a870441ba4c995b80) --- boot/bootutil/include/bootutil/crypto/ecdsa.h | 6 +++--- boot/zephyr/Kconfig | 4 ++-- boot/zephyr/include/mcuboot_config/mcuboot_config.h | 2 +- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/boot/bootutil/include/bootutil/crypto/ecdsa.h b/boot/bootutil/include/bootutil/crypto/ecdsa.h index 4fc7b7516..7fc5474e2 100644 --- a/boot/bootutil/include/bootutil/crypto/ecdsa.h +++ b/boot/bootutil/include/bootutil/crypto/ecdsa.h @@ -475,7 +475,7 @@ static int bootutil_ecdsa_parse_public_key(bootutil_ecdsa_context *ctx, } #endif /* !MCUBOOT_BUILTIN_KEY */ -#if !defined(CONFIG_NRF_BOOT_SIGNATURE_USING_ITS) +#if !defined(CONFIG_NCS_BOOT_SIGNATURE_USING_ITS) /* Verify the signature against the provided hash. The signature gets parsed from * the encoding first, then PSA Crypto has a dedicated API for ECDSA verification */ @@ -494,7 +494,7 @@ static inline int bootutil_ecdsa_verify(bootutil_ecdsa_context *ctx, return (int) psa_verify_hash(ctx->key_id, PSA_ALG_ECDSA(ctx->required_algorithm), hash, hlen, reformatted_signature, 2*ctx->curve_byte_count); } -#else /* !CONFIG_NRF_BOOT_SIGNATURE_USING_ITS */ +#else /* !CONFIG_NCS_BOOT_SIGNATURE_USING_ITS */ static const psa_key_id_t builtin_key_ids[] = { 0x40022100, @@ -541,7 +541,7 @@ static inline int bootutil_ecdsa_verify(bootutil_ecdsa_context *ctx, return status == PSA_SUCCESS ? 0 : 2; } -#endif /* !CONFIG_NRF_BOOT_SIGNATURE_USING_ITS */ +#endif /* !CONFIG_NCS_BOOT_SIGNATURE_USING_ITS */ #elif defined(MCUBOOT_USE_MBED_TLS) diff --git a/boot/zephyr/Kconfig b/boot/zephyr/Kconfig index 5aa3f0cd8..a46922eb2 100644 --- a/boot/zephyr/Kconfig +++ b/boot/zephyr/Kconfig @@ -435,14 +435,14 @@ config BOOT_KMU_KEYS_REVOCATION help Enabling KMU key revocation backend. -config NRF_BOOT_SIGNATURE_USING_ITS +config NCS_BOOT_SIGNATURE_USING_ITS bool "Use ITS stored keys for signature verification" depends on NRF_SECURITY help MCUboot will use keys provisioned to the internal trusted storage for signature verification instead of compiling in key data from a file. -if !BOOT_SIGNATURE_USING_KMU && !NRF_BOOT_SIGNATURE_USING_ITS +if !BOOT_SIGNATURE_USING_KMU && !NCS_BOOT_SIGNATURE_USING_ITS config BOOT_SIGNATURE_KEY_FILE string "PEM key file" diff --git a/boot/zephyr/include/mcuboot_config/mcuboot_config.h b/boot/zephyr/include/mcuboot_config/mcuboot_config.h index 6b5784c86..4fd821f85 100644 --- a/boot/zephyr/include/mcuboot_config/mcuboot_config.h +++ b/boot/zephyr/include/mcuboot_config/mcuboot_config.h @@ -68,7 +68,7 @@ #define MCUBOOT_HW_KEY #endif -#ifdef CONFIG_NRF_BOOT_SIGNATURE_USING_ITS +#ifdef CONFIG_NCS_BOOT_SIGNATURE_USING_ITS #define MCUBOOT_BUILTIN_KEY #endif From 335b6df85c2da36dd985b342456a7add5a35b564 Mon Sep 17 00:00:00 2001 From: Michal Kozikowski Date: Fri, 22 Aug 2025 12:59:08 +0200 Subject: [PATCH 363/420] [nrf noup] Support for ed25519 signature verification using ITS Thic commit introduces support for ed25519 signature verification when CONFIG_NCS_BOOT_SIGNATURE_USING_ITS is set (through PSA API). Signed-off-by: Michal Kozikowski (cherry picked from commit 227eb0a50d1b1fa52f853b2cc4ff1e8cca4bbf71) --- boot/bootutil/src/ed25519_psa.c | 38 ++++++++++++++++++++---------- boot/bootutil/src/image_ed25519.c | 6 +++-- boot/bootutil/src/image_validate.c | 6 ++--- 3 files changed, 32 insertions(+), 18 deletions(-) diff --git a/boot/bootutil/src/ed25519_psa.c b/boot/bootutil/src/ed25519_psa.c index 6393d996e..8460da7c8 100644 --- a/boot/bootutil/src/ed25519_psa.c +++ b/boot/bootutil/src/ed25519_psa.c @@ -26,22 +26,35 @@ BOOT_LOG_MODULE_REGISTER(ed25519_psa); #if defined(CONFIG_BOOT_SIGNATURE_USING_KMU) /* List of KMU stored key ids available for MCUboot */ #define MAKE_PSA_KMU_KEY_ID(id) PSA_KEY_HANDLE_FROM_CRACEN_KMU_SLOT(CRACEN_KMU_KEY_USAGE_SCHEME_RAW, id) -static psa_key_id_t kmu_key_ids[3] = { +static psa_key_id_t key_ids[] = { MAKE_PSA_KMU_KEY_ID(226), MAKE_PSA_KMU_KEY_ID(228), MAKE_PSA_KMU_KEY_ID(230) }; +#define KEY_SLOTS_COUNT CONFIG_BOOT_SIGNATURE_KMU_SLOTS + #if defined(CONFIG_BOOT_KMU_KEYS_REVOCATION) #include static psa_key_id_t *validated_with = NULL; #endif -BUILD_ASSERT(CONFIG_BOOT_SIGNATURE_KMU_SLOTS <= ARRAY_SIZE(kmu_key_ids), +BUILD_ASSERT(CONFIG_BOOT_SIGNATURE_KMU_SLOTS <= ARRAY_SIZE(key_ids), "Invalid number of KMU slots, up to 3 are supported on nRF54L15"); #endif -#if !defined(CONFIG_BOOT_SIGNATURE_USING_KMU) +#if defined(CONFIG_NCS_BOOT_SIGNATURE_USING_ITS) +static const psa_key_id_t key_ids[] = { + 0x40022100, + 0x40022101, + 0x40022102, + 0x40022103 +}; + +#define KEY_SLOTS_COUNT ARRAY_SIZE(key_ids) +#endif + +#if !defined(CONFIG_BOOT_SIGNATURE_USING_KMU) && !defined(CONFIG_NCS_BOOT_SIGNATURE_USING_ITS) int ED25519_verify(const uint8_t *message, size_t message_len, const uint8_t signature[EDDSA_SIGNAGURE_LENGTH], const uint8_t public_key[EDDSA_KEY_LENGTH]) @@ -102,7 +115,6 @@ int ED25519_verify(const uint8_t *message, size_t message_len, ARG_UNUSED(public_key); /* Set to any error */ psa_status_t status = PSA_ERROR_BAD_STATE; - int ret = 0; /* Fail by default */ /* Initialize PSA Crypto */ status = psa_crypto_init(); @@ -113,24 +125,24 @@ int ED25519_verify(const uint8_t *message, size_t message_len, status = PSA_ERROR_BAD_STATE; - for (int i = 0; i < CONFIG_BOOT_SIGNATURE_KMU_SLOTS; ++i) { - psa_key_id_t kid = kmu_key_ids[i]; + for (int i = 0; i < KEY_SLOTS_COUNT; ++i) { + psa_key_id_t kid = key_ids[i]; status = psa_verify_message(kid, PSA_ALG_PURE_EDDSA, message, message_len, signature, EDDSA_SIGNAGURE_LENGTH); if (status == PSA_SUCCESS) { - ret = 1; #if defined(CONFIG_BOOT_KMU_KEYS_REVOCATION) - validated_with = kmu_key_ids + i; + validated_with = key_ids + i; #endif - break; + return 1; } - BOOT_LOG_ERR("ED25519 signature verification failed %d", status); } - return ret; + BOOT_LOG_ERR("ED25519 signature verification failed %d", status); + + return 0; } #if defined(CONFIG_BOOT_KMU_KEYS_REVOCATION) int exec_revoke(void) @@ -149,12 +161,12 @@ int exec_revoke(void) goto out; } for (int i = 0; i < CONFIG_BOOT_SIGNATURE_KMU_SLOTS; i++) { - if ((kmu_key_ids + i) == validated_with) { + if ((key_ids + i) == validated_with) { break; } BOOT_LOG_DBG("Invalidating key ID %d", i); - status = psa_destroy_key(kmu_key_ids[i]); + status = psa_destroy_key(key_ids[i]); if (status == PSA_SUCCESS) { BOOT_LOG_DBG("Success on key ID %d", i); } else { diff --git a/boot/bootutil/src/image_ed25519.c b/boot/bootutil/src/image_ed25519.c index 1a02811e3..177550749 100644 --- a/boot/bootutil/src/image_ed25519.c +++ b/boot/bootutil/src/image_ed25519.c @@ -36,6 +36,7 @@ extern int ED25519_verify(const uint8_t *message, size_t message_len, #if !defined(CONFIG_BOOT_SIGNATURE_USING_KMU) #if !defined(MCUBOOT_KEY_IMPORT_BYPASS_ASN) +#if !defined(CONFIG_NCS_BOOT_SIGNATURE_USING_ITS) /* * Parse the public key used for signing. */ @@ -78,6 +79,7 @@ bootutil_import_key(uint8_t **cp, uint8_t *end) } #endif /* !defined(MCUBOOT_KEY_IMPORT_BYPASS_ASN) */ #endif +#endif /* Signature verification base function. * The function takes buffer of specified length and tries to verify @@ -93,7 +95,7 @@ bootutil_verify(uint8_t *buf, uint32_t blen, int rc; FIH_DECLARE(fih_rc, FIH_FAILURE); uint8_t *pubkey = NULL; -#if !defined(CONFIG_BOOT_SIGNATURE_USING_KMU) +#if !defined(CONFIG_BOOT_SIGNATURE_USING_KMU) && !defined(CONFIG_NCS_BOOT_SIGNATURE_USING_ITS) uint8_t *end; #endif @@ -106,7 +108,7 @@ bootutil_verify(uint8_t *buf, uint32_t blen, goto out; } -#if !defined(CONFIG_BOOT_SIGNATURE_USING_KMU) +#if !defined(CONFIG_BOOT_SIGNATURE_USING_KMU) && !defined(CONFIG_NCS_BOOT_SIGNATURE_USING_ITS) pubkey = (uint8_t *)bootutil_keys[key_id].key; end = pubkey + *bootutil_keys[key_id].len; diff --git a/boot/bootutil/src/image_validate.c b/boot/bootutil/src/image_validate.c index fd1a6a925..efa1c1363 100644 --- a/boot/bootutil/src/image_validate.c +++ b/boot/bootutil/src/image_validate.c @@ -541,13 +541,13 @@ bootutil_img_validate(struct boot_loader_state *state, case EXPECTED_SIG_TLV: { BOOT_LOG_DBG("bootutil_img_validate: EXPECTED_SIG_TLV == %d", EXPECTED_SIG_TLV); -#if !defined(CONFIG_BOOT_SIGNATURE_USING_KMU) +#if !defined(CONFIG_BOOT_SIGNATURE_USING_KMU) && !defined(CONFIG_NCS_BOOT_SIGNATURE_USING_ITS) /* Ignore this signature if it is out of bounds. */ if (key_id < 0 || key_id >= bootutil_key_cnt) { key_id = -1; continue; } -#endif /* !defined(CONFIG_BOOT_SIGNATURE_USING_KMU) */ +#endif /* !defined(CONFIG_BOOT_SIGNATURE_USING_KMU) && !defined(CONFIG_NCS_BOOT_SIGNATURE_USING_ITS) */ if (!EXPECTED_SIG_LEN(len) || len > sizeof(buf)) { rc = -1; goto out; @@ -864,7 +864,7 @@ bootutil_img_validate(struct boot_loader_state *state, if (type == IMAGE_TLV_DECOMP_SIGNATURE) { /* Ignore this signature if it is out of bounds. */ -#if !defined(CONFIG_BOOT_SIGNATURE_USING_KMU) +#if !defined(CONFIG_BOOT_SIGNATURE_USING_KMU) && !defined(CONFIG_NCS_BOOT_SIGNATURE_USING_ITS) if (key_id < 0 || key_id >= bootutil_key_cnt) { key_id = -1; continue; From 2c3b2be77b5e5e5a294f494e1c5ab02da4845888 Mon Sep 17 00:00:00 2001 From: Tomasz Chyrowicz Date: Fri, 5 Sep 2025 15:49:29 +0200 Subject: [PATCH 364/420] [nrf noup] zephyr: Add basic UUID checks implementation Provide an implementation for MCUboot UUID checks that specify a single, common vendor identifier and a unique class identifier for each image. Ref: NCSDK-34175 Signed-off-by: Tomasz Chyrowicz (cherry picked from commit 25f49810540e2ef2cba43ef8388ea78418f642d0) --- boot/zephyr/CMakeLists.txt | 3 ++ boot/zephyr/Kconfig | 2 + boot/zephyr/uuid/CMakeLists.txt | 74 ++++++++++++++++++++++++++ boot/zephyr/uuid/Kconfig | 55 +++++++++++++++++++ boot/zephyr/uuid/Kconfig.uuid.template | 29 ++++++++++ boot/zephyr/uuid/uuid.c | 74 ++++++++++++++++++++++++++ 6 files changed, 237 insertions(+) create mode 100644 boot/zephyr/uuid/CMakeLists.txt create mode 100644 boot/zephyr/uuid/Kconfig create mode 100644 boot/zephyr/uuid/Kconfig.uuid.template create mode 100644 boot/zephyr/uuid/uuid.c diff --git a/boot/zephyr/CMakeLists.txt b/boot/zephyr/CMakeLists.txt index 01da13a89..866364cd7 100644 --- a/boot/zephyr/CMakeLists.txt +++ b/boot/zephyr/CMakeLists.txt @@ -51,6 +51,9 @@ if(CONFIG_BOOT_USE_NRF_CC310_BL) endif() endif() +# Include the UUID generation code +add_subdirectory(uuid) + zephyr_library_include_directories( include ) diff --git a/boot/zephyr/Kconfig b/boot/zephyr/Kconfig index a46922eb2..92c27aed7 100644 --- a/boot/zephyr/Kconfig +++ b/boot/zephyr/Kconfig @@ -1158,6 +1158,8 @@ config MCUBOOT_UUID_CID Provide an image class identification scheme to prevent processing images for a different CPU or device produced by the same vendor. +rsource "uuid/Kconfig" + config BOOT_WATCHDOG_FEED bool "Feed the watchdog while doing swap" default y if WATCHDOG diff --git a/boot/zephyr/uuid/CMakeLists.txt b/boot/zephyr/uuid/CMakeLists.txt new file mode 100644 index 000000000..2f5dde2fc --- /dev/null +++ b/boot/zephyr/uuid/CMakeLists.txt @@ -0,0 +1,74 @@ +# +# Copyright (c) 2025 Nordic Semiconductor ASA +# +# SPDX-License-Identifier: LicenseRef-Nordic-5-Clause +# + +if(CONFIG_NCS_MCUBOOT_UUID_SINGLE_VID) + if(CONFIG_MCUBOOT_UUID_VID OR CONFIG_MCUBOOT_UUID_CID) + zephyr_library_sources( + uuid.c + ) + endif() + + # Generate VID value and raw value definition + if(CONFIG_MCUBOOT_UUID_VID OR CONFIG_MCUBOOT_UUID_CID) + if("${CONFIG_NCS_MCUBOOT_UUID_VID_VALUE}" STREQUAL "" AND CONFIG_MCUBOOT_UUID_VID) + message(WARNING "VID value not set") + return() + endif() + + string(REGEX MATCHALL "^([0-9A-F][0-9A-F]|\-)+$" match_parts "${CONFIG_NCS_MCUBOOT_UUID_VID_VALUE}") + if("${match_parts}" STREQUAL "${CONFIG_NCS_MCUBOOT_UUID_VID_VALUE}") + set(UUID_VID ${match_parts}) + else() + set(UUID_DNS_NAMESPACE 6ba7b810-9dad-11d1-80b4-00c04fd430c8) + string( + UUID UUID_VID + NAMESPACE ${UUID_DNS_NAMESPACE} + NAME ${CONFIG_NCS_MCUBOOT_UUID_VID_VALUE} + TYPE SHA1 UPPER + ) + endif() + + if(CONFIG_MCUBOOT_UUID_VID) + # Convert UUID into C array. + string(REGEX REPLACE "([0-9A-F][0-9A-F])\-?" "0x\\1, " UUID_VID_RAW "${UUID_VID}") + zephyr_compile_definitions(NCS_MCUBOOT_UUID_VID_VALUE=${UUID_VID_RAW}) + endif() + endif() + + # Generate VID value(s) and raw value definition(s) + if(CONFIG_MCUBOOT_UUID_CID) + set(MCUBOOT_IMAGES_COUNT ${CONFIG_UPDATEABLE_IMAGE_NUMBER}) + foreach(image_id RANGE ${MCUBOOT_IMAGES_COUNT}) + if(CONFIG_NCS_MCUBOOT_UUID_CID_IMAGE_${image_id}) + if("${CONFIG_NCS_MCUBOOT_UUID_CID_IMAGE_${image_id}_VALUE}" STREQUAL "") + message(WARNING "CID value not set for image ${image_id}") + return() + endif() + + # Check if RAW UUID format is used + string(REGEX MATCHALL "^([0-9A-F][0-9A-F]|\-)+$" match_parts "${CONFIG_NCS_MCUBOOT_UUID_CID_IMAGE_${image_id}_VALUE}") + if("${match_parts}" STREQUAL "${CONFIG_NCS_MCUBOOT_UUID_CID_IMAGE_${image_id}_VALUE}") + set(UUID_CID_IMAGE_${image_id} ${match_parts}) + elseif(NOT "${UUID_VID}" STREQUAL "") + # If not - generate UUID based on VID and CID values + string( + UUID UUID_CID_IMAGE_${image_id} + NAMESPACE ${UUID_VID} + NAME ${CONFIG_NCS_MCUBOOT_UUID_CID_IMAGE_${image_id}_VALUE} + TYPE SHA1 UPPER + ) + else() + message(WARNING "VID value not set, cannot generate CID for image ${image_id}") + return() + endif() + + # Convert UUID into C array. + string(REGEX REPLACE "([0-9A-F][0-9A-F])\-?" "0x\\1, " UUID_CID_IMAGE_${image_id}_RAW "${UUID_CID_IMAGE_${image_id}}") + zephyr_compile_definitions(NCS_MCUBOOT_UUID_CID_IMAGE_${image_id}_VALUE=${UUID_CID_IMAGE_${image_id}_RAW}) + endif() + endforeach() + endif() +endif() diff --git a/boot/zephyr/uuid/Kconfig b/boot/zephyr/uuid/Kconfig new file mode 100644 index 000000000..b6e4c66c2 --- /dev/null +++ b/boot/zephyr/uuid/Kconfig @@ -0,0 +1,55 @@ +# +# Copyright (c) 2025 Nordic Semiconductor ASA +# +# SPDX-License-Identifier: LicenseRef-Nordic-5-Clause +# + +if MCUBOOT_UUID_VID || MCUBOOT_UUID_CID + +menu "Vendor and image Class UUIDs" + +choice NCS_MCUBOOT_UUID_IMPLEMENTATION + prompt "UUID checks implementation" + default NCS_MCUBOOT_UUID_SINGLE_VID + +config NCS_MCUBOOT_UUID_SINGLE_VID + bool "Single VID and one CID per image" + help + This implementation allows to specify a single, common Vendor UUID + (VID) for all images and a unique Class UUID (CID) for each image. + +endchoice # NCS_MCUBOOT_UUID_IMPLEMENTATION + +if NCS_MCUBOOT_UUID_SINGLE_VID + +config NCS_MCUBOOT_UUID_VID_VALUE + string "Vendor name" + default "" + help + The vendor unique identifier. + The following formats are supported: + - Domain name (i.e. amce.corp) used to generate RFC 9562 UUID5 + identifier. + - Raw UUID (i.e. 12345678-1234-5678-1234-567812345678) + - Raw HEX UUID (i.e. 12345678123456781234567812345678) + +if MCUBOOT_UUID_CID + +image=0 +rsource "Kconfig.uuid.template" +image=1 +rsource "Kconfig.uuid.template" +image=2 +rsource "Kconfig.uuid.template" +image=3 +rsource "Kconfig.uuid.template" +image=4 +rsource "Kconfig.uuid.template" + +endif # MCUBOOT_UUID_CID + +endif # NCS_MCUBOOT_UUID_SINGLE_VID + +endmenu + +endif # MCUBOOT_UUID_VID || MCUBOOT_UUID_CID diff --git a/boot/zephyr/uuid/Kconfig.uuid.template b/boot/zephyr/uuid/Kconfig.uuid.template new file mode 100644 index 000000000..c916935c7 --- /dev/null +++ b/boot/zephyr/uuid/Kconfig.uuid.template @@ -0,0 +1,29 @@ +# +# Copyright (c) 2025 Nordic Semiconductor ASA +# +# SPDX-License-Identifier: LicenseRef-Nordic-5-Clause +# + +if UPDATEABLE_IMAGE_NUMBER > $(image) + +config NCS_MCUBOOT_UUID_CID_IMAGE_$(image)_VALUE + string "Image class name (image $(image))" + default "" + help + The image class unique identifier. + The following formats are supported: + - Image class name (i.e. nRF5340_door_lock_btperipheral). + This format requires NCS_MCUBOOT_UUID_VID_VALUE to be defined + as the VID UUID is used as the namespace for generating RFC 9562 + UUID5 identifier. + - Raw UUID (i.e. 12345678-1234-5678-1234-567812345678) + - Raw HEX UUID (i.e. 12345678123456781234567812345678) + +config NCS_MCUBOOT_UUID_CID_IMAGE_$(image) + bool + default y + depends on NCS_MCUBOOT_UUID_CID_IMAGE_$(image)_VALUE != "" + help + Helper symbol to simplify the active CId list generation. + +endif # UPDATEABLE_IMAGE_NUMBER > $(image) diff --git a/boot/zephyr/uuid/uuid.c b/boot/zephyr/uuid/uuid.c new file mode 100644 index 000000000..28b73bc1f --- /dev/null +++ b/boot/zephyr/uuid/uuid.c @@ -0,0 +1,74 @@ +/* + * Copyright (c) 2018 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: LicenseRef-Nordic-5-Clause + */ + +#include + +#define IMAGE_ID_COUNT CONFIG_UPDATEABLE_IMAGE_NUMBER +#define CID_INIT(index, label) \ + static const struct image_uuid label = {{ \ + NCS_MCUBOOT_UUID_CID_IMAGE_## index ##_VALUE \ + }} +#define CID_CONFIG(index) UTIL_CAT(CONFIG_NCS_MCUBOOT_UUID_CID_IMAGE_, index) +#define CID_DEFINE(index, prefix) \ + IF_ENABLED(CID_CONFIG(index), (CID_INIT(index, prefix##index))) + +#define CID_CONDITION(index, label) \ + if (image_id == index) { \ + *uuid_cid = &label; \ + FIH_RET(FIH_SUCCESS); \ + } +#define CID_CHECK(index, prefix) \ + IF_ENABLED(CID_CONFIG(index), (CID_CONDITION(index, prefix##index))) + +static fih_ret boot_uuid_compare(const struct image_uuid *uuid1, const struct image_uuid *uuid2) +{ + return fih_ret_encode_zero_equality(memcmp(uuid1->raw, uuid2->raw, + ARRAY_SIZE(uuid1->raw))); +} + +#ifdef CONFIG_MCUBOOT_UUID_CID +LISTIFY(IMAGE_ID_COUNT, CID_DEFINE, (;), uuid_cid_image_); + +static fih_ret boot_uuid_cid_get(uint32_t image_id, const struct image_uuid **uuid_cid) +{ + if (uuid_cid != NULL) { + LISTIFY(IMAGE_ID_COUNT, CID_CHECK, (), uuid_cid_image_) + } + + FIH_RET(FIH_FAILURE); +} +#endif /* CONFIG_MCUBOOT_UUID_CID */ + +fih_ret boot_uuid_init(void) +{ + FIH_RET(FIH_SUCCESS); +} + +#ifdef CONFIG_MCUBOOT_UUID_VID +fih_ret boot_uuid_vid_match(uint32_t image_id, const struct image_uuid *uuid_vid) +{ + const struct image_uuid uuid_vid_c = {{ + NCS_MCUBOOT_UUID_VID_VALUE + }}; + + return boot_uuid_compare(uuid_vid, &uuid_vid_c); +} +#endif /* CONFIG_MCUBOOT_UUID_VID */ + +#ifdef CONFIG_MCUBOOT_UUID_CID +fih_ret boot_uuid_cid_match(uint32_t image_id, const struct image_uuid *uuid_cid) +{ + FIH_DECLARE(ret_code, FIH_FAILURE); + const struct image_uuid *exp_uuid_cid = NULL; + + FIH_CALL(boot_uuid_cid_get, ret_code, image_id, &exp_uuid_cid); + if (FIH_NOT_EQ(ret_code, FIH_SUCCESS) && FIH_NOT_EQ(ret_code, FIH_FAILURE)) { + FIH_RET(FIH_FAILURE); + } + + return boot_uuid_compare(uuid_cid, exp_uuid_cid); +} +#endif /* CONFIG_MCUBOOT_UUID_CID */ From 3fc7ca5e12be700d42d552a6ee55078686dc4879 Mon Sep 17 00:00:00 2001 From: Artur Hadasz Date: Tue, 9 Sep 2025 12:42:37 +0200 Subject: [PATCH 365/420] [nrf noup] boot: Fix test failing with bootloader requests nrf-squash! [nrf noup] boot: Improve bootloader request handling Setting "test" for image was failing when using bootloader requests due to an incorrect value being returned from send_boot_request. Signed-off-by: Artur Hadasz (cherry picked from commit 7b333ffd5ba2d01b731f528f2be89864abbf7ca3) --- boot/bootutil/src/bootutil_public.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/boot/bootutil/src/bootutil_public.c b/boot/bootutil/src/bootutil_public.c index eac5beeeb..9686511f2 100644 --- a/boot/bootutil/src/bootutil_public.c +++ b/boot/bootutil/src/bootutil_public.c @@ -524,10 +524,12 @@ send_boot_request(uint8_t magic, uint8_t image_ok, bool confirm, int image_id, } else { rc = 0; } -#ifdef CONFIG_NCS_MCUBOOT_BOOT_REQUEST_TEST_SETS_BOOT_PREFERENCE } else { +#ifdef CONFIG_NCS_MCUBOOT_BOOT_REQUEST_TEST_SETS_BOOT_PREFERENCE BOOT_LOG_DBG("Set image preference: %d, %d", image_id, slot_id); rc = boot_request_set_preferred_slot(image_id, slot_id); +#else + rc = 0; #endif /* CONFIG_NCS_MCUBOOT_BOOT_REQUEST_TEST_SETS_BOOT_PREFERENCE */ } if (rc != 0) { From 4e25b7a914810c5583eab0327b842227bfc52940 Mon Sep 17 00:00:00 2001 From: Artur Hadasz Date: Thu, 11 Sep 2025 13:35:37 +0200 Subject: [PATCH 366/420] [nrf noup] bootloader: Fix logging in bootloader requests module nrf-squash! [nrf noup] bootloader: Add bootloader requests boot_request_retention.c could not be built if logs were disabled. Signed-off-by: Artur Hadasz (cherry picked from commit 26d9f6eaaf27abfb9ee4a2a062f666a4d87cfad0) --- boot/bootutil/zephyr/src/boot_request_retention.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/boot/bootutil/zephyr/src/boot_request_retention.c b/boot/bootutil/zephyr/src/boot_request_retention.c index 023f5af5e..234dfb5cf 100644 --- a/boot/bootutil/zephyr/src/boot_request_retention.c +++ b/boot/bootutil/zephyr/src/boot_request_retention.c @@ -14,7 +14,7 @@ /** Additional memory used by the retention subsystem (2B - prefix, 4B - CRC).*/ #define BOOT_REQUEST_ENTRY_METADATA_SIZE (2 + 4) -MCUBOOT_LOG_MODULE_REGISTER(bootloader_request); +BOOT_LOG_MODULE_REGISTER(bootloader_request); static const struct device *bootloader_request_dev = DEVICE_DT_GET(DT_CHOSEN(nrf_bootloader_request)); From cb297debeee5a5878c3e3be1b2466ba63772253b Mon Sep 17 00:00:00 2001 From: Dominik Ermel Date: Thu, 3 Jul 2025 17:50:21 +0000 Subject: [PATCH 367/420] [nrf noup] bootutil: Locking KMU keys Lock KMU keys before passing execution to application. Signed-off-by: Dominik Ermel (cherry picked from commit b6b46a782d503cc52b41672e096fb526daaac31c) --- boot/bootutil/src/ed25519_psa.c | 27 +++++++++++++++++++++++++++ boot/zephyr/include/nrf_cleanup.h | 11 +++++++++++ boot/zephyr/main.c | 7 +++++++ 3 files changed, 45 insertions(+) diff --git a/boot/bootutil/src/ed25519_psa.c b/boot/bootutil/src/ed25519_psa.c index 8460da7c8..3df1acbdd 100644 --- a/boot/bootutil/src/ed25519_psa.c +++ b/boot/bootutil/src/ed25519_psa.c @@ -177,4 +177,31 @@ int exec_revoke(void) return ret; } #endif /* CONFIG_BOOT_KMU_KEYS_REVOCATION */ + +void nrf_crypto_keys_housekeeping(void) +{ + psa_status_t status; + + /* We will continue through all keys, even if we have error while + * processing any of it. Only doing BOOT_LOG_DBG, as we do not + * really want to inform on failures to lock. + */ + for (int i = 0; i < CONFIG_BOOT_SIGNATURE_KMU_SLOTS; ++i) { + psa_key_attributes_t attr; + + status = psa_get_key_attributes(key_ids[i], &attr); + BOOT_LOG_DBG("KMU key 0x%x(%d) attr query status == %d", + key_ids[i], i, status); + + if (status == PSA_SUCCESS) { + status = cracen_kmu_block(&attr); + BOOT_LOG_DBG("KMU key lock status == %d", status); + } + + status = psa_purge_key(key_ids[i]); + BOOT_LOG_DBG("KMU key 0x%x(%d) purge status == %d", + key_ids[i], i, status); + } +} + #endif diff --git a/boot/zephyr/include/nrf_cleanup.h b/boot/zephyr/include/nrf_cleanup.h index 9e87e13f5..8cd8fe377 100644 --- a/boot/zephyr/include/nrf_cleanup.h +++ b/boot/zephyr/include/nrf_cleanup.h @@ -21,4 +21,15 @@ void nrf_cleanup_peripheral(void); */ void nrf_cleanup_ns_ram(void); +/** + * Crypto key storage housekeeping. Intended to clean up key objects from + * crypto backend and apply key policies that should take effect after + * MCUboot no longer needs access to keys. + */ +#if defined(CONFIG_BOOT_SIGNATURE_USING_KMU) +extern void nrf_crypto_keys_housekeeping(void); +#else +#define nrf_crypto_keys_housekeeping() do {} while (0) +#endif + #endif diff --git a/boot/zephyr/main.c b/boot/zephyr/main.c index bc4fc314c..643f88836 100644 --- a/boot/zephyr/main.c +++ b/boot/zephyr/main.c @@ -839,6 +839,13 @@ int main(void) mcuboot_status_change(MCUBOOT_STATUS_BOOTABLE_IMAGE_FOUND); + /* From this point MCUboot does not need access to crypto keys. + * Clean up backend key objects and apply key access policies that + * will take effect from now through entire boot session and application + * run. + */ + nrf_crypto_keys_housekeeping(); + #if USE_PARTITION_MANAGER && CONFIG_FPROTECT #ifdef PM_S1_ADDRESS From a5f3c93fe74fb1b07e634ab306a33b3461e69521 Mon Sep 17 00:00:00 2001 From: Andrzej Puzdrowski Date: Fri, 1 Aug 2025 18:00:14 +0200 Subject: [PATCH 368/420] [nrf noup] boot/zephyr: nRF54h20 resume from S2RAM (hardened) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Application need special support in the bootloader in order to resume for suspend to RAM. MCUboot is immediate actor which redirects execution to the application (application reset vector) when wake-up from S2RAM is detected. Detection is based on HW (NRF_RESETINFO) and hardened using additional check over independent source of truth (variable with magic value). Thanks to above the application is resuming using its routines - instead of mocking that by routines compiled in by the MCUboot. Implementation is able to support only MCUboot modes with a swap. Direct-XIP is not handled as it require a way to run-time recognization of active application slot. Signed-off-by: Karol Lasończyk Signed-off-by: Tomasz Chyrowicz Signed-off-by: Andrzej Puzdrowski (cherry picked from commit b26db4dc3b8e937b4d9b3fee733f95f1902e7c7f) --- boot/zephyr/CMakeLists.txt | 4 ++ boot/zephyr/nrf54h20_custom_s2ram.c | 97 +++++++++++++++++++++++++++++ 2 files changed, 101 insertions(+) create mode 100644 boot/zephyr/nrf54h20_custom_s2ram.c diff --git a/boot/zephyr/CMakeLists.txt b/boot/zephyr/CMakeLists.txt index 866364cd7..6bd93f35a 100644 --- a/boot/zephyr/CMakeLists.txt +++ b/boot/zephyr/CMakeLists.txt @@ -496,6 +496,10 @@ if(CONFIG_MCUBOOT_CLEANUP_ARM_CORE) ) endif() +if(CONFIG_SOC_NRF54H20_PM_S2RAM_OVERRIDE) + zephyr_library_sources(${BOOT_DIR}/zephyr/nrf54h20_custom_s2ram.c) +endif() + if(CONFIG_MCUBOOT_BOOT_BANNER) # Replace Zephyr's boot banner with the MCUboot one zephyr_sources(kernel/banner.c) diff --git a/boot/zephyr/nrf54h20_custom_s2ram.c b/boot/zephyr/nrf54h20_custom_s2ram.c new file mode 100644 index 000000000..7b70e22fe --- /dev/null +++ b/boot/zephyr/nrf54h20_custom_s2ram.c @@ -0,0 +1,97 @@ +/* + * Copyright (c) 2025 Nordic Semiconductor ASA + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +#include +#include "pm_s2ram.h" +#include "power.h" + +#include +#include + +#include "bootutil/fault_injection_hardening.h" + +#if DT_NODE_EXISTS(DT_NODELABEL(mcuboot_s2ram)) &&\ + DT_NODE_HAS_COMPAT(DT_NODELABEL(mcuboot_s2ram), zephyr_memory_region) +/* Linker section name is given by `zephyr,memory-region` property of + * `zephyr,memory-region` compatible DT node with nodelabel `mcuboot_s2ram`. + */ +__attribute__((section(DT_PROP(DT_NODELABEL(mcuboot_s2ram), zephyr_memory_region)))) +volatile struct mcuboot_resume_s mcuboot_resume; +#else +#error "mcuboot resume support section not defined in dts" +#endif + +#define FIXED_PARTITION_ADDR(node_label) \ + (DT_REG_ADDR(DT_NODELABEL(node_label)) + \ + COND_CODE_0(DT_FIXED_PARTITION_EXISTS(DT_NODELABEL(node_label)), (0), \ + (DT_REG_ADDR(DT_GPARENT(DT_NODELABEL(node_label)))))) + + +int soc_s2ram_suspend(pm_s2ram_system_off_fn_t system_off) +{ + (void)(system_off); + return -1; +} + +void pm_s2ram_mark_set(void) +{ + /* empty */ +} + +struct arm_vector_table { + uint32_t msp; + uint32_t reset; +}; + +/* This could be read from slot's image_header.ih_hdr_size, but immediate value + * is much faster to reach + */ +#define APP_EXE_START_OFFSET 0x800 /* nRF54H20 */ + +bool pm_s2ram_mark_check_and_clear(void) +{ + uint32_t reset_reason = nrf_resetinfo_resetreas_local_get(NRF_RESETINFO); + + if (reset_reason != NRF_RESETINFO_RESETREAS_LOCAL_UNRETAINED_MASK) { + /* Normal boot */ + return false; + } + + /* S2RAM resume expected, do doublecheck */ + if (mcuboot_resume.magic == MCUBOOT_S2RAM_RESUME_MAGIC) { + /* clear magic to avoid accidental reuse */ + mcuboot_resume.magic = 0; + } else { + /* magic not valid, normal boot */ + goto resume_failed; + } + + /* s2ram boot */ + struct arm_vector_table *vt; + vt = (struct arm_vector_table *) + (FIXED_PARTITION_ADDR(slot0_partition) + APP_EXE_START_OFFSET); + + /* Jump to application */ + __asm__ volatile ( + /* vt->reset -> r0 */ + " mov r0, %0\n" + /* vt->msp -> r1 */ + " mov r1, %1\n" + /* set stack pointer */ + " msr msp, r1\n" + /* jump to reset vector of an app */ + " bx r0\n" + : + : "r" (vt->reset), "r" (vt->msp) + : "r0", "r1", "memory" + ); + +resume_failed: + FIH_PANIC; + + return true; +} From ea35f98c24e5a8897f726bfd99d6b3bdd16017af Mon Sep 17 00:00:00 2001 From: Andrzej Puzdrowski Date: Tue, 9 Sep 2025 17:01:37 +0200 Subject: [PATCH 369/420] [nrf noup] boot/zephyr/socs: nrf54h20 prj.conf for S2RAM Added configuration which pre-configures MCUboot so It is able to support operation of resuming the App from S2RAM by the application itself. Signed-off-by: Andrzej Puzdrowski (cherry picked from commit c39029507179e3e1707eb46ca002a0780bb5b5b4) --- boot/zephyr/socs/nrf54h20_cpuapp.conf | 13 +++++++++++++ 1 file changed, 13 insertions(+) create mode 100644 boot/zephyr/socs/nrf54h20_cpuapp.conf diff --git a/boot/zephyr/socs/nrf54h20_cpuapp.conf b/boot/zephyr/socs/nrf54h20_cpuapp.conf new file mode 100644 index 000000000..09ccb19b2 --- /dev/null +++ b/boot/zephyr/socs/nrf54h20_cpuapp.conf @@ -0,0 +1,13 @@ +# Copyright (c) 2025 Nordic Semiconductor ASA +# +# SPDX-License-Identifier: Apache-2.0 +# + +# Configuration which is needed for supporting resume the application execution +# after suspend to RAM (S2RAM) requested by the application. +# MCUboot does not support S2RAM itself, but serves as an immediate actor while waking up +# from suspension. +CONFIG_PM=y +CONFIG_PM_S2RAM=y +CONFIG_PM_S2RAM_CUSTOM_MARKING=y +CONFIG_SOC_NRF54H20_PM_S2RAM_OVERRIDE=y From b8200d359f216440ae1ba0f41b577075508122e3 Mon Sep 17 00:00:00 2001 From: Kari Hamalainen Date: Tue, 16 Sep 2025 17:22:26 +0300 Subject: [PATCH 370/420] [nrf noup] ci: add reopen for manifest-pr action Previously reopening of PR did not reopen manifest PR. This commit will enable reopening of manifest PR in such case. Signed-off-by: Kari Hamalainen (cherry picked from commit d0796dc9b79833eb4fccd0af8fc7c969ea8a0de5) --- .github/workflows/manifest-PR.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/manifest-PR.yml b/.github/workflows/manifest-PR.yml index a871aa381..473301146 100644 --- a/.github/workflows/manifest-PR.yml +++ b/.github/workflows/manifest-PR.yml @@ -1,7 +1,7 @@ name: handle manifest PR on: pull_request_target: - types: [opened, synchronize, closed] + types: [opened, synchronize, closed, reopened] branches: - main From 0d5b49de2308449a4a9ba16f84887b7342b8701a Mon Sep 17 00:00:00 2001 From: Dominik Ermel Date: Tue, 9 Sep 2025 12:43:14 +0000 Subject: [PATCH 371/420] [nrf noup] bootutil: Remove bootutil_find_key from code nrf-squash! [nrf noup] bootutil: Add support for KMU stored ED25519 signature key It is now only provided by bootutil_find_key.c. Signed-off-by: Dominik Ermel --- boot/bootutil/src/image_validate.c | 69 ------------------------------ 1 file changed, 69 deletions(-) diff --git a/boot/bootutil/src/image_validate.c b/boot/bootutil/src/image_validate.c index efa1c1363..16ff9c09c 100644 --- a/boot/bootutil/src/image_validate.c +++ b/boot/bootutil/src/image_validate.c @@ -118,76 +118,7 @@ BOOT_LOG_MODULE_DECLARE(mcuboot); # define KEY_BUF_SIZE (SIG_BUF_SIZE + 24) #endif /* !MCUBOOT_HW_KEY */ -#if !defined(CONFIG_BOOT_SIGNATURE_USING_KMU) -#if !defined(MCUBOOT_HW_KEY) -static int -bootutil_find_key(uint8_t *keyhash, uint8_t keyhash_len) -{ - bootutil_sha_context sha_ctx; - int i; - const struct bootutil_key *key; - uint8_t hash[IMAGE_HASH_SIZE]; - - BOOT_LOG_DBG("bootutil_find_key"); - - if (keyhash_len > IMAGE_HASH_SIZE) { - return -1; - } - - for (i = 0; i < bootutil_key_cnt; i++) { - key = &bootutil_keys[i]; - bootutil_sha_init(&sha_ctx); - bootutil_sha_update(&sha_ctx, key->key, *key->len); - bootutil_sha_finish(&sha_ctx, hash); - bootutil_sha_drop(&sha_ctx); - if (!memcmp(hash, keyhash, keyhash_len)) { - return i; - } - } - return -1; -} -#else /* !MCUBOOT_HW_KEY */ -extern unsigned int pub_key_len; -static int -bootutil_find_key(uint8_t image_index, uint8_t *key, uint16_t key_len) -{ - bootutil_sha_context sha_ctx; - uint8_t hash[IMAGE_HASH_SIZE]; - uint8_t key_hash[IMAGE_HASH_SIZE]; - size_t key_hash_size = sizeof(key_hash); - int rc; - FIH_DECLARE(fih_rc, FIH_FAILURE); - - BOOT_LOG_DBG("bootutil_find_key: image_index %d", image_index); - - bootutil_sha_init(&sha_ctx); - bootutil_sha_update(&sha_ctx, key, key_len); - bootutil_sha_finish(&sha_ctx, hash); - bootutil_sha_drop(&sha_ctx); - - rc = boot_retrieve_public_key_hash(image_index, key_hash, &key_hash_size); - if (rc) { - return -1; - } - - /* Adding hardening to avoid this potential attack: - * - Image is signed with an arbitrary key and the corresponding public - * key is added as a TLV field. - * - During public key validation (comparing against key-hash read from - * HW) a fault is injected to accept the public key as valid one. - */ - FIH_CALL(boot_fih_memequal, fih_rc, hash, key_hash, key_hash_size); - if (FIH_EQ(fih_rc, FIH_SUCCESS)) { - bootutil_keys[0].key = key; - pub_key_len = key_len; - return 0; - } - - return -1; -} -#endif /* !MCUBOOT_HW_KEY */ #endif /* !MCUBOOT_BUILTIN_KEY */ -#endif /* !defined(CONFIG_BOOT_SIGNATURE_USING_KMU) */ #endif /* EXPECTED_SIG_TLV */ #if defined(MCUBOOT_SIGN_PURE) From 98b9e4b76abf89e5feb8df4b08a794d50c0cbaa8 Mon Sep 17 00:00:00 2001 From: Dominik Ermel Date: Tue, 9 Sep 2025 12:49:03 +0000 Subject: [PATCH 372/420] [nrf noup] loader: Use BOOT_SLOT_PRIMARY and BOOT_SLOT_SECONDARY MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit nrf-squash! [nrf noup] loader: Add firmware version check downgrade prevention The commit replaces BOOT_PRIMARY_SLOT and BOOT_SECONDARY_SLOT with BOOT_SLOT_PRIMARY and BOOT_SLOT_SECONDARY respectively. Signed-off-by: Dominik Ermel --- boot/bootutil/src/loader.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/boot/bootutil/src/loader.c b/boot/bootutil/src/loader.c index 043d2cd0f..a16bbe1f3 100644 --- a/boot/bootutil/src/loader.c +++ b/boot/bootutil/src/loader.c @@ -1071,11 +1071,11 @@ boot_validate_slot(struct boot_loader_state *state, int slot, #if defined(CONFIG_SOC_NRF5340_CPUAPP) && defined(CONFIG_NRF53_MULTI_IMAGE_UPDATE) \ && defined(CONFIG_PCD_APP) && defined(CONFIG_PCD_READ_NETCORE_APP_VERSION) if (BOOT_CURR_IMG(state) == CONFIG_MCUBOOT_NETWORK_CORE_IMAGE_NUMBER) { - rc = pcd_version_cmp_net(fap, boot_img_hdr(state, BOOT_SECONDARY_SLOT)); + rc = pcd_version_cmp_net(fap, boot_img_hdr(state, BOOT_SLOT_SECONDARY)); } else { rc = boot_version_cmp( - &boot_img_hdr(state, BOOT_SECONDARY_SLOT)->ih_ver, - &boot_img_hdr(state, BOOT_PRIMARY_SLOT)->ih_ver); + &boot_img_hdr(state, BOOT_SLOT_SECONDARY)->ih_ver, + &boot_img_hdr(state, BOOT_SLOT_PRIMARY)->ih_ver); #if CONFIG_MCUBOOT_MCUBOOT_IMAGE_NUMBER != -1 if (rc >= 0 && BOOT_CURR_IMG(state) == CONFIG_MCUBOOT_MCUBOOT_IMAGE_NUMBER) { @@ -1096,8 +1096,8 @@ boot_validate_slot(struct boot_loader_state *state, int slot, } #else rc = boot_version_cmp( - &boot_img_hdr(state, BOOT_SECONDARY_SLOT)->ih_ver, - &boot_img_hdr(state, BOOT_PRIMARY_SLOT)->ih_ver); + &boot_img_hdr(state, BOOT_SLOT_SECONDARY)->ih_ver, + &boot_img_hdr(state, BOOT_SLOT_PRIMARY)->ih_ver); #if CONFIG_MCUBOOT_MCUBOOT_IMAGE_NUMBER != -1 if (rc >= 0 && BOOT_CURR_IMG(state) == CONFIG_MCUBOOT_MCUBOOT_IMAGE_NUMBER) { @@ -1116,7 +1116,7 @@ boot_validate_slot(struct boot_loader_state *state, int slot, } #endif #endif - if (rc < 0 && boot_check_header_erased(state, BOOT_PRIMARY_SLOT)) { + if (rc < 0 && boot_check_header_erased(state, BOOT_SLOT_PRIMARY)) { BOOT_LOG_ERR("insufficient version in secondary slot"); boot_scramble_slot(fap, slot); /* Image in the secondary slot does not satisfy version requirement. From 72179c9d2d49766b5e896ebc7ad40f135ab49f7b Mon Sep 17 00:00:00 2001 From: Dominik Ermel Date: Tue, 9 Sep 2025 12:53:04 +0000 Subject: [PATCH 373/420] [nrf noup] loader: Use BOOT_SLOT_PRIMARY and BOOT_SLOT_SECONDARY fixup! [nrf noup] boot: bootutil: loader: Add s0/s1 checking of MCUboot image The commit replaces BOOT_PRIMARY_SLOT and BOOT_SECONDARY_SLOT with BOOT_SLOT_PRIMARY and BOOT_SLOT_SECONDARY respectively. Signed-off-by: Dominik Ermel --- boot/bootutil/src/loader.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/boot/bootutil/src/loader.c b/boot/bootutil/src/loader.c index a16bbe1f3..c2d49e6a9 100644 --- a/boot/bootutil/src/loader.c +++ b/boot/bootutil/src/loader.c @@ -1084,7 +1084,7 @@ boot_validate_slot(struct boot_loader_state *state, int slot, */ int version_check; - version_check = boot_version_cmp(&boot_img_hdr(state, BOOT_SECONDARY_SLOT)->ih_ver, + version_check = boot_version_cmp(&boot_img_hdr(state, BOOT_SLOT_SECONDARY)->ih_ver, &mcuboot_s0_s1_image_version); /* Only update rc if the currently running version is newer */ @@ -1106,7 +1106,7 @@ boot_validate_slot(struct boot_loader_state *state, int slot, */ int version_check; - version_check = boot_version_cmp(&boot_img_hdr(state, BOOT_SECONDARY_SLOT)->ih_ver, + version_check = boot_version_cmp(&boot_img_hdr(state, BOOT_SLOT_SECONDARY)->ih_ver, &mcuboot_s0_s1_image_version); /* Only update rc if the currently running version is newer */ From 61083522148044647811a53f418aee5b9ed6fb69 Mon Sep 17 00:00:00 2001 From: Dominik Ermel Date: Tue, 9 Sep 2025 12:54:31 +0000 Subject: [PATCH 374/420] [nrf noup] loader: Use BOOT_SLOT_PRIMARY and BOOT_SLOT_SECONDARY nrf-squash! [nrf noup] loader: Do not check reset vector for XIP image The commit replaces BOOT_PRIMARY_SLOT and BOOT_SECONDARY_SLOT with BOOT_SLOT_PRIMARY and BOOT_SLOT_SECONDARY respectively. Signed-off-by: Dominik Ermel --- boot/bootutil/src/loader.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/boot/bootutil/src/loader.c b/boot/bootutil/src/loader.c index c2d49e6a9..f5b93302c 100644 --- a/boot/bootutil/src/loader.c +++ b/boot/bootutil/src/loader.c @@ -1167,12 +1167,12 @@ boot_validate_slot(struct boot_loader_state *state, int slot, * 0. This part of image is not bootable, as the XIP setup is done by the app in * image 0 slot, and it does not carry the reset vector. */ - if (fap == state->imgs[2][BOOT_SECONDARY_SLOT].area) { + if (fap == state->imgs[2][BOOT_SLOT_SECONDARY].area) { goto out; } #endif - if (fap == BOOT_IMG_AREA(state, BOOT_SECONDARY_SLOT)) { - const struct flash_area *pri_fa = BOOT_IMG_AREA(state, BOOT_PRIMARY_SLOT); + if (fap == BOOT_IMG_AREA(state, BOOT_SLOT_SECONDARY)) { + const struct flash_area *pri_fa = BOOT_IMG_AREA(state, BOOT_SLOT_PRIMARY); struct image_header *secondary_hdr = boot_img_hdr(state, slot); uint32_t reset_value = 0; uint32_t reset_addr = secondary_hdr->ih_hdr_size + sizeof(reset_value); From a72f4f326ad71fdf87d4b8cf8d61eda0ad7b698d Mon Sep 17 00:00:00 2001 From: Dominik Ermel Date: Tue, 9 Sep 2025 12:55:46 +0000 Subject: [PATCH 375/420] [nrf noup] loader: Use BOOT_SLOT_PRIMARY and BOOT_SLOT_SECONDARY nrf-squash! [nrf noup] loader: introduced cleanup of unusable secondary slot The commit replaces BOOT_PRIMARY_SLOT and BOOT_SECONDARY_SLOT with BOOT_SLOT_PRIMARY and BOOT_SLOT_SECONDARY respectively. Signed-off-by: Dominik Ermel --- boot/bootutil/src/loader.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/boot/bootutil/src/loader.c b/boot/bootutil/src/loader.c index f5b93302c..709753f55 100644 --- a/boot/bootutil/src/loader.c +++ b/boot/bootutil/src/loader.c @@ -1409,7 +1409,7 @@ static void sec_slot_cleanup_if_unusable(void) const struct flash_area *secondary_fa; int rc; - rc = flash_area_open(flash_area_id_from_multi_image_slot(idx, BOOT_SECONDARY_SLOT), + rc = flash_area_open(flash_area_id_from_multi_image_slot(idx, BOOT_SLOT_SECONDARY), &secondary_fa); if (!rc) { rc = flash_area_erase(secondary_fa, 0, secondary_fa->fa_size); From e72408e93097e42469cdc7a7bc7286b18a9d28f8 Mon Sep 17 00:00:00 2001 From: Dominik Ermel Date: Tue, 9 Sep 2025 13:01:49 +0000 Subject: [PATCH 376/420] [nrf noup] loader: Use BOOT_SLOT_PRIMARY and BOOT_SLOT_SECONDARY nrf-squash! [nrf noup] boot: nrf53-specific customizations The commit replaces BOOT_PRIMARY_SLOT and BOOT_SECONDARY_SLOT with BOOT_SLOT_PRIMARY and BOOT_SLOT_SECONDARY respectively. Signed-off-by: Dominik Ermel --- boot/bootutil/src/loader.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/boot/bootutil/src/loader.c b/boot/bootutil/src/loader.c index 709753f55..45603a292 100644 --- a/boot/bootutil/src/loader.c +++ b/boot/bootutil/src/loader.c @@ -1461,7 +1461,7 @@ boot_validated_swap_type(struct boot_loader_state *state, #if defined(PM_S1_ADDRESS) || defined(PM_CPUNET_B0N_ADDRESS) const struct flash_area *secondary_fa = - BOOT_IMG_AREA(state, BOOT_SECONDARY_SLOT); + BOOT_IMG_AREA(state, BOOT_SLOT_SECONDARY); struct image_header *hdr = boot_img_hdr(state, BOOT_SECONDARY_SLOT); uint32_t reset_addr = 0; int rc = 0; From 3b4341c427ddd921793b759a3be151bf8300dcc9 Mon Sep 17 00:00:00 2001 From: Dominik Ermel Date: Tue, 9 Sep 2025 13:03:19 +0000 Subject: [PATCH 377/420] [nrf noup] loader: Use BOOT_SLOT_PRIMARY and BOOT_SLOT_SECONDARY nrf-squash! [nrf noup] loader: Fix reading reset addr to support ext flash The commit replaces BOOT_PRIMARY_SLOT and BOOT_SECONDARY_SLOT with BOOT_SLOT_PRIMARY and BOOT_SLOT_SECONDARY respectively. Signed-off-by: Dominik Ermel --- boot/bootutil/src/loader.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/boot/bootutil/src/loader.c b/boot/bootutil/src/loader.c index 45603a292..ce21322e3 100644 --- a/boot/bootutil/src/loader.c +++ b/boot/bootutil/src/loader.c @@ -1462,7 +1462,7 @@ boot_validated_swap_type(struct boot_loader_state *state, #if defined(PM_S1_ADDRESS) || defined(PM_CPUNET_B0N_ADDRESS) const struct flash_area *secondary_fa = BOOT_IMG_AREA(state, BOOT_SLOT_SECONDARY); - struct image_header *hdr = boot_img_hdr(state, BOOT_SECONDARY_SLOT); + struct image_header *hdr = boot_img_hdr(state, BOOT_SLOT_SECONDARY); uint32_t reset_addr = 0; int rc = 0; /* Patch needed for NCS. Since image 0 (the app) and image 1 (the other From 98b6e78de31db132366252b89bc6b4001f9474d2 Mon Sep 17 00:00:00 2001 From: Dominik Ermel Date: Tue, 9 Sep 2025 13:04:17 +0000 Subject: [PATCH 378/420] [nrf noup] loader: Use BOOT_SLOT_PRIMARY and BOOT_SLOT_SECONDARY nrf-squash! [nrf noup] boot: Add support for NSIB and multi-image The commit replaces BOOT_PRIMARY_SLOT and BOOT_SECONDARY_SLOT with BOOT_SLOT_PRIMARY and BOOT_SLOT_SECONDARY respectively. Signed-off-by: Dominik Ermel --- boot/bootutil/src/loader.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/boot/bootutil/src/loader.c b/boot/bootutil/src/loader.c index ce21322e3..0d56b9713 100644 --- a/boot/bootutil/src/loader.c +++ b/boot/bootutil/src/loader.c @@ -1490,7 +1490,7 @@ boot_validated_swap_type(struct boot_loader_state *state, { const struct flash_area *primary_fa; rc = flash_area_open(flash_area_id_from_multi_image_slot( - BOOT_CURR_IMG(state), BOOT_PRIMARY_SLOT), + BOOT_CURR_IMG(state), BOOT_SLOT_PRIMARY), &primary_fa); if (rc != 0) { return BOOT_SWAP_TYPE_FAIL; From 2b997f2d434ce5c7e05ce087f896aea25592684a Mon Sep 17 00:00:00 2001 From: Dominik Ermel Date: Tue, 9 Sep 2025 13:05:52 +0000 Subject: [PATCH 379/420] [nrf noup] loader: Use BOOT_SLOT_PRIMARY and BOOT_SLOT_SECONDARY nrf-squash! [nrf noup] zephyr: Add support for compressed image updates The commit replaces BOOT_PRIMARY_SLOT and BOOT_SECONDARY_SLOT with BOOT_SLOT_PRIMARY and BOOT_SLOT_SECONDARY respectively. Signed-off-by: Dominik Ermel --- boot/bootutil/src/loader.c | 2 +- boot/zephyr/decompression.c | 12 ++++++------ 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/boot/bootutil/src/loader.c b/boot/bootutil/src/loader.c index 0d56b9713..3d86c6d67 100644 --- a/boot/bootutil/src/loader.c +++ b/boot/bootutil/src/loader.c @@ -1832,7 +1832,7 @@ boot_copy_region(struct boot_loader_state *state, #endif #ifdef MCUBOOT_DECOMPRESS_IMAGES - hdr = boot_img_hdr(state, BOOT_SECONDARY_SLOT); + hdr = boot_img_hdr(state, BOOT_SLOT_SECONDARY); if (MUST_DECOMPRESS(fap_src, BOOT_CURR_IMG(state), hdr)) { /* Use alternative function for compressed images */ diff --git a/boot/zephyr/decompression.c b/boot/zephyr/decompression.c index ce4fe0b2b..c8b279a75 100644 --- a/boot/zephyr/decompression.c +++ b/boot/zephyr/decompression.c @@ -64,24 +64,24 @@ bool boot_is_compressed_header_valid(const struct image_header *hdr, const struc uint32_t protected_tlvs_size; uint32_t decompressed_size; - primary_fa_id = flash_area_id_from_multi_image_slot(BOOT_CURR_IMG(state), BOOT_PRIMARY_SLOT); + primary_fa_id = flash_area_id_from_multi_image_slot(BOOT_CURR_IMG(state), BOOT_SLOT_PRIMARY); if (primary_fa_id == fap->fa_id) { BOOT_LOG_ERR("Primary slots cannot be compressed, image: %d", BOOT_CURR_IMG(state)); return false; } - if (BOOT_IMG_AREA(state, BOOT_PRIMARY_SLOT) == NULL) { + if (BOOT_IMG_AREA(state, BOOT_SLOT_PRIMARY) == NULL) { opened_flash_area = true; } - rc = flash_area_open(primary_fa_id, &BOOT_IMG_AREA(state, BOOT_PRIMARY_SLOT)); + rc = flash_area_open(primary_fa_id, &BOOT_IMG_AREA(state, BOOT_SLOT_PRIMARY)); assert(rc == 0); - size_check = flash_area_get_size(BOOT_IMG_AREA(state, BOOT_PRIMARY_SLOT)); + size_check = flash_area_get_size(BOOT_IMG_AREA(state, BOOT_SLOT_PRIMARY)); if (opened_flash_area) { - (void)flash_area_close(BOOT_IMG_AREA(state, BOOT_PRIMARY_SLOT)); + (void)flash_area_close(BOOT_IMG_AREA(state, BOOT_SLOT_PRIMARY)); } rc = bootutil_get_img_decomp_size(hdr, fap, &decompressed_size); @@ -1100,7 +1100,7 @@ int boot_copy_region_decompress(struct boot_loader_state *state, const struct fl uint8_t decryption_block_size = 0; #endif - hdr = boot_img_hdr(state, BOOT_SECONDARY_SLOT); + hdr = boot_img_hdr(state, BOOT_SLOT_SECONDARY); #ifdef MCUBOOT_ENC_IMAGES rc = bootutil_get_img_decrypted_comp_size(hdr, fap_src, &comp_size); From ea6bb5c467625b39fd3ad59775e08fe70889199d Mon Sep 17 00:00:00 2001 From: Dominik Ermel Date: Tue, 9 Sep 2025 13:06:49 +0000 Subject: [PATCH 380/420] [nrf noup] loader: Use BOOT_SLOT_PRIMARY and BOOT_SLOT_SECONDARY nrf-squash! [nrf noup] treewide: add NCS partition manager support The commit replaces BOOT_PRIMARY_SLOT and BOOT_SECONDARY_SLOT with BOOT_SLOT_PRIMARY and BOOT_SLOT_SECONDARY respectively. Signed-off-by: Dominik Ermel --- boot/bootutil/src/loader.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/boot/bootutil/src/loader.c b/boot/bootutil/src/loader.c index 3d86c6d67..9d5af212a 100644 --- a/boot/bootutil/src/loader.c +++ b/boot/bootutil/src/loader.c @@ -2951,7 +2951,7 @@ context_boot_go(struct boot_loader_state *state, struct boot_rsp *rsp) if (!image_validated_by_nsib) #endif { - FIH_CALL(boot_validate_slot, fih_rc, state, BOOT_PRIMARY_SLOT, NULL, 0); + FIH_CALL(boot_validate_slot, fih_rc, state, BOOT_SLOT_PRIMARY, NULL, 0); /* Check for all possible values is redundant in normal operation it * is meant to prevent FI attack. */ From a290437b3348209f18fe176d0b6d393062972d8e Mon Sep 17 00:00:00 2001 From: Dominik Ermel Date: Tue, 9 Sep 2025 13:07:45 +0000 Subject: [PATCH 381/420] [nrf noup] loader: Use BOOT_SLOT_PRIMARY and BOOT_SLOT_SECONDARY nrf-squash! [nrf noup] treewide: Add support for sysbuild assigned images The commit replaces BOOT_PRIMARY_SLOT and BOOT_SECONDARY_SLOT with BOOT_SLOT_PRIMARY and BOOT_SLOT_SECONDARY respectively. Signed-off-by: Dominik Ermel --- boot/bootutil/src/swap_nsib.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/boot/bootutil/src/swap_nsib.c b/boot/bootutil/src/swap_nsib.c index 079e193d5..f8d6e8a88 100644 --- a/boot/bootutil/src/swap_nsib.c +++ b/boot/bootutil/src/swap_nsib.c @@ -40,7 +40,7 @@ void nsib_swap_run(struct boot_loader_state *state, struct boot_status *bs) BOOT_LOG_INF("Starting swap using nsib algorithm."); - sector_sz = boot_img_sector_size(state, BOOT_SECONDARY_SLOT, 0); + sector_sz = boot_img_sector_size(state, BOOT_SLOT_SECONDARY, 0); #if (CONFIG_NCS_IS_VARIANT_IMAGE) rc = flash_area_open(PM_S0_ID, &fap_pri); From a9a760f896f2da81df41a118fde244974eb6b54b Mon Sep 17 00:00:00 2001 From: Jukka Rissanen Date: Mon, 15 Sep 2025 12:52:45 +0300 Subject: [PATCH 382/420] [nrf noup] loader: Too many params when calling bootutil_img_validate There was one extra parameter when calling bootutil_img_validate() so remove it. Signed-off-by: Jukka Rissanen --- boot/bootutil/src/loader.c | 5 ----- 1 file changed, 5 deletions(-) diff --git a/boot/bootutil/src/loader.c b/boot/bootutil/src/loader.c index 9d5af212a..232557414 100644 --- a/boot/bootutil/src/loader.c +++ b/boot/bootutil/src/loader.c @@ -773,13 +773,8 @@ boot_image_check(struct boot_loader_state *state, struct image_header *hdr, BOOT_LOG_DBG("Image validation attempt %d/%d", i, CONFIG_NCS_MCUBOOT_IMG_VALIDATE_ATTEMPT_COUNT); #endif /* CONFIG_NCS_MCUBOOT_IMG_VALIDATE_ATTEMPT_COUNT > 1 */ -#if defined(MCUBOOT_SWAP_USING_OFFSET) && defined(MCUBOOT_SERIAL_RECOVERY) - FIH_CALL(bootutil_img_validate, fih_rc, state, hdr, fap, tmpbuf, BOOT_TMPBUF_SZ, - NULL, 0, NULL, 0); -#else FIH_CALL(bootutil_img_validate, fih_rc, state, hdr, fap, tmpbuf, BOOT_TMPBUF_SZ, NULL, 0, NULL); -#endif if (FIH_EQ(fih_rc, FIH_SUCCESS)) { #if CONFIG_NCS_MCUBOOT_IMG_VALIDATE_ATTEMPT_COUNT > 1 From 347a912ae51966547060d44ff3081d7e1a695d42 Mon Sep 17 00:00:00 2001 From: Jamie McCrae Date: Tue, 16 Sep 2025 10:54:55 +0100 Subject: [PATCH 383/420] [nrf noup] boot: zephyr: Prevent old USB stack warning Prevents a deprecation warning from failing builds when the old USB stack is used for USB DFU or serial recovery modes Signed-off-by: Jamie McCrae --- boot/zephyr/Kconfig | 2 ++ boot/zephyr/Kconfig.serial_recovery | 1 + 2 files changed, 3 insertions(+) diff --git a/boot/zephyr/Kconfig b/boot/zephyr/Kconfig index 92c27aed7..1d3417270 100644 --- a/boot/zephyr/Kconfig +++ b/boot/zephyr/Kconfig @@ -1008,6 +1008,7 @@ config BOOT_USB_DFU_WAIT select IMG_MANAGER select STREAM_FLASH select MULTITHREADING + imply DEPRECATION_TEST help If y, MCUboot waits for a prescribed duration of time to allow for USB DFU to be invoked. Please note DFU always updates the @@ -1020,6 +1021,7 @@ config BOOT_USB_DFU_GPIO select IMG_MANAGER select STREAM_FLASH select MULTITHREADING + imply DEPRECATION_TEST help If y, MCUboot uses GPIO to detect whether to invoke USB DFU. diff --git a/boot/zephyr/Kconfig.serial_recovery b/boot/zephyr/Kconfig.serial_recovery index b6c71e5e0..c57e48197 100644 --- a/boot/zephyr/Kconfig.serial_recovery +++ b/boot/zephyr/Kconfig.serial_recovery @@ -38,6 +38,7 @@ config BOOT_SERIAL_UART config BOOT_SERIAL_CDC_ACM bool "CDC ACM" select USB_DEVICE_STACK + imply DEPRECATION_TEST help This setting will choose CDC ACM for serial recovery unless chosen "zephyr,uart-mcumgr" is present, in which case the chosen takes From e8ddb173eee7dbfd4d2b7b0d16c2882c3e2174c9 Mon Sep 17 00:00:00 2001 From: Jamie McCrae Date: Tue, 16 Sep 2025 11:48:53 +0100 Subject: [PATCH 384/420] [nrf noup] boot: bootutil: Fix b0 checks nrf-squash! [nrf noup] treewide: add NCS partition manager support Fixes invalid checks for b0 that would wrongly skip checking if partition sizes were valid for the non-b0 updates when b0 updates were generally enabled, and ports the check to swap using offset also Signed-off-by: Jamie McCrae --- boot/bootutil/src/swap_move.c | 23 ++++++++++++++++------- boot/bootutil/src/swap_offset.c | 22 ++++++++++++++++++++++ boot/bootutil/src/swap_scratch.c | 29 +++++++++++++++++++---------- 3 files changed, 57 insertions(+), 17 deletions(-) diff --git a/boot/bootutil/src/swap_move.c b/boot/bootutil/src/swap_move.c index 75dadfe91..a183ce8b0 100644 --- a/boot/bootutil/src/swap_move.c +++ b/boot/bootutil/src/swap_move.c @@ -230,6 +230,12 @@ boot_status_internal_off(const struct boot_status *bs, int elem_sz) int boot_slots_compatible(struct boot_loader_state *state) { + size_t num_sectors_pri; + size_t num_sectors_sec; + size_t sector_sz_pri = 0; + size_t sector_sz_sec = 0; + size_t i; + #ifdef PM_S1_ADDRESS /* Patch needed for NCS. In this case, image 1 primary points to the other * B1 slot (ie S0 or S1), and image 0 primary points to the app. @@ -240,13 +246,17 @@ boot_slots_compatible(struct boot_loader_state *state) * partition manager is in use, and since we have the same sector size * in all of our flash. */ +#if CONFIG_MCUBOOT_NETWORK_CORE_IMAGE_NUMBER != -1 + if (BOOT_CURR_IMG(state) == CONFIG_MCUBOOT_NETWORK_CORE_IMAGE_NUMBER) { return 1; -#else - size_t num_sectors_pri; - size_t num_sectors_sec; - size_t sector_sz_pri = 0; - size_t sector_sz_sec = 0; - size_t i; + } +#endif +#if CONFIG_MCUBOOT_MCUBOOT_IMAGE_NUMBER != -1 + if (BOOT_CURR_IMG(state) == CONFIG_MCUBOOT_MCUBOOT_IMAGE_NUMBER) { + return 1; + } +#endif +#endif num_sectors_pri = boot_img_num_sectors(state, BOOT_SLOT_PRIMARY); num_sectors_sec = boot_img_num_sectors(state, BOOT_SLOT_SECONDARY); @@ -307,7 +317,6 @@ boot_slots_compatible(struct boot_loader_state *state) } return 1; -#endif /* PM_S1_ADDRESS */ } #define BOOT_LOG_SWAP_STATE(area, state) \ diff --git a/boot/bootutil/src/swap_offset.c b/boot/bootutil/src/swap_offset.c index f0b2d0634..27862ea00 100644 --- a/boot/bootutil/src/swap_offset.c +++ b/boot/bootutil/src/swap_offset.c @@ -310,6 +310,28 @@ int boot_slots_compatible(struct boot_loader_state *state) size_t sector_sz_sec = 0; size_t i; +#ifdef PM_S1_ADDRESS + /* Patch needed for NCS. In this case, image 1 primary points to the other + * B1 slot (ie S0 or S1), and image 0 primary points to the app. + * With this configuration, image 0 and image 1 share the secondary slot. + * Hence, the primary slot of image 1 will be *smaller* than image 1's + * secondary slot. This is not allowed in upstream mcuboot, so we need + * this patch to allow it. Also, all of these checks are redundant when + * partition manager is in use, and since we have the same sector size + * in all of our flash. + */ +#if CONFIG_MCUBOOT_NETWORK_CORE_IMAGE_NUMBER != -1 + if (BOOT_CURR_IMG(state) == CONFIG_MCUBOOT_NETWORK_CORE_IMAGE_NUMBER) { + return 1; + } +#endif +#if CONFIG_MCUBOOT_MCUBOOT_IMAGE_NUMBER != -1 + if (BOOT_CURR_IMG(state) == CONFIG_MCUBOOT_MCUBOOT_IMAGE_NUMBER) { + return 1; + } +#endif +#endif + num_sectors_pri = boot_img_num_sectors(state, BOOT_SLOT_PRIMARY); num_sectors_sec = boot_img_num_sectors(state, BOOT_SLOT_SECONDARY); diff --git a/boot/bootutil/src/swap_scratch.c b/boot/bootutil/src/swap_scratch.c index f01f407b2..35fc8bf0c 100644 --- a/boot/bootutil/src/swap_scratch.c +++ b/boot/bootutil/src/swap_scratch.c @@ -271,6 +271,16 @@ boot_status_internal_off(const struct boot_status *bs, int elem_sz) int boot_slots_compatible(struct boot_loader_state *state) { + size_t num_sectors_primary; + size_t num_sectors_secondary; + size_t sz0, sz1; + size_t primary_slot_sz, secondary_slot_sz; +#ifndef MCUBOOT_OVERWRITE_ONLY + size_t scratch_sz; +#endif + size_t i, j; + int8_t smaller; + #ifdef PM_S1_ADDRESS /* Patch needed for NCS. In this case, image 1 primary points to the other * B1 slot (ie S0 or S1), and image 0 primary points to the app. @@ -281,17 +291,17 @@ boot_slots_compatible(struct boot_loader_state *state) * partition manager is in use, and since we have the same sector size * in all of our flash. */ +#if CONFIG_MCUBOOT_NETWORK_CORE_IMAGE_NUMBER != -1 + if (BOOT_CURR_IMG(state) == CONFIG_MCUBOOT_NETWORK_CORE_IMAGE_NUMBER) { return 1; -#else - size_t num_sectors_primary; - size_t num_sectors_secondary; - size_t sz0, sz1; - size_t primary_slot_sz, secondary_slot_sz; -#ifndef MCUBOOT_OVERWRITE_ONLY - size_t scratch_sz; + } +#endif +#if CONFIG_MCUBOOT_MCUBOOT_IMAGE_NUMBER != -1 + if (BOOT_CURR_IMG(state) == CONFIG_MCUBOOT_MCUBOOT_IMAGE_NUMBER) { + return 1; + } +#endif #endif - size_t i, j; - int8_t smaller; num_sectors_primary = boot_img_num_sectors(state, BOOT_SLOT_PRIMARY); num_sectors_secondary = boot_img_num_sectors(state, BOOT_SLOT_SECONDARY); @@ -380,7 +390,6 @@ boot_slots_compatible(struct boot_loader_state *state) #endif return 1; -#endif /* PM_S1_ADDRESS */ } #define BOOT_LOG_SWAP_STATE(area, state) \ From 40861fd7351604d38af6345e56fe7422529561e6 Mon Sep 17 00:00:00 2001 From: Jukka Rissanen Date: Thu, 18 Sep 2025 14:08:12 +0300 Subject: [PATCH 385/420] [nrf noup] boot/zephyr/socs: nrf54h20 prj.conf fix CONFIG_PM enables CONFIG_PM_DEVICE by default, this is not desired for MCUBOOT as PM_DEVICE requires multithreading Signed-off-by: Jukka Rissanen --- boot/zephyr/socs/nrf54h20_cpuapp.conf | 1 + 1 file changed, 1 insertion(+) diff --git a/boot/zephyr/socs/nrf54h20_cpuapp.conf b/boot/zephyr/socs/nrf54h20_cpuapp.conf index 09ccb19b2..9e75ccbb9 100644 --- a/boot/zephyr/socs/nrf54h20_cpuapp.conf +++ b/boot/zephyr/socs/nrf54h20_cpuapp.conf @@ -8,6 +8,7 @@ # MCUboot does not support S2RAM itself, but serves as an immediate actor while waking up # from suspension. CONFIG_PM=y +CONFIG_PM_DEVICE=n CONFIG_PM_S2RAM=y CONFIG_PM_S2RAM_CUSTOM_MARKING=y CONFIG_SOC_NRF54H20_PM_S2RAM_OVERRIDE=y From a999034ba25e3118a2c23b4a1a3d6dcc3920a16f Mon Sep 17 00:00:00 2001 From: Grzegorz Chwierut Date: Wed, 17 Sep 2025 15:28:05 +0200 Subject: [PATCH 386/420] [nrf noup] boot/zephyr: update nrf54l15dk ext flash configs nrf-squash! [nrf noup] boot/zephyr: add nrf54l15dk ext flash configs Fprotect is enabled by default, size of MCUboot must be less than 62KB. Removed PM_PARTITION_SIZE_MCUBOOT to use the default value. Fixes NCSDK-35436 Signed-off-by: Grzegorz Chwierut --- boot/zephyr/boards/nrf54l15dk_nrf54l15_cpuapp_ext_flash.conf | 1 - 1 file changed, 1 deletion(-) diff --git a/boot/zephyr/boards/nrf54l15dk_nrf54l15_cpuapp_ext_flash.conf b/boot/zephyr/boards/nrf54l15dk_nrf54l15_cpuapp_ext_flash.conf index ec944f828..15a9a228d 100644 --- a/boot/zephyr/boards/nrf54l15dk_nrf54l15_cpuapp_ext_flash.conf +++ b/boot/zephyr/boards/nrf54l15dk_nrf54l15_cpuapp_ext_flash.conf @@ -1,7 +1,6 @@ CONFIG_SPI=y CONFIG_SPI_NOR=y CONFIG_FLASH=y -CONFIG_PM_PARTITION_SIZE_MCUBOOT=0x14000 CONFIG_MAIN_STACK_SIZE=20480 CONFIG_BOOT_MAX_IMG_SECTORS=512 CONFIG_SPI_NOR_FLASH_LAYOUT_PAGE_SIZE=4096 From 70846f71403aca338c208c1049c9b11f4189d5a9 Mon Sep 17 00:00:00 2001 From: Grzegorz Chwierut Date: Fri, 26 Sep 2025 18:07:58 +0200 Subject: [PATCH 387/420] Revert "[nrf noup] boot/zephyr: update nrf54l15dk ext flash configs" This reverts commit a999034ba25e3118a2c23b4a1a3d6dcc3920a16f. --- boot/zephyr/boards/nrf54l15dk_nrf54l15_cpuapp_ext_flash.conf | 1 + 1 file changed, 1 insertion(+) diff --git a/boot/zephyr/boards/nrf54l15dk_nrf54l15_cpuapp_ext_flash.conf b/boot/zephyr/boards/nrf54l15dk_nrf54l15_cpuapp_ext_flash.conf index 15a9a228d..ec944f828 100644 --- a/boot/zephyr/boards/nrf54l15dk_nrf54l15_cpuapp_ext_flash.conf +++ b/boot/zephyr/boards/nrf54l15dk_nrf54l15_cpuapp_ext_flash.conf @@ -1,6 +1,7 @@ CONFIG_SPI=y CONFIG_SPI_NOR=y CONFIG_FLASH=y +CONFIG_PM_PARTITION_SIZE_MCUBOOT=0x14000 CONFIG_MAIN_STACK_SIZE=20480 CONFIG_BOOT_MAX_IMG_SECTORS=512 CONFIG_SPI_NOR_FLASH_LAYOUT_PAGE_SIZE=4096 From a0de30740855a90c64d57000bdb4ec212ec7090e Mon Sep 17 00:00:00 2001 From: Grzegorz Chwierut Date: Fri, 26 Sep 2025 18:08:10 +0200 Subject: [PATCH 388/420] Revert "[nrf noup] boot/zephyr: add nrf54l15dk ext flash configs" This reverts commit 5ef6baed45e914285714c0ff5058e2a19cd43c31. --- .../nrf54l15dk_nrf54l05_cpuapp.conf} | 0 .../nrf54l15dk_nrf54l10_cpuapp.conf} | 0 .../boards/nrf54l15dk_nrf54l15_cpuapp.conf | 16 +++++++ .../nrf54l15dk_nrf54l15_cpuapp_ext_flash.conf | 9 ---- ...f54l15dk_nrf54l15_cpuapp_ext_flash.overlay | 48 ------------------- boot/zephyr/prj.conf | 1 + boot/zephyr/socs/nrf54l15_cpuapp.conf | 14 ------ 7 files changed, 17 insertions(+), 71 deletions(-) rename boot/zephyr/{socs/nrf54l05_cpuapp.conf => boards/nrf54l15dk_nrf54l05_cpuapp.conf} (100%) rename boot/zephyr/{socs/nrf54l10_cpuapp.conf => boards/nrf54l15dk_nrf54l10_cpuapp.conf} (100%) create mode 100644 boot/zephyr/boards/nrf54l15dk_nrf54l15_cpuapp.conf delete mode 100644 boot/zephyr/boards/nrf54l15dk_nrf54l15_cpuapp_ext_flash.conf delete mode 100644 boot/zephyr/boards/nrf54l15dk_nrf54l15_cpuapp_ext_flash.overlay diff --git a/boot/zephyr/socs/nrf54l05_cpuapp.conf b/boot/zephyr/boards/nrf54l15dk_nrf54l05_cpuapp.conf similarity index 100% rename from boot/zephyr/socs/nrf54l05_cpuapp.conf rename to boot/zephyr/boards/nrf54l15dk_nrf54l05_cpuapp.conf diff --git a/boot/zephyr/socs/nrf54l10_cpuapp.conf b/boot/zephyr/boards/nrf54l15dk_nrf54l10_cpuapp.conf similarity index 100% rename from boot/zephyr/socs/nrf54l10_cpuapp.conf rename to boot/zephyr/boards/nrf54l15dk_nrf54l10_cpuapp.conf diff --git a/boot/zephyr/boards/nrf54l15dk_nrf54l15_cpuapp.conf b/boot/zephyr/boards/nrf54l15dk_nrf54l15_cpuapp.conf new file mode 100644 index 000000000..1dbd7c1ab --- /dev/null +++ b/boot/zephyr/boards/nrf54l15dk_nrf54l15_cpuapp.conf @@ -0,0 +1,16 @@ +# Copyright (c) 2024 Nordic Semiconductor ASA +# +# SPDX-License-Identifier: Apache-2.0 +# +CONFIG_BOOT_MAX_IMG_SECTORS=256 + +# Ensure that the SPI NOR driver is disabled by default +CONFIG_SPI_NOR=n + +# TODO: below are not yet supported and need fixing +CONFIG_FPROTECT=n + +CONFIG_BOOT_WATCHDOG_FEED=n + +# Ensure the fastest RRAM write operations +CONFIG_NRF_RRAM_WRITE_BUFFER_SIZE=32 diff --git a/boot/zephyr/boards/nrf54l15dk_nrf54l15_cpuapp_ext_flash.conf b/boot/zephyr/boards/nrf54l15dk_nrf54l15_cpuapp_ext_flash.conf deleted file mode 100644 index ec944f828..000000000 --- a/boot/zephyr/boards/nrf54l15dk_nrf54l15_cpuapp_ext_flash.conf +++ /dev/null @@ -1,9 +0,0 @@ -CONFIG_SPI=y -CONFIG_SPI_NOR=y -CONFIG_FLASH=y -CONFIG_PM_PARTITION_SIZE_MCUBOOT=0x14000 -CONFIG_MAIN_STACK_SIZE=20480 -CONFIG_BOOT_MAX_IMG_SECTORS=512 -CONFIG_SPI_NOR_FLASH_LAYOUT_PAGE_SIZE=4096 -# Ensure that the qspi driver is disabled by default -CONFIG_NORDIC_QSPI_NOR=n diff --git a/boot/zephyr/boards/nrf54l15dk_nrf54l15_cpuapp_ext_flash.overlay b/boot/zephyr/boards/nrf54l15dk_nrf54l15_cpuapp_ext_flash.overlay deleted file mode 100644 index ba6274221..000000000 --- a/boot/zephyr/boards/nrf54l15dk_nrf54l15_cpuapp_ext_flash.overlay +++ /dev/null @@ -1,48 +0,0 @@ -/ { - chosen { - nordic,pm-ext-flash = &mx25r64; - zephyr,code-partition = &boot_partition; - }; -}; - -/delete-node/ &boot_partition; -/delete-node/ &slot0_partition; -/delete-node/ &slot1_partition; - -/delete-node/ &storage_partition; - -&cpuapp_rram { - reg = < 0x0 DT_SIZE_K(1524) >; - - partitions { - boot_partition: partition@0 { - label = "mcuboot"; - reg = <0x000000000 0x00014000>; - }; - - slot0_partition: partition@14000 { - label = "image-0"; - reg = <0x000014000 0x0015A000>; - }; - - storage_partition: partition@16E000 { - label = "storage"; - reg = < 0x16E000 0x9000 >; - }; - }; -}; - -&mx25r64 { - status = "okay"; - - partitions { - compatible = "fixed-partitions"; - #address-cells = <1>; - #size-cells = <1>; - - slot1_partition: partition@0 { - label = "image-1"; - reg = <0x000000000 0x0015A000>; - }; - }; -}; diff --git a/boot/zephyr/prj.conf b/boot/zephyr/prj.conf index df37b82fb..41d4187c0 100644 --- a/boot/zephyr/prj.conf +++ b/boot/zephyr/prj.conf @@ -12,6 +12,7 @@ CONFIG_BOOT_BOOTSTRAP=n # CONFIG_HEAP_MEM_POOL_SIZE is not set CONFIG_FLASH=y +CONFIG_FPROTECT=y ### Various Zephyr boards enable features that we don't want. # CONFIG_BT is not set diff --git a/boot/zephyr/socs/nrf54l15_cpuapp.conf b/boot/zephyr/socs/nrf54l15_cpuapp.conf index 645325513..8db9d2d23 100644 --- a/boot/zephyr/socs/nrf54l15_cpuapp.conf +++ b/boot/zephyr/socs/nrf54l15_cpuapp.conf @@ -1,17 +1,3 @@ -# Copyright (c) 2024 Nordic Semiconductor ASA -# -# SPDX-License-Identifier: Apache-2.0 -# -CONFIG_BOOT_MAX_IMG_SECTORS=256 - -# Ensure that the SPI NOR driver is disabled by default -CONFIG_SPI_NOR=n - -CONFIG_BOOT_WATCHDOG_FEED=n - -# Ensure the fastest RRAM write operations -CONFIG_NRF_RRAM_WRITE_BUFFER_SIZE=32 - # Link Time Optimizations CONFIG_ISR_TABLES_LOCAL_DECLARATION=y CONFIG_LTO=y From bba107ff2e26a88ff01e5f9f179822f1d240ac17 Mon Sep 17 00:00:00 2001 From: Grzegorz Chwierut Date: Fri, 26 Sep 2025 12:15:05 +0200 Subject: [PATCH 389/420] [nrf fromtree] zephyr: nRF54L05 and L10 configuration with LTO enabled Enable LTO to cut down the MCUboot size for nrf54l10 and nrf54l05. Signed-off-by: Grzegorz Chwierut (cherry picked from commit 3c8e571775291dd5da7119b1f24b765bd935a97c) --- boot/zephyr/socs/nrf54l05_cpuapp.conf | 3 +++ boot/zephyr/socs/nrf54l10_cpuapp.conf | 3 +++ 2 files changed, 6 insertions(+) create mode 100644 boot/zephyr/socs/nrf54l05_cpuapp.conf create mode 100644 boot/zephyr/socs/nrf54l10_cpuapp.conf diff --git a/boot/zephyr/socs/nrf54l05_cpuapp.conf b/boot/zephyr/socs/nrf54l05_cpuapp.conf new file mode 100644 index 000000000..8db9d2d23 --- /dev/null +++ b/boot/zephyr/socs/nrf54l05_cpuapp.conf @@ -0,0 +1,3 @@ +# Link Time Optimizations +CONFIG_ISR_TABLES_LOCAL_DECLARATION=y +CONFIG_LTO=y diff --git a/boot/zephyr/socs/nrf54l10_cpuapp.conf b/boot/zephyr/socs/nrf54l10_cpuapp.conf new file mode 100644 index 000000000..8db9d2d23 --- /dev/null +++ b/boot/zephyr/socs/nrf54l10_cpuapp.conf @@ -0,0 +1,3 @@ +# Link Time Optimizations +CONFIG_ISR_TABLES_LOCAL_DECLARATION=y +CONFIG_LTO=y From e18423574537bf8e289f3e87bc72787ac86053a4 Mon Sep 17 00:00:00 2001 From: Mateusz Michalek Date: Thu, 7 Nov 2024 11:09:18 +0100 Subject: [PATCH 390/420] [nrf noup] boot/zephyr: add nrf54l15dk ext flash configs Moved configs from nrf54l15pdk. Turn protection on fprotect by default. Signed-off-by: Andrzej Puzdrowski Signed-off-by: Mateusz Michalek Signed-off-by: Michal Kozikowski Signed-off-by: Jamie McCrae (cherry picked from commit 835b63f3a179634b5c265aa1f39f4834b54bd9cc) --- .../boards/nrf54l15dk_nrf54l05_cpuapp.conf | 13 ----- .../boards/nrf54l15dk_nrf54l10_cpuapp.conf | 13 ----- .../boards/nrf54l15dk_nrf54l15_cpuapp.conf | 16 ------- .../nrf54l15dk_nrf54l15_cpuapp_ext_flash.conf | 9 ++++ ...f54l15dk_nrf54l15_cpuapp_ext_flash.overlay | 48 +++++++++++++++++++ boot/zephyr/prj.conf | 1 - boot/zephyr/socs/nrf54l05_cpuapp.conf | 14 ++++++ boot/zephyr/socs/nrf54l10_cpuapp.conf | 14 ++++++ boot/zephyr/socs/nrf54l15_cpuapp.conf | 14 ++++++ 9 files changed, 99 insertions(+), 43 deletions(-) delete mode 100644 boot/zephyr/boards/nrf54l15dk_nrf54l05_cpuapp.conf delete mode 100644 boot/zephyr/boards/nrf54l15dk_nrf54l10_cpuapp.conf delete mode 100644 boot/zephyr/boards/nrf54l15dk_nrf54l15_cpuapp.conf create mode 100644 boot/zephyr/boards/nrf54l15dk_nrf54l15_cpuapp_ext_flash.conf create mode 100644 boot/zephyr/boards/nrf54l15dk_nrf54l15_cpuapp_ext_flash.overlay diff --git a/boot/zephyr/boards/nrf54l15dk_nrf54l05_cpuapp.conf b/boot/zephyr/boards/nrf54l15dk_nrf54l05_cpuapp.conf deleted file mode 100644 index c8fcd32c3..000000000 --- a/boot/zephyr/boards/nrf54l15dk_nrf54l05_cpuapp.conf +++ /dev/null @@ -1,13 +0,0 @@ -# Copyright (c) 2024 Nordic Semiconductor ASA -# -# SPDX-License-Identifier: Apache-2.0 -# -CONFIG_BOOT_MAX_IMG_SECTORS=256 - -# Ensure that the SPI NOR driver is disabled by default -CONFIG_SPI_NOR=n - -CONFIG_BOOT_WATCHDOG_FEED=n - -# Ensure the fastest RRAM write operations -CONFIG_NRF_RRAM_WRITE_BUFFER_SIZE=32 diff --git a/boot/zephyr/boards/nrf54l15dk_nrf54l10_cpuapp.conf b/boot/zephyr/boards/nrf54l15dk_nrf54l10_cpuapp.conf deleted file mode 100644 index c8fcd32c3..000000000 --- a/boot/zephyr/boards/nrf54l15dk_nrf54l10_cpuapp.conf +++ /dev/null @@ -1,13 +0,0 @@ -# Copyright (c) 2024 Nordic Semiconductor ASA -# -# SPDX-License-Identifier: Apache-2.0 -# -CONFIG_BOOT_MAX_IMG_SECTORS=256 - -# Ensure that the SPI NOR driver is disabled by default -CONFIG_SPI_NOR=n - -CONFIG_BOOT_WATCHDOG_FEED=n - -# Ensure the fastest RRAM write operations -CONFIG_NRF_RRAM_WRITE_BUFFER_SIZE=32 diff --git a/boot/zephyr/boards/nrf54l15dk_nrf54l15_cpuapp.conf b/boot/zephyr/boards/nrf54l15dk_nrf54l15_cpuapp.conf deleted file mode 100644 index 1dbd7c1ab..000000000 --- a/boot/zephyr/boards/nrf54l15dk_nrf54l15_cpuapp.conf +++ /dev/null @@ -1,16 +0,0 @@ -# Copyright (c) 2024 Nordic Semiconductor ASA -# -# SPDX-License-Identifier: Apache-2.0 -# -CONFIG_BOOT_MAX_IMG_SECTORS=256 - -# Ensure that the SPI NOR driver is disabled by default -CONFIG_SPI_NOR=n - -# TODO: below are not yet supported and need fixing -CONFIG_FPROTECT=n - -CONFIG_BOOT_WATCHDOG_FEED=n - -# Ensure the fastest RRAM write operations -CONFIG_NRF_RRAM_WRITE_BUFFER_SIZE=32 diff --git a/boot/zephyr/boards/nrf54l15dk_nrf54l15_cpuapp_ext_flash.conf b/boot/zephyr/boards/nrf54l15dk_nrf54l15_cpuapp_ext_flash.conf new file mode 100644 index 000000000..ec944f828 --- /dev/null +++ b/boot/zephyr/boards/nrf54l15dk_nrf54l15_cpuapp_ext_flash.conf @@ -0,0 +1,9 @@ +CONFIG_SPI=y +CONFIG_SPI_NOR=y +CONFIG_FLASH=y +CONFIG_PM_PARTITION_SIZE_MCUBOOT=0x14000 +CONFIG_MAIN_STACK_SIZE=20480 +CONFIG_BOOT_MAX_IMG_SECTORS=512 +CONFIG_SPI_NOR_FLASH_LAYOUT_PAGE_SIZE=4096 +# Ensure that the qspi driver is disabled by default +CONFIG_NORDIC_QSPI_NOR=n diff --git a/boot/zephyr/boards/nrf54l15dk_nrf54l15_cpuapp_ext_flash.overlay b/boot/zephyr/boards/nrf54l15dk_nrf54l15_cpuapp_ext_flash.overlay new file mode 100644 index 000000000..ba6274221 --- /dev/null +++ b/boot/zephyr/boards/nrf54l15dk_nrf54l15_cpuapp_ext_flash.overlay @@ -0,0 +1,48 @@ +/ { + chosen { + nordic,pm-ext-flash = &mx25r64; + zephyr,code-partition = &boot_partition; + }; +}; + +/delete-node/ &boot_partition; +/delete-node/ &slot0_partition; +/delete-node/ &slot1_partition; + +/delete-node/ &storage_partition; + +&cpuapp_rram { + reg = < 0x0 DT_SIZE_K(1524) >; + + partitions { + boot_partition: partition@0 { + label = "mcuboot"; + reg = <0x000000000 0x00014000>; + }; + + slot0_partition: partition@14000 { + label = "image-0"; + reg = <0x000014000 0x0015A000>; + }; + + storage_partition: partition@16E000 { + label = "storage"; + reg = < 0x16E000 0x9000 >; + }; + }; +}; + +&mx25r64 { + status = "okay"; + + partitions { + compatible = "fixed-partitions"; + #address-cells = <1>; + #size-cells = <1>; + + slot1_partition: partition@0 { + label = "image-1"; + reg = <0x000000000 0x0015A000>; + }; + }; +}; diff --git a/boot/zephyr/prj.conf b/boot/zephyr/prj.conf index 41d4187c0..df37b82fb 100644 --- a/boot/zephyr/prj.conf +++ b/boot/zephyr/prj.conf @@ -12,7 +12,6 @@ CONFIG_BOOT_BOOTSTRAP=n # CONFIG_HEAP_MEM_POOL_SIZE is not set CONFIG_FLASH=y -CONFIG_FPROTECT=y ### Various Zephyr boards enable features that we don't want. # CONFIG_BT is not set diff --git a/boot/zephyr/socs/nrf54l05_cpuapp.conf b/boot/zephyr/socs/nrf54l05_cpuapp.conf index 8db9d2d23..645325513 100644 --- a/boot/zephyr/socs/nrf54l05_cpuapp.conf +++ b/boot/zephyr/socs/nrf54l05_cpuapp.conf @@ -1,3 +1,17 @@ +# Copyright (c) 2024 Nordic Semiconductor ASA +# +# SPDX-License-Identifier: Apache-2.0 +# +CONFIG_BOOT_MAX_IMG_SECTORS=256 + +# Ensure that the SPI NOR driver is disabled by default +CONFIG_SPI_NOR=n + +CONFIG_BOOT_WATCHDOG_FEED=n + +# Ensure the fastest RRAM write operations +CONFIG_NRF_RRAM_WRITE_BUFFER_SIZE=32 + # Link Time Optimizations CONFIG_ISR_TABLES_LOCAL_DECLARATION=y CONFIG_LTO=y diff --git a/boot/zephyr/socs/nrf54l10_cpuapp.conf b/boot/zephyr/socs/nrf54l10_cpuapp.conf index 8db9d2d23..645325513 100644 --- a/boot/zephyr/socs/nrf54l10_cpuapp.conf +++ b/boot/zephyr/socs/nrf54l10_cpuapp.conf @@ -1,3 +1,17 @@ +# Copyright (c) 2024 Nordic Semiconductor ASA +# +# SPDX-License-Identifier: Apache-2.0 +# +CONFIG_BOOT_MAX_IMG_SECTORS=256 + +# Ensure that the SPI NOR driver is disabled by default +CONFIG_SPI_NOR=n + +CONFIG_BOOT_WATCHDOG_FEED=n + +# Ensure the fastest RRAM write operations +CONFIG_NRF_RRAM_WRITE_BUFFER_SIZE=32 + # Link Time Optimizations CONFIG_ISR_TABLES_LOCAL_DECLARATION=y CONFIG_LTO=y diff --git a/boot/zephyr/socs/nrf54l15_cpuapp.conf b/boot/zephyr/socs/nrf54l15_cpuapp.conf index 8db9d2d23..645325513 100644 --- a/boot/zephyr/socs/nrf54l15_cpuapp.conf +++ b/boot/zephyr/socs/nrf54l15_cpuapp.conf @@ -1,3 +1,17 @@ +# Copyright (c) 2024 Nordic Semiconductor ASA +# +# SPDX-License-Identifier: Apache-2.0 +# +CONFIG_BOOT_MAX_IMG_SECTORS=256 + +# Ensure that the SPI NOR driver is disabled by default +CONFIG_SPI_NOR=n + +CONFIG_BOOT_WATCHDOG_FEED=n + +# Ensure the fastest RRAM write operations +CONFIG_NRF_RRAM_WRITE_BUFFER_SIZE=32 + # Link Time Optimizations CONFIG_ISR_TABLES_LOCAL_DECLARATION=y CONFIG_LTO=y From 35be0b72fe8601a9ac9e2c8a8e29eb8a76512aac Mon Sep 17 00:00:00 2001 From: Grzegorz Chwierut Date: Wed, 17 Sep 2025 15:28:05 +0200 Subject: [PATCH 391/420] [nrf noup] boot/zephyr: update nrf54l15dk ext flash configs nrf-squash! [nrf noup] boot/zephyr: add nrf54l15dk ext flash configs Fprotect is enabled by default, size of MCUboot must be less than 62KB. Removed PM_PARTITION_SIZE_MCUBOOT to use the default value. Fixes NCSDK-35436 Signed-off-by: Grzegorz Chwierut --- boot/zephyr/boards/nrf54l15dk_nrf54l15_cpuapp_ext_flash.conf | 1 - 1 file changed, 1 deletion(-) diff --git a/boot/zephyr/boards/nrf54l15dk_nrf54l15_cpuapp_ext_flash.conf b/boot/zephyr/boards/nrf54l15dk_nrf54l15_cpuapp_ext_flash.conf index ec944f828..15a9a228d 100644 --- a/boot/zephyr/boards/nrf54l15dk_nrf54l15_cpuapp_ext_flash.conf +++ b/boot/zephyr/boards/nrf54l15dk_nrf54l15_cpuapp_ext_flash.conf @@ -1,7 +1,6 @@ CONFIG_SPI=y CONFIG_SPI_NOR=y CONFIG_FLASH=y -CONFIG_PM_PARTITION_SIZE_MCUBOOT=0x14000 CONFIG_MAIN_STACK_SIZE=20480 CONFIG_BOOT_MAX_IMG_SECTORS=512 CONFIG_SPI_NOR_FLASH_LAYOUT_PAGE_SIZE=4096 From 511e742327020ebe42df2e4b45a3ca8d0f3e6611 Mon Sep 17 00:00:00 2001 From: Artur Hadasz Date: Mon, 29 Sep 2025 13:10:39 +0200 Subject: [PATCH 392/420] [nrf noup] nrf_cleanup: temporary GRTC cleanup with no counter reset nrf-squash! [nrf noup] nrf_cleanup: nRF54h: fix missing peripheral cleanup The GRTC should not reset its value and stop running when switching for MCUBoot to application. Also in general, this should not be done in case of reset - so the nrfx_grtc_unit function should not reset the counter value. This will be fixed in nrfx (NRFX-8487), but the solution is needed quicker. Hence, a temporary uninit function for GRTC was added in nrf_cleanup, fixing this issue for MCUBoot. Signed-off-by: Artur Hadasz --- boot/zephyr/nrf_cleanup.c | 28 +++++++++++++++++++++++++++- 1 file changed, 27 insertions(+), 1 deletion(-) diff --git a/boot/zephyr/nrf_cleanup.c b/boot/zephyr/nrf_cleanup.c index 5ddc74a64..c1e5a178e 100644 --- a/boot/zephyr/nrf_cleanup.c +++ b/boot/zephyr/nrf_cleanup.c @@ -52,9 +52,35 @@ static inline void nrf_cleanup_rtc(NRF_RTC_Type * rtc_reg) #endif #if defined(CONFIG_NRF_GRTC_TIMER) + +/** + * This function is temporary and should be removed once nrfx_grtc_uninit + * no longer resets the counter - see NRFX-8487. + */ +static inline void nrfx_grtc_uninit_no_counter_reset(void) +{ + uint32_t ch_mask = NRFX_GRTC_CONFIG_ALLOWED_CC_CHANNELS_MASK; + +#if NRF_GRTC_HAS_RTCOUNTER + uint32_t grtc_all_int_mask = (NRFX_GRTC_CONFIG_ALLOWED_CC_CHANNELS_MASK | + GRTC_NON_SYSCOMPARE_INT_MASK); +#else + uint32_t grtc_all_int_mask = NRFX_GRTC_CONFIG_ALLOWED_CC_CHANNELS_MASK; +#endif + + nrfy_grtc_int_disable(NRF_GRTC, grtc_all_int_mask); + + for (uint8_t chan = 0; ch_mask; chan++, ch_mask >>= 1) + { + nrfx_grtc_syscounter_cc_disable(chan); + nrfx_grtc_channel_free(chan); + } + nrfy_grtc_int_uninit(NRF_GRTC); +} + static inline void nrf_cleanup_grtc(void) { - nrfx_grtc_uninit(); + nrfx_grtc_uninit_no_counter_reset(); } #endif From 388a9da9f2ce0b80af9208e758f0859792daf0e6 Mon Sep 17 00:00:00 2001 From: Tomasz Chyrowicz Date: Mon, 29 Sep 2025 12:01:14 +0200 Subject: [PATCH 393/420] [nrf fromtree] hooks: Use dedicated type for slot numbers Use the dedicated type to specify the slot number. Signed-off-by: Tomasz Chyrowicz (cherry picked from commit d5b0dcb9aaee397fc105ae2228e8030038c3d871) --- boot/bootutil/include/bootutil/boot_hooks.h | 2 +- boot/zephyr/hooks_sample.c | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/boot/bootutil/include/bootutil/boot_hooks.h b/boot/bootutil/include/bootutil/boot_hooks.h index f5b10e8c7..96414e3df 100644 --- a/boot/bootutil/include/bootutil/boot_hooks.h +++ b/boot/bootutil/include/bootutil/boot_hooks.h @@ -282,6 +282,6 @@ int flash_area_get_device_id_hook(const struct flash_area *fa, * @return 0 if a slot was requested; * BOOT_HOOK_REGULAR follow the normal execution path. */ -int boot_find_next_slot_hook(struct boot_loader_state *state, uint8_t image, uint32_t *active_slot); +int boot_find_next_slot_hook(struct boot_loader_state *state, uint8_t image, enum boot_slot *active_slot); #endif /*H_BOOTUTIL_HOOKS*/ diff --git a/boot/zephyr/hooks_sample.c b/boot/zephyr/hooks_sample.c index fc7bd2fa4..42639965e 100644 --- a/boot/zephyr/hooks_sample.c +++ b/boot/zephyr/hooks_sample.c @@ -94,7 +94,8 @@ int boot_img_install_stat_hook(int image_index, int slot, int *img_install_stat) return BOOT_HOOK_REGULAR; } -int boot_find_next_slot_hook(struct boot_loader_state *state, uint8_t image, uint32_t *active_slot) +int boot_find_next_slot_hook(struct boot_loader_state *state, uint8_t image, + enum boot_slot *active_slot) { return BOOT_HOOK_REGULAR; } From 85349537b3bc4e8e9e7542abd0303adf28177dcb Mon Sep 17 00:00:00 2001 From: Tomasz Chyrowicz Date: Mon, 29 Sep 2025 12:04:07 +0200 Subject: [PATCH 394/420] [nrf noup] mcuboot: Use dedicated type for slot numbers nrf-squash! [nrf noup] bootloader: Add bootloader requests Change bootloader request module, so it uses the new, dedicated type to point to the specific slot. Ref: NCSDK-35199 Signed-off-by: Tomasz Chyrowicz --- boot/bootutil/include/bootutil/boot_request.h | 11 +++---- boot/bootutil/src/bootutil_public.c | 2 +- .../zephyr/src/boot_request_retention.c | 30 +++++++++---------- boot/zephyr/main.c | 4 +-- 4 files changed, 24 insertions(+), 23 deletions(-) diff --git a/boot/bootutil/include/bootutil/boot_request.h b/boot/bootutil/include/bootutil/boot_request.h index b1e8f891e..c92a91d4e 100644 --- a/boot/bootutil/include/bootutil/boot_request.h +++ b/boot/bootutil/include/bootutil/boot_request.h @@ -13,6 +13,7 @@ extern "C" { #include #include +#include /** Special value, indicating that there is no preferred slot. */ #define BOOT_REQUEST_NO_PREFERRED_SLOT UINT32_MAX @@ -25,7 +26,7 @@ extern "C" { * * @return 0 if requested, negative error code otherwise. */ -int boot_request_confirm_slot(uint8_t image, uint32_t slot); +int boot_request_confirm_slot(uint8_t image, enum boot_slot slot); /** * @brief Request a bootloader to boot the specified slot of an image. @@ -35,7 +36,7 @@ int boot_request_confirm_slot(uint8_t image, uint32_t slot); * * @return 0 if requested, negative error code otherwise. */ -int boot_request_set_preferred_slot(uint8_t image, uint32_t slot); +int boot_request_set_preferred_slot(uint8_t image, enum boot_slot slot); /** * @brief Request a bootloader to boot recovery image. @@ -59,16 +60,16 @@ int boot_request_enter_firmware_loader(void); * * @return true if requested, false otherwise. */ -bool boot_request_check_confirmed_slot(uint8_t image, uint32_t slot); +bool boot_request_check_confirmed_slot(uint8_t image, enum boot_slot slot); /** * @brief Find if there is a request to boot certain slot of the specified image. * * @param[in] image Image number. * - * @return slot number if requested, BOOT_REQUEST_NO_PREFERRED_SLOT otherwise. + * @return slot number if requested, BOOT_SLOT_NONE otherwise. */ -uint32_t boot_request_get_preferred_slot(uint8_t image); +enum boot_slot boot_request_get_preferred_slot(uint8_t image); /** * @brief Check if there is a request to boot recovery image. diff --git a/boot/bootutil/src/bootutil_public.c b/boot/bootutil/src/bootutil_public.c index 9686511f2..c43a47a8b 100644 --- a/boot/bootutil/src/bootutil_public.c +++ b/boot/bootutil/src/bootutil_public.c @@ -511,7 +511,7 @@ boot_write_copy_done(const struct flash_area *fap) #ifdef SEND_BOOT_REQUEST static int send_boot_request(uint8_t magic, uint8_t image_ok, bool confirm, int image_id, - uint32_t slot_id) + enum boot_slot slot_id) { int rc = BOOT_EBADIMAGE; diff --git a/boot/bootutil/zephyr/src/boot_request_retention.c b/boot/bootutil/zephyr/src/boot_request_retention.c index 234dfb5cf..e7fc393a0 100644 --- a/boot/bootutil/zephyr/src/boot_request_retention.c +++ b/boot/bootutil/zephyr/src/boot_request_retention.c @@ -155,7 +155,7 @@ int boot_request_clear(void) return retention_clear(bootloader_request_dev); } -int boot_request_confirm_slot(uint8_t image, uint32_t slot) +int boot_request_confirm_slot(uint8_t image, enum boot_slot slot) { uint8_t value = BOOT_REQUEST_SLOT_INVALID; size_t req_entry; @@ -167,10 +167,10 @@ int boot_request_confirm_slot(uint8_t image, uint32_t slot) } switch (slot) { - case 0: + case BOOT_SLOT_PRIMARY: value = BOOT_REQUEST_SLOT_PRIMARY; break; - case 1: + case BOOT_SLOT_SECONDARY: value = BOOT_REQUEST_SLOT_SECONDARY; break; default: @@ -181,7 +181,7 @@ int boot_request_confirm_slot(uint8_t image, uint32_t slot) sizeof(value)); } -bool boot_request_check_confirmed_slot(uint8_t image, uint32_t slot) +bool boot_request_check_confirmed_slot(uint8_t image, enum boot_slot slot) { uint8_t value = BOOT_REQUEST_SLOT_INVALID; size_t req_entry; @@ -200,9 +200,9 @@ bool boot_request_check_confirmed_slot(uint8_t image, uint32_t slot) switch (value) { case BOOT_REQUEST_SLOT_PRIMARY: - return (slot == 0); + return (slot == BOOT_SLOT_PRIMARY); case BOOT_REQUEST_SLOT_SECONDARY: - return (slot == 1); + return (slot == BOOT_SLOT_SECONDARY); default: break; } @@ -210,7 +210,7 @@ bool boot_request_check_confirmed_slot(uint8_t image, uint32_t slot) return false; } -int boot_request_set_preferred_slot(uint8_t image, uint32_t slot) +int boot_request_set_preferred_slot(uint8_t image, enum boot_slot slot) { uint8_t value = BOOT_REQUEST_SLOT_INVALID; size_t req_entry; @@ -222,10 +222,10 @@ int boot_request_set_preferred_slot(uint8_t image, uint32_t slot) } switch (slot) { - case 0: + case BOOT_SLOT_PRIMARY: value = BOOT_REQUEST_SLOT_PRIMARY; break; - case 1: + case BOOT_SLOT_SECONDARY: value = BOOT_REQUEST_SLOT_SECONDARY; break; default: @@ -237,7 +237,7 @@ int boot_request_set_preferred_slot(uint8_t image, uint32_t slot) } #ifdef CONFIG_FIND_NEXT_SLOT_HOOKS -uint32_t boot_request_get_preferred_slot(uint8_t image) +enum boot_slot boot_request_get_preferred_slot(uint8_t image) { uint8_t value = BOOT_REQUEST_SLOT_INVALID; size_t req_entry; @@ -245,25 +245,25 @@ uint32_t boot_request_get_preferred_slot(uint8_t image) ret = boot_request_entry_find(BOOT_REQUEST_IMG_PREFERENCE, image, &req_entry); if (ret != 0) { - return BOOT_REQUEST_NO_PREFERRED_SLOT; + return BOOT_SLOT_NONE; } ret = retention_read(bootloader_request_dev, req_entry * sizeof(value), (void *)&value, sizeof(value)); if (ret != 0) { - return BOOT_REQUEST_NO_PREFERRED_SLOT; + return BOOT_SLOT_NONE; } switch (value) { case BOOT_REQUEST_SLOT_PRIMARY: - return 0; + return BOOT_SLOT_PRIMARY; case BOOT_REQUEST_SLOT_SECONDARY: - return 1; + return BOOT_SLOT_SECONDARY; default: break; } - return BOOT_REQUEST_NO_PREFERRED_SLOT; + return BOOT_SLOT_NONE; } #endif /* CONFIG_FIND_NEXT_SLOT_HOOKS */ diff --git a/boot/zephyr/main.c b/boot/zephyr/main.c index 643f88836..16c8a9404 100644 --- a/boot/zephyr/main.c +++ b/boot/zephyr/main.c @@ -616,7 +616,7 @@ static int boot_prevalidate(void) { #ifdef CONFIG_NRF_MCUBOOT_BOOT_REQUEST uint8_t image_index; - uint32_t slot; + enum boot_slot slot; uint32_t area_id; const struct flash_area *fap; int rc = boot_request_init(); @@ -626,7 +626,7 @@ static int boot_prevalidate(void) } for (image_index = 0; image_index < BOOT_IMAGE_NUMBER; ++image_index) { - for (slot = 0; slot < BOOT_REQUEST_NUM_SLOTS; slot++) { + for (slot = BOOT_SLOT_PRIMARY; slot < BOOT_SLOT_COUNT; slot++) { if (boot_request_check_confirmed_slot(image_index, slot)) { BOOT_LOG_DBG("Confirm image: %d slot: %d due to bootloader request.", image_index, slot); From 7c44ed0191a633efc4c50e18bd0c71c5d839bcb9 Mon Sep 17 00:00:00 2001 From: Mateusz Michalek Date: Fri, 26 Sep 2025 11:51:06 +0200 Subject: [PATCH 395/420] [nrf fromtree] boot: bootutil: write_sz fix fixes missing array bug. Signed-off-by: Mateusz Michalek (cherry picked from commit 5e1be19fbc2afde8f7a6eb2ad8e3b31e5c3921cd) --- boot/bootutil/src/bootutil_priv.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/boot/bootutil/src/bootutil_priv.h b/boot/bootutil/src/bootutil_priv.h index b97825ed4..784baf7e7 100644 --- a/boot/bootutil/src/bootutil_priv.h +++ b/boot/bootutil/src/bootutil_priv.h @@ -253,7 +253,7 @@ struct boot_loader_state { #endif uint8_t swap_type[BOOT_IMAGE_NUMBER]; - uint32_t write_sz; + uint32_t write_sz[BOOT_IMAGE_NUMBER]; #if defined(MCUBOOT_SWAP_USING_OFFSET) uint32_t secondary_offset[BOOT_IMAGE_NUMBER]; @@ -480,7 +480,7 @@ static inline bool boot_u16_safe_add(uint16_t *dest, uint16_t a, uint16_t b) #endif #define BOOT_IMG(state, slot) ((state)->imgs[BOOT_CURR_IMG(state)][(slot)]) #define BOOT_IMG_AREA(state, slot) (BOOT_IMG(state, slot).area) -#define BOOT_WRITE_SZ(state) ((state)->write_sz) +#define BOOT_WRITE_SZ(state) ((state)->write_sz[BOOT_CURR_IMG(state)]) #define BOOT_SWAP_TYPE(state) ((state)->swap_type[BOOT_CURR_IMG(state)]) #define BOOT_TLV_OFF(hdr) ((hdr)->ih_hdr_size + (hdr)->ih_img_size) From 049dc0be638b4ec453f34919260d25905a76cfc6 Mon Sep 17 00:00:00 2001 From: Tomasz Chyrowicz Date: Fri, 3 Oct 2025 13:06:02 +0200 Subject: [PATCH 396/420] [nrf fromtree] bootutil: Fix minor issues Fix uninitialized variable warning as well as compile time issue, when the slotted dependencies are enabled. Signed-off-by: Tomasz Chyrowicz (cherry picked from commit 9ca088179e611ebd0054b0ef503039132c7a0ad1) --- boot/bootutil/src/loader.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/boot/bootutil/src/loader.c b/boot/bootutil/src/loader.c index 232557414..6c05b3b2b 100644 --- a/boot/bootutil/src/loader.c +++ b/boot/bootutil/src/loader.c @@ -612,7 +612,7 @@ boot_verify_slot_dependencies(struct boot_loader_state *state, uint32_t slot) #ifdef MCUBOOT_VERSION_CMP_USE_SLOT_NUMBER /* Validate against possible dependency slot values. */ - switch(dep->slot) { + switch(dep.slot) { case VERSION_DEP_SLOT_ACTIVE: case VERSION_DEP_SLOT_PRIMARY: case VERSION_DEP_SLOT_SECONDARY: From f34b20b2b159e4f1dc30dcf20efefb31701c7b78 Mon Sep 17 00:00:00 2001 From: Tomasz Chyrowicz Date: Fri, 3 Oct 2025 13:30:09 +0200 Subject: [PATCH 397/420] [nrf noup] mcuboot: Fix warning nrf-squash! [nrf noup] bootloader: Add bootloader requests Fix a warning for uninitialized variable. Ref: NCSDK-35733 Signed-off-by: Tomasz Chyrowicz --- boot/bootutil/src/bootutil_public.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/boot/bootutil/src/bootutil_public.c b/boot/bootutil/src/bootutil_public.c index c43a47a8b..f54dd6151 100644 --- a/boot/bootutil/src/bootutil_public.c +++ b/boot/bootutil/src/bootutil_public.c @@ -563,6 +563,9 @@ static int flash_area_to_image_slot(const struct flash_area *fa, uint32_t *slot) ++i; } + + /* Image not found */ + *slot = UINT32_MAX; #else (void)fa; if (slot != NULL) { From 26e93ba6a1317a42b946757cafc761e4900ff495 Mon Sep 17 00:00:00 2001 From: Tomasz Chyrowicz Date: Fri, 19 Sep 2025 15:21:51 +0200 Subject: [PATCH 398/420] [nrf fromtree] boot: zephyr: Fix IO-based entrance method If a device uses RESETINFO, than there are some bits set in the resetinfo, even for reboots that should allow to interpret and enter the device recovery. That way it is possible to recover a device through serial recovery if the main application resets due to i.e. watchdog. Signed-off-by: Tomasz Chyrowicz (cherry picked from commit cc9852984f799d8d992594f966c472173925731f) --- boot/zephyr/include/io/io.h | 39 +++++++++++++++++++++++++++++++++++++ 1 file changed, 39 insertions(+) diff --git a/boot/zephyr/include/io/io.h b/boot/zephyr/include/io/io.h index 563281fa2..f0a9ba6eb 100644 --- a/boot/zephyr/include/io/io.h +++ b/boot/zephyr/include/io/io.h @@ -67,6 +67,45 @@ static inline bool io_boot_skip_serial_recovery() { uint32_t rr = nrfx_reset_reason_get(); +#ifdef NRF_RESETINFO + /* The following reset reasons should allow to enter firmware recovery or + * loader through an IO state. + */ + const uint32_t allowed_reset_reasons = ( + /* Reset from power on reset (reset reason POR or BOR). */ + NRFX_RESET_REASON_POR_MASK +#ifdef RESETINFO_RESETREAS_GLOBAL_RESETPOR_Msk + /* Reset from power on reset (reset reason other than POR or BOR). */ + | RESETINFO_RESETREAS_GLOBAL_RESETPOR_Msk +#endif + /* Reset from pin reset is not masked: it always enables the io-based recovery. */ + /* Reset from the watchdog timer. */ + | NRFX_RESET_REASON_DOG_MASK + /* Reset from CTRL-AP. */ + | NRFX_RESET_REASON_CTRLAP_MASK + /* Reset due to secure domain system reset request. */ + | NRFX_RESET_REASON_SREQ_MASK + /* Reset due to secure domain watchdog 0 timer. */ + | NRFX_RESET_REASON_SECWDT0_MASK + /* Reset due to secure domain watchdog 1 timer. */ + | NRFX_RESET_REASON_SECWDT1_MASK + /* Reset due to secure domain lockup. */ + | NRFX_RESET_REASON_LOCKUP_MASK +#if NRF_RESETINFO_HAS_LOCAL_WDT + /* Reset from the local watchdog timer 0. */ + | NRFX_RESET_REASON_LOCAL_DOG0_MASK + /* Reset from the local watchdog timer 1. */ + | NRFX_RESET_REASON_LOCAL_DOG1_MASK +#endif + /* Reset from the local soft reset request. */ + | NRFX_RESET_REASON_LOCAL_SREQ_MASK + /* Reset from local CPU lockup. */ + | NRFX_RESET_REASON_LOCAL_LOCKUP_MASK + ); + + rr &= ~allowed_reset_reasons; +#endif /* NRF_RESETINFO */ + return !(rr == 0 || (rr & NRFX_RESET_REASON_RESETPIN_MASK)); } #else From 077bfe53f05d6c9b3297639735e57dfae083bd2c Mon Sep 17 00:00:00 2001 From: Andrzej Puzdrowski Date: Tue, 30 Sep 2025 14:22:18 +0200 Subject: [PATCH 399/420] [nrf noup] boot/zephyr/nrf54h20_custom_s2ram: direct-xip support Added direct-xip support: * new API for marking active slot to be used by boot_go() routines. * jump vector assignment which is basing on above designation. Signed-off-by: Andrzej Puzdrowski --- boot/zephyr/nrf54h20_custom_s2ram.c | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/boot/zephyr/nrf54h20_custom_s2ram.c b/boot/zephyr/nrf54h20_custom_s2ram.c index 7b70e22fe..51146e7b3 100644 --- a/boot/zephyr/nrf54h20_custom_s2ram.c +++ b/boot/zephyr/nrf54h20_custom_s2ram.c @@ -30,6 +30,20 @@ volatile struct mcuboot_resume_s mcuboot_resume; COND_CODE_0(DT_FIXED_PARTITION_EXISTS(DT_NODELABEL(node_label)), (0), \ (DT_REG_ADDR(DT_GPARENT(DT_NODELABEL(node_label)))))) +#define S2RAM_SLOT_INFO_A 0x37 +#define S2RAM_SLOT_INFO_B 0xA4 + +#ifdef CONFIG_BOOT_DIRECT_XIP +/* Called by the image manager when setting the image as active for current boot. */ +void s2ram_designate_slot(uint8_t slot) +{ + if (slot == 0) { + mcuboot_resume.slot_info = S2RAM_SLOT_INFO_A; + } else { + mcuboot_resume.slot_info = S2RAM_SLOT_INFO_B; + } +} +#endif int soc_s2ram_suspend(pm_s2ram_system_off_fn_t system_off) { @@ -72,8 +86,22 @@ bool pm_s2ram_mark_check_and_clear(void) /* s2ram boot */ struct arm_vector_table *vt; + +#ifdef CONFIG_BOOT_DIRECT_XIP + if (mcuboot_resume.slot_info == S2RAM_SLOT_INFO_A) { + vt = (struct arm_vector_table *) + (FIXED_PARTITION_ADDR(slot0_partition) + APP_EXE_START_OFFSET); + } else if (mcuboot_resume.slot_info == S2RAM_SLOT_INFO_B) { + vt = (struct arm_vector_table *) + (FIXED_PARTITION_ADDR(slot1_partition) + APP_EXE_START_OFFSET); + } else { + /* invalid slot info */ + goto resume_failed; + } +#else vt = (struct arm_vector_table *) (FIXED_PARTITION_ADDR(slot0_partition) + APP_EXE_START_OFFSET); +#endif /* Jump to application */ __asm__ volatile ( From 1c8a5953c5411bb1e453c3747a4d13ac0680ff14 Mon Sep 17 00:00:00 2001 From: Andrzej Puzdrowski Date: Tue, 30 Sep 2025 14:25:29 +0200 Subject: [PATCH 400/420] [nrf noup] bootutil/loader: integrate nRF54h S2RAM with diect-xip Added call which designate active slot so MCUBoot can jump to proper slot when CPU is resuming from S2RAM. Signed-off-by: Andrzej Puzdrowski --- boot/bootutil/src/loader.c | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/boot/bootutil/src/loader.c b/boot/bootutil/src/loader.c index 6c05b3b2b..b7f407e0e 100644 --- a/boot/bootutil/src/loader.c +++ b/boot/bootutil/src/loader.c @@ -84,6 +84,10 @@ int pcd_version_cmp_net(const struct flash_area *fap, struct image_header *hdr); #include "bootutil/key_revocation.h" #endif +#ifdef CONFIG_SOC_NRF54H20_PM_S2RAM_OVERRIDE +void s2ram_designate_slot(uint8_t slot); +#endif + BOOT_LOG_MODULE_DECLARE(mcuboot); static struct boot_loader_state boot_data; @@ -3600,6 +3604,11 @@ context_boot_go(struct boot_loader_state *state, struct boot_rsp *rsp) } } +#ifdef CONFIG_SOC_NRF54H20_PM_S2RAM_OVERRIDE + /* Designate the slot to be used by the PM_S2RAM resume module */ + s2ram_designate_slot((uint8_t)state->slot_usage[0].active_slot); +#endif + /* All image loaded successfully. */ #ifdef MCUBOOT_HAVE_LOGGING print_loaded_images(state); From 754f9586875dd72de367704e42c2121eb60696c3 Mon Sep 17 00:00:00 2001 From: Jamie McCrae Date: Fri, 12 Sep 2025 11:09:19 +0100 Subject: [PATCH 401/420] [nrf noup] bootutil: Use correct set of KMU key slots nrf-squash! [nrf noup] bootutil: Add support for KMU stored ED25519 signature key Will instead use the immutable bootloader key slot IDs if b0 is not enabled, adds a Kconfig which can be used to fall back to the previous slot IDs for previously deployed bootloaders Signed-off-by: Jamie McCrae --- boot/bootutil/src/ed25519_psa.c | 15 ++++++++++++--- boot/zephyr/Kconfig | 11 +++++++++++ 2 files changed, 23 insertions(+), 3 deletions(-) diff --git a/boot/bootutil/src/ed25519_psa.c b/boot/bootutil/src/ed25519_psa.c index 3df1acbdd..c7e3910b1 100644 --- a/boot/bootutil/src/ed25519_psa.c +++ b/boot/bootutil/src/ed25519_psa.c @@ -25,11 +25,20 @@ BOOT_LOG_MODULE_REGISTER(ed25519_psa); #if defined(CONFIG_BOOT_SIGNATURE_USING_KMU) /* List of KMU stored key ids available for MCUboot */ +#define PSA_KEY_INDEX_SIZE 2 + +#if CONFIG_MCUBOOT_MCUBOOT_IMAGE_NUMBER != -1 || \ + defined(CONFIG_NCS_BOOT_SIGNATURE_KMU_UROT_MAPPING) +#define PSA_KEY_STARTING_ID 226 +#else +#define PSA_KEY_STARTING_ID 242 +#endif + #define MAKE_PSA_KMU_KEY_ID(id) PSA_KEY_HANDLE_FROM_CRACEN_KMU_SLOT(CRACEN_KMU_KEY_USAGE_SCHEME_RAW, id) static psa_key_id_t key_ids[] = { - MAKE_PSA_KMU_KEY_ID(226), - MAKE_PSA_KMU_KEY_ID(228), - MAKE_PSA_KMU_KEY_ID(230) + MAKE_PSA_KMU_KEY_ID(PSA_KEY_STARTING_ID), + MAKE_PSA_KMU_KEY_ID(PSA_KEY_STARTING_ID + PSA_KEY_INDEX_SIZE), + MAKE_PSA_KMU_KEY_ID(PSA_KEY_STARTING_ID + (2 * PSA_KEY_INDEX_SIZE)) }; #define KEY_SLOTS_COUNT CONFIG_BOOT_SIGNATURE_KMU_SLOTS diff --git a/boot/zephyr/Kconfig b/boot/zephyr/Kconfig index 1d3417270..5e7f10ae0 100644 --- a/boot/zephyr/Kconfig +++ b/boot/zephyr/Kconfig @@ -421,6 +421,17 @@ config BOOT_SIGNATURE_KMU_SLOTS Selects the number of KMU key slots (also known as generations) to use when verifying an image. +config NCS_BOOT_SIGNATURE_KMU_UROT_MAPPING + bool "Use original mapping [DEPRECATED]" + depends on SOC_SERIES_NRF54LX + depends on MCUBOOT_MCUBOOT_IMAGE_NUMBER = -1 + select DEPRECATED + help + When this option is enabled, it will use the UROT_PUBKEY key slot IDs for the MCUboot + image which are assigned for the non-immutable bootloader IDs, otherwise it will use + the key set for the mode that MCUboot is used in (non-immutable slots when b0 is + enabled, or immutable slots when b0 is not enabled). + endif config BOOT_KEYS_REVOCATION From dd353bcef4b90e0aa93cf12b7fec880e048f640e Mon Sep 17 00:00:00 2001 From: Andrzej Puzdrowski Date: Thu, 18 Sep 2025 15:56:42 +0200 Subject: [PATCH 402/420] [nrf noup] boot/zephyr: improve S2RAM resume support using dedicated API nrf-squash! [nrf noup] boot/zephyr: nRF54h20 resume from S2RAM (hardened) CONFIG_ARM_SOC_START_HOOK=y allow to rework the resume from S2RAM code to work without PM_S2RAM mocking. It allows to implement only what really needed from the MCUboot perspective. Signed-off-by: Andrzej Puzdrowski --- boot/bootutil/src/loader.c | 4 +-- boot/zephyr/CMakeLists.txt | 3 +- boot/zephyr/nrf54h20_custom_s2ram.S | 43 +++++++++++++++++++++++++++++ boot/zephyr/nrf54h20_custom_s2ram.c | 17 ++---------- 4 files changed, 49 insertions(+), 18 deletions(-) create mode 100644 boot/zephyr/nrf54h20_custom_s2ram.S diff --git a/boot/bootutil/src/loader.c b/boot/bootutil/src/loader.c index b7f407e0e..12be5cff3 100644 --- a/boot/bootutil/src/loader.c +++ b/boot/bootutil/src/loader.c @@ -84,7 +84,7 @@ int pcd_version_cmp_net(const struct flash_area *fap, struct image_header *hdr); #include "bootutil/key_revocation.h" #endif -#ifdef CONFIG_SOC_NRF54H20_PM_S2RAM_OVERRIDE +#ifdef CONFIG_SOC_EARLY_RESET_HOOK void s2ram_designate_slot(uint8_t slot); #endif @@ -3604,7 +3604,7 @@ context_boot_go(struct boot_loader_state *state, struct boot_rsp *rsp) } } -#ifdef CONFIG_SOC_NRF54H20_PM_S2RAM_OVERRIDE +#ifdef CONFIG_SOC_EARLY_RESET_HOOK /* Designate the slot to be used by the PM_S2RAM resume module */ s2ram_designate_slot((uint8_t)state->slot_usage[0].active_slot); #endif diff --git a/boot/zephyr/CMakeLists.txt b/boot/zephyr/CMakeLists.txt index 6bd93f35a..b34824def 100644 --- a/boot/zephyr/CMakeLists.txt +++ b/boot/zephyr/CMakeLists.txt @@ -496,7 +496,8 @@ if(CONFIG_MCUBOOT_CLEANUP_ARM_CORE) ) endif() -if(CONFIG_SOC_NRF54H20_PM_S2RAM_OVERRIDE) +if(CONFIG_SOC_EARLY_RESET_HOOK) + zephyr_library_sources(${BOOT_DIR}/zephyr/nrf54h20_custom_s2ram.S) zephyr_library_sources(${BOOT_DIR}/zephyr/nrf54h20_custom_s2ram.c) endif() diff --git a/boot/zephyr/nrf54h20_custom_s2ram.S b/boot/zephyr/nrf54h20_custom_s2ram.S new file mode 100644 index 000000000..1ffa17f42 --- /dev/null +++ b/boot/zephyr/nrf54h20_custom_s2ram.S @@ -0,0 +1,43 @@ +/* + * Copyright (c) 2025, Nordic Semiconductor ASA + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/** + * @file + * @brief ARM Cortex-M suspend-to-RAM resume intermediary code (S2RAM) + */ + + + +/* + * resume or + * reboot reboot==T + *[S2RAM sleep]---------->[ boot (reset.S) ]---->[soc_early_reset_hook]---------->[regular boot] + * | + * | resume==T + * \/ + * [jump to well-known] + * [ App reset vector ] + */ + + + +#include +#include + +GTEXT(pm_s2ram_mark_check_and_mediate) + +GTEXT(soc_early_reset_hook) +SECTION_FUNC(TEXT, soc_early_reset_hook) +#if DT_NODE_EXISTS(DT_NODELABEL(pm_s2ram_stack)) &&\ + DT_NODE_HAS_COMPAT(DT_NODELABEL(pm_s2ram_stack), zephyr_memory_region) + ldr r0, =DT_REG_ADDR(DT_NODELABEL(pm_s2ram_stack)) + DT_REG_SIZE(DT_NODELABEL(pm_s2ram_stack)) +#else +#error "The support of bridge for S2RAM resume requires dedicated small stack" +#endif + msr msp, r0 + push {r0, lr} + bl pm_s2ram_mark_check_and_mediate + pop {r0, pc} diff --git a/boot/zephyr/nrf54h20_custom_s2ram.c b/boot/zephyr/nrf54h20_custom_s2ram.c index 51146e7b3..faa8d9b46 100644 --- a/boot/zephyr/nrf54h20_custom_s2ram.c +++ b/boot/zephyr/nrf54h20_custom_s2ram.c @@ -45,17 +45,6 @@ void s2ram_designate_slot(uint8_t slot) } #endif -int soc_s2ram_suspend(pm_s2ram_system_off_fn_t system_off) -{ - (void)(system_off); - return -1; -} - -void pm_s2ram_mark_set(void) -{ - /* empty */ -} - struct arm_vector_table { uint32_t msp; uint32_t reset; @@ -66,13 +55,13 @@ struct arm_vector_table { */ #define APP_EXE_START_OFFSET 0x800 /* nRF54H20 */ -bool pm_s2ram_mark_check_and_clear(void) +void pm_s2ram_mark_check_and_mediate(void) { uint32_t reset_reason = nrf_resetinfo_resetreas_local_get(NRF_RESETINFO); if (reset_reason != NRF_RESETINFO_RESETREAS_LOCAL_UNRETAINED_MASK) { /* Normal boot */ - return false; + return; } /* S2RAM resume expected, do doublecheck */ @@ -120,6 +109,4 @@ bool pm_s2ram_mark_check_and_clear(void) resume_failed: FIH_PANIC; - - return true; } From 6256d9f6df644231fd196c94a5a92f23c1ad24d4 Mon Sep 17 00:00:00 2001 From: Andrzej Puzdrowski Date: Fri, 26 Sep 2025 13:56:46 +0200 Subject: [PATCH 403/420] [nrf noup] boot/zephyr/socs: update nrf54h20 prj.conf for S2RAM nrf-squash! [nrf noup] boot/zephyr/socs: nrf54h20 prj.conf for S2RAM Updated in order to use optimized configuration. Signed-off-by: Andrzej Puzdrowski --- boot/zephyr/socs/nrf54h20_cpuapp.conf | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/boot/zephyr/socs/nrf54h20_cpuapp.conf b/boot/zephyr/socs/nrf54h20_cpuapp.conf index 9e75ccbb9..2a6df8b12 100644 --- a/boot/zephyr/socs/nrf54h20_cpuapp.conf +++ b/boot/zephyr/socs/nrf54h20_cpuapp.conf @@ -7,8 +7,4 @@ # after suspend to RAM (S2RAM) requested by the application. # MCUboot does not support S2RAM itself, but serves as an immediate actor while waking up # from suspension. -CONFIG_PM=y -CONFIG_PM_DEVICE=n -CONFIG_PM_S2RAM=y -CONFIG_PM_S2RAM_CUSTOM_MARKING=y -CONFIG_SOC_NRF54H20_PM_S2RAM_OVERRIDE=y +CONFIG_SOC_EARLY_RESET_HOOK=y From 473f7d775201ad1f7276330f206cd1823eb9149c Mon Sep 17 00:00:00 2001 From: Andrzej Puzdrowski Date: Mon, 13 Oct 2025 15:38:41 +0200 Subject: [PATCH 404/420] [nrf noup] boards/thingy53_nrf5340_cpuapp: defaulat to LTO make linking time optimization default for the target. Signed-off-by: Andrzej Puzdrowski --- boot/zephyr/boards/thingy53_nrf5340_cpuapp.conf | 3 +++ 1 file changed, 3 insertions(+) diff --git a/boot/zephyr/boards/thingy53_nrf5340_cpuapp.conf b/boot/zephyr/boards/thingy53_nrf5340_cpuapp.conf index bbef18460..4c27c5da6 100644 --- a/boot/zephyr/boards/thingy53_nrf5340_cpuapp.conf +++ b/boot/zephyr/boards/thingy53_nrf5340_cpuapp.conf @@ -73,3 +73,6 @@ CONFIG_FLASH_SIMULATOR_STATS=n # Enable custom command to erase settings partition. CONFIG_ENABLE_MGMT_PERUSER=y CONFIG_BOOT_MGMT_CUSTOM_STORAGE_ERASE=y + +CONFIG_ISR_TABLES_LOCAL_DECLARATION=y +CONFIG_LTO=y From 1a0361b1403121995bb6da407a5394049d183999 Mon Sep 17 00:00:00 2001 From: Dominik Ermel Date: Wed, 1 Oct 2025 12:20:37 +0000 Subject: [PATCH 405/420] [nrf fromtree] bootutil: Fix log module registration Use BOOT_LOG_MODULE_REGISTER(mcuboot_psa_enc), instead of BOOT_LOG_MODULE_DECLARE. Signed-off-by: Dominik Ermel (cherry picked from commit 8a07053d42e592c85cb35b79c4de1b7749943387) --- boot/bootutil/src/encrypted_psa.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/boot/bootutil/src/encrypted_psa.c b/boot/bootutil/src/encrypted_psa.c index 55f7f6f2d..1ef57184d 100644 --- a/boot/bootutil/src/encrypted_psa.c +++ b/boot/bootutil/src/encrypted_psa.c @@ -25,7 +25,7 @@ #include "bootutil_priv.h" #include "bootutil/bootutil_log.h" -BOOT_LOG_MODULE_DECLARE(mcuboot_psa_enc); +BOOT_LOG_MODULE_REGISTER(mcuboot_psa_enc); #if defined(MCUBOOT_HMAC_SHA512) #define PSA_HMAC_HKDF_SHA PSA_ALG_SHA_512 From 9be087ccb0295a6c9a89e85736220f6528e89697 Mon Sep 17 00:00:00 2001 From: Mateusz Michalek Date: Mon, 13 Oct 2025 09:02:20 +0200 Subject: [PATCH 406/420] [nrf noup] boot: zephyr: HMAC_SHA512 for nrf54L series Kconfig nrf-squash! [nrf noup] zephyr: Enforce HMAC-SHA512 for NRF54L with X25519 sets SHA512 for all 54L series Signed-off-by: Mateusz Michalek --- boot/zephyr/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/boot/zephyr/Kconfig b/boot/zephyr/Kconfig index 5e7f10ae0..f738ac66a 100644 --- a/boot/zephyr/Kconfig +++ b/boot/zephyr/Kconfig @@ -795,7 +795,7 @@ if BOOT_ENCRYPT_X25519 && BOOT_USE_PSA_CRYPTO choice BOOT_HMAC_SHA prompt "SHA used for HMAC and HKDF in encryption key exchange" - default BOOT_HMAC_SHA512 if BOOT_ENCRYPT_X25519 && (SOC_NRF54L15_CPUAPP || SOC_NRF54LM20A_ENGA_CPUAPP) + default BOOT_HMAC_SHA512 if BOOT_ENCRYPT_X25519 && SOC_SERIES_NRF54LX default BOOT_HMAC_SHA256 help HMAC/HKDF sha algorithm may be selected to synchronize sha From 1a9ec9300e75d321a478ed89a5f7eceff13c859e Mon Sep 17 00:00:00 2001 From: Tomasz Chyrowicz Date: Thu, 25 Sep 2025 16:11:59 +0200 Subject: [PATCH 407/420] [nrf noup] boot: Configure ROM_END_OFFSET images Add a possibility to specify, which images should have the ROM_END_OFFSET automatically adjusted. Use the UpdateableImages_Get(..) functionality to configure all updateable images (including radio images as well as variants) in the default configuration. Ref: NCSDK-35612 Signed-off-by: Tomasz Chyrowicz --- boot/zephyr/sysbuild/CMakeLists.txt | 42 ++++++++++++++++++++--------- 1 file changed, 29 insertions(+), 13 deletions(-) diff --git a/boot/zephyr/sysbuild/CMakeLists.txt b/boot/zephyr/sysbuild/CMakeLists.txt index 5a2a881b7..555136a4d 100644 --- a/boot/zephyr/sysbuild/CMakeLists.txt +++ b/boot/zephyr/sysbuild/CMakeLists.txt @@ -25,19 +25,35 @@ function(${SYSBUILD_CURRENT_MODULE_NAME}_post_image_cmake) return() endif() - foreach(image ${IMAGES}) - set(app_type) - get_property(app_type TARGET ${image} PROPERTY APP_TYPE) - - if("${app_type}" STREQUAL "MAIN") - sysbuild_get(mcuboot_image_footer_size IMAGE mcuboot CACHE) - sysbuild_get(mcuboot_image_upgrade_footer_size IMAGE mcuboot CACHE) - math(EXPR mcuboot_image_footer_size "${mcuboot_image_footer_size}" OUTPUT_FORMAT HEXADECIMAL) - math(EXPR mcuboot_image_upgrade_footer_size "${mcuboot_image_upgrade_footer_size}" OUTPUT_FORMAT HEXADECIMAL) - - set_property(TARGET ${image} APPEND_STRING PROPERTY CONFIG "CONFIG_ROM_END_OFFSET=${mcuboot_image_footer_size}\n") - set_property(TARGET ${image} APPEND_STRING PROPERTY CONFIG "CONFIG_MCUBOOT_UPDATE_FOOTER_SIZE=${mcuboot_image_upgrade_footer_size}\n") - return() + set(auto_images) + if("${SB_CONFIG_MCUBOOT_IMAGES_ROM_END_OFFSET_AUTO}" STREQUAL "") + UpdateableImage_Get(auto_images ALL) + + # If the list of updateable images is empty, look for the "MAIN" image type. + list(LENGTH auto_images num_auto_images) + if(num_auto_images EQUAL 0) + foreach(image ${IMAGES}) + set(app_type) + get_property(app_type TARGET ${image} PROPERTY APP_TYPE) + + if("${app_type}" STREQUAL "MAIN") + list(APPEND auto_images ${image}) + endif() + endforeach() endif() + else() + set(auto_images "${SB_CONFIG_MCUBOOT_IMAGES_ROM_END_OFFSET_AUTO}") + endif() + + foreach(image ${auto_images}) + set(mcuboot_image_footer_size) + set(mcuboot_image_upgrade_footer_size) + sysbuild_get(mcuboot_image_footer_size IMAGE mcuboot CACHE) + sysbuild_get(mcuboot_image_upgrade_footer_size IMAGE mcuboot CACHE) + math(EXPR mcuboot_image_footer_size "${mcuboot_image_footer_size}" OUTPUT_FORMAT HEXADECIMAL) + math(EXPR mcuboot_image_upgrade_footer_size "${mcuboot_image_upgrade_footer_size}" OUTPUT_FORMAT HEXADECIMAL) + + set_property(TARGET ${image} APPEND_STRING PROPERTY CONFIG "CONFIG_ROM_END_OFFSET=${mcuboot_image_footer_size}\n") + set_property(TARGET ${image} APPEND_STRING PROPERTY CONFIG "CONFIG_MCUBOOT_UPDATE_FOOTER_SIZE=${mcuboot_image_upgrade_footer_size}\n") endforeach() endfunction(${SYSBUILD_CURRENT_MODULE_NAME}_post_image_cmake) From 6227edc0c27378e68e748065e3fd28288dc0e79a Mon Sep 17 00:00:00 2001 From: Artur Hadasz Date: Wed, 15 Oct 2025 13:55:32 +0200 Subject: [PATCH 408/420] [nrf noup] boot/zephyr: fix and rename nrf54l15dk ext flash configs nrf-squash! [nrf noup] boot/zephyr: update nrf54l15dk ext flash configs This commit removes the partition definitions from nrf54L ext flash configs, as they are no longer needed, as the pure DTS configuration is no longer supported on nRF54L. They also caused issues, as they were not compatible with nRF54L10 and nRF54L05. It renames nrf54l15dk_nrf54l15_cpuapp_ext_flash.* overlays to nrf54l15dk_ext_flash.*, as now the same configuration can be used on nRF54L15, nRF54L10 and nRF54L05. Signed-off-by: Artur Hadasz --- ...t_flash.conf => nrf54l15dk_ext_flash.conf} | 0 .../boards/nrf54l15dk_ext_flash.overlay | 9 ++++ ...f54l15dk_nrf54l15_cpuapp_ext_flash.overlay | 48 ------------------- 3 files changed, 9 insertions(+), 48 deletions(-) rename boot/zephyr/boards/{nrf54l15dk_nrf54l15_cpuapp_ext_flash.conf => nrf54l15dk_ext_flash.conf} (100%) create mode 100644 boot/zephyr/boards/nrf54l15dk_ext_flash.overlay delete mode 100644 boot/zephyr/boards/nrf54l15dk_nrf54l15_cpuapp_ext_flash.overlay diff --git a/boot/zephyr/boards/nrf54l15dk_nrf54l15_cpuapp_ext_flash.conf b/boot/zephyr/boards/nrf54l15dk_ext_flash.conf similarity index 100% rename from boot/zephyr/boards/nrf54l15dk_nrf54l15_cpuapp_ext_flash.conf rename to boot/zephyr/boards/nrf54l15dk_ext_flash.conf diff --git a/boot/zephyr/boards/nrf54l15dk_ext_flash.overlay b/boot/zephyr/boards/nrf54l15dk_ext_flash.overlay new file mode 100644 index 000000000..410388bfa --- /dev/null +++ b/boot/zephyr/boards/nrf54l15dk_ext_flash.overlay @@ -0,0 +1,9 @@ +/ { + chosen { + nordic,pm-ext-flash = &mx25r64; + }; +}; + +&mx25r64 { + status = "okay"; +}; diff --git a/boot/zephyr/boards/nrf54l15dk_nrf54l15_cpuapp_ext_flash.overlay b/boot/zephyr/boards/nrf54l15dk_nrf54l15_cpuapp_ext_flash.overlay deleted file mode 100644 index ba6274221..000000000 --- a/boot/zephyr/boards/nrf54l15dk_nrf54l15_cpuapp_ext_flash.overlay +++ /dev/null @@ -1,48 +0,0 @@ -/ { - chosen { - nordic,pm-ext-flash = &mx25r64; - zephyr,code-partition = &boot_partition; - }; -}; - -/delete-node/ &boot_partition; -/delete-node/ &slot0_partition; -/delete-node/ &slot1_partition; - -/delete-node/ &storage_partition; - -&cpuapp_rram { - reg = < 0x0 DT_SIZE_K(1524) >; - - partitions { - boot_partition: partition@0 { - label = "mcuboot"; - reg = <0x000000000 0x00014000>; - }; - - slot0_partition: partition@14000 { - label = "image-0"; - reg = <0x000014000 0x0015A000>; - }; - - storage_partition: partition@16E000 { - label = "storage"; - reg = < 0x16E000 0x9000 >; - }; - }; -}; - -&mx25r64 { - status = "okay"; - - partitions { - compatible = "fixed-partitions"; - #address-cells = <1>; - #size-cells = <1>; - - slot1_partition: partition@0 { - label = "image-1"; - reg = <0x000000000 0x0015A000>; - }; - }; -}; From 1734eeb0c92562dcef18cc9a24382216500a2d61 Mon Sep 17 00:00:00 2001 From: Jamie McCrae Date: Wed, 8 Oct 2025 12:29:37 +0100 Subject: [PATCH 409/420] [nrf fromtree] scripts: Safely fix python files Uses ruff with --fix to fix python files in this folder Signed-off-by: Jamie McCrae (cherry picked from commit f23154c251e07013d45c9f97c875404e83e7d2dc) --- scripts/assemble.py | 14 ++++----- scripts/imgtool/boot_record.py | 2 +- scripts/imgtool/dumpinfo.py | 29 ++++++++--------- scripts/imgtool/image.py | 47 +++++++++++----------------- scripts/imgtool/keys/__init__.py | 18 +++++------ scripts/imgtool/keys/ecdsa.py | 3 +- scripts/imgtool/keys/ecdsa_test.py | 3 +- scripts/imgtool/keys/ed25519.py | 5 ++- scripts/imgtool/keys/ed25519_test.py | 3 +- scripts/imgtool/keys/general.py | 31 +++++++++--------- scripts/imgtool/keys/privatebytes.py | 5 ++- scripts/imgtool/keys/rsa.py | 13 ++++---- scripts/imgtool/keys/rsa_test.py | 4 +-- scripts/imgtool/keys/x25519.py | 3 +- scripts/imgtool/main.py | 46 +++++++++++++-------------- scripts/setup.py | 1 - scripts/tests/test_commands.py | 3 +- scripts/tests/test_compression.py | 5 ++- scripts/tests/test_keys.py | 4 +-- 19 files changed, 107 insertions(+), 132 deletions(-) diff --git a/scripts/assemble.py b/scripts/assemble.py index 05f979379..f73668d72 100755 --- a/scripts/assemble.py +++ b/scripts/assemble.py @@ -22,13 +22,13 @@ import argparse import errno -import io -import re import os import os.path import pickle +import re import sys + def same_keys(a, b): """Determine if the dicts a and b have the same keys in them""" for ak in a.keys(): @@ -42,7 +42,7 @@ def same_keys(a, b): offset_re = re.compile(r"^#define DT_FLASH_AREA_([0-9A-Z_]+)_OFFSET(_0)?\s+(0x[0-9a-fA-F]+|[0-9]+)$") size_re = re.compile(r"^#define DT_FLASH_AREA_([0-9A-Z_]+)_SIZE(_0)?\s+(0x[0-9a-fA-F]+|[0-9]+)$") -class Assembly(): +class Assembly: def __init__(self, output, bootdir, edt): self.find_slots(edt) try: @@ -83,7 +83,7 @@ def find_slots(self, edt): def add_image(self, source, partition): with open(self.output, 'ab') as ofd: pos = ofd.tell() - print("partition {}, pos={}, offset={}".format(partition, pos, self.offsets[partition])) + print(f"partition {partition}, pos={pos}, offset={self.offsets[partition]}") if pos > self.offsets[partition]: raise Exception("Partitions not in order, unsupported") if pos < self.offsets[partition]: @@ -92,16 +92,16 @@ def add_image(self, source, partition): with open(source, 'rb') as rfd: ibuf = rfd.read() if len(ibuf) > self.sizes[partition]: - raise Exception("Image {} is too large for partition".format(source)) + raise Exception(f"Image {source} is too large for partition") ofd.write(ibuf) def find_board_name(bootdir): dot_config = os.path.join(bootdir, "zephyr", ".config") - with open(dot_config, "r") as f: + with open(dot_config) as f: for line in f: if line.startswith("CONFIG_BOARD="): return line.split("=", 1)[1].strip('"') - raise Exception("Expected CONFIG_BOARD line in {}".format(dot_config)) + raise Exception(f"Expected CONFIG_BOARD line in {dot_config}") def main(): parser = argparse.ArgumentParser() diff --git a/scripts/imgtool/boot_record.py b/scripts/imgtool/boot_record.py index fb98b2eab..f683fac73 100644 --- a/scripts/imgtool/boot_record.py +++ b/scripts/imgtool/boot_record.py @@ -48,5 +48,5 @@ def create_sw_component_data(sw_type, sw_version, sw_measurement_description, # Note: The measurement value must be the last item of the property # list because later it will be modified by the bootloader. last_key = list(properties.keys())[-1] - assert SwComponent.MEASUREMENT_VALUE == last_key, 'Measurement value is not the last item of the property list' + assert last_key == SwComponent.MEASUREMENT_VALUE, 'Measurement value is not the last item of the property list' return dumps(properties) diff --git a/scripts/imgtool/dumpinfo.py b/scripts/imgtool/dumpinfo.py index 40ece79f1..c4f31cb40 100644 --- a/scripts/imgtool/dumpinfo.py +++ b/scripts/imgtool/dumpinfo.py @@ -19,7 +19,6 @@ """ import os.path import struct -import sys import click import yaml @@ -51,7 +50,7 @@ def parse_enc(key_field_len): if key_field_len is not None: - return "(len: {}, if BOOT_SWAP_SAVE_ENCTLV is unset)".format(hex(key_field_len)) + return f"(len: {hex(key_field_len)}, if BOOT_SWAP_SAVE_ENCTLV is unset)" else: return "Image not encrypted" @@ -69,7 +68,7 @@ def parse_status(status_hex): def parse_boot_magic(trailer_magic): magic = "" for i in range(BOOT_MAGIC_SIZE): - magic += "{0:#04x} ".format(trailer_magic[i]) + magic += f"{trailer_magic[i]:#04x} " if i == (BOOT_MAGIC_SIZE / 2 - 1): magic += ("\n" + " ") return magic @@ -103,16 +102,15 @@ def print_tlv_records(tlv_list): tlv_type, tlv_length, tlv_data = tlv.keys() if tlv[tlv_type] in TLV_TYPES: - print(" " * indent, "{}: {} ({})".format( - tlv_type, TLV_TYPES[tlv[tlv_type]], hex(tlv[tlv_type]))) + print(" " * indent, f"{tlv_type}: {TLV_TYPES[tlv[tlv_type]]} ({hex(tlv[tlv_type])})") else: print(" " * indent, "{}: {} ({})".format( tlv_type, "UNKNOWN", hex(tlv[tlv_type]))) - print(" " * indent, "{}: ".format(tlv_length), hex(tlv[tlv_length])) - print(" " * indent, "{}: ".format(tlv_data), end="") + print(" " * indent, f"{tlv_length}: ", hex(tlv[tlv_length])) + print(" " * indent, f"{tlv_data}: ", end="") for j, data in enumerate(tlv[tlv_data]): - print("{0:#04x}".format(data), end=" ") + print(f"{data:#04x}", end=" ") if ((j + 1) % 8 == 0) and ((j + 1) != len(tlv[tlv_data])): print("\n", end=" " * (indent + 7)) print() @@ -133,7 +131,7 @@ def dump_imginfo(imgfile, outfile=None, silent=False): with open(imgfile, "rb") as f: b = f.read() except FileNotFoundError: - raise click.UsageError("Image file not found ({})".format(imgfile)) + raise click.UsageError(f"Image file not found ({imgfile})") # Parsing the image header _header = struct.unpack('IIHHIIBBHI', b[:28]) @@ -268,8 +266,7 @@ def dump_imginfo(imgfile, outfile=None, silent=False): if value & image.IMAGE_F[flag]: if flag_string: flag_string += ("\n" + (" " * 20)) - flag_string += "{} ({})".format( - flag, hex(image.IMAGE_F[flag])) + flag_string += f"{flag} ({hex(image.IMAGE_F[flag])})" value = flag_string if not isinstance(value, str): @@ -279,7 +276,7 @@ def dump_imginfo(imgfile, outfile=None, silent=False): # Image payload _sectionoff = header["hdr_size"] - frame_header_text = "Payload (offset: {})".format(hex(_sectionoff)) + frame_header_text = f"Payload (offset: {hex(_sectionoff)})" frame_content = "FW image (size: {} Bytes)".format(hex(header["img_size"])) print_in_frame(frame_header_text, frame_content) @@ -287,7 +284,7 @@ def dump_imginfo(imgfile, outfile=None, silent=False): _sectionoff += header["img_size"] if protected_tlv_size != 0: # Protected TLV area - section_name = "Protected TLV area (offset: {})".format(hex(_sectionoff)) + section_name = f"Protected TLV area (offset: {hex(_sectionoff)})" print_in_row(section_name) print("magic: ", hex(tlv_area["tlv_hdr_prot"]["magic"])) print("area size:", hex(tlv_area["tlv_hdr_prot"]["tlv_tot"])) @@ -295,7 +292,7 @@ def dump_imginfo(imgfile, outfile=None, silent=False): print("#" * _LINE_LENGTH) _sectionoff += protected_tlv_size - section_name = "TLV area (offset: {})".format(hex(_sectionoff)) + section_name = f"TLV area (offset: {hex(_sectionoff)})" print_in_row(section_name) print("magic: ", hex(tlv_area["tlv_hdr"]["magic"])) print("area size:", hex(tlv_area["tlv_hdr"]["tlv_tot"])) @@ -305,8 +302,8 @@ def dump_imginfo(imgfile, outfile=None, silent=False): if _img_pad_size: _sectionoff += tlv_area["tlv_hdr"]["tlv_tot"] _erased_val = b[_sectionoff] - frame_header_text = "Image padding (offset: {})".format(hex(_sectionoff)) - frame_content = "padding ({})".format(hex(_erased_val)) + frame_header_text = f"Image padding (offset: {hex(_sectionoff)})" + frame_content = f"padding ({hex(_erased_val)})" print_in_frame(frame_header_text, frame_content) # Image trailer diff --git a/scripts/imgtool/image.py b/scripts/imgtool/image.py index 2f68f9929..598dc6e10 100755 --- a/scripts/imgtool/image.py +++ b/scripts/imgtool/image.py @@ -20,19 +20,13 @@ Image signing and management. """ -from . import version as versmod -from .boot_record import create_sw_component_data -import click import copy -from enum import Enum -import array -from intelhex import IntelHex import hashlib -import array import os.path import re import struct import uuid +from collections import namedtuple from enum import Enum import click @@ -46,11 +40,10 @@ from cryptography.hazmat.primitives.serialization import Encoding, PublicFormat from intelhex import IntelHex -from . import version as versmod, keys +from . import keys +from . import version as versmod from .boot_record import create_sw_component_data -from .keys import rsa, ecdsa, x25519 - -from collections import namedtuple +from .keys import ecdsa, rsa, x25519 IMAGE_MAGIC = 0x96f3b83d IMAGE_HEADER_SIZE = 32 @@ -125,7 +118,7 @@ def align_up(num, align): return (num + (align - 1)) & ~(align - 1) -class TLV(): +class TLV: def __init__(self, endian, magic=TLV_INFO_MAGIC): self.magic = magic self.buf = bytearray() @@ -141,9 +134,8 @@ def add(self, kind, payload): e = STRUCT_ENDIAN_DICT[self.endian] if isinstance(kind, int): if not TLV_VENDOR_RES_MIN <= kind <= TLV_VENDOR_RES_MAX: - msg = "Invalid custom TLV type value '0x{:04x}', allowed " \ - "value should be between 0x{:04x} and 0x{:04x}".format( - kind, TLV_VENDOR_RES_MIN, TLV_VENDOR_RES_MAX) + msg = f"Invalid custom TLV type value '0x{kind:04x}', allowed " \ + f"value should be between 0x{TLV_VENDOR_RES_MIN:04x} and 0x{TLV_VENDOR_RES_MAX:04x}" raise click.UsageError(msg) buf = struct.pack(e + 'HH', kind, len(payload)) else: @@ -153,7 +145,7 @@ def add(self, kind, payload): def get(self): if len(self.buf) == 0: - return bytes() + return b"" e = STRUCT_ENDIAN_DICT[self.endian] header = struct.pack(e + 'HH', self.magic, len(self)) return header + bytes(self.buf) @@ -177,7 +169,7 @@ def get(self): def is_sha_tlv(tlv): - return tlv in TLV_SHA_TO_SHA_AND_ALG.keys() + return tlv in TLV_SHA_TO_SHA_AND_ALG def tlv_sha_to_sha(tlv): @@ -224,8 +216,8 @@ def key_and_user_sha_to_alg_and_tlv(key, user_sha, is_pure = False): allowed = allowed_key_ssh[type(key)] except KeyError: - raise click.UsageError("Colud not find allowed hash algorithms for {}" - .format(type(key))) + raise click.UsageError(f"Colud not find allowed hash algorithms for {type(key)}" + ) # Pure enforces auto, and user selection is ignored if user_sha == 'auto' or is_pure: @@ -234,8 +226,8 @@ def key_and_user_sha_to_alg_and_tlv(key, user_sha, is_pure = False): if user_sha in allowed: return USER_SHA_TO_ALG_AND_TLV[user_sha] - raise click.UsageError("Key {} can not be used with --sha {}; allowed sha are one of {}" - .format(key.sig_type(), user_sha, allowed)) + raise click.UsageError(f"Key {key.sig_type()} can not be used with --sha {user_sha}; allowed sha are one of {allowed}" + ) def get_digest(tlv_type, hash_region): @@ -461,9 +453,8 @@ def check_trailer(self): self.save_enctlv, self.enctlv_len) padding = self.slot_size - (len(self.payload) + tsize) if padding < 0: - msg = "Image size (0x{:x}) + trailer (0x{:x}) exceeds " \ - "requested size 0x{:x}".format( - len(self.payload), tsize, self.slot_size) + msg = f"Image size (0x{len(self.payload):x}) + trailer (0x{tsize:x}) exceeds " \ + f"requested size 0x{self.slot_size:x}" raise click.UsageError(msg) def ecies_hkdf(self, enckey, plainkey, hmac_sha_alg): @@ -550,9 +541,8 @@ def create(self, key, public_key_format, enckey, dependencies=None, if sw_type is not None: if len(sw_type) > MAX_SW_TYPE_LENGTH: - msg = "'{}' is too long ({} characters) for sw_type. Its " \ - "maximum allowed length is 12 characters.".format( - sw_type, len(sw_type)) + msg = f"'{sw_type}' is too long ({len(sw_type)} characters) for sw_type. Its " \ + "maximum allowed length is 12 characters." raise click.UsageError(msg) image_version = (str(self.version.major) + '.' @@ -853,8 +843,7 @@ def _trailer_size(self, write_size, max_sectors, overwrite_only, enckey, return self.max_align * 2 + magic_align_size else: if write_size not in set([1, 2, 4, 8, 16, 32]): - raise click.BadParameter("Invalid alignment: {}".format( - write_size)) + raise click.BadParameter(f"Invalid alignment: {write_size}") m = DEFAULT_MAX_SECTORS if max_sectors is None else max_sectors trailer = m * 3 * write_size # status area if enckey is not None: diff --git a/scripts/imgtool/keys/__init__.py b/scripts/imgtool/keys/__init__.py index ed2fed57e..b37337af0 100644 --- a/scripts/imgtool/keys/__init__.py +++ b/scripts/imgtool/keys/__init__.py @@ -21,19 +21,17 @@ from cryptography.hazmat.backends import default_backend from cryptography.hazmat.primitives import serialization -from cryptography.hazmat.primitives.asymmetric.rsa import ( - RSAPrivateKey, RSAPublicKey) from cryptography.hazmat.primitives.asymmetric.ec import ( - EllipticCurvePrivateKey, EllipticCurvePublicKey) -from cryptography.hazmat.primitives.asymmetric.ed25519 import ( - Ed25519PrivateKey, Ed25519PublicKey) -from cryptography.hazmat.primitives.asymmetric.x25519 import ( - X25519PrivateKey, X25519PublicKey) + EllipticCurvePrivateKey, + EllipticCurvePublicKey, +) +from cryptography.hazmat.primitives.asymmetric.ed25519 import Ed25519PrivateKey, Ed25519PublicKey +from cryptography.hazmat.primitives.asymmetric.rsa import RSAPrivateKey, RSAPublicKey +from cryptography.hazmat.primitives.asymmetric.x25519 import X25519PrivateKey, X25519PublicKey -from .rsa import RSA, RSAPublic, RSAUsageError, RSA_KEY_SIZES -from .ecdsa import (ECDSA256P1, ECDSA256P1Public, - ECDSA384P1, ECDSA384P1Public, ECDSAUsageError) +from .ecdsa import ECDSA256P1, ECDSA384P1, ECDSA256P1Public, ECDSA384P1Public, ECDSAUsageError from .ed25519 import Ed25519, Ed25519Public, Ed25519UsageError +from .rsa import RSA, RSA_KEY_SIZES, RSAPublic, RSAUsageError from .x25519 import X25519, X25519Public, X25519UsageError diff --git a/scripts/imgtool/keys/ecdsa.py b/scripts/imgtool/keys/ecdsa.py index 52357b1d0..2f34dcc5e 100644 --- a/scripts/imgtool/keys/ecdsa.py +++ b/scripts/imgtool/keys/ecdsa.py @@ -4,7 +4,6 @@ # SPDX-License-Identifier: Apache-2.0 import os.path -import hashlib from cryptography.hazmat.backends import default_backend from cryptography.hazmat.primitives import serialization @@ -27,7 +26,7 @@ def __init__(self, key): self.key = key def _unsupported(self, name): - raise ECDSAUsageError("Operation {} requires private key".format(name)) + raise ECDSAUsageError(f"Operation {name} requires private key") def _get_public(self): return self.key diff --git a/scripts/imgtool/keys/ecdsa_test.py b/scripts/imgtool/keys/ecdsa_test.py index 55f6cc489..8a6bb374a 100644 --- a/scripts/imgtool/keys/ecdsa_test.py +++ b/scripts/imgtool/keys/ecdsa_test.py @@ -16,7 +16,8 @@ sys.path.insert(0, os.path.abspath(os.path.join(os.path.dirname(__file__), '../..'))) -from imgtool.keys import load, ECDSA256P1, ECDSAUsageError +from imgtool.keys import ECDSA256P1, ECDSAUsageError, load + class EcKeyGeneration(unittest.TestCase): diff --git a/scripts/imgtool/keys/ed25519.py b/scripts/imgtool/keys/ed25519.py index a9959a665..9184a0dd6 100644 --- a/scripts/imgtool/keys/ed25519.py +++ b/scripts/imgtool/keys/ed25519.py @@ -22,7 +22,7 @@ def shortname(self): return "ed25519" def _unsupported(self, name): - raise Ed25519UsageError("Operation {} requires private key".format(name)) + raise Ed25519UsageError(f"Operation {name} requires private key") def _get_public(self): return self.key @@ -87,8 +87,7 @@ def _get_public(self): return self.key.public_key() def get_private_bytes(self, minimal, format): - raise Ed25519UsageError("Operation not supported with {} keys".format( - self.shortname())) + raise Ed25519UsageError(f"Operation not supported with {self.shortname()} keys") def export_private(self, path, passwd=None): """ diff --git a/scripts/imgtool/keys/ed25519_test.py b/scripts/imgtool/keys/ed25519_test.py index ae9ea49c0..9a2d1cb0c 100644 --- a/scripts/imgtool/keys/ed25519_test.py +++ b/scripts/imgtool/keys/ed25519_test.py @@ -12,11 +12,10 @@ import unittest from cryptography.exceptions import InvalidSignature -from cryptography.hazmat.primitives.asymmetric import ed25519 sys.path.insert(0, os.path.abspath(os.path.join(os.path.dirname(__file__), '../..'))) -from imgtool.keys import load, Ed25519, Ed25519UsageError +from imgtool.keys import Ed25519, Ed25519UsageError, load class Ed25519KeyGeneration(unittest.TestCase): diff --git a/scripts/imgtool/keys/general.py b/scripts/imgtool/keys/general.py index 4ff700c49..dfb4e3663 100644 --- a/scripts/imgtool/keys/general.py +++ b/scripts/imgtool/keys/general.py @@ -2,16 +2,15 @@ # SPDX-License-Identifier: Apache-2.0 -import binascii -import io import os import sys -from cryptography.hazmat.primitives.hashes import Hash, SHA256 + +from cryptography.hazmat.primitives.hashes import SHA256, Hash AUTOGEN_MESSAGE = "/* Autogenerated by imgtool.py, do not edit. */" -class FileHandler(object): +class FileHandler: def __init__(self, file, *args, **kwargs): self.file_in = file self.args = args @@ -29,7 +28,7 @@ def __exit__(self, *args): self.file.close() -class KeyClass(object): +class KeyClass: def _emit(self, header, trailer, encoded_bytes, indent, file=sys.stdout, len_format=None): with FileHandler(file, 'w') as file: @@ -45,7 +44,7 @@ def _emit_to_output(self, header, trailer, encoded_bytes, indent, file, print("\n" + indent, end='', file=file) else: print(" ", end='', file=file) - print("0x{:02x},".format(b), end='', file=file) + print(f"0x{b:02x},", end='', file=file) print("\n" + trailer, file=file) if len_format is not None: print(len_format.format(len(encoded_bytes)), file=file) @@ -62,26 +61,26 @@ def _emit_raw(self, encoded_bytes, file): def emit_c_public(self, file=sys.stdout): self._emit( - header="const unsigned char {}_pub_key[] = {{" - .format(self.shortname()), + header=f"const unsigned char {self.shortname()}_pub_key[] = {{" + , trailer="};", encoded_bytes=self.get_public_bytes(), indent=" ", - len_format="const unsigned int {}_pub_key_len = {{}};" - .format(self.shortname()), + len_format=f"const unsigned int {self.shortname()}_pub_key_len = {{}};" + , file=file) def emit_c_public_hash(self, file=sys.stdout): digest = Hash(SHA256()) digest.update(self.get_public_bytes()) self._emit( - header="const unsigned char {}_pub_key_hash[] = {{" - .format(self.shortname()), + header=f"const unsigned char {self.shortname()}_pub_key_hash[] = {{" + , trailer="};", encoded_bytes=digest.finalize(), indent=" ", - len_format="const unsigned int {}_pub_key_hash_len = {{}};" - .format(self.shortname()), + len_format=f"const unsigned int {self.shortname()}_pub_key_hash_len = {{}};" + , file=file) def emit_raw_public(self, file=sys.stdout): @@ -94,8 +93,8 @@ def emit_raw_public_hash(self, file=sys.stdout): def emit_rust_public(self, file=sys.stdout): self._emit( - header="static {}_PUB_KEY: &[u8] = &[" - .format(self.shortname().upper()), + header=f"static {self.shortname().upper()}_PUB_KEY: &[u8] = &[" + , trailer="];", encoded_bytes=self.get_public_bytes(), indent=" ", diff --git a/scripts/imgtool/keys/privatebytes.py b/scripts/imgtool/keys/privatebytes.py index 8027ac858..abb98c18e 100644 --- a/scripts/imgtool/keys/privatebytes.py +++ b/scripts/imgtool/keys/privatebytes.py @@ -3,13 +3,12 @@ from cryptography.hazmat.primitives import serialization -class PrivateBytesMixin(): +class PrivateBytesMixin: def _get_private_bytes(self, minimal, format, exclass): if format is None: format = self._DEFAULT_FORMAT if format not in self._VALID_FORMATS: - raise exclass("{} does not support {}".format( - self.shortname(), format)) + raise exclass(f"{self.shortname()} does not support {format}") return format, self.key.private_bytes( encoding=serialization.Encoding.DER, format=self._VALID_FORMATS[format], diff --git a/scripts/imgtool/keys/rsa.py b/scripts/imgtool/keys/rsa.py index d4793c538..a61a8d746 100644 --- a/scripts/imgtool/keys/rsa.py +++ b/scripts/imgtool/keys/rsa.py @@ -7,13 +7,12 @@ from cryptography.hazmat.backends import default_backend from cryptography.hazmat.primitives import serialization from cryptography.hazmat.primitives.asymmetric import rsa -from cryptography.hazmat.primitives.asymmetric.padding import PSS, MGF1 +from cryptography.hazmat.primitives.asymmetric.padding import MGF1, PSS from cryptography.hazmat.primitives.hashes import SHA256 from .general import KeyClass from .privatebytes import PrivateBytesMixin - # Sizes that bootutil will recognize RSA_KEY_SIZES = [2048, 3072] @@ -34,7 +33,7 @@ def shortname(self): return "rsa" def _unsupported(self, name): - raise RSAUsageError("Operation {} requires private key".format(name)) + raise RSAUsageError(f"Operation {name} requires private key") def _get_public(self): return self.key @@ -65,10 +64,10 @@ def export_public(self, path): f.write(pem) def sig_type(self): - return "PKCS1_PSS_RSA{}_SHA256".format(self.key_size()) + return f"PKCS1_PSS_RSA{self.key_size()}_SHA256" def sig_tlv(self): - return"RSA{}".format(self.key_size()) + return f"RSA{self.key_size()}" def sig_len(self): return self.key_size() / 8 @@ -94,8 +93,8 @@ def __init__(self, key): @staticmethod def generate(key_size=2048): if key_size not in RSA_KEY_SIZES: - raise RSAUsageError("Key size {} is not supported by MCUboot" - .format(key_size)) + raise RSAUsageError(f"Key size {key_size} is not supported by MCUboot" + ) pk = rsa.generate_private_key( public_exponent=65537, key_size=key_size, diff --git a/scripts/imgtool/keys/rsa_test.py b/scripts/imgtool/keys/rsa_test.py index 7610106bc..f0b2ecbe1 100644 --- a/scripts/imgtool/keys/rsa_test.py +++ b/scripts/imgtool/keys/rsa_test.py @@ -11,14 +11,14 @@ import unittest from cryptography.exceptions import InvalidSignature -from cryptography.hazmat.primitives.asymmetric.padding import PSS, MGF1 +from cryptography.hazmat.primitives.asymmetric.padding import MGF1, PSS from cryptography.hazmat.primitives.hashes import SHA256 # Setup sys path so 'imgtool' is in it. sys.path.insert(0, os.path.abspath(os.path.join(os.path.dirname(__file__), '../..'))) -from imgtool.keys import load, RSA, RSAUsageError +from imgtool.keys import RSA, RSAUsageError, load from imgtool.keys.rsa import RSA_KEY_SIZES diff --git a/scripts/imgtool/keys/x25519.py b/scripts/imgtool/keys/x25519.py index a99cf183e..00ef0d1de 100644 --- a/scripts/imgtool/keys/x25519.py +++ b/scripts/imgtool/keys/x25519.py @@ -4,7 +4,6 @@ # SPDX-License-Identifier: Apache-2.0 -from cryptography.hazmat.backends import default_backend from cryptography.hazmat.primitives import serialization from cryptography.hazmat.primitives.asymmetric import x25519 @@ -24,7 +23,7 @@ def shortname(self): return "x25519" def _unsupported(self, name): - raise X25519UsageError("Operation {} requires private key".format(name)) + raise X25519UsageError(f"Operation {name} requires private key") def _get_public(self): return self.key diff --git a/scripts/imgtool/main.py b/scripts/imgtool/main.py index 646c9e961..b0b1b0dba 100755 --- a/scripts/imgtool/main.py +++ b/scripts/imgtool/main.py @@ -17,22 +17,22 @@ # See the License for the specific language governing permissions and # limitations under the License. -import re -import click +import base64 import getpass -import imgtool.keys as keys -import sys -import struct -import os import lzma -import hashlib -import base64 +import re +import struct +import sys from collections import namedtuple + +import click + +import imgtool.keys as keys from imgtool import image, imgtool_version -from imgtool.version import decode_version from imgtool.dumpinfo import dump_imginfo -from .keys import ( - RSAUsageError, ECDSAUsageError, Ed25519UsageError, X25519UsageError) +from imgtool.version import decode_version + +from .keys import ECDSAUsageError, Ed25519UsageError, RSAUsageError, X25519UsageError comp_default_dictsize=131072 comp_default_pb=2 @@ -241,9 +241,9 @@ def verify(key, imgfile): print("Image was correctly validated") print("Image version: {}.{}.{}+{}".format(*version)) if digest: - print("Image digest: {}".format(digest.hex())) + print(f"Image digest: {digest.hex()}") if signature and digest is None: - print("Image signature over image: {}".format(signature.hex())) + print(f"Image signature over image: {signature.hex()}") return elif ret == image.VerifyResult.INVALID_MAGIC: print("Invalid image magic; is this an MCUboot image?") @@ -256,7 +256,7 @@ def verify(key, imgfile): elif ret == image.VerifyResult.KEY_MISMATCH: print("Key type does not match TLV record") else: - print("Unknown return code: {}".format(ret)) + print(f"Unknown return code: {ret}") sys.exit(1) @@ -278,7 +278,7 @@ def validate_version(ctx, param, value): decode_version(value) return value except ValueError as e: - raise click.BadParameter("{}".format(e)) + raise click.BadParameter(f"{e}") def validate_security_counter(ctx, param, value): @@ -290,16 +290,16 @@ def validate_security_counter(ctx, param, value): return int(value, 0) except ValueError: raise click.BadParameter( - "{} is not a valid integer. Please use code literals " + f"{value} is not a valid integer. Please use code literals " "prefixed with 0b/0B, 0o/0O, or 0x/0X as necessary." - .format(value)) + ) def validate_header_size(ctx, param, value): min_hdr_size = image.IMAGE_HEADER_SIZE if value < min_hdr_size: raise click.BadParameter( - "Minimum value for -H/--header-size is {}".format(min_hdr_size)) + f"Minimum value for -H/--header-size is {min_hdr_size}") return value @@ -309,12 +309,12 @@ def get_dependencies(ctx, param, value): images = re.findall(r"\((\d+)", value) if len(images) == 0: raise click.BadParameter( - "Image dependency format is invalid: {}".format(value)) + f"Image dependency format is invalid: {value}") raw_versions = re.findall(r",\s*((active|primary|secondary)\s*,)?\s*([0-9.+]+)\)", value) if len(images) != len(raw_versions): raise click.BadParameter( - '''There's a mismatch between the number of dependency images - and versions in: {}'''.format(value)) + f'''There's a mismatch between the number of dependency images + and versions in: {value}''') for raw_version in raw_versions: try: decoded_version = decode_version(raw_version[2]) @@ -335,7 +335,7 @@ def get_dependencies(ctx, param, value): 0 ) except ValueError as e: - raise click.BadParameter("{}".format(e)) + raise click.BadParameter(f"{e}") versions.append(slotted_version) dependencies = dict() dependencies[image.DEP_IMAGES_KEY] = images @@ -598,7 +598,7 @@ 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; + keep_comp_size = False if enckey: keep_comp_size = True compressed_img.create(key, public_key_format, enckey, diff --git a/scripts/setup.py b/scripts/setup.py index c97de95ac..02b266650 100644 --- a/scripts/setup.py +++ b/scripts/setup.py @@ -1,7 +1,6 @@ # SPDX-License-Identifier: Apache-2.0 import setuptools - from imgtool import imgtool_version setuptools.setup( diff --git a/scripts/tests/test_commands.py b/scripts/tests/test_commands.py index c0c605213..4ef794e25 100644 --- a/scripts/tests/test_commands.py +++ b/scripts/tests/test_commands.py @@ -15,10 +15,9 @@ from importlib import metadata import pytest - from click.testing import CliRunner -from imgtool.main import imgtool from imgtool import imgtool_version +from imgtool.main import imgtool from packaging.version import Version # all available imgtool commands diff --git a/scripts/tests/test_compression.py b/scripts/tests/test_compression.py index 35597ec29..9483097d5 100644 --- a/scripts/tests/test_compression.py +++ b/scripts/tests/test_compression.py @@ -16,14 +16,13 @@ import pytest from click.testing import CliRunner - from imgtool.image import Image from imgtool.main import ( - comp_default_lp, comp_default_dictsize, comp_default_lc, - create_lzma2_header, + comp_default_lp, comp_default_pb, + create_lzma2_header, imgtool, ) diff --git a/scripts/tests/test_keys.py b/scripts/tests/test_keys.py index a812ba2f1..92a50a45f 100644 --- a/scripts/tests/test_keys.py +++ b/scripts/tests/test_keys.py @@ -12,9 +12,9 @@ # See the License for the specific language governing permissions and # limitations under the License. -import pytest - import subprocess + +import pytest from click.testing import CliRunner from imgtool import main as imgtool_main from imgtool.main import imgtool From 9f768d21fc379021dbfb3eacb96f18ed20f7fda7 Mon Sep 17 00:00:00 2001 From: Jamie McCrae Date: Wed, 8 Oct 2025 12:31:11 +0100 Subject: [PATCH 410/420] [nrf fromtree] scripts: Non-safely fix python files Uses ruff with --unsafe-fixes to fix python files in this folder This is a separate commit so it can be reverted if it causes problems Signed-off-by: Jamie McCrae (cherry picked from commit 497688bafff2c3e183a016b68fc51f1bedf488c9) --- scripts/assemble.py | 9 +++------ scripts/imgtool/dumpinfo.py | 2 +- scripts/imgtool/image.py | 9 ++++----- scripts/imgtool/keys/general.py | 2 +- scripts/imgtool/main.py | 31 ++++++++++++++----------------- 5 files changed, 23 insertions(+), 30 deletions(-) diff --git a/scripts/assemble.py b/scripts/assemble.py index f73668d72..63603f9ff 100755 --- a/scripts/assemble.py +++ b/scripts/assemble.py @@ -31,13 +31,10 @@ def same_keys(a, b): """Determine if the dicts a and b have the same keys in them""" - for ak in a.keys(): + for ak in a: if ak not in b: return False - for bk in b.keys(): - if bk not in a: - return False - return True + return all(bk in a for bk in b) offset_re = re.compile(r"^#define DT_FLASH_AREA_([0-9A-Z_]+)_OFFSET(_0)?\s+(0x[0-9a-fA-F]+|[0-9]+)$") size_re = re.compile(r"^#define DT_FLASH_AREA_([0-9A-Z_]+)_SIZE(_0)?\s+(0x[0-9a-fA-F]+|[0-9]+)$") @@ -130,7 +127,7 @@ def main(): sys.path.insert(0, os.path.join(zephyr_base, "scripts", "dts", "python-devicetree", "src")) import devicetree.edtlib - board = find_board_name(args.bootdir) + find_board_name(args.bootdir) edt_pickle = os.path.join(args.bootdir, "zephyr", "edt.pickle") with open(edt_pickle, 'rb') as f: diff --git a/scripts/imgtool/dumpinfo.py b/scripts/imgtool/dumpinfo.py index c4f31cb40..3866c9a10 100644 --- a/scripts/imgtool/dumpinfo.py +++ b/scripts/imgtool/dumpinfo.py @@ -262,7 +262,7 @@ def dump_imginfo(imgfile, outfile=None, silent=False): flag_string = hex(value) else: flag_string = "" - for flag in image.IMAGE_F.keys(): + for flag in image.IMAGE_F: if value & image.IMAGE_F[flag]: if flag_string: flag_string += ("\n" + (" " * 20)) diff --git a/scripts/imgtool/image.py b/scripts/imgtool/image.py index 598dc6e10..3a2724c48 100755 --- a/scripts/imgtool/image.py +++ b/scripts/imgtool/image.py @@ -598,11 +598,10 @@ def create(self, key, public_key_format, enckey, dependencies=None, self.payload.extend(pad) compression_flags = 0x0 - if compression_tlvs is not None: - if compression_type in ["lzma2", "lzma2armthumb"]: - compression_flags = IMAGE_F['COMPRESSED_LZMA2'] - if compression_type == "lzma2armthumb": - compression_flags |= IMAGE_F['COMPRESSED_ARM_THUMB'] + if compression_tlvs is not None and compression_type in ["lzma2", "lzma2armthumb"]: + compression_flags = IMAGE_F['COMPRESSED_LZMA2'] + if compression_type == "lzma2armthumb": + compression_flags |= IMAGE_F['COMPRESSED_ARM_THUMB'] # This adds the header to the payload as well if encrypt_keylen == 256: self.add_header(enckey, protected_tlv_size, compression_flags, 256) diff --git a/scripts/imgtool/keys/general.py b/scripts/imgtool/keys/general.py index dfb4e3663..fdaab147f 100644 --- a/scripts/imgtool/keys/general.py +++ b/scripts/imgtool/keys/general.py @@ -17,7 +17,7 @@ def __init__(self, file, *args, **kwargs): self.kwargs = kwargs def __enter__(self): - if isinstance(self.file_in, (str, bytes, os.PathLike)): + if isinstance(self.file_in, str | bytes | os.PathLike): self.file = open(self.file_in, *self.args, **self.kwargs) else: self.file = self.file_in diff --git a/scripts/imgtool/main.py b/scripts/imgtool/main.py index b0b1b0dba..9b79969d0 100755 --- a/scripts/imgtool/main.py +++ b/scripts/imgtool/main.py @@ -43,8 +43,7 @@ MIN_PYTHON_VERSION = (3, 6) if sys.version_info < MIN_PYTHON_VERSION: - sys.exit("Python %s.%s or newer is required by imgtool." - % MIN_PYTHON_VERSION) + sys.exit("Python {}.{} or newer is required by imgtool.".format(*MIN_PYTHON_VERSION)) SlottedSemiSemVersion = namedtuple('SemiSemVersion', ['major', 'minor', 'revision', 'build', 'slot']) @@ -358,9 +357,8 @@ def convert(self, value, param, ctx): try: return int(value, 0) except ValueError: - self.fail('%s is not a valid integer. Please use code literals ' - 'prefixed with 0b/0B, 0o/0O, or 0x/0X as necessary.' - % value, param, ctx) + self.fail(f'{value} is not a valid integer. Please use code literals ' + 'prefixed with 0b/0B, 0o/0O, or 0x/0X as necessary.', param, ctx) @click.argument('outfile') @@ -501,16 +499,15 @@ def sign(key, public_key_format, align, version, pad_sig, header_size, img.load(infile) key = load_key(key) if key else None enckey = load_key(encrypt) if encrypt else None - if enckey and key: - if ((isinstance(key, keys.ECDSA256P1) and - not isinstance(enckey, keys.ECDSA256P1Public)) - or (isinstance(key, keys.ECDSA384P1) and - not isinstance(enckey, keys.ECDSA384P1Public)) - or (isinstance(key, keys.RSA) and - not isinstance(enckey, keys.RSAPublic))): - # FIXME - raise click.UsageError("Signing and encryption must use the same " - "type of key") + if enckey and key and ((isinstance(key, keys.ECDSA256P1) and + not isinstance(enckey, keys.ECDSA256P1Public)) + or (isinstance(key, keys.ECDSA384P1) and + not isinstance(enckey, keys.ECDSA384P1Public)) + or (isinstance(key, keys.RSA) and + not isinstance(enckey, keys.RSAPublic))): + # FIXME + raise click.UsageError("Signing and encryption must use the same " + "type of key") if pad_sig and hasattr(key, 'pad_sig'): key.pad_sig = True @@ -520,10 +517,10 @@ def sign(key, public_key_format, align, version, pad_sig, header_size, for tlv in custom_tlv: tag = int(tlv[0], 0) if tag in custom_tlvs: - raise click.UsageError('Custom TLV %s already exists.' % hex(tag)) + raise click.UsageError(f'Custom TLV {hex(tag)} already exists.') if tag in image.TLV_VALUES.values(): raise click.UsageError( - 'Custom TLV %s conflicts with predefined TLV.' % hex(tag)) + f'Custom TLV {hex(tag)} conflicts with predefined TLV.') value = tlv[1] if value.startswith('0x'): From 4b5901fd2f91c7390f1c6ddccf45835a778b8d80 Mon Sep 17 00:00:00 2001 From: Tomasz Chyrowicz Date: Wed, 15 Oct 2025 13:29:51 +0200 Subject: [PATCH 411/420] [nrf fromtree] Revert "loader: Allow to specify slot number in version" This reverts commit dce784a2f2a045c3643b9baf02e9f4fc40530b7b. Signed-off-by: Tomasz Chyrowicz (cherry picked from commit b192716c969ad358bb3a1db60c898212f3275c55) --- boot/bootutil/include/bootutil/image.h | 8 - boot/bootutil/src/loader.c | 172 +----------------- boot/zephyr/Kconfig | 9 - .../include/mcuboot_config/mcuboot_config.h | 4 - docs/design.md | 17 -- docs/imgtool.md | 13 +- scripts/imgtool/image.py | 3 +- scripts/imgtool/main.py | 32 +--- 8 files changed, 6 insertions(+), 252 deletions(-) diff --git a/boot/bootutil/include/bootutil/image.h b/boot/bootutil/include/bootutil/image.h index fdd473132..3d103f8da 100644 --- a/boot/bootutil/include/bootutil/image.h +++ b/boot/bootutil/include/bootutil/image.h @@ -146,10 +146,6 @@ extern "C" { */ #define IMAGE_TLV_ANY 0xffff /* Used to iterate over all TLV */ -#define VERSION_DEP_SLOT_ACTIVE 0x00 /* Check dependency against active slot. */ -#define VERSION_DEP_SLOT_PRIMARY 0x01 /* Check dependency against primary slot. */ -#define VERSION_DEP_SLOT_SECONDARY 0x02 /* Check dependency against secondary slot. */ - STRUCT_PACKED image_version { uint8_t iv_major; uint8_t iv_minor; @@ -159,11 +155,7 @@ STRUCT_PACKED image_version { struct image_dependency { uint8_t image_id; /* Image index (from 0) */ -#ifdef MCUBOOT_VERSION_CMP_USE_SLOT_NUMBER - uint8_t slot; /* Image slot */ -#else uint8_t _pad1; -#endif /* MCUBOOT_VERSION_CMP_USE_SLOT_NUMBER */ uint16_t _pad2; struct image_version image_min_version; /* Indicates at minimum which * version of firmware must be diff --git a/boot/bootutil/src/loader.c b/boot/bootutil/src/loader.c index 12be5cff3..faffab03a 100644 --- a/boot/bootutil/src/loader.c +++ b/boot/bootutil/src/loader.c @@ -391,24 +391,6 @@ boot_verify_slot_dependency(struct boot_loader_state *state, uint8_t swap_type = state->swap_type[dep->image_id]; dep_slot = BOOT_IS_UPGRADE(swap_type) ? BOOT_SLOT_SECONDARY : BOOT_SLOT_PRIMARY; -#elif defined(MCUBOOT_VERSION_CMP_USE_SLOT_NUMBER) - switch(dep->slot) { - case VERSION_DEP_SLOT_ACTIVE: - dep_slot = state->slot_usage[dep->image_id].active_slot; - break; - case VERSION_DEP_SLOT_PRIMARY: - dep_slot = BOOT_SLOT_PRIMARY; - break; - case VERSION_DEP_SLOT_SECONDARY: - dep_slot = BOOT_SLOT_SECONDARY; - break; - default: - return -1; - } - - if (!state->slot_usage[dep->image_id].slot_available[dep_slot]) { - return -1; - } #else dep_slot = state->slot_usage[dep->image_id].active_slot; #endif @@ -446,27 +428,7 @@ boot_verify_slot_dependency(struct boot_loader_state *state, } #endif -#ifdef MCUBOOT_VERSION_CMP_USE_SLOT_NUMBER - if (rc == 0) { - switch(dep->slot) { - case VERSION_DEP_SLOT_PRIMARY: - state->slot_usage[dep->image_id].slot_available[BOOT_SLOT_PRIMARY] = true; - state->slot_usage[dep->image_id].slot_available[BOOT_SLOT_SECONDARY] = false; - state->slot_usage[dep->image_id].active_slot = BOOT_SLOT_PRIMARY; - break; - case VERSION_DEP_SLOT_SECONDARY: - state->slot_usage[dep->image_id].slot_available[BOOT_SLOT_PRIMARY] = false; - state->slot_usage[dep->image_id].slot_available[BOOT_SLOT_SECONDARY] = true; - state->slot_usage[dep->image_id].active_slot = BOOT_SLOT_SECONDARY; - break; - case VERSION_DEP_SLOT_ACTIVE: - default: - break; - } - } -#endif /* MCUBOOT_VERSION_CMP_USE_SLOT_NUMBER */ - -return rc; + return rc; } #if !defined(MCUBOOT_DIRECT_XIP) && !defined(MCUBOOT_RAM_LOAD) @@ -614,19 +576,6 @@ boot_verify_slot_dependencies(struct boot_loader_state *state, uint32_t slot) goto done; } -#ifdef MCUBOOT_VERSION_CMP_USE_SLOT_NUMBER - /* Validate against possible dependency slot values. */ - switch(dep.slot) { - case VERSION_DEP_SLOT_ACTIVE: - case VERSION_DEP_SLOT_PRIMARY: - case VERSION_DEP_SLOT_SECONDARY: - break; - default: - rc = BOOT_EBADARGS; - goto done; - } -#endif /* MCUBOOT_VERSION_CMP_USE_SLOT_NUMBER */ - /* Verify dependency and modify the swap type if not satisfied. */ rc = boot_verify_slot_dependency(state, &dep); if (rc != 0) { @@ -3281,124 +3230,6 @@ boot_select_or_erase(struct boot_loader_state *state) } #endif /* MCUBOOT_DIRECT_XIP && MCUBOOT_DIRECT_XIP_REVERT */ -#ifdef MCUBOOT_VERSION_CMP_USE_SLOT_NUMBER -/** - * Tries to load a slot for all the images with validation. - * - * @param state Boot loader status information. - * - * @return 0 on success; nonzero on failure. - */ -fih_ret -boot_load_and_validate_images(struct boot_loader_state *state) -{ - uint32_t active_slot; - int rc; - fih_ret fih_rc; - uint32_t slot; - - /* Go over all the images and all slots and validate them */ - IMAGES_ITER(BOOT_CURR_IMG(state)) { - for (slot = 0; slot < BOOT_NUM_SLOTS; slot++) { -#if BOOT_IMAGE_NUMBER > 1 - if (state->img_mask[BOOT_CURR_IMG(state)]) { - continue; - } -#endif - - /* Save the number of the active slot. */ - state->slot_usage[BOOT_CURR_IMG(state)].active_slot = slot; - -#ifdef MCUBOOT_DIRECT_XIP - rc = boot_rom_address_check(state); - if (rc != 0) { - /* The image is placed in an unsuitable slot. */ - state->slot_usage[BOOT_CURR_IMG(state)].slot_available[slot] = false; - state->slot_usage[BOOT_CURR_IMG(state)].active_slot = BOOT_SLOT_NONE; - continue; - } - -#ifdef MCUBOOT_DIRECT_XIP_REVERT - rc = boot_select_or_erase(state); - if (rc != 0) { - /* The selected image slot has been erased. */ - state->slot_usage[BOOT_CURR_IMG(state)].slot_available[slot] = false; - state->slot_usage[BOOT_CURR_IMG(state)].active_slot = BOOT_SLOT_NONE; - continue; - } -#endif /* MCUBOOT_DIRECT_XIP_REVERT */ -#endif /* MCUBOOT_DIRECT_XIP */ - -#ifdef MCUBOOT_RAM_LOAD - /* Image is first loaded to RAM and authenticated there in order to - * prevent TOCTOU attack during image copy. This could be applied - * when loading images from external (untrusted) flash to internal - * (trusted) RAM and image is authenticated before copying. - */ - rc = boot_load_image_to_sram(state); - if (rc != 0 ) { - /* Image cannot be ramloaded. */ - boot_remove_image_from_flash(state, slot); - state->slot_usage[BOOT_CURR_IMG(state)].slot_available[slot] = false; - state->slot_usage[BOOT_CURR_IMG(state)].active_slot = BOOT_SLOT_NONE; - continue; - } -#endif /* MCUBOOT_RAM_LOAD */ - - FIH_CALL(boot_validate_slot, fih_rc, state, slot, NULL, 0); - if (FIH_NOT_EQ(fih_rc, FIH_SUCCESS)) { - /* Image is invalid. */ -#ifdef MCUBOOT_RAM_LOAD - boot_remove_image_from_sram(state); -#endif /* MCUBOOT_RAM_LOAD */ - state->slot_usage[BOOT_CURR_IMG(state)].slot_available[slot] = false; - state->slot_usage[BOOT_CURR_IMG(state)].active_slot = BOOT_SLOT_NONE; - continue; - } - - /* Valid image loaded from a slot, go to the next slot. */ - state->slot_usage[BOOT_CURR_IMG(state)].active_slot = BOOT_SLOT_NONE; - } - } - - /* Go over all the images and all slots and validate them */ - IMAGES_ITER(BOOT_CURR_IMG(state)) { - /* All slots tried until a valid image found. Breaking from this loop - * means that a valid image found or already loaded. If no slot is - * found the function returns with error code. */ - while (true) { - /* Go over all the slots and try to load one */ - active_slot = state->slot_usage[BOOT_CURR_IMG(state)].active_slot; - if (active_slot != BOOT_SLOT_NONE){ - /* A slot is already active, go to next image. */ - break; - } - - rc = BOOT_HOOK_FIND_SLOT_CALL(boot_find_next_slot_hook, BOOT_HOOK_REGULAR, - state, BOOT_CURR_IMG(state), &active_slot); - if (rc == BOOT_HOOK_REGULAR) { - active_slot = find_slot_with_highest_version(state); - } - - if (active_slot == BOOT_SLOT_NONE) { - BOOT_LOG_INF("No slot to load for image %d", - BOOT_CURR_IMG(state)); - FIH_RET(FIH_FAILURE); - } - - /* Save the number of the active slot. */ - state->slot_usage[BOOT_CURR_IMG(state)].active_slot = active_slot; - - /* Valid image loaded from a slot, go to the next image. */ - break; - } - } - - FIH_RET(FIH_SUCCESS); -} - -#else /* MCUBOOT_VERSION_CMP_USE_SLOT_NUMBER */ - /** * Tries to load a slot for all the images with validation. * @@ -3501,7 +3332,6 @@ boot_load_and_validate_images(struct boot_loader_state *state) FIH_RET(FIH_SUCCESS); } -#endif /* MCUBOOT_VERSION_CMP_USE_SLOT_NUMBER */ /** * Updates the security counter for the current image. diff --git a/boot/zephyr/Kconfig b/boot/zephyr/Kconfig index f738ac66a..fb8d7e2fd 100644 --- a/boot/zephyr/Kconfig +++ b/boot/zephyr/Kconfig @@ -1103,15 +1103,6 @@ config BOOT_VERSION_CMP_USE_BUILD_NUMBER minor and revision. Enable this option to take into account the build number as well. -config BOOT_VERSION_CMP_USE_SLOT_NUMBER - bool "Use slot number while comparing image version" - depends on (UPDATEABLE_IMAGE_NUMBER > 1) || BOOT_DIRECT_XIP || \ - BOOT_RAM_LOAD || MCUBOOT_DOWNGRADE_PREVENTION - help - By default, the image slot comparison relies only on active slot. - Enable this option to take into account the specified slot number - instead. - choice BOOT_DOWNGRADE_PREVENTION_CHOICE prompt "Downgrade prevention" optional diff --git a/boot/zephyr/include/mcuboot_config/mcuboot_config.h b/boot/zephyr/include/mcuboot_config/mcuboot_config.h index 4fd821f85..2d759217b 100644 --- a/boot/zephyr/include/mcuboot_config/mcuboot_config.h +++ b/boot/zephyr/include/mcuboot_config/mcuboot_config.h @@ -130,10 +130,6 @@ #define MCUBOOT_VERSION_CMP_USE_BUILD_NUMBER #endif -#ifdef CONFIG_BOOT_VERSION_CMP_USE_SLOT_NUMBER -#define MCUBOOT_VERSION_CMP_USE_SLOT_NUMBER -#endif - #ifdef CONFIG_BOOT_SWAP_SAVE_ENCTLV #define MCUBOOT_SWAP_SAVE_ENCTLV 1 #endif diff --git a/docs/design.md b/docs/design.md index f31c2d452..595c6a401 100755 --- a/docs/design.md +++ b/docs/design.md @@ -944,23 +944,6 @@ process is presented below. + Boot into image in the primary slot of the 0th image position\ (other image in the boot chain is started by another image). -By enabling the `MCUBOOT_VERSION_CMP_USE_SLOT_NUMBER` configuration option, -the dependency check may be extended to match for a specified slot of a specific -image. This functionality is useful in a multi-core system when Direct XIP mode -is used. -In this case, the main image can be started from one of the two (primary or -secondary) slots. -If there is a fixed connection between the slots of two different images, -e.g. if the main image always chainloads a companion image from the same slot, -the check must take this into account and only consider a matching slot when -resolving dependencies. - -There are three values that can be passed when specifying dependencies: - -1. ``active``: the dependency should be checked against either primary or secondary slot. -2. ``primary``: the dependency should be checked only against primary slot. -3. ``secondary``: the dependency should be checked only against secondary slot. - ### [Multiple image boot for RAM loading and direct-xip](#multiple-image-boot-for-ram-loading-and-direct-xip) The operation of the bootloader is different when the ram-load or the diff --git a/docs/imgtool.md b/docs/imgtool.md index c68652dca..958e1af15 100644 --- a/docs/imgtool.md +++ b/docs/imgtool.md @@ -91,8 +91,7 @@ primary slot and adds a header and trailer that the bootloader is expecting: the `auto` keyword to automatically generate it from the image version. -d, --dependencies TEXT Add dependence on another image, format: - "(,[,] - ), ... " + "(,), ... " --pad-sig Add 0-2 bytes of padding to ECDSA signature (for mcuboot <1.5) -H, --header-size INTEGER [required] @@ -183,16 +182,6 @@ which the current image depends on. The `image_version` is the minimum version of that image to satisfy compliance. For example `-d "(1, 1.2.3+0)"` means this image depends on Image 1 which version has to be at least 1.2.3+0. -In addition, a dependency can specify the slot as follows: -`-d "(image_id, slot, image_version)"`. The `image_id` is the number of the -image on which the current image depends. -The slot specifies which slots of the image are to be taken into account -(`active`: primary or secondary, `primary`: only primary `secondary`: only -secondary slot). The `image_version` is the minimum version of that image to -fulfill the requirements. -For example `-d "(1, primary, 1.2.3+0)"` means that this image depends on the -primary slot of the Image 1, whose version must be at least 1.2.3+0. - The `--public-key-format` argument can be used to distinguish where the public key is stored for image authentication. The `hash` option is used by default, in which case only the hash of the public key is added to the TLV area (the full diff --git a/scripts/imgtool/image.py b/scripts/imgtool/image.py index 3a2724c48..017307bab 100755 --- a/scripts/imgtool/image.py +++ b/scripts/imgtool/image.py @@ -627,9 +627,8 @@ def create(self, key, public_key_format, enckey, dependencies=None, if dependencies is not None: for i in range(dependencies_num): payload = struct.pack( - e + 'BB2x' + 'BBHI', + e + 'B3x' + 'BBHI', int(dependencies[DEP_IMAGES_KEY][i]), - dependencies[DEP_VERSIONS_KEY][i].slot, dependencies[DEP_VERSIONS_KEY][i].major, dependencies[DEP_VERSIONS_KEY][i].minor, dependencies[DEP_VERSIONS_KEY][i].revision, diff --git a/scripts/imgtool/main.py b/scripts/imgtool/main.py index 9b79969d0..c4abf06f1 100755 --- a/scripts/imgtool/main.py +++ b/scripts/imgtool/main.py @@ -23,7 +23,6 @@ import re import struct import sys -from collections import namedtuple import click @@ -45,14 +44,6 @@ if sys.version_info < MIN_PYTHON_VERSION: sys.exit("Python {}.{} or newer is required by imgtool.".format(*MIN_PYTHON_VERSION)) -SlottedSemiSemVersion = namedtuple('SemiSemVersion', ['major', 'minor', 'revision', - 'build', 'slot']) - -DEPENDENCY_SLOT_VALUES = { - 'active': 0x00, - 'primary': 0x01, - 'secondary': 0x02 -} def gen_rsa2048(keyfile, passwd): keys.RSA.generate().export_private(path=keyfile, passwd=passwd) @@ -309,33 +300,16 @@ def get_dependencies(ctx, param, value): if len(images) == 0: raise click.BadParameter( f"Image dependency format is invalid: {value}") - raw_versions = re.findall(r",\s*((active|primary|secondary)\s*,)?\s*([0-9.+]+)\)", value) + raw_versions = re.findall(r",\s*([0-9.+]+)\)", value) if len(images) != len(raw_versions): raise click.BadParameter( f'''There's a mismatch between the number of dependency images and versions in: {value}''') for raw_version in raw_versions: try: - decoded_version = decode_version(raw_version[2]) - if len(raw_version[1]) > 0: - slotted_version = SlottedSemiSemVersion( - decoded_version.major, - decoded_version.minor, - decoded_version.revision, - decoded_version.build, - DEPENDENCY_SLOT_VALUES[raw_version[1]] - ) - else: - slotted_version = SlottedSemiSemVersion( - decoded_version.major, - decoded_version.minor, - decoded_version.revision, - decoded_version.build, - 0 - ) + versions.append(decode_version(raw_version)) except ValueError as e: raise click.BadParameter(f"{e}") - versions.append(slotted_version) dependencies = dict() dependencies[image.DEP_IMAGES_KEY] = images dependencies[image.DEP_VERSIONS_KEY] = versions @@ -429,7 +403,7 @@ def convert(self, value, param, ctx): '(for mcuboot <1.5)') @click.option('-d', '--dependencies', callback=get_dependencies, required=False, help='''Add dependence on another image, format: - "(,[,]), ... "''') + "(,), ... "''') @click.option('-s', '--security-counter', callback=validate_security_counter, help='Specify the value of security counter. Use the `auto` ' 'keyword to automatically generate it from the image version.') From 92b8fd3308f968da0143cbee1d6bb2cfa440f73b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Eivind=20J=C3=B8lsgard?= Date: Wed, 15 Oct 2025 13:43:31 +0200 Subject: [PATCH 412/420] [nrf noup] boot: zephyr: update for NCS BM include folder structure MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit nrf-squash! [nrf noup] boot: zephyr: Add bm firmware loader code Update for NCS BM include folder structure. Signed-off-by: Eivind Jølsgard --- boot/zephyr/io_bm.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/boot/zephyr/io_bm.c b/boot/zephyr/io_bm.c index 788bfab9e..2e37c6aab 100644 --- a/boot/zephyr/io_bm.c +++ b/boot/zephyr/io_bm.c @@ -29,7 +29,7 @@ #include "bootutil/bootutil_log.h" #include -#include +#include #if defined(CONFIG_BOOT_SERIAL_PIN_RESET) || defined(CONFIG_BOOT_FIRMWARE_LOADER_PIN_RESET) #include From 697ca33a67777cf55045d1b33ababc9511eaa227 Mon Sep 17 00:00:00 2001 From: Artur Hadasz Date: Fri, 10 Oct 2025 15:12:57 +0200 Subject: [PATCH 413/420] [nrf noup] boot: zephyr: Region protection adjustments for nRF54L nrf-squash! [nrf noup] boot: zephyr: Disable self RWX This commit fixes a couple of issues regarding MCUBoot region protection for nRF54L. Also, support for region and protection is added for nRF54LM20 and nRF54LV10 platforms. Signed-off-by: Artur Hadasz --- boot/zephyr/Kconfig | 8 ++++- boot/zephyr/main.c | 73 +++++++++++++++++++++++++++++++++++++++------ 2 files changed, 71 insertions(+), 10 deletions(-) diff --git a/boot/zephyr/Kconfig b/boot/zephyr/Kconfig index fb8d7e2fd..49b458e8e 100644 --- a/boot/zephyr/Kconfig +++ b/boot/zephyr/Kconfig @@ -496,9 +496,15 @@ config MCUBOOT_CLEANUP_RAM help Sets contents of memory to 0 before jumping to application. +config NCS_MCUBOOT_DISABLE_SELF_RWX_SUPPORTED + bool + default y if SOC_NRF54L15_CPUAPP || SOC_NRF54L10_CPUAPP || SOC_NRF54L05_CPUAPP + default y if SOC_NRF54LV10A_ENGA_CPUAPP + default y if SOC_NRF54LM20A_ENGA_CPUAPP + config NCS_MCUBOOT_DISABLE_SELF_RWX bool "Disable read and execution on self NVM" - depends on (SOC_NRF54L15_CPUAPP || SOC_NRF54L10_CPUAPP || SOC_NRF54L05_CPUAPP) && !FPROTECT + depends on NCS_MCUBOOT_DISABLE_SELF_RWX_SUPPORTED && !FPROTECT help Sets RRAMC's region no.4 protection before jumping to application. It disables reads writes and execution memory area which holds MCUBOOT. diff --git a/boot/zephyr/main.c b/boot/zephyr/main.c index 16c8a9404..ad36a60a2 100644 --- a/boot/zephyr/main.c +++ b/boot/zephyr/main.c @@ -150,9 +150,12 @@ K_SEM_DEFINE(boot_log_sem, 1, 1); * !defined(CONFIG_LOG_MODE_MINIMAL) */ +#if USE_PARTITION_MANAGER +#include +#endif + #if USE_PARTITION_MANAGER && CONFIG_FPROTECT #include -#include #endif #if CONFIG_MCUBOOT_NRF_CLEANUP_PERIPHERAL @@ -173,9 +176,48 @@ K_SEM_DEFINE(boot_log_sem, 1, 1); #define RRAMC_REGION_RWX_LSB 0 #define RRAMC_REGION_RWX_WIDTH 3 -#define RRAMC_REGION_TO_LOCK_ADDR NRF_RRAMC->REGION[4].CONFIG -#define RRAMC_REGION_TO_LOCK_ADDR_H (((uint32_t)(&(RRAMC_REGION_TO_LOCK_ADDR))) >> 16) -#define RRAMC_REGION_TO_LOCK_ADDR_L (((uint32_t)(&(RRAMC_REGION_TO_LOCK_ADDR))) & 0x0000fffful) + +#define RRAMC_REGION_NUMBER 4 +#define NRF_RRAM_REGION_SIZE_UNIT 0x400 +#define NRF_RRAM_REGION_ADDRESS_RESOLUTION 0x400 + +#if defined(CONFIG_SOC_NRF54L15_CPUAPP) || defined(CONFIG_SOC_NRF54L05_CPUAPP) || \ + defined(CONFIG_SOC_NRF54L10_CPUAPP) +#define MAX_PROTECTED_REGION_SIZE (31 * 1024) +#elif defined(CONFIG_SOC_NRF54LV10A_ENGA_CPUAPP) || defined(CONFIG_SOC_NRF54LM20A_ENGA_CPUAPP) +#define MAX_PROTECTED_REGION_SIZE (127 * 1024) +#elif defined(CONFIG_SOC_NRF54LS05B_ENGA_CPUAPP) +#define MAX_PROTECTED_REGION_SIZE (1023 * 1024) +#endif + +#define RRAMC_REGION_CONFIG NRF_RRAMC->REGION[RRAMC_REGION_NUMBER].CONFIG +#define RRAMC_REGION_CONFIG_H (((uint32_t)(&(RRAMC_REGION_CONFIG))) >> 16) +#define RRAMC_REGION_CONFIG_L (((uint32_t)(&(RRAMC_REGION_CONFIG))) & 0x0000fffful) + +#define RRAMC_REGION_ADDRESS NRF_RRAMC->REGION[RRAMC_REGION_NUMBER].ADDRESS +#define RRAMC_REGION_ADDRESS_H (((uint32_t)(&(RRAMC_REGION_ADDRESS))) >> 16) +#define RRAMC_REGION_ADDRESS_L (((uint32_t)(&(RRAMC_REGION_ADDRESS))) & 0x0000fffful) + +#if (CONFIG_NCS_IS_VARIANT_IMAGE) +#define PROTECTED_REGION_START PM_S1_IMAGE_ADDRESS +#define PROTECTED_REGION_SIZE PM_S1_IMAGE_SIZE +#else +#define PROTECTED_REGION_START PM_MCUBOOT_ADDRESS +#define PROTECTED_REGION_SIZE PM_MCUBOOT_SIZE +#endif + +BUILD_ASSERT((PROTECTED_REGION_START % NRF_RRAM_REGION_ADDRESS_RESOLUTION) == 0, + "Start of protected region is not aligned - not possible to protect"); + +BUILD_ASSERT((PROTECTED_REGION_SIZE % NRF_RRAM_REGION_SIZE_UNIT) == 0, + "Size of protected region is not aligned - not possible to protect"); + +BUILD_ASSERT(PROTECTED_REGION_SIZE <= MAX_PROTECTED_REGION_SIZE, + "Size of protected region is too big for protection"); + +#define PROTECTED_REGION_START_H ((PROTECTED_REGION_START) >> 16) +#define PROTECTED_REGION_START_L ((PROTECTED_REGION_START) & 0x0000fffful) + #endif /* CONFIG_NCS_MCUBOOT_DISABLE_SELF_RWX */ BOOT_LOG_MODULE_REGISTER(mcuboot); @@ -245,11 +287,20 @@ static void __ramfunc jump_in(uint32_t reset) " ldr r2, [r1]\n" /* Size of the region should be set at this point * by NSIB's DISABLE_NEXT_W. - * If not, set it according partition size. + * If not, the region has not been configured yet. + * Set the size and address to the partition size and address. */ " ands r4, r2, %12\n" " cbnz r4, clear_rwx\n" + /* Set the size of the protected region */ " movt r2, %8\n" + /* Set the address of the protected region */ + " movw r5, %13\n" + " movt r5, %14\n" + " movw r6, %15\n" + " movt r6, %16\n" + " str r6, [r5]\n" + " dsb\n" "clear_rwx:\n" " bfc r2, %9, %10\n" /* Disallow further modifications */ @@ -270,13 +321,17 @@ static void __ramfunc jump_in(uint32_t reset) "r" (CLEANUP_RAM_GAP_SIZE), "i" (0) #ifdef CONFIG_NCS_MCUBOOT_DISABLE_SELF_RWX - , "i" (RRAMC_REGION_TO_LOCK_ADDR_L), - "i" (RRAMC_REGION_TO_LOCK_ADDR_H), - "i" (CONFIG_PM_PARTITION_SIZE_B0_IMAGE / 1024), + , "i" (RRAMC_REGION_CONFIG_L), + "i" (RRAMC_REGION_CONFIG_H), + "i" ((PROTECTED_REGION_SIZE) / (NRF_RRAM_REGION_SIZE_UNIT)), "i" (RRAMC_REGION_RWX_LSB), "i" (RRAMC_REGION_RWX_WIDTH), "i" (RRAMC_REGION_CONFIG_LOCK_Msk), - "i" (RRAMC_REGION_CONFIG_SIZE_Msk) + "i" (RRAMC_REGION_CONFIG_SIZE_Msk), + "i" (RRAMC_REGION_ADDRESS_L), + "i" (RRAMC_REGION_ADDRESS_H), + "i" (PROTECTED_REGION_START_L), + "i" (PROTECTED_REGION_START_H) #endif /* CONFIG_NCS_MCUBOOT_DISABLE_SELF_RWX */ : "r0", "r1", "r2", "r3", "r4", "r5", "r6", "memory" ); From a8161d7dcccd9503c48678219dd535ebd24b7c3c Mon Sep 17 00:00:00 2001 From: Bjarki Arge Andreasen Date: Tue, 21 Oct 2025 09:30:48 +0200 Subject: [PATCH 414/420] [nrf fromtree] boot: zephyr: boards: remove nrf54h20dk overlay The nrf54h20dk overlay is no longer required as the gpio pad groups have been removed. Signed-off-by: Bjarki Arge Andreasen (cherry picked from commit 71b41e38e9f5d278178be17f6d42f2559f8e46aa) --- .../boards/nrf54h20dk_nrf54h20_cpuapp.overlay | 59 ------------------- 1 file changed, 59 deletions(-) delete mode 100644 boot/zephyr/boards/nrf54h20dk_nrf54h20_cpuapp.overlay diff --git a/boot/zephyr/boards/nrf54h20dk_nrf54h20_cpuapp.overlay b/boot/zephyr/boards/nrf54h20dk_nrf54h20_cpuapp.overlay deleted file mode 100644 index 15156e5ea..000000000 --- a/boot/zephyr/boards/nrf54h20dk_nrf54h20_cpuapp.overlay +++ /dev/null @@ -1,59 +0,0 @@ -/* - * Copyright (c) 2025 Nordic Semiconductor ASA - * - * SPDX-License-Identifier: Apache-2.0 - */ - -/ { - chosen { - zephyr,code-partition = &boot_partition; - }; -}; - -&gdpwr { - status = "disabled"; -}; - -&gdpwr_fast_active_0 { - status = "disabled"; -}; - -&gdpwr_fast_active_1 { - status = "disabled"; -}; - -&gdpwr_fast_main { - status = "disabled"; -}; - -&gdpwr_slow_active { - status = "disabled"; -}; - -&gdpwr_slow_main { - status = "disabled"; -}; - -&gpio_pad_group0 { - status = "disabled"; -}; - -&gpio_pad_group1 { - status = "disabled"; -}; - -&gpio_pad_group2 { - status = "disabled"; -}; - -&gpio_pad_group6 { - status = "disabled"; -}; - -&gpio_pad_group7 { - status = "disabled"; -}; - -&gpio_pad_group9 { - status = "disabled"; -}; From 484a6f30394abbc2b9f404e715e99271fcf926aa Mon Sep 17 00:00:00 2001 From: Tomasz Chyrowicz Date: Mon, 27 Oct 2025 13:42:34 +0100 Subject: [PATCH 415/420] [nrf noup] Handle pending confirm requests fixup! [nrf noup] bootloader: Add bootloader requests Interpret pending bootloader requests while investigating the confirm flag. Signed-off-by: Tomasz Chyrowicz --- boot/bootutil/src/bootutil_public.c | 91 ++++++++++--------- .../zephyr/src/boot_request_retention.c | 2 - boot/zephyr/Kconfig | 11 --- 3 files changed, 50 insertions(+), 54 deletions(-) diff --git a/boot/bootutil/src/bootutil_public.c b/boot/bootutil/src/bootutil_public.c index f54dd6151..7365eac5b 100644 --- a/boot/bootutil/src/bootutil_public.c +++ b/boot/bootutil/src/bootutil_public.c @@ -398,9 +398,59 @@ boot_write_image_ok(const struct flash_area *fap) return boot_write_trailer_flag(fap, off, BOOT_FLAG_SET); } +#if defined(SEND_BOOT_REQUEST) || (!defined(MCUBOOT_BOOTUTIL_LIB_FOR_DIRECT_XIP)) +static int flash_area_to_image_slot(const struct flash_area *fa, uint32_t *slot) +{ + int id = flash_area_get_id(fa); +#if BOOT_IMAGE_NUMBER > 1 + uint8_t i = 0; + + for (i = 0; i < BOOT_IMAGE_NUMBER; i++) { + if (FLASH_AREA_IMAGE_PRIMARY(i) == id) { + if (slot != NULL) { + *slot = 0; + } + return i; + } else if (FLASH_AREA_IMAGE_SECONDARY(i) == id) { + if (slot != NULL) { + *slot = 1; + } + return i; + } + } + + /* Image not found */ + *slot = UINT32_MAX; +#else + (void)fa; + if (slot != NULL) { + if (FLASH_AREA_IMAGE_PRIMARY(0) == id) { + *slot = 0; + } else if (FLASH_AREA_IMAGE_SECONDARY(0) == id) { + *slot = 1; + } else { + *slot = UINT32_MAX; + } + } +#endif + return 0; +} +#endif /* SEND_BOOT_REQUEST || !MCUBOOT_BOOTUTIL_LIB_FOR_DIRECT_XIP */ + int boot_read_image_ok(const struct flash_area *fap, uint8_t *image_ok) { +#ifdef SEND_BOOT_REQUEST + enum boot_slot slot_id = BOOT_SLOT_NONE; + int image_id = flash_area_to_image_slot(fap, &slot_id); + bool confirm_pending = boot_request_check_confirmed_slot(image_id, slot_id); + + if (confirm_pending) { + BOOT_LOG_DBG("Image confirmation pending for image %d slot %d", image_id, slot_id); + *image_ok = BOOT_FLAG_SET; + return 0; + } +#endif /* SEND_BOOT_REQUEST */ return boot_read_flag(fap, image_ok, boot_image_ok_off(fap)); } @@ -541,47 +591,6 @@ send_boot_request(uint8_t magic, uint8_t image_ok, bool confirm, int image_id, } #endif /* SEND_BOOT_REQUEST */ -#if defined(SEND_BOOT_REQUEST) || (!defined(MCUBOOT_BOOTUTIL_LIB_FOR_DIRECT_XIP)) -static int flash_area_to_image_slot(const struct flash_area *fa, uint32_t *slot) -{ - int id = flash_area_get_id(fa); -#if BOOT_IMAGE_NUMBER > 1 - uint8_t i = 0; - - while (i < BOOT_IMAGE_NUMBER) { - if (FLASH_AREA_IMAGE_PRIMARY(i) == id) { - if (slot != NULL) { - *slot = 0; - } - return i; - } else if (FLASH_AREA_IMAGE_SECONDARY(i) == id) { - if (slot != NULL) { - *slot = 1; - } - return i; - } - - ++i; - } - - /* Image not found */ - *slot = UINT32_MAX; -#else - (void)fa; - if (slot != NULL) { - if (FLASH_AREA_IMAGE_PRIMARY(0) == id) { - *slot = 0; - } else if (FLASH_AREA_IMAGE_SECONDARY(0) == id) { - *slot = 1; - } else { - *slot = UINT32_MAX; - } - } -#endif - return 0; -} -#endif /* defined(SEND_BOOT_REQUEST) || (!defined(MCUBOOT_BOOTUTIL_LIB_FOR_DIRECT_XIP)) */ - #ifndef MCUBOOT_BOOTUTIL_LIB_FOR_DIRECT_XIP int boot_set_next(const struct flash_area *fa, bool active, bool confirm) diff --git a/boot/bootutil/zephyr/src/boot_request_retention.c b/boot/bootutil/zephyr/src/boot_request_retention.c index e7fc393a0..9cde6da04 100644 --- a/boot/bootutil/zephyr/src/boot_request_retention.c +++ b/boot/bootutil/zephyr/src/boot_request_retention.c @@ -236,7 +236,6 @@ int boot_request_set_preferred_slot(uint8_t image, enum boot_slot slot) sizeof(value)); } -#ifdef CONFIG_FIND_NEXT_SLOT_HOOKS enum boot_slot boot_request_get_preferred_slot(uint8_t image) { uint8_t value = BOOT_REQUEST_SLOT_INVALID; @@ -265,7 +264,6 @@ enum boot_slot boot_request_get_preferred_slot(uint8_t image) return BOOT_SLOT_NONE; } -#endif /* CONFIG_FIND_NEXT_SLOT_HOOKS */ int boot_request_enter_recovery(void) { diff --git a/boot/zephyr/Kconfig b/boot/zephyr/Kconfig index 49b458e8e..222a724a5 100644 --- a/boot/zephyr/Kconfig +++ b/boot/zephyr/Kconfig @@ -1441,15 +1441,4 @@ config NCS_MCUBOOT_IMG_VALIDATE_ATTEMPT_WAIT_MS Time between image validation attempts, in milliseconds. Allows for recovery from transient bit flips or similar situations. -config NCS_MCUBOOT_BOOT_REQUEST_TEST_SETS_BOOT_PREFERENCE - bool "Set boot preference if a slot is marked for test" - help - This option allows to verify boot preference requests through issuing - the image test. - Using this option is not recommended in production systems, because - it will boot any newly transferred image, even if it has a lower - version than the current one. - The rollback protection (using security counters) will still be - effective. - source "Kconfig.zephyr" From 459288d6a13cede9fa09e314b21a979a6cc6e3f2 Mon Sep 17 00:00:00 2001 From: Artur Hadasz Date: Fri, 31 Oct 2025 09:09:21 +0100 Subject: [PATCH 416/420] [nrf noup] bootutil: Fix ITS key locking compile error nrf-squash! [nrf noup] bootutil: Locking KMU keys KMU key locking is not available in case ITS is used. Old code cause compilation errors when build for signature using ITS. Signed-off-by: Artur Hadasz --- boot/bootutil/src/ed25519_psa.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/boot/bootutil/src/ed25519_psa.c b/boot/bootutil/src/ed25519_psa.c index c7e3910b1..541fc0155 100644 --- a/boot/bootutil/src/ed25519_psa.c +++ b/boot/bootutil/src/ed25519_psa.c @@ -187,6 +187,7 @@ int exec_revoke(void) } #endif /* CONFIG_BOOT_KMU_KEYS_REVOCATION */ +#if defined(CONFIG_BOOT_SIGNATURE_USING_KMU) void nrf_crypto_keys_housekeeping(void) { psa_status_t status; @@ -212,5 +213,6 @@ void nrf_crypto_keys_housekeeping(void) key_ids[i], i, status); } } +#endif #endif From 82b1eee2b24f49fa0ef8eb0c9b9cf25fd9fe0ef5 Mon Sep 17 00:00:00 2001 From: Mateusz Michalek Date: Mon, 3 Nov 2025 09:54:56 +0100 Subject: [PATCH 417/420] [nrf noup] boot: zephyr: BM key revocation nrf-squash! [nrf noup] boot: zephyr: Add bm firmware loader code adds KMU key reocation to BM firmware loader. Signed-off-by: Mateusz Michalek --- boot/zephyr/firmware_loader_bm.c | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/boot/zephyr/firmware_loader_bm.c b/boot/zephyr/firmware_loader_bm.c index 14d5c96bd..e8f43a9d1 100644 --- a/boot/zephyr/firmware_loader_bm.c +++ b/boot/zephyr/firmware_loader_bm.c @@ -15,6 +15,7 @@ #include "bootutil/bootutil_public.h" #include "bootutil/fault_injection_hardening.h" #include +#include "bootutil/key_revocation.h" #include "io/io.h" #include "mcuboot_config/mcuboot_config.h" @@ -249,6 +250,15 @@ boot_go(struct boot_rsp *rsp) } #endif +#if defined(CONFIG_BOOT_KEYS_REVOCATION) + if (softdevice_image_valid == true && firmware_loader_image_valid == true) { + allow_revoke(); + if (revoke() != BOOT_KEY_REVOKE_OK) { + return -1; + } + } +#endif /*CONFIG_BOOT_KEYS_REVOCATION*/ + if (app_installer_image_valid == true && app_installer_is_installer_image == true) { /* Installer image is present, this gets priority */ BOOT_LOG_DBG("Booting installer"); From 0d263faf6e55a697ee336f2fbef0af095802f979 Mon Sep 17 00:00:00 2001 From: Mateusz Michalek Date: Mon, 3 Nov 2025 09:55:26 +0100 Subject: [PATCH 418/420] [nrf noup] bootutil: ed25519_psa: multi verification revocation take into account multiple verification done in one boot. Make sure only unused keys are revoked. Signed-off-by: Mateusz Michalek --- boot/bootutil/src/ed25519_psa.c | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/boot/bootutil/src/ed25519_psa.c b/boot/bootutil/src/ed25519_psa.c index 541fc0155..87097f36c 100644 --- a/boot/bootutil/src/ed25519_psa.c +++ b/boot/bootutil/src/ed25519_psa.c @@ -45,7 +45,8 @@ static psa_key_id_t key_ids[] = { #if defined(CONFIG_BOOT_KMU_KEYS_REVOCATION) #include -static psa_key_id_t *validated_with = NULL; +#define VALIDATED_WITH_UNINITIALIZED INT32_MAX +static int32_t validated_with = VALIDATED_WITH_UNINITIALIZED; #endif BUILD_ASSERT(CONFIG_BOOT_SIGNATURE_KMU_SLOTS <= ARRAY_SIZE(key_ids), @@ -142,7 +143,9 @@ int ED25519_verify(const uint8_t *message, size_t message_len, EDDSA_SIGNAGURE_LENGTH); if (status == PSA_SUCCESS) { #if defined(CONFIG_BOOT_KMU_KEYS_REVOCATION) - validated_with = key_ids + i; + if(i < validated_with) { + validated_with = i; + } #endif return 1; } @@ -159,7 +162,7 @@ int exec_revoke(void) int ret = BOOT_KEY_REVOKE_OK; psa_status_t status = psa_crypto_init(); - if (!validated_with) { + if (validated_with == VALIDATED_WITH_UNINITIALIZED) { ret = BOOT_KEY_REVOKE_INVALID; goto out; } @@ -170,7 +173,7 @@ int exec_revoke(void) goto out; } for (int i = 0; i < CONFIG_BOOT_SIGNATURE_KMU_SLOTS; i++) { - if ((key_ids + i) == validated_with) { + if ( i == validated_with) { break; } BOOT_LOG_DBG("Invalidating key ID %d", i); @@ -179,7 +182,7 @@ int exec_revoke(void) if (status == PSA_SUCCESS) { BOOT_LOG_DBG("Success on key ID %d", i); } else { - BOOT_LOG_ERR("Key invalidation failed with: %d", status); + BOOT_LOG_DBG("Key invalidation failed with: %d", status); } } out: From ff54861d064af1cd89c73ca4ad746195b56a100f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Adam=20Szczygie=C5=82?= Date: Fri, 17 Oct 2025 15:23:04 +0200 Subject: [PATCH 419/420] WIP - add configs and implementation for ocrypto (nrf_oberon). MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit At the moment hello_world_mini_boot sample builds but app image verification at boot fails - TBD. Signed-off-by: Adam Szczygieł --- boot/bootutil/include/bootutil/crypto/ecdsa.h | 47 ++++++++++++++-- boot/bootutil/include/bootutil/crypto/sha.h | 53 ++++++++++++++++++- boot/bootutil/zephyr/CMakeLists.txt | 5 ++ boot/zephyr/Kconfig | 10 ++++ .../include/mcuboot_config/mcuboot_config.h | 2 + 5 files changed, 113 insertions(+), 4 deletions(-) diff --git a/boot/bootutil/include/bootutil/crypto/ecdsa.h b/boot/bootutil/include/bootutil/crypto/ecdsa.h index 7fc5474e2..066cb222f 100644 --- a/boot/bootutil/include/bootutil/crypto/ecdsa.h +++ b/boot/bootutil/include/bootutil/crypto/ecdsa.h @@ -35,7 +35,8 @@ #if (defined(MCUBOOT_USE_TINYCRYPT) + \ defined(MCUBOOT_USE_CC310) + \ defined(MCUBOOT_USE_NRF_EXTERNAL_CRYPTO) + \ - defined(MCUBOOT_USE_PSA_OR_MBED_TLS)) != 1 + defined(MCUBOOT_USE_PSA_OR_MBED_TLS) + \ + defined(MCUBOOT_USE_NRF_OBERON_EXPERIMENT)) != 1 #error "One crypto backend must be defined: either CC310/TINYCRYPT/MBED_TLS/PSA_CRYPTO" #endif @@ -58,6 +59,10 @@ #define MCUBOOT_ECDSA_NEED_ASN1_SIG #endif /* MCUBOOT_USE_MBED_TLS */ +#if defined(MCUBOOT_USE_NRF_OBERON_EXPERIMENT) + #include +#endif /* MCUBOOT_USE_NRF_OBERON_EXPERIMENT */ + /*TODO: remove this after cypress port mbedtls to abstract crypto api */ #if defined(MCUBOOT_USE_CC310) || defined(MCUBOOT_USE_MBED_TLS) #define NUM_ECC_BYTES (256 / 8) @@ -136,7 +141,7 @@ static int bootutil_import_key(uint8_t **cp, uint8_t *end) } #endif /* (MCUBOOT_USE_TINYCRYPT || MCUBOOT_USE_MBED_TLS || MCUBOOT_USE_CC310) && !MCUBOOT_USE_PSA_CRYPTO */ -#ifndef MCUBOOT_USE_PSA_CRYPTO +#if !defined(MCUBOOT_USE_PSA_CRYPTO) && !defined(MCUBOOT_USE_NRF_OBERON_EXPERIMENT) /* * cp points to ASN1 string containing an integer. * Verify the tag, and that the length is 32 bytes. Helper function. @@ -186,7 +191,7 @@ static int bootutil_decode_sig(uint8_t signature[NUM_ECC_BYTES * 2], uint8_t *cp } return 0; } -#endif /* !MCUBOOT_USE_PSA_CRYPTO */ +#endif /* !defined(MCUBOOT_USE_PSA_CRYPTO) && !defined(MCUBOOT_USE_NRF_OBERON_EXPERIMENT) */ #if defined(MCUBOOT_USE_TINYCRYPT) typedef uintptr_t bootutil_ecdsa_context; @@ -719,6 +724,42 @@ static inline int bootutil_ecdsa_parse_public_key(bootutil_ecdsa_context *ctx, } #endif /* MCUBOOT_USE_NRF_EXTERNAL_CRYPTO */ +#if defined(MCUBOOT_USE_NRF_OBERON_EXPERIMENT) +typedef uintptr_t bootutil_ecdsa_context; + +static inline void bootutil_ecdsa_init(bootutil_ecdsa_context *ctx) +{ + (void)ctx; +} + +static inline void bootutil_ecdsa_drop(bootutil_ecdsa_context *ctx) +{ + (void)ctx; +} + +static inline int bootutil_ecdsa_verify(bootutil_ecdsa_context *ctx, + uint8_t *pk, size_t pk_len, + uint8_t *hash, size_t hash_len, + uint8_t *sig, size_t sig_len) +{ + if (pk == NULL || hash == NULL || sig == NULL) { + return -1; + } + + return ocrypto_ecdsa_p256_verify_hash(sig, hash, pk); +} + +static inline int bootutil_ecdsa_parse_public_key(bootutil_ecdsa_context *ctx, + uint8_t **cp,uint8_t *end) +{ + /* NOTE: No corresponding funciton in ocrypto */ + (void)ctx; + (void)cp; + (void)end; + return 0; +} +#endif /* MCUBOOT_USE_NRF_OBERON_EXPERIMENT */ + #ifdef __cplusplus } #endif diff --git a/boot/bootutil/include/bootutil/crypto/sha.h b/boot/bootutil/include/bootutil/crypto/sha.h index b83a3ec40..6191ac906 100644 --- a/boot/bootutil/include/bootutil/crypto/sha.h +++ b/boot/bootutil/include/bootutil/crypto/sha.h @@ -31,7 +31,8 @@ #if (defined(MCUBOOT_USE_PSA_OR_MBED_TLS) + \ defined(MCUBOOT_USE_TINYCRYPT) + \ defined(MCUBOOT_USE_NRF_EXTERNAL_CRYPTO) + \ - defined(MCUBOOT_USE_CC310)) != 1 + defined(MCUBOOT_USE_CC310) + \ + defined(MCUBOOT_USE_NRF_OBERON_EXPERIMENT)) != 1 #error "One crypto backend must be defined: either CC310/MBED_TLS/TINYCRYPT/PSA_CRYPTO" #endif @@ -82,6 +83,10 @@ #include #endif /* MCUBOOT_USE_CC310 */ +#if defined(MCUBOOT_USE_NRF_OBERON_EXPERIMENT) + #include +#endif /* MCUBOOT_USE_NRF_OBERON_EXPERIMENT */ + #include #ifdef __cplusplus @@ -302,6 +307,52 @@ static inline int bootutil_sha_finish(bootutil_sha_context *ctx, } #endif /* MCUBOOT_USE_NRF_EXTERNAL_CRYPTO */ +#if defined(MCUBOOT_USE_NRF_OBERON_EXPERIMENT) +typedef ocrypto_sha256_ctx bootutil_sha_context; + +static inline int bootutil_sha_init(bootutil_sha_context *ctx) +{ + if (ctx == NULL) { + return -1; + } + + ocrypto_sha256_init(ctx); + return 0; +} + +static inline int bootutil_sha_drop(bootutil_sha_context *ctx) +{ + /* NOTE: No corresponding function for ocrypto_sha256 */ + (void)ctx; + return 0; +} + +static inline int bootutil_sha_update(bootutil_sha_context *ctx, + const void *data, + uint32_t data_len) +{ + if (ctx == NULL || data == NULL) { + return -1; + } + + ocrypto_sha256_update(ctx, (const uint8_t *)data, (size_t)data_len); + + return 0; +} + +static inline int bootutil_sha_finish(bootutil_sha_context *ctx, + uint8_t *output) +{ + if (ctx == NULL || output == NULL) { + return -1; + } + + ocrypto_sha256_final(ctx, output); + return 0; +} + +#endif /* MCUBOOT_USE_NRF_OBERON_EXPERIMENT */ + #ifdef __cplusplus } #endif diff --git a/boot/bootutil/zephyr/CMakeLists.txt b/boot/bootutil/zephyr/CMakeLists.txt index 111cf4f1d..968bab2d4 100644 --- a/boot/bootutil/zephyr/CMakeLists.txt +++ b/boot/bootutil/zephyr/CMakeLists.txt @@ -45,6 +45,11 @@ if(CONFIG_BOOT_USE_PSA_CRYPTO) ) endif() +if(CONFIG_BOOT_USE_NRF_OBERON_EXPERIMENT) + target_include_directories(MCUBOOT_BOOTUTIL INTERFACE ${OBERON_BASE}/include) + zephyr_link_libraries(nrfxlib_crypto) +endif() + if(CONFIG_BOOT_USE_MBEDTLS OR CONFIG_BOOT_USE_PSA_CRYPTO AND NOT CONFIG_NRF_SECURITY) zephyr_link_libraries(mbedTLS) endif() diff --git a/boot/zephyr/Kconfig b/boot/zephyr/Kconfig index 222a724a5..524e9c8b0 100644 --- a/boot/zephyr/Kconfig +++ b/boot/zephyr/Kconfig @@ -54,6 +54,12 @@ config BOOT_USE_CC310 config BOOT_USE_NRF_CC310_BL bool +config BOOT_USE_NRF_OBERON_EXPERIMENT + bool + default n + help + Use nrf oberon. + config NRFXLIB_CRYPTO bool @@ -286,6 +292,10 @@ choice BOOT_ECDSA_IMPLEMENTATION default BOOT_ECDSA_PSA if NRF_SECURITY default BOOT_ECDSA_TINYCRYPT +config BOOT_ECDSA_NRF_OBERON_EXPERIMENT + bool "Use nrf oberon" + select BOOT_USE_NRF_OBERON_EXPERIMENT + config BOOT_ECDSA_TINYCRYPT bool "Use tinycrypt" select BOOT_USE_TINYCRYPT diff --git a/boot/zephyr/include/mcuboot_config/mcuboot_config.h b/boot/zephyr/include/mcuboot_config/mcuboot_config.h index 2d759217b..1e445e24f 100644 --- a/boot/zephyr/include/mcuboot_config/mcuboot_config.h +++ b/boot/zephyr/include/mcuboot_config/mcuboot_config.h @@ -51,6 +51,8 @@ #define MCUBOOT_USE_PSA_CRYPTO #elif defined(CONFIG_BOOT_USE_NRF_EXTERNAL_CRYPTO) #define MCUBOOT_USE_NRF_EXTERNAL_CRYPTO +#elif defined(CONFIG_BOOT_USE_NRF_OBERON_EXPERIMENT) +#define MCUBOOT_USE_NRF_OBERON_EXPERIMENT #endif #ifdef CONFIG_BOOT_IMG_HASH_ALG_SHA512 From 0c0a5daae68490a1d9eb2ab0acf2a589305fee42 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Adam=20Szczygie=C5=82?= Date: Tue, 21 Oct 2025 13:41:31 +0200 Subject: [PATCH 420/420] Add the missing parts to make ocrypto_ verification work MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Adam Szczygieł --- boot/bootutil/include/bootutil/crypto/ecdsa.h | 29 ++++++++++++++----- 1 file changed, 21 insertions(+), 8 deletions(-) diff --git a/boot/bootutil/include/bootutil/crypto/ecdsa.h b/boot/bootutil/include/bootutil/crypto/ecdsa.h index 066cb222f..17c6a862f 100644 --- a/boot/bootutil/include/bootutil/crypto/ecdsa.h +++ b/boot/bootutil/include/bootutil/crypto/ecdsa.h @@ -64,7 +64,7 @@ #endif /* MCUBOOT_USE_NRF_OBERON_EXPERIMENT */ /*TODO: remove this after cypress port mbedtls to abstract crypto api */ -#if defined(MCUBOOT_USE_CC310) || defined(MCUBOOT_USE_MBED_TLS) +#if defined(MCUBOOT_USE_CC310) || defined(MCUBOOT_USE_MBED_TLS) || defined(MCUBOOT_USE_NRF_OBERON_EXPERIMENT) #define NUM_ECC_BYTES (256 / 8) #endif @@ -88,7 +88,8 @@ extern "C" { #endif #if (defined(MCUBOOT_USE_TINYCRYPT) || defined(MCUBOOT_USE_MBED_TLS) || \ - defined(MCUBOOT_USE_CC310) || defined(MCUBOOT_USE_NRF_EXTERNAL_CRYPTO)) \ + defined(MCUBOOT_USE_CC310) || defined(MCUBOOT_USE_NRF_EXTERNAL_CRYPTO) || \ + defined(MCUBOOT_USE_NRF_OBERON_EXPERIMENT)) \ && !defined(MCUBOOT_USE_PSA_CRYPTO) /* * Declaring these like this adds NULL termination. @@ -141,7 +142,7 @@ static int bootutil_import_key(uint8_t **cp, uint8_t *end) } #endif /* (MCUBOOT_USE_TINYCRYPT || MCUBOOT_USE_MBED_TLS || MCUBOOT_USE_CC310) && !MCUBOOT_USE_PSA_CRYPTO */ -#if !defined(MCUBOOT_USE_PSA_CRYPTO) && !defined(MCUBOOT_USE_NRF_OBERON_EXPERIMENT) +#if !defined(MCUBOOT_USE_PSA_CRYPTO) /* * cp points to ASN1 string containing an integer. * Verify the tag, and that the length is 32 bytes. Helper function. @@ -191,7 +192,7 @@ static int bootutil_decode_sig(uint8_t signature[NUM_ECC_BYTES * 2], uint8_t *cp } return 0; } -#endif /* !defined(MCUBOOT_USE_PSA_CRYPTO) && !defined(MCUBOOT_USE_NRF_OBERON_EXPERIMENT) */ +#endif /* !defined(MCUBOOT_USE_PSA_CRYPTO) */ #if defined(MCUBOOT_USE_TINYCRYPT) typedef uintptr_t bootutil_ecdsa_context; @@ -746,16 +747,28 @@ static inline int bootutil_ecdsa_verify(bootutil_ecdsa_context *ctx, return -1; } - return ocrypto_ecdsa_p256_verify_hash(sig, hash, pk); + uint8_t signature[2 * NUM_ECC_BYTES]; + int rc = bootutil_decode_sig(signature, sig, sig + sig_len); + if (rc) { + return -1; + } + + /* Only support uncompressed keys */ + if (pk[0] != 0x04) { + return -1; + } + /* Skip the first byte holding key format */ + pk++; + + rc = ocrypto_ecdsa_p256_verify_hash(signature, hash, pk); + return rc; } static inline int bootutil_ecdsa_parse_public_key(bootutil_ecdsa_context *ctx, uint8_t **cp,uint8_t *end) { - /* NOTE: No corresponding funciton in ocrypto */ (void)ctx; - (void)cp; - (void)end; + return bootutil_import_key(cp, end); return 0; } #endif /* MCUBOOT_USE_NRF_OBERON_EXPERIMENT */