diff --git a/.github/workflows/backport.yml b/.github/workflows/backport.yml new file mode 100644 index 000000000..a6f3a2d5d --- /dev/null +++ b/.github/workflows/backport.yml @@ -0,0 +1,19 @@ +name: Backport +on: + pull_request: + types: + - closed + - labeled + +jobs: + backport: + runs-on: ubuntu-18.04 + name: Backport + steps: + - name: Backport Bot + uses: Gaurav0/backport@v1.0.24 + with: + bot_username: NordicBuilder + bot_token: 151a9b45052f9ee8be5a59963d31ad7b92c3ecb5 + bot_token_key: 67bb1f1f998d546859786a4088917c65415c0ebd + github_token: ${{ secrets.GITHUB_TOKEN }} \ No newline at end of file diff --git a/.gitlint b/.gitlint new file mode 100644 index 000000000..512813bbb --- /dev/null +++ b/.gitlint @@ -0,0 +1,57 @@ +# All these sections are optional, edit this file as you like. +[general] +ignore=title-trailing-punctuation, T3, title-max-length, T1, body-hard-tab, B3, B1 +# verbosity should be a value between 1 and 3, the commandline -v flags take precedence over this +verbosity = 3 +# By default gitlint will ignore merge commits. Set to 'false' to disable. +ignore-merge-commits=true +# Enable debug mode (prints more output). Disabled by default +debug = false + +# Set the extra-path where gitlint will search for user defined rules +# See http://jorisroovers.github.io/gitlint/user_defined_rules for details +extra-path=../../zephyr/scripts/gitlint + +[title-max-length-no-revert] +line-length=72 + +[body-min-line-count] +min-line-count=1 + +[body-max-line-count] +max-line-count=200 + +[title-starts-with-subsystem] +regex = ^(?!subsys:)(([^:]+):)(\s([^:]+):)*\s(.+)$ + +[title-must-not-contain-word] +# Comma-separated list of words that should not occur in the title. Matching is case +# insensitive. It's fine if the keyword occurs as part of a larger word (so "WIPING" +# will not cause a violation, but "WIP: my title" will. +words=wip + +[title-match-regex] +# python like regex (https://docs.python.org/2/library/re.html) that the +# commit-msg title must be matched to. +# Note that the regex can contradict with other rules if not used correctly +# (e.g. title-must-not-contain-word). +#regex=^US[0-9]* + +[max-line-length-with-exceptions] +# B1 = body-max-line-length +line-length=72 + +[body-min-length] +min-length=3 + +[body-is-missing] +# Whether to ignore this rule on merge commits (which typically only have a title) +# default = True +ignore-merge-commits=false + +[body-changed-file-mention] +# List of files that need to be explicitly mentioned in the body when they are changed +# This is useful for when developers often erroneously edit certain files or git submodules. +# By specifying this rule, developers can only change the file when they explicitly reference +# it in the commit message. +#files=gitlint/rules.py,README.md diff --git a/Jenkinsfile b/Jenkinsfile new file mode 100644 index 000000000..8220afe03 --- /dev/null +++ b/Jenkinsfile @@ -0,0 +1,6 @@ +@Library("CI_LIB") _ + +def pipeline = new ncs.sdk_mcuboot.Main() + +pipeline.run(JOB_NAME) + diff --git a/boot/boot_serial/src/boot_serial.c b/boot/boot_serial/src/boot_serial.c index d0f0eb0cd..1e4faf133 100644 --- a/boot/boot_serial/src/boot_serial.c +++ b/boot/boot_serial/src/boot_serial.c @@ -626,6 +626,7 @@ boot_serial_start(const struct boot_uart_funcs *f) while (1) { rc = f->read(in_buf + off, sizeof(in_buf) - off, &full_line); if (rc <= 0 && !full_line) { + k_yield(); continue; } off += rc; diff --git a/boot/bootutil/include/bootutil/crypto/ecdsa_p256.h b/boot/bootutil/include/bootutil/crypto/ecdsa_p256.h index b77cd347c..a658ba854 100644 --- a/boot/bootutil/include/bootutil/crypto/ecdsa_p256.h +++ b/boot/bootutil/include/bootutil/crypto/ecdsa_p256.h @@ -14,6 +14,7 @@ #if (defined(MCUBOOT_USE_TINYCRYPT) + \ defined(MCUBOOT_USE_CC310) + \ + defined(MCUBOOT_USE_NRF_EXTERNAL_CRYPTO) + \ defined(MCUBOOT_USE_MBED_TLS)) != 1 #error "One crypto backend must be defined: either CC310 or TINYCRYPT" #endif @@ -29,6 +30,11 @@ #define BOOTUTIL_CRYPTO_ECDSA_P256_HASH_SIZE (4 * 8) #endif /* MCUBOOT_USE_CC310 */ +#if defined(MCUBOOT_USE_NRF_EXTERNAL_CRYPTO) + #include + #define BOOTUTIL_CRYPTO_ECDSA_P256_HASH_SIZE (4 * 8) +#endif /* MCUBOOT_USE_NRF_EXTERNAL_CRYPTO */ + #ifdef __cplusplus extern "C" { #endif @@ -76,6 +82,27 @@ static inline int bootutil_ecdsa_p256_verify(bootutil_ecdsa_p256_context *ctx, u } #endif /* MCUBOOT_USE_CC310 */ +#if defined(MCUBOOT_USE_NRF_EXTERNAL_CRYPTO) +typedef uintptr_t bootutil_ecdsa_p256_context; + +static inline void bootutil_ecdsa_p256_init(bootutil_ecdsa_p256_context *ctx) +{ + (void)ctx; +} + +static inline void bootutil_ecdsa_p256_drop(bootutil_ecdsa_p256_context *ctx) +{ + (void)ctx; +} + +static inline int bootutil_ecdsa_p256_verify(bootutil_ecdsa_p256_context *ctx, uint8_t *pk, uint8_t *hash, uint8_t *sig) +{ + (void)ctx; + return bl_secp256r1_validate(hash, BOOTUTIL_CRYPTO_ECDSA_P256_HASH_SIZE, + pk, sig); +} +#endif /* MCUBOOT_USE_NRF_EXTERNAL_CRYPTO */ + #ifdef __cplusplus } #endif diff --git a/boot/bootutil/include/bootutil/crypto/sha256.h b/boot/bootutil/include/bootutil/crypto/sha256.h index 00c321893..2c8140dbc 100644 --- a/boot/bootutil/include/bootutil/crypto/sha256.h +++ b/boot/bootutil/include/bootutil/crypto/sha256.h @@ -21,6 +21,7 @@ #if (defined(MCUBOOT_USE_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 or TINYCRYPT" #endif @@ -134,6 +135,37 @@ static inline int bootutil_sha256_finish(bootutil_sha256_context *ctx, } #endif /* MCUBOOT_USE_CC310 */ +#if defined(MCUBOOT_USE_NRF_EXTERNAL_CRYPTO) + +#include + +typedef bl_sha256_ctx_t bootutil_sha256_context; + +static inline void bootutil_sha256_init(bootutil_sha256_context *ctx) +{ + bl_sha256_init(ctx); +} + +static inline void bootutil_sha256_drop(bootutil_sha256_context *ctx) +{ + (void)ctx; +} + +static inline int bootutil_sha256_update(bootutil_sha256_context *ctx, + const void *data, + uint32_t data_len) +{ + return bl_sha256_update(ctx, data, data_len); +} + +static inline int bootutil_sha256_finish(bootutil_sha256_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/bootutil/src/image_ec256.c b/boot/bootutil/src/image_ec256.c index f5b813593..d181cfe2c 100644 --- a/boot/bootutil/src/image_ec256.c +++ b/boot/bootutil/src/image_ec256.c @@ -33,7 +33,11 @@ #ifdef MCUBOOT_USE_CC310 #define NUM_ECC_BYTES (256 / 8) #endif -#if defined (MCUBOOT_USE_TINYCRYPT) || defined (MCUBOOT_USE_CC310) +#ifdef MCUBOOT_USE_NRF_EXTERNAL_CRYPTO +#define NUM_ECC_BYTES (256 / 8) +#endif +#if defined (MCUBOOT_USE_TINYCRYPT) || defined (MCUBOOT_USE_CC310) \ + || defined (MCUBOOT_USE_NRF_EXTERNAL_CRYPTO) #include "bootutil/sign_key.h" #include "mbedtls/oid.h" diff --git a/boot/bootutil/src/loader.c b/boot/bootutil/src/loader.c index b81a7cea3..716e3edd0 100644 --- a/boot/bootutil/src/loader.c +++ b/boot/bootutil/src/loader.c @@ -45,6 +45,10 @@ #include "bootutil/boot_record.h" #include "bootutil/fault_injection_hardening.h" +#ifdef CONFIG_SOC_NRF5340_CPUAPP +#include +#endif + #ifdef MCUBOOT_ENC_IMAGES #include "bootutil/enc_key.h" #endif @@ -90,6 +94,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 { @@ -715,6 +728,47 @@ boot_validated_swap_type(struct boot_loader_state *state, { int swap_type; fih_int 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; + /* 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. + */ + + 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 + 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)) { @@ -728,7 +782,31 @@ 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"); + rc = swap_erase_trailer_sectors(state, + secondary_fa); + swap_type = BOOT_SWAP_TYPE_NONE; + } + } +#endif /* CONFIG_SOC_NRF5340_CPUAPP */ } return swap_type; @@ -1839,10 +1917,23 @@ 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); - if (fih_not_eq(fih_rc, FIH_SUCCESS)) { - goto out; - } +#ifdef PM_S1_ADDRESS + /* Patch needed for NCS. If secure boot is enabled, then mcuboot + * will be stored in either partition S0 or S1. Image 1 primary + * will point to the 'other' Sx partition. Hence, image 1 primary + * does not contain a valid image until mcuboot has been upgraded. + * Note that B0 will perform validation of the active mcuboot image, + * so there is no security lost by skipping this check for image 1 + * primary. + */ + if (BOOT_CURR_IMG(state) == 0) +#endif + { + FIH_CALL(boot_validate_slot, fih_rc, state, BOOT_PRIMARY_SLOT, NULL); + if (fih_not_eq(fih_rc, FIH_SUCCESS)) { + goto out; + } + } #else /* Even if we're not re-validating the primary slot, we could be booting * onto an empty flash chip. At least do a basic sanity check that diff --git a/boot/bootutil/src/swap_move.c b/boot/bootutil/src/swap_move.c index f2883f626..71d35361f 100644 --- a/boot/bootutil/src/swap_move.c +++ b/boot/bootutil/src/swap_move.c @@ -211,6 +211,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; @@ -247,6 +259,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 55fa61f0f..e37caccee 100644 --- a/boot/bootutil/src/swap_scratch.c +++ b/boot/bootutil/src/swap_scratch.c @@ -175,6 +175,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; @@ -260,6 +272,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/zephyr/CMakeLists.txt b/boot/zephyr/CMakeLists.txt index 49b0fa017..32ec9627e 100644 --- a/boot/zephyr/CMakeLists.txt +++ b/boot/zephyr/CMakeLists.txt @@ -74,8 +74,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( @@ -163,6 +161,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() # Since here we are not using Zephyr's mbedTLS but rather our own, we need @@ -274,6 +274,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(GENERATED_PUBKEY ${ZEPHYR_BINARY_DIR}/autogen-pubkey.c) add_custom_command( OUTPUT ${GENERATED_PUBKEY} @@ -294,3 +301,9 @@ zephyr_library_sources( ${BOOT_DIR}/zephyr/arm_cleanup.c ) endif() + +if(CONFIG_MCUBOOT_NRF_CLEANUP_PERIPHERAL) +zephyr_library_sources( + ${BOOT_DIR}/zephyr/nrf_cleanup.c +) +endif() diff --git a/boot/zephyr/Kconfig b/boot/zephyr/Kconfig index ef3e834e3..0b57d86e2 100644 --- a/boot/zephyr/Kconfig +++ b/boot/zephyr/Kconfig @@ -16,6 +16,18 @@ config MCUBOOT select USE_DT_CODE_PARTITION if HAS_FLASH_LOAD_OFFSET select MCUBOOT_BOOTUTIL_LIB +partition=MCUBOOT +partition-size=0xc000 +source "${ZEPHYR_BASE}/../nrf/subsys/partition_manager/Kconfig.template.partition_size" + +partition=MCUBOOT_SCRATCH +partition-size=0x1e000 +source "${ZEPHYR_BASE}/../nrf/subsys/partition_manager/Kconfig.template.partition_size" + +partition=MCUBOOT_PAD +partition-size=0x200 +source "${ZEPHYR_BASE}/../nrf/subsys/partition_manager/Kconfig.template.partition_size" + config BOOT_USE_MBEDTLS bool # Hidden option @@ -47,15 +59,18 @@ config BOOT_USE_CC310 config BOOT_USE_NRF_CC310_BL bool - default n - -config NRFXLIB_CRYPTO - bool - default n + select NRF_CC310_BL -config NRF_CC310_BL +config BOOT_USE_NRF_EXTERNAL_CRYPTO bool + # Hidden option default n + # When building for ECDSA, we use our own copy of mbedTLS, so the + # Zephyr one must not be enabled or the MBEDTLS_CONFIG_FILE macros + # will collide. + depends on ! MBEDTLS + help + Use Shared crypto for crypto primitives. menu "MCUBoot settings" @@ -69,6 +84,7 @@ config SINGLE_APPLICATION_SLOT choice prompt "Signature type" + default BOOT_SIGNATURE_TYPE_ECDSA_P256 if HAS_HW_NRF_CC310 default BOOT_SIGNATURE_TYPE_RSA config BOOT_SIGNATURE_TYPE_NONE @@ -93,9 +109,11 @@ config BOOT_SIGNATURE_TYPE_ECDSA_P256 if BOOT_SIGNATURE_TYPE_ECDSA_P256 choice prompt "Ecdsa implementation" - default BOOT_ECDSA_TINYCRYPT + default BOOT_NRF_EXTERNAL_CRYPTO if SECURE_BOOT + default BOOT_ECDSA_CC310 if HAS_HW_NRF_CC310 + default BOOT_TINYCRYPT -config BOOT_ECDSA_TINYCRYPT +config BOOT_TINYCRYPT bool "Use tinycrypt" select BOOT_USE_TINYCRYPT @@ -106,8 +124,14 @@ config BOOT_ECDSA_CC310 select NRF_CC310_BL select NRFXLIB_CRYPTO select BOOT_USE_CC310 + +config BOOT_NRF_EXTERNAL_CRYPTO + bool "Use Shared Crypto from bootloader" + select BOOT_USE_NRF_EXTERNAL_CRYPTO + endchoice # Ecdsa implementation -endif + +endif #BOOT_SIGNATURE_TYPE_ECDSA_P256 config BOOT_SIGNATURE_TYPE_ED25519 bool "Edwards curve digital signatures using ed25519" @@ -134,7 +158,6 @@ config BOOT_SIGNATURE_KEY_FILE default "root-ed25519.pem" if BOOT_SIGNATURE_TYPE_ED25519 default "root-rsa-3072.pem" if BOOT_SIGNATURE_TYPE_RSA && BOOT_SIGNATURE_TYPE_RSA_LEN=3072 default "root-rsa-2048.pem" if BOOT_SIGNATURE_TYPE_RSA && BOOT_SIGNATURE_TYPE_RSA_LEN=2048 - default "" help You can use either absolute or relative path. In case relative path is used, the build system assumes that it starts @@ -163,6 +186,11 @@ config MCUBOOT_CLEANUP_ARM_CORE by default, if they are chain-loadable by MCUboot, so MCUboot does not need to perform such a cleanup itself. +config MCUBOOT_NRF_CLEANUP_PERIPHERAL + bool "Perform peripheral cleanup before chain-load the application" + depends on SOC_FAMILY_NRF + default y + config MBEDTLS_CFG_FILE default "mcuboot-mbedtls-cfg.h" diff --git a/boot/zephyr/boards/thingy91_nrf52840.conf b/boot/zephyr/boards/thingy91_nrf52840.conf new file mode 100644 index 000000000..18a1a4943 --- /dev/null +++ b/boot/zephyr/boards/thingy91_nrf52840.conf @@ -0,0 +1,38 @@ +# 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 +CONFIG_BOOT_SERIAL_DETECT_PORT="GPIO_1" +CONFIG_BOOT_SERIAL_DETECT_PIN=13 +CONFIG_BOOT_SERIAL_DETECT_PIN_VAL=0 + +# Required by USB +CONFIG_MULTITHREADING=y + +# USB +CONFIG_USB=y +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..6e671a286 --- /dev/null +++ b/boot/zephyr/boards/thingy91_nrf9160.conf @@ -0,0 +1,16 @@ +# 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 +CONFIG_BOOT_SERIAL_DETECT_PORT="GPIO_0" +CONFIG_BOOT_SERIAL_DETECT_PIN=26 +CONFIG_BOOT_SERIAL_DETECT_PIN_VAL=0 diff --git a/boot/zephyr/include/mcuboot_config/mcuboot_config.h b/boot/zephyr/include/mcuboot_config/mcuboot_config.h index 8f2b1575b..2feddf03b 100644 --- a/boot/zephyr/include/mcuboot_config/mcuboot_config.h +++ b/boot/zephyr/include/mcuboot_config/mcuboot_config.h @@ -40,9 +40,8 @@ #define MCUBOOT_USE_TINYCRYPT #elif defined(CONFIG_BOOT_USE_CC310) #define MCUBOOT_USE_CC310 -#ifdef CONFIG_BOOT_USE_NRF_CC310_BL -#define MCUBOOT_USE_NRF_CC310_BL -#endif +#elif defined(CONFIG_BOOT_USE_NRF_EXTERNAL_CRYPTO) +#define MCUBOOT_USE_NRF_EXTERNAL_CRYPTO #endif #ifdef CONFIG_BOOT_HW_KEY diff --git a/boot/zephyr/include/nrf_cleanup.h b/boot/zephyr/include/nrf_cleanup.h new file mode 100644 index 000000000..2b175634e --- /dev/null +++ b/boot/zephyr/include/nrf_cleanup.h @@ -0,0 +1,19 @@ +/* + * Copyright (c) 2020 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: LicenseRef-BSD-5-Clause-Nordic + */ + +#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/include/sysflash/sysflash.h b/boot/zephyr/include/sysflash/sysflash.h index 99ca27371..25479900f 100644 --- a/boot/zephyr/include/sysflash/sysflash.h +++ b/boot/zephyr/include/sysflash/sysflash.h @@ -3,6 +3,51 @@ #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 @@ -55,4 +100,6 @@ #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 1b0c8f52f..72a62cc22 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 747d36ca0..b0a9ec6a7 100644 --- a/boot/zephyr/main.c +++ b/boot/zephyr/main.c @@ -33,6 +33,10 @@ #include "bootutil/fault_injection_hardening.h" #include "flash_map_backend/flash_map_backend.h" +#ifdef CONFIG_FW_INFO +#include +#endif + #ifdef CONFIG_MCUBOOT_SERIAL #include "boot_serial/boot_serial.h" #include "serial_adapter/serial_adapter.h" @@ -51,6 +55,10 @@ const struct boot_uart_funcs boot_funcs = { #include #endif +#ifdef CONFIG_SOC_NRF5340_CPUAPP +#include +#endif + /* CONFIG_LOG_MINIMAL is the legacy Kconfig property, * replaced by CONFIG_LOG_MODE_MINIMAL. */ @@ -83,6 +91,16 @@ K_SEM_DEFINE(boot_log_sem, 1, 1); #define ZEPHYR_BOOT_LOG_STOP() do { } while (false) #endif /* defined(CONFIG_LOG) && !defined(CONFIG_LOG_IMMEDIATE) */ +#if USE_PARTITION_MANAGER && CONFIG_FPROTECT +#include +#include + +#endif + +#if CONFIG_MCUBOOT_NRF_CLEANUP_PERIPHERAL +#include +#endif + #ifdef CONFIG_SOC_FAMILY_NRF #include @@ -146,6 +164,21 @@ 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_NRF_CLEANUP_PERIPHERAL + nrf_cleanup_peripheral(); +#endif #if CONFIG_MCUBOOT_CLEANUP_ARM_CORE cleanup_arm_nvic(); /* cleanup NVIC registers */ @@ -411,7 +444,33 @@ void main(void) rsp.br_image_off); BOOT_LOG_INF("Jumping to the first image slot"); + +#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 */ +#if defined(CONFIG_SOC_NRF5340_CPUAPP) && defined(PM_CPUNET_B0N_ADDRESS) + pcd_lock_ram(); +#endif + ZEPHYR_BOOT_LOG_STOP(); + do_boot(&rsp); BOOT_LOG_ERR("Never should get here"); diff --git a/boot/zephyr/nrf_cleanup.c b/boot/zephyr/nrf_cleanup.c new file mode 100644 index 000000000..2f7cf2d68 --- /dev/null +++ b/boot/zephyr/nrf_cleanup.c @@ -0,0 +1,49 @@ +/* + * Copyright (c) 2020 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: LicenseRef-BSD-5-Clause-Nordic + */ + +#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_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); +#endif +#if defined(NRF_UARTE1) + nrf_uarte_disable(NRF_UARTE1); + nrf_uarte_int_disable(NRF_UARTE1, 0xFFFFFFFF); +#endif + nrf_cleanup_clock(); +} diff --git a/boot/zephyr/overlay-minimal-external-crypto.conf b/boot/zephyr/overlay-minimal-external-crypto.conf new file mode 100644 index 000000000..a4bc98bf5 --- /dev/null +++ b/boot/zephyr/overlay-minimal-external-crypto.conf @@ -0,0 +1,46 @@ +# +# Copyright (c) 2020 Nordic Semiconductor ASA +# +# SPDX-License-Identifier: LicenseRef-BSD-5-Clause-Nordic +# + +# These configurations should be used when using nrf/samples/bootloader +# as the immutable bootloader (B0), and MCUBoot as the second stage updateable +# bootloader. With this configuration, MCUBoot will re-use the crypto +# functionality from B0, and fit within 16kB. + +CONFIG_NCS_SAMPLES_DEFAULTS=n +CONFIG_LOG=n +CONFIG_BOOT_BANNER=n +CONFIG_PRINTK=n +CONFIG_CONSOLE=n +CONFIG_UART_CONSOLE=n +CONFIG_SERIAL=n +CONFIG_SECURE_BOOT_DEBUG=n +CONFIG_ASSERT=n +CONFIG_RESET_ON_FATAL_ERROR=n +CONFIG_REBOOT=n +CONFIG_GPIO=n +CONFIG_CLOCK_CONTROL=n +CONFIG_MINIMAL_LIBC_MALLOC=n +CONFIG_MINIMAL_LIBC_CALLOC=n +CONFIG_MINIMAL_LIBC_REALLOCARRAY=n +CONFIG_SIZE_OPTIMIZATIONS=y +CONFIG_NO_RUNTIME_CHECKS=y +CONFIG_CONSOLE_HANDLER=n +CONFIG_NRF_RTC_TIMER=n +CONFIG_SYS_CLOCK_EXISTS=n + +# 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 + +# Set 16kB as flash size +CONFIG_PM_PARTITION_SIZE_MCUBOOT=0x3e00 diff --git a/boot/zephyr/pm.yml b/boot/zephyr/pm.yml new file mode 100644 index 000000000..003bcea28 --- /dev/null +++ b/boot/zephyr/pm.yml @@ -0,0 +1,44 @@ +#include + +mcuboot: + size: CONFIG_PM_PARTITION_SIZE_MCUBOOT + placement: + before: [mcuboot_primary] + +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 applicaton +# slot configuration. +#if !defined(CONFIG_SINGLE_APPLICATION_SLOT) +mcuboot_secondary: + share_size: [mcuboot_primary] + placement: + align: {start: CONFIG_FPROTECT_BLOCK_SIZE} + after: mcuboot_primary +#endif + +#if !defined(CONFIG_BOOT_SWAP_USING_MOVE) && !defined(CONFIG_SINGLE_APPLICATION_SLOT) +mcuboot_scratch: + size: CONFIG_PM_PARTITION_SIZE_MCUBOOT_SCRATCH + placement: + after: app + align: {start: CONFIG_FPROTECT_BLOCK_SIZE} +#endif + +# 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 'spm' partition if that is present. + # If 'spm' partition is not present, it must be placed before the 'app'. + 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 7df1254cd..dade88558 100644 --- a/boot/zephyr/prj.conf +++ b/boot/zephyr/prj.conf @@ -1,5 +1,4 @@ CONFIG_CONSOLE_HANDLER=y -CONFIG_DEBUG=y CONFIG_SYSTEM_CLOCK_DISABLE=y CONFIG_SYS_POWER_MANAGEMENT=n @@ -24,6 +23,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/zephyr/module.yml b/zephyr/module.yml index c4293e387..797b0fa10 100644 --- a/zephyr/module.yml +++ b/zephyr/module.yml @@ -1,4 +1,5 @@ samples: - boot/zephyr build: - cmake: ./boot/bootutil/zephyr + cmake-ext: True + kconfig-ext: True