From 1003366bd5db4dfcb3e93bd8a690e6cff7972383 Mon Sep 17 00:00:00 2001 From: LIYOU ZHOU Date: Wed, 22 Aug 2018 15:41:20 +0100 Subject: [PATCH] v3.4.0 (#5) * Add configuration file for a bootloader with default RoT and internal flash firmware storage for Nucleo_F429ZI and K64F * Application start address can be configured independently of application jump address to support cases where the vector table is not at the start of the firmware image. * Active Metadata Header is no longer required to be directly in front of the the active application. It's location can be independently configured. * Add configuration for new platforms: NRF52, NUCLEO_F411RE * Upgrade to mbed-os-5.9.4 * Downgrade to sd-driver-0.1.2 to reduce binary size * Use NVSTORE API shipped with Mbed-OS instead of SOTP API to retrieve the Root of Trust. * Clean up configuration * Guard sd block device instantiation so that when internal flash firmware storage is used, all sd-driver code can be linked out. * Clean up coding style to conform to [mbed-os coding style](https://os.mbed.com/docs/latest/reference/style.html). * Wrap ARM_UCP_FLASHIAP_BLOCKDEVICE so that it only contains the necessary read functions. This reduces binary size. * SOTP is being replaced with NVSTORE which is shipped in Mbed-OS. As NVSTORE is binary compatible with SOTP there is no breakage. The configuration of offsets are still be the same. * In order to keep bootloader size to a minimum, please use latest arm-none-eabi-gcc. Current version is tested with version 7.3.1 which produces binary size smaller than 32k for K64F, UBLOX_EVK_ODIN_W2 and NUCLEO_F429ZI. --- .astyleignore | 2 + .astylerc | 59 +++++ .mbedignore | 55 ++--- README.md | 52 ++-- ...nfig.h => bootloader_mbedtls_user_config.h | 0 ...sotp.json => internal_flash_fake_rot.json} | 44 ++-- configs/internal_flash_nvstore.json | 45 ++++ configs/nrf52_block_device_fake_rot.json | 46 ++++ configs/nrf52_internal_flash_fake_rot.json | 45 ++++ configs/uicr-0x74000.hex | 3 + firmware_update_test/firmware_update_test.cpp | 46 ++-- ...arm_uc_pal_flashiap_blockdevice_readonly.c | 23 ++ fix-mbed-os-compile/pal_polyfill.c | 6 - mbed-cloud-client.lib | 2 +- mbed-os.lib | 2 +- mbed_app.json | 118 +++++---- minimal-printf.lib | 2 +- power_cut_test/bootloader_power_cut_test.cpp | 5 +- power_cut_test/test_mbed_app.json | 67 ------ power_cut_test/test_plan.md | 14 -- sd-driver.lib | 2 +- sotp_fs_config_MbedOS.h | 31 --- source/active_application.cpp | 223 ++++++++++-------- source/active_application.h | 6 +- source/bootloader_common.c | 26 +- source/bootloader_config.h | 17 +- source/example_insecure_rot.c | 10 +- source/main.cpp | 58 +++-- source/{sotp_rot.c => nvstore_rot.cpp} | 38 +-- source/upgrade.cpp | 122 ++++------ source/upgrade.h | 4 +- 31 files changed, 595 insertions(+), 578 deletions(-) create mode 100644 .astyleignore create mode 100644 .astylerc mode change 100644 => 100755 .mbedignore rename mbedtls_mbed_client_config.h => bootloader_mbedtls_user_config.h (100%) rename configs/{internal_flash_sotp.json => internal_flash_fake_rot.json} (50%) create mode 100755 configs/internal_flash_nvstore.json create mode 100644 configs/nrf52_block_device_fake_rot.json create mode 100644 configs/nrf52_internal_flash_fake_rot.json create mode 100644 configs/uicr-0x74000.hex create mode 100644 fix-mbed-os-compile/arm_uc_pal_flashiap_blockdevice_readonly.c delete mode 100644 fix-mbed-os-compile/pal_polyfill.c delete mode 100644 power_cut_test/test_mbed_app.json delete mode 100644 power_cut_test/test_plan.md delete mode 100644 sotp_fs_config_MbedOS.h rename source/{sotp_rot.c => nvstore_rot.cpp} (63%) diff --git a/.astyleignore b/.astyleignore new file mode 100644 index 0000000..d834f52 --- /dev/null +++ b/.astyleignore @@ -0,0 +1,2 @@ +BUILD +scripts diff --git a/.astylerc b/.astylerc new file mode 100644 index 0000000..2dc9a81 --- /dev/null +++ b/.astylerc @@ -0,0 +1,59 @@ +# Mbed OS code style definition file for astyle + +# Don't create backup files, let git handle it +suffix=none + +# K&R style +style=kr + +# 1 TBS addition to k&r, add braces to one liners +# Use -j as it was changed in astyle from brackets to braces, this way it is compatible with older astyle versions +-j + +# 4 spaces, convert tabs to spaces +indent=spaces=4 +convert-tabs + +# Indent switches and cases +indent-switches + +# Remove spaces in and around parentheses +unpad-paren + +# Insert a space after if, while, for, and around operators +pad-header +pad-oper + +# Pointer/reference operators go next to the name (on the right) +align-pointer=name +align-reference=name + +# Attach { for classes and namespaces +attach-namespaces +attach-classes + +# Extend longer lines, define maximum 120 value. This results in aligned code, +# otherwise the lines are broken and not consistent +max-continuation-indent=120 + + +# Style formatting options for Update Client codebase. + +# Each line no greater than 120 characters. +--max-code-length=120 + +# Display only files that have been formatted. +-Q + +# Keep one-line blocks, especially for union initialization of error structs. +--keep-one-line-blocks + +# Indent pre-processor block +# --indent-preproc-block + +# Delete empty lines +# --delete-empty-lines + +# Attach the return type to a function definition or declaration. +--attach-return-type # Definition +--attach-return-type-decl # Declaration diff --git a/.mbedignore b/.mbedignore old mode 100644 new mode 100755 index db19478..db116f5 --- a/.mbedignore +++ b/.mbedignore @@ -12,12 +12,24 @@ mbed-os/features/FEATURE_COMMON_PAL/mbed-trace/test/* mbed-os/features/FEATURE_COMMON_PAL/nanostack-libservice/source/* mbed-os/features/FEATURE_COMMON_PAL/nanostack-libservice/test/* mbed-os/features/FEATURE_UVISOR/* +mbed-os/features/unsupported/* +mbed-os/features/cellular/* +mbed-os/features/lorawan/* mbed-os/features/nanostack/* mbed-os/features/netsocket/* mbed-os/features/storage/* mbed-os/features/filesystem/littlefs/* mbed-os/features/filesystem/fat/* -mbed-os/features/unsupported/* +mbed-os/features/device_key/* +mbed-os/targets/TARGET_STM/TARGET_STM32F4/TARGET_STM32F437xG/TARGET_UBLOX_C030/onboard_modem_api.c +mbed-os/targets/TARGET_STM/TARGET_STM32F4/TARGET_STM32F437xG/TARGET_UBLOX_C030/onboard_modem_api.h +mbed-os/targets/TARGET_STM/TARGET_STM32F4/TARGET_STM32F437xG/TARGET_UBLOX_C030/min_battery_voltage.c +mbed-os/targets/TARGET_STM/TARGET_STM32F4/TARGET_STM32F437xG/TARGET_UBLOX_C030/min_battery_voltage.h +mbed-os/targets/TARGET_STM/TARGET_STM32F4/TARGET_STM32F439xI/TARGET_MODULE_UBLOX_ODIN_W2/sdk/ublox-odin-w2-drivers/default_wifi_interface.cpp +mbed-os/features/frameworks/mbed-client-randlib/* +mbed-os/features/frameworks/mbed-coap/* +mbed-os/features/frameworks/mbed-trace/* +mbed-os/features/frameworks/nanostack-libservice/* mbed-cloud-client/update-client-hub/source/* mbed-cloud-client/update-client-hub/modules/atomic-queue/* mbed-cloud-client/update-client-hub/modules/control-center/* @@ -33,24 +45,9 @@ mbed-cloud-client/update-client-hub/modules/pal-filesystem/* mbed-cloud-client/update-client-hub/modules/pal-target-specific/* mbed-cloud-client/update-client-hub/modules/source-http/* mbed-cloud-client/update-client-hub/modules/source-manager/* +mbed-cloud-client/update-client-hub/modules/resume-engine/* mbed-cloud-client/update-client-hub/modules/common/source/arm_uc_scheduler.c -mbed-cloud-client/mbed-client-pal/Test/* -mbed-cloud-client/mbed-client-pal/Utils/* -mbed-cloud-client/mbed-client-pal/Examples/* -mbed-cloud-client/mbed-client-pal/Source/PAL-Impl/pal_init.c -mbed-cloud-client/mbed-client-pal/Source/PAL-Impl/Modules/Crypto/* -mbed-cloud-client/mbed-client-pal/Source/PAL-Impl/Modules/Networking/* -mbed-cloud-client/mbed-client-pal/Source/PAL-Impl/Modules/RTOS/* -mbed-cloud-client/mbed-client-pal/Source/PAL-Impl/Modules/TLS/* -mbed-cloud-client/mbed-client-pal/Source/PAL-Impl/Modules/Update/* -mbed-cloud-client/mbed-client-pal/Source/PAL-Impl/Modules/Storage/FileSystem/* -mbed-cloud-client/mbed-client-pal/Source/Port/Reference-Impl/Lib_Specific/* -mbed-cloud-client/mbed-client-pal/Source/Port/Reference-Impl/OS_Specific/FreeRTOS/* -mbed-cloud-client/mbed-client-pal/Source/Port/Reference-Impl/OS_Specific/Linux/* -mbed-cloud-client/mbed-client-pal/Source/Port/Reference-Impl/OS_Specific/mbedOS/Networking/* -mbed-cloud-client/mbed-client-pal/Source/Port/Reference-Impl/OS_Specific/mbedOS/RTOS/* -mbed-cloud-client/mbed-client-pal/Source/Port/Reference-Impl/OS_Specific/mbedOS/Update/* -mbed-cloud-client/mbed-client-pal/Source/Port/Reference-Impl/OS_Specific/mbedOS/Storage/FileSystem/* +mbed-cloud-client/mbed-client-pal/* mbed-cloud-client/CMakeLists.txt mbed-cloud-client/DOXYGEN_FRONTPAGE.md mbed-cloud-client/Jenkinsfile @@ -58,27 +55,7 @@ mbed-cloud-client/LICENSE mbed-cloud-client/README.md mbed-cloud-client/contributions.md mbed-cloud-client/doxygen/* -mbed-cloud-client/factory-configurator-client/CMakeLists.txt -mbed-cloud-client/factory-configurator-client/DOXYGEN_FRONTPAGE.md -mbed-cloud-client/factory-configurator-client/common_includes.cmake -mbed-cloud-client/factory-configurator-client/crypto-service/* -mbed-cloud-client/factory-configurator-client/factory-configurator-client/* -mbed-cloud-client/factory-configurator-client/fcc-bundle-handler/* -mbed-cloud-client/factory-configurator-client/fcc-output-info-handler/* -mbed-cloud-client/factory-configurator-client/ftcd-comm-base/* -mbed-cloud-client/factory-configurator-client/ftcd-comm-serial/* -mbed-cloud-client/factory-configurator-client/ftcd-comm-socket/* -mbed-cloud-client/factory-configurator-client/key-config-manager/* -mbed-cloud-client/factory-configurator-client/logger/* -mbed-cloud-client/factory-configurator-client/mbed-trace-helper/* -mbed-cloud-client/factory-configurator-client/secsrv-cbor/* -mbed-cloud-client/factory-configurator-client/storage/* -mbed-cloud-client/factory-configurator-client/utils/* -mbed-cloud-client/factory-configurator-client/mbed-client-esfs/Test/* -mbed-cloud-client/factory-configurator-client/mbed-client-esfs/Tools/* -mbed-cloud-client/factory-configurator-client/mbed-client-esfs/source/esfs.c -mbed-cloud-client/factory-configurator-client/mbed-client-esfs/source/esfs_file_name.c -mbed-cloud-client/factory-configurator-client/mbed-client-esfs/source/esfs_performance.c +mbed-cloud-client/factory-configurator-client/* mbed-cloud-client/mbed-client/* mbed-cloud-client/mbed-client-randlib/* mbed-cloud-client/mbed-cloud-client/* diff --git a/README.md b/README.md index ca7f8b7..3ddcb9f 100644 --- a/README.md +++ b/README.md @@ -7,30 +7,51 @@ Generic bootloader to be used in conjunction with [mbed-cloud-client](https://gi 1. Install `mbed-cli` https://github.com/ARMmbed/mbed-cli 1. Run `mbed deploy` to pull in dependencies 1. Compile by running `mbed compile -t GCC_ARM -m (K64F|NUCLEO_F429ZI|UBLOX_EVK_ODIN_W2) --profile=tiny.json` -1. Use this [script](https://github.com/ARMmbed/mbed-cloud-client-example/blob/master/tools/combine_bootloader_with_app.py) to combine the bootloader with application `python tools/combine_bootloader_with_app.py -a {application.bin} -b {bootloader.bin} --app-offset {firmware_metadata_header_address+firmware_metadata_header_size} --header-offset {firmware_metadata_header_address} -o {combined.bin}`. +1. Use this [script](https://github.com/ARMmbed/mbed-cloud-client-example/blob/master/tools/combine_bootloader_with_app.py) to combine the bootloader with application `python tools/combine_bootloader_with_app.py -a {application.bin} -b {bootloader.bin} --app-offset {application-start-address} --header-offset {firmware_metadata_header_address} -o {combined.bin}`. 1. Flash `{combined.bin}` to device by drag and drop. ## Metadata Header The metadata header is the bootloader update interface. Each stage of the boot sequence leading up to and including the application (except the root bootloader) is paired with a metadata header (containing version, size, hash etc.). Information contained in the metadata header allows validation and ordering of available firmwares. -The firmware metadata header structure can be found [here](https://github.com/ARMmbed/mbed-cloud-client/blob/master/update-client-hub/modules/common/update-client-common/arm_uc_metadata_header_v2.h). There are two header formats, internal and external. The external header format is meant to be used when storing firmware on external storage which is assumed to be insecure. Hence the external header format contains extra security information prevent external tampering of the header data. +The firmware metadata header structure can be found [here](https://github.com/ARMmbed/mbed-cloud-client/blob/master/update-client-hub/modules/common/update-client-common/arm_uc_metadata_header_v2.h). There are two header formats, internal and external. The external header format is used for storing firmware on external storage which is assumed to be insecure. Hence the external header format contains extra security information to prevent external tampering of the header data. ## Configurations -User **must** set in `mbed_app.json`: +NOTE: All these configurations must be set the same in the mbed cloud client when compiling the corresponding application for successful update operation. + +### Active Application and Header + 1. `update-client.application-details`, Address at which the metadata header of the active firmware is written. **Must align to flash erase boundary** -1. `application-start-address`, Address at which The application starts **Must align to vector table size boundary and flash write page boundary**. It is assumed the region between `update-client.application-details` and `application-start-address` contains only the header. MUST be the same as "target.mbed_app_start" in the application. +1. `application-start-address`, Address at which the application starts **Must align to vector table size boundary and flash write page boundary**. +1. `application-jump-address`, Optional address for the application's entry point (vector table) if this is different from `application-start-address`. + +If the `application-start-address` is set less than one erase sector after the `update-client.application-details`, the two regions will be erased together. Otherwise the two regions will be erased separately in which case `application-start-address` must also align to **flash erase boundary**. + +If `application-jump-address` is not set, the `application-start-address` will be used as the application's entry point. The entry point MUST be the same as "target.mbed_app_start" in the application. + +### Firmware Candidate Storage + +1. `MBED_CLOUD_CLIENT_UPDATE_STORAGE`, This need to be set in the "macros" section of `mbed_app.json`. Choices are ARM_UCP_FLASHIAP_BLOCKDEVICE and ARM_UCP_FLASHIAP. This determines whether the firmware is stored on a blockdevice or internal flash. If blockdevice is used `ARM_UC_USE_PAL_BLOCKDEVICE=1` must also be set. 1. `update-client.storage-address`, The address in sd block device or internal flash where the firmware candidates are stored. **Must align to flash erase boundary** 1. `update-client.storage-size`, total size on the block device or internal flash reserved for firmware storage. It will be rounded up to align with flash erase sector size automatically. 1. `update-client.storage-locations`, The number of slots in the firmware storage. 1. `update-client.storage-page`, The write page size of the underlying storage. -If you are using SOTP to provide the RoT, you must set the following: -- "sotp-section-1-address", "sotp-section-1-size", "sotp-section-2-address", "sotp-section-2-size" -The addresses **Must align to flash erase boundary**. The sizes must be full sector sized and at least 1k large. +NOTE: See the [mbed cloud client documentation](https://cloud.mbed.com/docs/current/porting/update-k64f-port.html) for more information about storage options avaiable and porting to new platforms. + +### Device Secret Key + +The bootloader uses device secret key to authenticate anything that is stored on external storage. The update client must be able to obtain the same key as the bootlaoder. The key is derived from a device root of trust using the algorithm [here](https://github.com/ARMmbed/mbed-cloud-client/blob/master/update-client-hub/modules/common/source/arm_uc_crypto.c#L401). -All these configurations must be set the same in the mbed cloud client when compiling the corresponding application for successful update operation. +You may choose to use NVSTORE to store the device RoT. During first boot mbed cloud client will generate a random number from an available entropy source and storge it in NVSTORE on internal flash. On subsequent boots, the RoT will be read from NVSTORE. To enable NVSTORE RoT, you must set the following: +1. Macro `ARM_BOOTLOADER_USE_NVSTORE_ROT=1` to enable the RoT implementation [here](https://github.com/ARMmbed/mbed-bootloader/blob/master/source/nvstore_rot.cpp). +1. "nvstore.area_1_address", "nvstore.area_1_size", "nvstore.area_2_address", "nvstore.area_2_size". The addresses **Must align to flash erase boundary**. The sizes must be full sector sized and at least 1k. +1. NVSTORE and SOTP are binary compatible hence the bootloader works with any software that uses SOTP as long as the offsets are set the same. + +Alternatively you can choose to use a custom device specific RoT by implementing the function `mbed_cloud_client_get_rot_128bit`. An example can be found [here](https://github.com/ARMmbed/mbed-bootloader-internal/blob/master/source/example_insecure_rot.c#L40). + +### MISC User **may** set in `mbed_app.json`: 1. `MAX_COPY_RETRIES`, The number of retries after a failed copy attempt. @@ -39,7 +60,9 @@ User **may** set in `mbed_app.json`: 1. `SHOW_PROGRESS_BAR`, Set to 1 to print a progress bar for various processes. ## Flash Layout + ### The flash layout for K64F with SOTP and firmware storage on internal flash + ``` +--------------------------+ | LittleFS | @@ -66,24 +89,25 @@ User **may** set in `mbed_app.json`: |Active App Metadata Header| | | +--------------------------+ <-+ update-client.application-details - | SOTP_2 | - +--------------------------+ <-+ sotp-section-2-address - | SOTP_1 | - +--------------------------+ <-+ sotp-section-1-address + | NVSTORE_2 | + +--------------------------+ <-+ nvstore.area_2_address + | NVSTORE_1 | + +--------------------------+ <-+ nvstore.area_1_address | | | Bootloader | | | - | | +--------------------------+ <-+ 0 ``` ### Notes on Flash Layout + - Internal Flash Only layout can be enabled by compiling the bootloader with the internal_flash_sotp.json configuration file `--app-config configs/internal_flash_sotp.json`. By default the firmware storage region and filesystem is on [external sd card](#external-storage). - The default flash layout is tested with GCC_ARM compiler and tiny.json compiler profile only. If a different compiler is used, the bootloader binary size will be larger and the offsets needs to be adjusted. -- The SOTP regions require 1 flash erase sector each with at least 1k of space. +- The NVSTORE regions require 1 flash erase sector each with at least 1k of space. - The LittleFS requires 2 flash sectors per folder and 1 sector per file as well as 2 sectors for the filesystem itself. ### Alignment + **Flash Erase Boundary**: Flash can usually only be erased in blocks of specific sizes, this is platform specific and hence many regions need to align to this boundary. **Flash Page Boundary**: Flash can usually only be written in blocks of specific sizes, this is platform specific and hence many regions need to align to this boundary. diff --git a/mbedtls_mbed_client_config.h b/bootloader_mbedtls_user_config.h similarity index 100% rename from mbedtls_mbed_client_config.h rename to bootloader_mbedtls_user_config.h diff --git a/configs/internal_flash_sotp.json b/configs/internal_flash_fake_rot.json similarity index 50% rename from configs/internal_flash_sotp.json rename to configs/internal_flash_fake_rot.json index 5660d41..85afb30 100755 --- a/configs/internal_flash_sotp.json +++ b/configs/internal_flash_fake_rot.json @@ -1,15 +1,14 @@ { "macros": [ - "MBEDTLS_USER_CONFIG_FILE=\"mbedtls_mbed_client_config.h\"", + "MBEDTLS_USER_CONFIG_FILE=\"bootloader_mbedtls_user_config.h\"", + "PAL_USER_DEFINED_CONFIGURATION=\"bootloader_pal_user_config.h\"", "MAX_COPY_RETRIES=1", "SHOW_PROGRESS_BAR=1", "MAX_BOOT_RETRIES=3", "ARM_UC_USE_PAL_CRYPTO=0", - "Mutex=PlatformMutex", - "PAL_USE_INTERNAL_FLASH=1", - "PAL_THREAD_SAFETY=0", - "ARM_UC_USE_SOTP=1", - "MBED_CLOUD_CLIENT_UPDATE_STORAGE=ARM_UCP_FLASHIAP" + "ARM_BOOTLOADER_USE_NVSTORE_ROT=0", + "MBED_CLOUD_CLIENT_UPDATE_STORAGE=ARM_UCP_FLASHIAP", + "Mutex=PlatformMutex" ], "config": { "application-start-address": { @@ -19,26 +18,6 @@ "max-application-size": { "help": "Maximum size of the active application", "value": null - }, - "sotp-section-1-address": { - "help": "Flash sector address for SOTP sector 1", - "macro_name": "PAL_INTERNAL_FLASH_SECTION_1_ADDRESS", - "value": null - }, - "sotp-section-1-size": { - "help": "Flash sector size for SOTP sector 1", - "macro_name": "PAL_INTERNAL_FLASH_SECTION_1_SIZE", - "value": null - }, - "sotp-section-2-address": { - "help": "Flash sector address for SOTP sector 2", - "macro_name": "PAL_INTERNAL_FLASH_SECTION_2_ADDRESS", - "value": null - }, - "sotp-section-2-size": { - "help": "Flash sector size for SOTP sector 2", - "macro_name": "PAL_INTERNAL_FLASH_SECTION_2_SIZE", - "value": null } }, "target_overrides": { @@ -50,10 +29,6 @@ "update-client.firmware-header-version": "2" }, "K64F": { - "sotp-section-1-address" : "( 32*1024)", - "sotp-section-1-size" : "( 4*1024)", - "sotp-section-2-address" : "( 36*1024)", - "sotp-section-2-size" : "( 4*1024)", "update-client.application-details": "( 40*1024)", "application-start-address" : "( 41*1024)", "max-application-size" : "(MBED_CONF_UPDATE_CLIENT_STORAGE_ADDRESS-MBED_CONF_APP_APPLICATION_START_ADDRESS)", @@ -61,6 +36,15 @@ "update-client.storage-size" : "(388*1024)", "update-client.storage-locations" : 1, "update-client.storage-page" : 8 + }, + "NUCLEO_F429ZI": { + "update-client.application-details": "(0x08000000+64*1024)", + "application-start-address" : "(0x08000000+65*1024)", + "max-application-size" : "(MBED_CONF_UPDATE_CLIENT_STORAGE_ADDRESS-MBED_CONF_APP_APPLICATION_START_ADDRESS)", + "update-client.storage-address" : "(0x08000000+1024*1024)", + "update-client.storage-size" : "(512*1024)", + "update-client.storage-locations" : 1, + "update-client.storage-page" : 1 } } } diff --git a/configs/internal_flash_nvstore.json b/configs/internal_flash_nvstore.json new file mode 100755 index 0000000..5b00833 --- /dev/null +++ b/configs/internal_flash_nvstore.json @@ -0,0 +1,45 @@ +{ + "macros": [ + "MBEDTLS_USER_CONFIG_FILE=\"bootloader_mbedtls_user_config.h\"", + "PAL_USER_DEFINED_CONFIGURATION=\"bootloader_pal_user_config.h\"", + "MAX_COPY_RETRIES=1", + "SHOW_PROGRESS_BAR=1", + "MAX_BOOT_RETRIES=3", + "ARM_UC_USE_PAL_CRYPTO=0", + "ARM_BOOTLOADER_USE_NVSTORE_ROT=1", + "MBED_CLOUD_CLIENT_UPDATE_STORAGE=ARM_UCP_FLASHIAP", + "Mutex=PlatformMutex" + ], + "config": { + "application-start-address": { + "help": "Address of the active application firmware in flash", + "value": null + }, + "max-application-size": { + "help": "Maximum size of the active application", + "value": null + } + }, + "target_overrides": { + "*": { + "target.features_remove": ["LWIP"], + "target.features_add": ["COMMON_PAL"], + "platform.stdio-baud-rate": 115200, + "platform.stdio-flush-at-exit": false, + "update-client.firmware-header-version": "2" + }, + "K64F": { + "nvstore.area_1_address" : "( 32*1024)", + "nvstore.area_1_size" : "( 4*1024)", + "nvstore.area_2_address" : "( 36*1024)", + "nvstore.area_2_size" : "( 4*1024)", + "update-client.application-details": "( 40*1024)", + "application-start-address" : "( 41*1024)", + "max-application-size" : "(MBED_CONF_UPDATE_CLIENT_STORAGE_ADDRESS-MBED_CONF_APP_APPLICATION_START_ADDRESS)", + "update-client.storage-address" : "(532*1024)", + "update-client.storage-size" : "(492*1024)", + "update-client.storage-locations" : 1, + "update-client.storage-page" : 8 + } + } +} diff --git a/configs/nrf52_block_device_fake_rot.json b/configs/nrf52_block_device_fake_rot.json new file mode 100644 index 0000000..87795a9 --- /dev/null +++ b/configs/nrf52_block_device_fake_rot.json @@ -0,0 +1,46 @@ +{ + "macros": [ + "MBEDTLS_USER_CONFIG_FILE=\"bootloader_mbedtls_user_config.h\"", + "PAL_USER_DEFINED_CONFIGURATION=\"bootloader_pal_user_config.h\"", + "MAX_COPY_RETRIES=1", + "SHOW_PROGRESS_BAR=1", + "MAX_BOOT_RETRIES=3", + "ARM_UC_USE_PAL_CRYPTO=0", + "ARM_BOOTLOADER_USE_NVSTORE_ROT=0", + "ARM_UC_USE_PAL_BLOCKDEVICE=1", + "MBED_CLOUD_CLIENT_UPDATE_STORAGE=ARM_UCP_FLASHIAP_BLOCKDEVICE", + "Mutex=PlatformMutex" + ], + "config": { + "application-start-address": { + "help": "Address of the active application firmware in flash", + "value": null + }, + "max-application-size": { + "help": "Maximum size of the active application", + "value": null + } + }, + "target_overrides": { + "*": { + "target.features_remove": ["LWIP"], + "target.features_add": ["COMMON_PAL"], + "platform.stdio-baud-rate": 115200, + "platform.stdio-flush-at-exit": false, + "update-client.firmware-header-version": "2" + }, + "NRF52_DK": { + "minimal-printf.console-output" : "SWO", + "target.app_offset" : "0x74000", + "update-client.application-details" : "(508*1024)", + "application-start-address" : "(152*1024)", + "max-application-size" : "((456-152)*1024)", + "update-client.storage-address" : "(64*1024*1024)", + "update-client.storage-size" : "(2*1024*1024)", + "update-client.storage-locations" : 1, + "update-client.storage-page" : 512, + "target.extra_labels_remove" : ["SOFTDEVICE_S132_FULL", "SOFTDEVICE_COMMON"], + "target.extra_labels_add" : ["SOFTDEVICE_S132_MBR"] + } + } +} diff --git a/configs/nrf52_internal_flash_fake_rot.json b/configs/nrf52_internal_flash_fake_rot.json new file mode 100644 index 0000000..a1e58ae --- /dev/null +++ b/configs/nrf52_internal_flash_fake_rot.json @@ -0,0 +1,45 @@ +{ + "macros": [ + "MBEDTLS_USER_CONFIG_FILE=\"bootloader_mbedtls_user_config.h\"", + "PAL_USER_DEFINED_CONFIGURATION=\"bootloader_pal_user_config.h\"", + "MAX_COPY_RETRIES=1", + "SHOW_PROGRESS_BAR=1", + "MAX_BOOT_RETRIES=3", + "ARM_UC_USE_PAL_CRYPTO=0", + "ARM_BOOTLOADER_USE_NVSTORE_ROT=0", + "MBED_CLOUD_CLIENT_UPDATE_STORAGE=ARM_UCP_FLASHIAP", + "Mutex=PlatformMutex" + ], + "config": { + "application-start-address": { + "help": "Address of the active application firmware in flash", + "value": null + }, + "max-application-size": { + "help": "Maximum size of the active application", + "value": null + } + }, + "target_overrides": { + "*": { + "target.features_remove": ["LWIP"], + "target.features_add": ["COMMON_PAL"], + "platform.stdio-baud-rate": 115200, + "platform.stdio-flush-at-exit": false, + "update-client.firmware-header-version": "2" + }, + "NRF52_DK": { + "minimal-printf.console-output" : "SWO", + "target.app_offset" : "0x74000", + "update-client.application-details" : "(508*1024)", + "application-start-address" : "(4*1024)", + "max-application-size" : "(232*1024)", + "update-client.storage-address" : "(236*1024)", + "update-client.storage-size" : "(228*1024)", + "update-client.storage-locations" : 1, + "update-client.storage-page" : 4, + "target.extra_labels_remove" : ["SOFTDEVICE_S132_FULL", "SOFTDEVICE_COMMON"], + "target.extra_labels_add" : ["SOFTDEVICE_S132_MBR"] + } + } +} diff --git a/configs/uicr-0x74000.hex b/configs/uicr-0x74000.hex new file mode 100644 index 0000000..c303174 --- /dev/null +++ b/configs/uicr-0x74000.hex @@ -0,0 +1,3 @@ +:020000041000EA +:041014000040070091 +:00000001FF diff --git a/firmware_update_test/firmware_update_test.cpp b/firmware_update_test/firmware_update_test.cpp index f3bbd1f..958979f 100755 --- a/firmware_update_test/firmware_update_test.cpp +++ b/firmware_update_test/firmware_update_test.cpp @@ -36,8 +36,8 @@ void copyAppToSDCard(uint32_t firmware_size) arm_uc_firmware_details_t details = { 0 }; tr_info("calculate firmware SHA256\r\n"); - const uint8_t* appStart = - (const uint8_t*) (MBED_CONF_APP_APPLICATION_START_ADDRESS); + const uint8_t *appStart = + (const uint8_t *)(MBED_CONF_APP_APPLICATION_START_ADDRESS); mbedtls_sha256(appStart, firmware_size, details.hash, 0); details.version = UINT32_MAX - 1; @@ -58,15 +58,11 @@ void copyAppToSDCard(uint32_t firmware_size) arm_uc_error_t ucp_status = ARM_UCP_Prepare(0, &details, &temp_buffer); /* wait for event if call was accepted */ - if (ucp_status.error == ERR_NONE) - { - while (event_callback == CLEAR_EVENT) - { + if (ucp_status.error == ERR_NONE) { + while (event_callback == CLEAR_EVENT) { __WFI(); } - } - else - { + } else { tr_error("ARM_UCP_Prepare failed\r\n"); } @@ -77,7 +73,7 @@ void copyAppToSDCard(uint32_t firmware_size) arm_uc_buffer_t write_buffer = { .size_max = firmware_size, .size = firmware_size, - .ptr = (uint8_t*) appStart + .ptr = (uint8_t *) appStart }; /* clear most recent event */ @@ -87,15 +83,11 @@ void copyAppToSDCard(uint32_t firmware_size) ucp_status = ARM_UCP_Write(0, 0, &write_buffer); /* wait for event if call was accepted */ - if (ucp_status.error == ERR_NONE) - { - while (event_callback == CLEAR_EVENT) - { + if (ucp_status.error == ERR_NONE) { + while (event_callback == CLEAR_EVENT) { __WFI(); } - } - else - { + } else { tr_error("ARM_UCP_Write failed\r\n"); } @@ -110,15 +102,11 @@ void copyAppToSDCard(uint32_t firmware_size) ucp_status = ARM_UCP_Finalize(0); /* wait for event if call was accepted */ - if (ucp_status.error == ERR_NONE) - { - while (event_callback == CLEAR_EVENT) - { + if (ucp_status.error == ERR_NONE) { + while (event_callback == CLEAR_EVENT) { __WFI(); } - } - else - { + } else { tr_error("ARM_UCP_Finalize failed\r\n"); } } @@ -138,18 +126,14 @@ void firmware_update_test_validate() void firmware_update_test_end() { - if (firmware_update_test_valid_flag) - { + if (firmware_update_test_valid_flag) { GREENTEA_TESTSUITE_RESULT(true); - } - else - { + } else { GREENTEA_TESTSUITE_RESULT(false); } /* test end block forever */ - for (;;) - { + for (;;) { __WFI(); } } diff --git a/fix-mbed-os-compile/arm_uc_pal_flashiap_blockdevice_readonly.c b/fix-mbed-os-compile/arm_uc_pal_flashiap_blockdevice_readonly.c new file mode 100644 index 0000000..8a1cca3 --- /dev/null +++ b/fix-mbed-os-compile/arm_uc_pal_flashiap_blockdevice_readonly.c @@ -0,0 +1,23 @@ +#include "update-client-pal-blockdevice/arm_uc_pal_blockdevice_implementation.h" +#include "update-client-pal-flashiap/arm_uc_pal_flashiap_implementation.h" + +#if defined(ARM_UC_USE_PAL_BLOCKDEVICE) && (ARM_UC_USE_PAL_BLOCKDEVICE==1) + +extern arm_uc_error_t ARM_UCP_FashIAP_BlockDevice_Initialize(ARM_UC_PAAL_UPDATE_SignalEvent_t callback); + +ARM_UC_PAAL_UPDATE ARM_UCP_FLASHIAP_BLOCKDEVICE_READ_ONLY = +{ + .Initialize = ARM_UCP_FashIAP_BlockDevice_Initialize, + .GetCapabilities = 0, + .GetMaxID = 0, + .Prepare = 0, + .Write = 0, + .Finalize = 0, + .Read = ARM_UC_PAL_BlockDevice_Read, + .Activate = 0, + .GetActiveFirmwareDetails = ARM_UC_PAL_FlashIAP_GetActiveDetails, + .GetFirmwareDetails = ARM_UC_PAL_BlockDevice_GetFirmwareDetails, + .GetInstallerDetails = 0 +}; + +#endif /* ARM_UC_USE_PAL_BLOCKDEVICE */ diff --git a/fix-mbed-os-compile/pal_polyfill.c b/fix-mbed-os-compile/pal_polyfill.c deleted file mode 100644 index 7169a88..0000000 --- a/fix-mbed-os-compile/pal_polyfill.c +++ /dev/null @@ -1,6 +0,0 @@ -#include - -palStatus_t pal_osDelay(uint32_t milliseconds) -{ - return PAL_SUCCESS; -} diff --git a/mbed-cloud-client.lib b/mbed-cloud-client.lib index 666e967..9ea6d31 100644 --- a/mbed-cloud-client.lib +++ b/mbed-cloud-client.lib @@ -1 +1 @@ -https://github.com/ARMmbed/mbed-cloud-client#ce9b8d23217bd5885c95d2d0ec6962272c82f5be +https://github.com/ARMmbed/mbed-cloud-client/#9b0bc6a2f3f1f5dbb5be1827db83004d531b99c9 diff --git a/mbed-os.lib b/mbed-os.lib index 23892aa..d5043fc 100644 --- a/mbed-os.lib +++ b/mbed-os.lib @@ -1 +1 @@ -https://github.com/ARMmbed/mbed-os/#eca67ca7dafab4ef70c21e2463b541132d0dd691 +https://github.com/ARMmbed/mbed-os/#485bdeee150e2bc8ed75e27d936060fb63a7a7d1 diff --git a/mbed_app.json b/mbed_app.json index 455bf6c..614cee0 100755 --- a/mbed_app.json +++ b/mbed_app.json @@ -1,46 +1,29 @@ { "macros": [ - "MBEDTLS_USER_CONFIG_FILE=\"mbedtls_mbed_client_config.h\"", - "PAL_USER_DEFINED_CONFIGURATION=\"sotp_fs_config_MbedOS.h\"", + "MBEDTLS_USER_CONFIG_FILE=\"bootloader_mbedtls_user_config.h\"", "MAX_COPY_RETRIES=1", "SHOW_PROGRESS_BAR=1", "MAX_BOOT_RETRIES=3", - "Mutex=PlatformMutex", - "PAL_USE_INTERNAL_FLASH=1", - "PAL_THREAD_SAFETY=0", "ARM_UC_USE_PAL_CRYPTO=0", - "ARM_UC_USE_SOTP=1", + "ARM_BOOTLOADER_USE_NVSTORE_ROT=1", "ARM_UC_USE_PAL_BLOCKDEVICE=1", + "ARM_UC_PAAL_TRACE_ENABLE=0", "MBED_CLOUD_CLIENT_UPDATE_STORAGE=ARM_UCP_FLASHIAP_BLOCKDEVICE", - "DEFAULT_MAX_APPLICATION_SIZE=(MBED_CONF_APP_FLASH_START_ADDRESS + MBED_CONF_APP_FLASH_SIZE - MBED_CONF_APP_APPLICATION_START_ADDRESS)" + "DEFAULT_MAX_APPLICATION_SIZE=(MBED_CONF_APP_FLASH_START_ADDRESS + MBED_CONF_APP_FLASH_SIZE - MBED_CONF_APP_APPLICATION_START_ADDRESS)", + "DISABLE_ERROR_DESCRIPTION=1", + "Mutex=PlatformMutex" ], "config": { "application-start-address": { - "help": "Address of the active application firmware in flash", + "help": "Address to the beginning of the active application firmware in flash", "value": null }, - "max-application-size": { - "help": "Maximum size of the active application", - "value": null - }, - "sotp-section-1-address": { - "help": "Flash sector address for SOTP sector 1", - "macro_name": "PAL_INTERNAL_FLASH_SECTION_1_ADDRESS", - "value": null - }, - "sotp-section-1-size": { - "help": "Flash sector size for SOTP sector 1", - "macro_name": "PAL_INTERNAL_FLASH_SECTION_1_SIZE", - "value": null - }, - "sotp-section-2-address": { - "help": "Flash sector address for SOTP sector 2", - "macro_name": "PAL_INTERNAL_FLASH_SECTION_2_ADDRESS", + "application-jump-address": { + "help": "Jump address for running the active application firmware", "value": null }, - "sotp-section-2-size": { - "help": "Flash sector size for SOTP sector 2", - "macro_name": "PAL_INTERNAL_FLASH_SECTION_2_SIZE", + "max-application-size": { + "help": "Maximum size of the active application", "value": null }, "flash-start-address": { @@ -66,10 +49,10 @@ "K64F": { "flash-start-address" : "0x0", "flash-size" : "(1024*1024)", - "sotp-section-1-address" : "(MBED_CONF_APP_FLASH_START_ADDRESS+32*1024)", - "sotp-section-1-size" : "(4*1024)", - "sotp-section-2-address" : "(MBED_CONF_APP_FLASH_START_ADDRESS+36*1024)", - "sotp-section-2-size" : "(4*1024)", + "nvstore.area_1_address" : "(MBED_CONF_APP_FLASH_START_ADDRESS+32*1024)", + "nvstore.area_1_size" : "(4*1024)", + "nvstore.area_2_address" : "(MBED_CONF_APP_FLASH_START_ADDRESS+36*1024)", + "nvstore.area_2_size" : "(4*1024)", "update-client.application-details": "(MBED_CONF_APP_FLASH_START_ADDRESS+40*1024)", "application-start-address" : "(MBED_CONF_APP_FLASH_START_ADDRESS+41*1024)", "max-application-size" : "DEFAULT_MAX_APPLICATION_SIZE" @@ -77,10 +60,10 @@ "K66F": { "flash-start-address" : "0x0", "flash-size" : "(2048*1024)", - "sotp-section-1-address" : "(MBED_CONF_APP_FLASH_START_ADDRESS+32*1024)", - "sotp-section-1-size" : "(4*1024)", - "sotp-section-2-address" : "(MBED_CONF_APP_FLASH_START_ADDRESS+36*1024)", - "sotp-section-2-size" : "(4*1024)", + "nvstore.area_1_address" : "(MBED_CONF_APP_FLASH_START_ADDRESS+32*1024)", + "nvstore.area_1_size" : "(4*1024)", + "nvstore.area_2_address" : "(MBED_CONF_APP_FLASH_START_ADDRESS+36*1024)", + "nvstore.area_2_size" : "(4*1024)", "update-client.application-details": "(MBED_CONF_APP_FLASH_START_ADDRESS+40*1024)", "application-start-address" : "(MBED_CONF_APP_FLASH_START_ADDRESS+41*1024)", "max-application-size" : "DEFAULT_MAX_APPLICATION_SIZE" @@ -88,10 +71,10 @@ "KW24D": { "flash-start-address" : "0x0", "flash-size" : "(512*1024)", - "sotp-section-1-address" : "(MBED_CONF_APP_FLASH_START_ADDRESS+32*1024)", - "sotp-section-1-size" : "(2*1024)", - "sotp-section-2-address" : "(MBED_CONF_APP_FLASH_START_ADDRESS+34*1024)", - "sotp-section-2-size" : "(2*1024)", + "nvstore.area_1_address" : "(MBED_CONF_APP_FLASH_START_ADDRESS+32*1024)", + "nvstore.area_1_size" : "(2*1024)", + "nvstore.area_2_address" : "(MBED_CONF_APP_FLASH_START_ADDRESS+34*1024)", + "nvstore.area_2_size" : "(2*1024)", "update-client.application-details": "(MBED_CONF_APP_FLASH_START_ADDRESS+36*1024)", "application-start-address" : "(MBED_CONF_APP_FLASH_START_ADDRESS+37*1024)", "max-application-size" : "DEFAULT_MAX_APPLICATION_SIZE" @@ -99,10 +82,10 @@ "NUCLEO_L476RG": { "flash-start-address" : "0x08000000", "flash-size" : "(1024*1024)", - "sotp-section-1-address" : "(MBED_CONF_APP_FLASH_START_ADDRESS+32*1024)", - "sotp-section-1-size" : "(2*1024)", - "sotp-section-2-address" : "(MBED_CONF_APP_FLASH_START_ADDRESS+34*1024)", - "sotp-section-2-size" : "(2*1024)", + "nvstore.area_1_address" : "(MBED_CONF_APP_FLASH_START_ADDRESS+32*1024)", + "nvstore.area_1_size" : "(2*1024)", + "nvstore.area_2_address" : "(MBED_CONF_APP_FLASH_START_ADDRESS+34*1024)", + "nvstore.area_2_size" : "(2*1024)", "update-client.application-details": "(MBED_CONF_APP_FLASH_START_ADDRESS+36*1024)", "application-start-address" : "(MBED_CONF_APP_FLASH_START_ADDRESS+38*1024)", "max-application-size" : "DEFAULT_MAX_APPLICATION_SIZE" @@ -110,21 +93,36 @@ "DISCO_L476VG": { "flash-start-address" : "0x08000000", "flash-size" : "(1024*1024)", - "sotp-section-1-address" : "(MBED_CONF_APP_FLASH_START_ADDRESS+32*1024)", - "sotp-section-1-size" : "(2*1024)", - "sotp-section-2-address" : "(MBED_CONF_APP_FLASH_START_ADDRESS+34*1024)", - "sotp-section-2-size" : "(2*1024)", + "nvstore.area_1_address" : "(MBED_CONF_APP_FLASH_START_ADDRESS+32*1024)", + "nvstore.area_1_size" : "(2*1024)", + "nvstore.area_2_address" : "(MBED_CONF_APP_FLASH_START_ADDRESS+34*1024)", + "nvstore.area_2_size" : "(2*1024)", "update-client.application-details": "(MBED_CONF_APP_FLASH_START_ADDRESS+36*1024)", "application-start-address" : "(MBED_CONF_APP_FLASH_START_ADDRESS+38*1024)", "max-application-size" : "DEFAULT_MAX_APPLICATION_SIZE" }, + "NUCLEO_F411RE": { + "flash-start-address" : "0x08000000", + "flash-size" : "(512*1024)", + "nvstore.area_1_address" : "(MBED_CONF_APP_FLASH_START_ADDRESS+32*1024)", + "nvstore.area_1_size" : "(16*1024)", + "nvstore.area_2_address" : "(MBED_CONF_APP_FLASH_START_ADDRESS+48*1024)", + "nvstore.area_2_size" : "(16*1024)", + "update-client.application-details": "(MBED_CONF_APP_FLASH_START_ADDRESS+64*1024)", + "application-start-address" : "(MBED_CONF_APP_FLASH_START_ADDRESS+65*1024)", + "max-application-size" : "DEFAULT_MAX_APPLICATION_SIZE", + "sd.SPI_CS" : "PB_9", + "sd.SPI_MOSI" : "PC_3", + "sd.SPI_MISO" : "PC_2", + "sd.SPI_CLK" : "PC_7" + }, "NUCLEO_F429ZI": { "flash-start-address" : "0x08000000", "flash-size" : "(2048*1024)", - "sotp-section-1-address" : "(MBED_CONF_APP_FLASH_START_ADDRESS+32*1024)", - "sotp-section-1-size" : "(16*1024)", - "sotp-section-2-address" : "(MBED_CONF_APP_FLASH_START_ADDRESS+48*1024)", - "sotp-section-2-size" : "(16*1024)", + "nvstore.area_1_address" : "(MBED_CONF_APP_FLASH_START_ADDRESS+32*1024)", + "nvstore.area_1_size" : "(16*1024)", + "nvstore.area_2_address" : "(MBED_CONF_APP_FLASH_START_ADDRESS+48*1024)", + "nvstore.area_2_size" : "(16*1024)", "update-client.application-details": "(MBED_CONF_APP_FLASH_START_ADDRESS+64*1024)", "application-start-address" : "(MBED_CONF_APP_FLASH_START_ADDRESS+65*1024)", "max-application-size" : "DEFAULT_MAX_APPLICATION_SIZE" @@ -133,10 +131,10 @@ "target.device_has_remove": ["EMAC"], "flash-start-address" : "0x08000000", "flash-size" : "(2048*1024)", - "sotp-section-1-address" : "(MBED_CONF_APP_FLASH_START_ADDRESS+32*1024)", - "sotp-section-1-size" : "(16*1024)", - "sotp-section-2-address" : "(MBED_CONF_APP_FLASH_START_ADDRESS+48*1024)", - "sotp-section-2-size" : "(16*1024)", + "nvstore.area_1_address" : "(MBED_CONF_APP_FLASH_START_ADDRESS+32*1024)", + "nvstore.area_1_size" : "(16*1024)", + "nvstore.area_2_address" : "(MBED_CONF_APP_FLASH_START_ADDRESS+48*1024)", + "nvstore.area_2_size" : "(16*1024)", "update-client.application-details": "(MBED_CONF_APP_FLASH_START_ADDRESS+64*1024)", "application-start-address" : "(MBED_CONF_APP_FLASH_START_ADDRESS+65*1024)", "max-application-size" : "DEFAULT_MAX_APPLICATION_SIZE" @@ -144,10 +142,10 @@ "UBLOX_C030_U201": { "flash-start-address" : "0x08000000", "flash-size" : "(1024*1024)", - "sotp-section-1-address" : "(MBED_CONF_APP_FLASH_START_ADDRESS+32*1024)", - "sotp-section-1-size" : "(16*1024)", - "sotp-section-2-address" : "(MBED_CONF_APP_FLASH_START_ADDRESS+48*1024)", - "sotp-section-2-size" : "(16*1024)", + "nvstore.area_1_address" : "(MBED_CONF_APP_FLASH_START_ADDRESS+32*1024)", + "nvstore.area_1_size" : "(16*1024)", + "nvstore.area_2_address" : "(MBED_CONF_APP_FLASH_START_ADDRESS+48*1024)", + "nvstore.area_2_size" : "(16*1024)", "update-client.application-details": "(MBED_CONF_APP_FLASH_START_ADDRESS+64*1024)", "application-start-address" : "(MBED_CONF_APP_FLASH_START_ADDRESS+65*1024)", "max-application-size" : "DEFAULT_MAX_APPLICATION_SIZE" diff --git a/minimal-printf.lib b/minimal-printf.lib index 7d202a2..5f6994c 100644 --- a/minimal-printf.lib +++ b/minimal-printf.lib @@ -1 +1 @@ -https://github.com/ARMmbed/minimal-printf/#613c02ed3eeb09b86c7d0c6c9ae0059bd0c31ae1 +https://github.com/ARMmbed/minimal-printf/#5cbf9d1dcb5812a8a804a55162b3118523a4eb77 diff --git a/power_cut_test/bootloader_power_cut_test.cpp b/power_cut_test/bootloader_power_cut_test.cpp index 2b0ab5f..8d017f1 100644 --- a/power_cut_test/bootloader_power_cut_test.cpp +++ b/power_cut_test/bootloader_power_cut_test.cpp @@ -23,7 +23,7 @@ #include "bootloader_power_cut_test.h" -DigitalOut JigTrigger(D2,0); +DigitalOut JigTrigger(D2, 0); Timeout JigTimeout; @@ -54,8 +54,7 @@ void power_cut_test_end() greentea_send_kv("power_cut_test_end", 0); /* test end block forever */ - for (;;) - { + for (;;) { __WFI(); } } diff --git a/power_cut_test/test_mbed_app.json b/power_cut_test/test_mbed_app.json deleted file mode 100644 index 3e26b69..0000000 --- a/power_cut_test/test_mbed_app.json +++ /dev/null @@ -1,67 +0,0 @@ -{ - "macros": [ - "MBEDTLS_USER_CONFIG_FILE=\"mbedtls_mbed_client_config.h\"", - "MAX_COPY_RETRIES=1", - "SHOW_PROGRESS_BAR=1", - "MAX_BOOT_RETRIES=3", - "Mutex=PlatformMutex", - "PAL_USE_INTERNAL_FLASH=1", - "PAL_THREAD_SAFETY=0", - "ARM_UC_USE_PAL_CRYPTO=0", - "ARM_UC_USE_SOTP=0", - "ARM_UC_USE_PAL_BLOCKDEVICE=1", - "MBED_CLOUD_CLIENT_UPDATE_STORAGE=ARM_UCP_FLASHIAP_BLOCKDEVICE", - "BOOTLOADER_POWER_CUT_TEST=1" - ], - "config": { - "application-start-address": { - "help": "Address of the active application firmware in flash", - "value": null - }, - "max-application-size": { - "help": "Maximum size of the active application", - "value": null - }, - "sotp-section-1-address": { - "help": "Flash sector address for SOTP sector 1", - "macro_name": "PAL_INTERNAL_FLASH_SECTION_1_ADDRESS", - "value": null - }, - "sotp-section-1-size": { - "help": "Flash sector size for SOTP sector 1", - "macro_name": "PAL_INTERNAL_FLASH_SECTION_1_SIZE", - "value": null - }, - "sotp-section-2-address": { - "help": "Flash sector address for SOTP sector 2", - "macro_name": "PAL_INTERNAL_FLASH_SECTION_2_ADDRESS", - "value": null - }, - "sotp-section-2-size": { - "help": "Flash sector size for SOTP sector 2", - "macro_name": "PAL_INTERNAL_FLASH_SECTION_2_SIZE", - "value": null - } - }, - "target_overrides": { - "*": { - "target.features_remove": ["LWIP"], - "target.features_add": ["COMMON_PAL"], - "platform.stdio-baud-rate": 9600, - "platform.stdio-flush-at-exit": false, - "update-client.storage-address": "1024*1024*64", - "update-client.storage-size": "1024*1024", - "update-client.storage-locations": 1, - "update-client.firmware-header-version": "2" - }, - "K64F": { - "sotp-section-1-address" : "32*1024", - "sotp-section-1-size" : "4*1024", - "sotp-section-2-address" : "36*1024", - "sotp-section-2-size" : "4*1024", - "update-client.application-details": "40*1024", - "application-start-address" : "41*1024", - "max-application-size" : "(1024*1024-MBED_CONF_APP_APPLICATION_START_ADDRESS)" - } - } -} diff --git a/power_cut_test/test_plan.md b/power_cut_test/test_plan.md deleted file mode 100644 index ab4bc01..0000000 --- a/power_cut_test/test_plan.md +++ /dev/null @@ -1,14 +0,0 @@ -# Test Plan - -## Power Cut Test Cases: - -1. power cut during writing firmware -2. power cut during reading firmware - -## How to run power cut test: - -``` -power_cut_test/setup_dependencies.sh -mbed compile -t GCC_ARM -m K64F -mbedgt --test-spec power_cut_test/test_spec.json -e power_cut_test/host_tests/ -v -V -``` diff --git a/sd-driver.lib b/sd-driver.lib index 702879f..8e74be5 100644 --- a/sd-driver.lib +++ b/sd-driver.lib @@ -1 +1 @@ -https://github.com/ARMmbed/sd-driver/#51dc1d2b2c073deee6146c83de42bb904c738d8d +https://github.com/ARMmbed/sd-driver/#ae7e7440054c9447f8255bdccbcc523b3f6dffe4 diff --git a/sotp_fs_config_MbedOS.h b/sotp_fs_config_MbedOS.h deleted file mode 100644 index b9c279c..0000000 --- a/sotp_fs_config_MbedOS.h +++ /dev/null @@ -1,31 +0,0 @@ -// ---------------------------------------------------------------------------- -// Copyright 2018 ARM Ltd. -// -// SPDX-License-Identifier: Apache-2.0 -// -// 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. -// ---------------------------------------------------------------------------- - -#ifndef PAL_HEADER_SOTP_FS -#define PAL_HEADER_SOTP_FS - -#define PAL_USE_HW_ROT 0 -#define PAL_USE_HW_RTC 0 -#define PAL_USE_HW_TRNG 1 -#define PAL_SIMULATOR_FLASH_OVER_FILE_SYSTEM 0 -#define PAL_USE_INTERNAL_FLASH 1 -#define PAL_USE_SECURE_TIME 1 - -#include "mbedOS_default.h" - -#endif //PAL_HEADER_SOTP_FS diff --git a/source/active_application.cpp b/source/active_application.cpp index 53bd9c0..5399a0f 100755 --- a/source/active_application.cpp +++ b/source/active_application.cpp @@ -51,14 +51,13 @@ void activeStorageDeinit(void) * Caller-allocated header structure. * @return true if the read succeeds. */ -bool readActiveFirmwareHeader(arm_uc_firmware_details_t* details) +bool readActiveFirmwareHeader(arm_uc_firmware_details_t *details) { tr_debug("readActiveFirmwareHeader"); bool result = false; - if (details) - { + if (details) { /* clear most recent UCP event */ event_callback = CLEAR_EVENT; @@ -68,17 +67,14 @@ bool readActiveFirmwareHeader(arm_uc_firmware_details_t* details) /* if the call was accepted, the event will indicate if the call succeeded */ - if (status.error == ERR_NONE) - { + if (status.error == ERR_NONE) { /* wait until the event has been set */ - while (event_callback == CLEAR_EVENT) - { + while (event_callback == CLEAR_EVENT) { __WFI(); } /* mark the firmware details as valid if so indicated by the event */ - if (event_callback == ARM_UC_PAAL_EVENT_GET_ACTIVE_FIRMWARE_DETAILS_DONE) - { + if (event_callback == ARM_UC_PAAL_EVENT_GET_ACTIVE_FIRMWARE_DETAILS_DONE) { result = true; } } @@ -99,20 +95,18 @@ bool readActiveFirmwareHeader(arm_uc_firmware_details_t* details) * EMPTY if no active application is present * ERROR if the validation fails */ -int checkActiveApplication(arm_uc_firmware_details_t* details) +int checkActiveApplication(arm_uc_firmware_details_t *details) { tr_debug("checkActiveApplication"); int result = RESULT_ERROR; - if (details) - { + if (details) { /* Read header and verify that it is valid */ bool headerValid = readActiveFirmwareHeader(details); /* calculate hash if header is valid and slot is not empty */ - if ((headerValid) && (details->size > 0)) - { + if ((headerValid) && (details->size > 0)) { uint32_t appStart = MBED_CONF_APP_APPLICATION_START_ADDRESS; tr_debug("header start: 0x%08" PRIX32, @@ -130,8 +124,7 @@ int checkActiveApplication(arm_uc_firmware_details_t* details) int32_t status = 0; /* read full image */ - while ((remaining > 0) && (status == 0)) - { + while ((remaining > 0) && (status == 0)) { /* read full buffer or what is remaining */ uint32_t readSize = (remaining > BUFFER_SIZE) ? BUFFER_SIZE : remaining; @@ -160,18 +153,13 @@ int checkActiveApplication(arm_uc_firmware_details_t* details) /* compare calculated hash with hash from header */ int diff = memcmp(details->hash, SHA, SIZEOF_SHA256); - if (diff == 0) - { + if (diff == 0) { result = RESULT_SUCCESS; - } - else - { + } else { printSHA256(details->hash); printSHA256(SHA); } - } - else if ((headerValid) && (details->size == 0)) - { + } else if ((headerValid) && (details->size == 0)) { /* header is valid but application size is 0 */ result = RESULT_EMPTY; } @@ -180,6 +168,48 @@ int checkActiveApplication(arm_uc_firmware_details_t* details) return result; } +int eraseSectorBySector(uint32_t addr, uint32_t size) +{ + tr_debug("Erasing from 0x%08" PRIX32 " to 0x%08" PRIX32, + (uint32_t) addr, (uint32_t) addr + size); + + int result = -1; + uint32_t erase_address = addr; + + /* Erase flash to make place for new application. Erasing sector by sector as some + platforms have varible sector sizes and mbed-os cannot deal with erasing multiple + sectors successfully in that case. https://github.com/ARMmbed/mbed-os/issues/6077 */ + while (erase_address < (addr + size)) { + uint32_t sector_size = flash.get_sector_size(erase_address); + result = flash.erase(erase_address, + sector_size); + if (result != 0) { + tr_debug("Erasing from 0x%08" PRIX32 " to 0x%08" PRIX32 " failed with retval %i", + erase_address, erase_address + sector_size, result); + break; + } else { + erase_address += sector_size; + } + } + + return result; +} + +uint32_t getSectorAlignedSize(uint32_t addr, uint32_t size) +{ + tr_debug("getSectorAlignedSize at 0x%08" PRIX32 " of size 0x%08" PRIX32, + (uint32_t) addr, (uint32_t) size); + + /* Find the exact end sector boundary. Some platforms have different sector + sizes from sector to sector. Hence we count the sizes 1 sector at a time here */ + uint32_t erase_address = addr; + while (erase_address < (addr + size)) { + erase_address += flash.get_sector_size(erase_address); + } + + return erase_address - addr; +} + /** * Wipe the ACTIVE firmware region in the flash */ @@ -187,78 +217,75 @@ bool eraseActiveFirmware(uint32_t firmwareSize) { tr_debug("eraseActiveFirmware"); - /* Find the exact end sector boundary. Some platforms have different sector - sizes from sector to sector. Hence we count the sizes 1 sector at a time here */ - uint32_t erase_address = FIRMWARE_METADATA_HEADER_ADDRESS; - uint32_t size_needed = FIRMWARE_METADATA_HEADER_SIZE + firmwareSize; - while (erase_address < (FIRMWARE_METADATA_HEADER_ADDRESS + size_needed)) - { - erase_address += flash.get_sector_size(erase_address); + uint32_t fw_metadata_hdr_size = getSectorAlignedSize(FIRMWARE_METADATA_HEADER_ADDRESS, + ARM_UC_INTERNAL_HEADER_SIZE_V2); + uint32_t size_needed = 0; + uint32_t erase_start_addr = 0; + int result = 0; + + if (((FIRMWARE_METADATA_HEADER_ADDRESS + fw_metadata_hdr_size) < \ + (MBED_CONF_APP_APPLICATION_START_ADDRESS)) || \ + (FIRMWARE_METADATA_HEADER_ADDRESS > MBED_CONF_APP_APPLICATION_START_ADDRESS)) { + /* header separate from app */ + tr_debug("Erasing header separately from active application"); + + /* erase header section first */ + result = eraseSectorBySector(FIRMWARE_METADATA_HEADER_ADDRESS, fw_metadata_hdr_size); + + /* setup erase of the application region */ + size_needed = firmwareSize; + erase_start_addr = MBED_CONF_APP_APPLICATION_START_ADDRESS; + } else { /* header contiguous with app */ + /* setup erase of the header + application region */ + size_needed = (MBED_CONF_APP_APPLICATION_START_ADDRESS - FIRMWARE_METADATA_HEADER_ADDRESS) + firmwareSize; + erase_start_addr = FIRMWARE_METADATA_HEADER_ADDRESS; } - /* check that the erase will not exceed MBED_CONF_APP_MAX_APPLICATION_SIZE */ - int result = -1; - if (erase_address < (MBED_CONF_APP_MAX_APPLICATION_SIZE + \ - MBED_CONF_APP_APPLICATION_START_ADDRESS)) - { - tr_debug("Erasing from 0x%08" PRIX32 " to 0x%08" PRIX32, - (uint32_t) FIRMWARE_METADATA_HEADER_ADDRESS, - (uint32_t) erase_address); - - /* Erase flash to make place for new application. Erasing sector by sector as some - platforms have varible sector sizes and mbed-os cannot deal with erasing multiple - sectors successfully in that case. https://github.com/ARMmbed/mbed-os/issues/6077 */ - erase_address = FIRMWARE_METADATA_HEADER_ADDRESS; - while (erase_address < (FIRMWARE_METADATA_HEADER_ADDRESS + size_needed)) - { - uint32_t sector_size = flash.get_sector_size(erase_address); - result = flash.erase(erase_address, - sector_size); - if (result != 0) - { - tr_debug("Erasing from 0x%08" PRIX32 " to 0x%08" PRIX32 " failed with retval %i", - erase_address, erase_address + sector_size, result); - break; - } - else - { - erase_address += sector_size; - } + if (result == 0) { + uint32_t erase_end_addr = erase_start_addr + \ + getSectorAlignedSize(erase_start_addr, + size_needed); + uint32_t max_end_addr = MBED_CONF_APP_MAX_APPLICATION_SIZE + \ + MBED_CONF_APP_APPLICATION_START_ADDRESS; + /* check that the erase will not exceed MBED_CONF_APP_MAX_APPLICATION_SIZE */ + if (erase_end_addr <= max_end_addr) { + result = eraseSectorBySector(erase_start_addr, size_needed); + } else { + result = -1; + tr_error("Firmware size 0x%" PRIX32 " rounded up to the nearest sector boundary 0x%" \ + PRIX32 " is larger than the maximum application size 0x%" PRIX32, + firmwareSize, erase_end_addr - MBED_CONF_APP_APPLICATION_START_ADDRESS, + MBED_CONF_APP_MAX_APPLICATION_SIZE); } } - else - { - tr_error("Firmware size 0x%" PRIX32 " rounded up to the nearest sector boundary 0x%" \ - PRIX32 " is larger than the maximum application size 0x%" PRIX32, - firmwareSize, erase_address - MBED_CONF_APP_APPLICATION_START_ADDRESS, - MBED_CONF_APP_MAX_APPLICATION_SIZE); - } return (result == 0); } -bool writeActiveFirmwareHeader(arm_uc_firmware_details_t* details) +bool writeActiveFirmwareHeader(arm_uc_firmware_details_t *details) { tr_debug("writeActiveFirmwareHeader"); bool result = false; - if (details) - { + if (details) { /* round up program size to nearest page size */ const uint32_t pageSize = flash.get_page_size(); const uint32_t programSize = (ARM_UC_INTERNAL_HEADER_SIZE_V2 + pageSize - 1) / pageSize * pageSize; + const uint32_t fw_metadata_hdr_size = \ + getSectorAlignedSize(FIRMWARE_METADATA_HEADER_ADDRESS, + ARM_UC_INTERNAL_HEADER_SIZE_V2); /* coverity[no_escape] */ MBED_BOOTLOADER_ASSERT((programSize <= BUFFER_SIZE), - "Header program size %" PRIu32 " bigger than buffer %d\r\n", - programSize, BUFFER_SIZE); + "Header program size %" PRIu32 " bigger than buffer %d\r\n", + programSize, BUFFER_SIZE); /* coverity[no_escape] */ - MBED_BOOTLOADER_ASSERT((programSize <= FIRMWARE_METADATA_HEADER_SIZE), - "Header program size %" PRIu32 " bigger than expected header %d\r\n", - programSize, FIRMWARE_METADATA_HEADER_SIZE); + MBED_BOOTLOADER_ASSERT((programSize <= fw_metadata_hdr_size), + "Header program size %" PRIu32 " bigger than expected header %d\r\n", + programSize, fw_metadata_hdr_size); /* pad buffer to 0xFF */ memset(buffer_array, 0xFF, programSize); @@ -274,8 +301,7 @@ bool writeActiveFirmwareHeader(arm_uc_firmware_details_t* details) &output_buffer); if ((status.error == ERR_NONE) && - (output_buffer.size == ARM_UC_INTERNAL_HEADER_SIZE_V2)) - { + (output_buffer.size == ARM_UC_INTERNAL_HEADER_SIZE_V2)) { /* write header using FlashIAP API */ int ret = flash.program(buffer_array, FIRMWARE_METADATA_HEADER_ADDRESS, @@ -288,14 +314,13 @@ bool writeActiveFirmwareHeader(arm_uc_firmware_details_t* details) return result; } -bool writeActiveFirmware(uint32_t index, arm_uc_firmware_details_t* details) +bool writeActiveFirmware(uint32_t index, arm_uc_firmware_details_t *details) { tr_debug("writeActiveFirmware"); bool result = false; - if (details) - { + if (details) { const uint32_t pageSize = flash.get_page_size(); /* we require app_start_addr fall on a page size boundary */ @@ -303,10 +328,10 @@ bool writeActiveFirmware(uint32_t index, arm_uc_firmware_details_t* details) /* coverity[no_escape] */ MBED_BOOTLOADER_ASSERT((app_start_addr % pageSize) == 0, - "Application (0x%" PRIX32 ") does not start on a " - "page size (0x%" PRIX32 ") aligned address\r\n", - app_start_addr, - pageSize); + "Application (0x%" PRIX32 ") does not start on a " + "page size (0x%" PRIX32 ") aligned address\r\n", + app_start_addr, + pageSize); /* round down the read size to a multiple of the page size that still fits inside the main buffer. @@ -324,31 +349,27 @@ bool writeActiveFirmware(uint32_t index, arm_uc_firmware_details_t* details) /* write firmware */ while ((offset < details->size) && - (retval == 0)) - { + (retval == 0)) { /* clear most recent UCP event */ event_callback = CLEAR_EVENT; /* set the number of bytes expected */ buffer.size = (details->size - offset) > buffer.size_max ? - buffer.size_max : (details->size - offset); + buffer.size_max : (details->size - offset); /* fill buffer using UCP */ arm_uc_error_t ucp_status = ARM_UCP_Read(index, offset, &buffer); /* wait for event if the call is accepted */ - if (ucp_status.error == ERR_NONE) - { - while (event_callback == CLEAR_EVENT) - { + if (ucp_status.error == ERR_NONE) { + while (event_callback == CLEAR_EVENT) { __WFI(); } } /* check status and actual read size */ if ((event_callback == ARM_UC_PAAL_EVENT_READ_DONE) && - (buffer.size > 0)) - { + (buffer.size > 0)) { /* the last page, in the last buffer might not be completely filled, round up the program size to include the last page */ @@ -358,8 +379,7 @@ bool writeActiveFirmware(uint32_t index, arm_uc_firmware_details_t* details) /* write one page at a time */ while ((programOffset < programSize) && - (retval == 0)) - { + (retval == 0)) { retval = flash.program(&(buffer.ptr[programOffset]), app_start_addr + offset + programOffset, pageSize); @@ -375,9 +395,7 @@ bool writeActiveFirmware(uint32_t index, arm_uc_firmware_details_t* details) offset, (uint32_t) details->size, programSize, app_start_addr + offset); offset += programSize; - } - else - { + } else { tr_error("ARM_UCP_Read returned 0 bytes"); /* set error and break out of loop */ @@ -396,7 +414,7 @@ bool writeActiveFirmware(uint32_t index, arm_uc_firmware_details_t* details) * Copy loop to update the application */ bool copyStoredApplication(uint32_t index, - arm_uc_firmware_details_t* details) + arm_uc_firmware_details_t *details) { tr_debug("copyStoredApplication"); @@ -412,8 +430,7 @@ bool copyStoredApplication(uint32_t index, /* Step 2. Write header */ /*************************************************************************/ - if (result) - { + if (result) { result = writeActiveFirmwareHeader(details); } @@ -421,8 +438,7 @@ bool copyStoredApplication(uint32_t index, /* Step 3. Copy application */ /*************************************************************************/ - if (result) - { + if (result) { result = writeActiveFirmware(index, details); } @@ -430,8 +446,7 @@ bool copyStoredApplication(uint32_t index, /* Step 4. Verify application */ /*************************************************************************/ - if (result) - { + if (result) { tr_info("Verify new active firmware:"); int recheck = checkActiveApplication(details); diff --git a/source/active_application.h b/source/active_application.h index 0dd69ee..e9354b7 100644 --- a/source/active_application.h +++ b/source/active_application.h @@ -29,7 +29,7 @@ void activeStorageDeinit(void); * Caller-allocated header structure. * @return true if the read succeeds. */ -bool readActiveFirmwareHeader(arm_uc_firmware_details_t* details); +bool readActiveFirmwareHeader(arm_uc_firmware_details_t *details); /** * Verify the integrity of the Active application @@ -43,6 +43,6 @@ bool readActiveFirmwareHeader(arm_uc_firmware_details_t* details); * EMPTY if no active application is present * ERROR if the validation fails */ -int checkActiveApplication(arm_uc_firmware_details_t* details); +int checkActiveApplication(arm_uc_firmware_details_t *details); -bool copyStoredApplication(uint32_t index, arm_uc_firmware_details_t* details); +bool copyStoredApplication(uint32_t index, arm_uc_firmware_details_t *details); diff --git a/source/bootloader_common.c b/source/bootloader_common.c index d1f93a7..d7214c7 100644 --- a/source/bootloader_common.c +++ b/source/bootloader_common.c @@ -26,7 +26,8 @@ uint32_t event_callback = CLEAR_EVENT; /* lookup table for printing hexadecimal values */ const char hexTable[16] = {'0', '1', '2', '3', '4', '5', '6', '7', - '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'}; + '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' + }; /** * @brief Event handler for UCP callbacks. @@ -49,8 +50,7 @@ void printSHA256(const uint8_t SHA[SIZEOF_SHA256]) /* allocate space for string */ char buffer[2 * SIZEOF_SHA256 + 1] = { 0 }; - for (uint_least8_t index = 0; index < SIZEOF_SHA256; index++) - { + for (uint_least8_t index = 0; index < SIZEOF_SHA256; index++) { uint8_t value = SHA[index]; buffer[2 * index] = hexTable[value >> 4]; @@ -67,31 +67,23 @@ void printProgress(uint32_t progress, uint32_t total) /* use 70 characters for the progress bar */ uint8_t percent = progress * 70 / total; - if (last_percent != percent) - { + if (last_percent != percent) { last_percent = percent; tr_trace("\r[BOOT] ["); /* print + for progress or a space otherwise */ - for (uint8_t index = 0; index < 70; index++) - { - if (index <= percent) - { + for (uint8_t index = 0; index < 70; index++) { + if (index <= percent) { tr_trace("+"); - } - else - { + } else { tr_trace(" "); } } /* finish progress bar with a newline once complete */ - if (progress >= total) - { + if (progress >= total) { tr_trace("]\r\n"); - } - else - { + } else { tr_trace("]"); /* explicitly flush debug channel, usually this is triggered by \n */ diff --git a/source/bootloader_config.h b/source/bootloader_config.h index b7e5846..a2cdc9e 100644 --- a/source/bootloader_config.h +++ b/source/bootloader_config.h @@ -27,7 +27,7 @@ #if !defined(MAX_FIRMWARE_LOCATIONS) || MAX_FIRMWARE_LOCATIONS <= 0 #error "configure update-client.storage-locations or MAX_FIRMWARE_LOCATIONS in mbed_app.json\n" \ - "To use pre configured profiles: mbed compile --app-config configs/.json" +"To use pre configured profiles: mbed compile --app-config configs/.json" #endif /* FIRMWARE_METADATA_HEADER_ADDRESS */ @@ -37,20 +37,7 @@ #if !defined(FIRMWARE_METADATA_HEADER_ADDRESS) #error "configure update-client.application-details or FIRMWARE_METADATA_HEADER_ADDRESS in mbed_app.json\n" \ - "To use pre configured profiles: mbed compile --app-config configs/.json" -#endif - -/* FIRMWARE_METADATA_HEADER_SIZE */ -#if defined(MBED_CONF_APP_APPLICATION_START_ADDRESS) && \ - defined(FIRMWARE_METADATA_HEADER_ADDRESS) -#define FIRMWARE_METADATA_HEADER_SIZE \ - (MBED_CONF_APP_APPLICATION_START_ADDRESS - \ - FIRMWARE_METADATA_HEADER_ADDRESS) -#endif - -#if !defined(FIRMWARE_METADATA_HEADER_SIZE) -#error "configure application_start_address in mbed_app.json\n" \ - "To use pre configured profiles: mbed compile --app-config configs/.json" +"To use pre configured profiles: mbed compile --app-config configs/.json" #endif #endif // BOOTLOADER_CONFIG_H diff --git a/source/example_insecure_rot.c b/source/example_insecure_rot.c index b5c65f3..0be26ab 100644 --- a/source/example_insecure_rot.c +++ b/source/example_insecure_rot.c @@ -16,7 +16,7 @@ // limitations under the License. // ---------------------------------------------------------------------------- -#if !defined(ARM_UC_USE_SOTP) || ARM_UC_USE_SOTP == 0 +#if !defined(ARM_BOOTLOADER_USE_NVSTORE_ROT) || ARM_BOOTLOADER_USE_NVSTORE_ROT == 0 #include #include @@ -41,17 +41,15 @@ int8_t mbed_cloud_client_get_rot_128bit(uint8_t *key_buf, uint32_t length) { #warning "You are using insecure Root Of Trust implementation, DO NOT USE IN PRODUCTION ENVIRONMENTS. REPLACE WITH A PROPER IMPLEMENTATION BEFORE USE" - if (length < DEVICE_KEY_SIZE_IN_BYTES || key_buf == NULL) - { + if (length < DEVICE_KEY_SIZE_IN_BYTES || key_buf == NULL) { return -1; } - for (uint8_t i = 0; i < DEVICE_KEY_SIZE_IN_BYTES; i++) - { + for (uint8_t i = 0; i < DEVICE_KEY_SIZE_IN_BYTES; i++) { key_buf[i] = i; } return 0; } -#endif // #if !defined(ARM_UC_USE_SOTP) || ARM_UC_USE_SOTP == 0 +#endif // #if !defined(ARM_BOOTLOADER_USE_NVSTORE_ROT) || ARM_BOOTLOADER_USE_NVSTORE_ROT == 0 diff --git a/source/main.cpp b/source/main.cpp index 336273e..37433c7 100755 --- a/source/main.cpp +++ b/source/main.cpp @@ -49,13 +49,20 @@ const arm_uc_installer_details_t bootloader = { .layout = BOOTLOADER_STORAGE_LAYOUT }; +/* use a cut down version of ARM_UCP_FLASHIAP_BLOCKDEVICE to reduce + binary size if ARM_UC_USE_PAL_BLOCKDEVICE is set and not running tests */ +#if defined(ARM_UC_USE_PAL_BLOCKDEVICE) && (ARM_UC_USE_PAL_BLOCKDEVICE==1) && \ + (!defined(BOOTLOADER_POWER_CUT_TEST) || (BOOTLOADER_POWER_CUT_TEST != 1)) +#define MBED_CLOUD_CLIENT_UPDATE_STORAGE ARM_UCP_FLASHIAP_BLOCKDEVICE_READ_ONLY +#endif + #ifdef MBED_CLOUD_CLIENT_UPDATE_STORAGE extern ARM_UC_PAAL_UPDATE MBED_CLOUD_CLIENT_UPDATE_STORAGE; #else #error Update client storage must be defined in user configuration file #endif -#if MBED_CLOUD_CLIENT_UPDATE_STORAGE == ARM_UCP_FLASHIAP_BLOCKDEVICE +#if defined(ARM_UC_USE_PAL_BLOCKDEVICE) && (ARM_UC_USE_PAL_BLOCKDEVICE==1) #include "SDBlockDevice.h" /* initialise sd card blockdevice */ @@ -68,14 +75,23 @@ SDBlockDevice sd(MBED_CONF_SD_SPI_MOSI, MBED_CONF_SD_SPI_MISO, MBED_CONF_SD_SPI_CLK, MBED_CONF_SD_SPI_CS); #endif -BlockDevice* arm_uc_blockdevice = &sd; +BlockDevice *arm_uc_blockdevice = &sd; +#endif + +#ifndef MBED_CONF_APP_APPLICATION_START_ADDRESS +#error Application start address must be defined +#endif + +/* If jump address is not set then default to start address. */ +#ifndef MBED_CONF_APP_APPLICATION_JUMP_ADDRESS +#define MBED_CONF_APP_APPLICATION_JUMP_ADDRESS MBED_CONF_APP_APPLICATION_START_ADDRESS #endif int main(void) { /* Use malloc to allocate uint64_t version number on the heap */ - heapVersion = (uint64_t*) malloc(sizeof(uint64_t)); - bootCounter = (uint8_t*) malloc(1); + heapVersion = (uint64_t *) malloc(sizeof(uint64_t)); + bootCounter = (uint8_t *) malloc(1); /* Set PAAL Update implementation before initializing Firmware Manager */ ARM_UCP_SetPAALUpdate(&MBED_CLOUD_CLIENT_UPDATE_STORAGE); @@ -84,8 +100,7 @@ int main(void) arm_uc_error_t ucp_result = ARM_UCP_Initialize(arm_ucp_event_handler); /* If a reboot message was left from last boot, print it here */ - if (existsErrorMessageLeadingToReboot()) - { + if (existsErrorMessageLeadingToReboot()) { tr_info("error message leading to reboot: %s", errorMessageLeadingToReboot()); } @@ -96,7 +111,7 @@ int main(void) copyAppToSDCard(firmware_size); power_cut_test_assert_state(POWER_CUT_TEST_STATE_START); #elif defined(FIRMWARE_UPDATE_TEST) && (FIRMWARE_UPDATE_TEST == 1) - const uint32_t firmware_size = 1024*16; + const uint32_t firmware_size = 1024 * 16; copyAppToSDCard(firmware_size); firmware_update_test_setup(); #endif @@ -105,15 +120,14 @@ int main(void) /* Print bootloader information */ /*************************************************************************/ - tr_info("mbed Bootloader"); + tr_info("Mbed Bootloader"); /* although not referenced, arm_size is used indirectly in sizeof() below */ /* coverity[set_but_not_used] */ uint8_t arm_size[] = BOOTLOADER_ARM_SOURCE_HASH; tr_trace("[BOOT] ARM: "); - for (uint32_t index = 0; index < sizeof(arm_size); index++) - { + for (uint32_t index = 0; index < sizeof(arm_size); index++) { tr_trace("%02" PRIX8, bootloader.arm_hash[index]); } tr_trace("\r\n"); @@ -123,8 +137,7 @@ int main(void) uint8_t oem_size[] = BOOTLOADER_OEM_SOURCE_HASH; tr_trace("[BOOT] OEM: "); - for (uint32_t index = 0; index < sizeof(oem_size); index++) - { + for (uint32_t index = 0; index < sizeof(oem_size); index++) { tr_trace("%02" PRIX8, bootloader.oem_hash[index]); } tr_trace("\r\n"); @@ -141,13 +154,11 @@ int main(void) bool canForward = true; /* check UCP initialization result */ - if (ucp_result.error == ERR_NONE) - { + if (ucp_result.error == ERR_NONE) { /* Initialize internal flash */ bool storageResult = activeStorageInit(); - if (storageResult) - { + if (storageResult) { /* Try to update firmware from journal */ canForward = upgradeApplicationFromStorage(); @@ -157,8 +168,7 @@ int main(void) } /* forward control to ACTIVE application if it is deemed sane */ - if (canForward) - { + if (canForward) { #if defined(BOOTLOADER_POWER_CUT_TEST) && (BOOTLOADER_POWER_CUT_TEST == 1) power_cut_test_assert_state(POWER_CUT_TEST_STATE_END); wait(5); @@ -167,30 +177,28 @@ int main(void) firmware_update_test_end(); #endif uint32_t app_start_addr = MBED_CONF_APP_APPLICATION_START_ADDRESS; - uint32_t app_stack_ptr = *((uint32_t*)(app_start_addr + 0)); - uint32_t app_jump_addr = *((uint32_t*)(app_start_addr + 4)); + uint32_t app_stack_ptr = *((uint32_t *)(MBED_CONF_APP_APPLICATION_JUMP_ADDRESS + 0)); + uint32_t app_jump_addr = *((uint32_t *)(MBED_CONF_APP_APPLICATION_JUMP_ADDRESS + 4)); tr_info("Application's start address: 0x%" PRIX32, app_start_addr); tr_info("Application's jump address: 0x%" PRIX32, app_jump_addr); tr_info("Application's stack address: 0x%" PRIX32, app_stack_ptr); tr_info("Forwarding to application...\r\n"); - mbed_start_application(app_start_addr); + mbed_start_application(MBED_CONF_APP_APPLICATION_JUMP_ADDRESS); } /* Reset bootCounter; this allows a user to reapply a new bootloader without having to power cycle the device. */ - if (bootCounter) - { + if (bootCounter) { *bootCounter = 0; } MBED_BOOTLOADER_ASSERT(false, "Failed to jump to application!"); /* coverity[no_escape] */ - for (;;) - { + for (;;) { __WFI(); } } diff --git a/source/sotp_rot.c b/source/nvstore_rot.cpp similarity index 63% rename from source/sotp_rot.c rename to source/nvstore_rot.cpp index a7429d5..419ca7a 100644 --- a/source/sotp_rot.c +++ b/source/nvstore_rot.cpp @@ -16,25 +16,17 @@ // limitations under the License. // ---------------------------------------------------------------------------- -#if defined(ARM_UC_USE_SOTP) && ARM_UC_USE_SOTP == 1 +#if defined(ARM_BOOTLOADER_USE_NVSTORE_ROT) && ARM_BOOTLOADER_USE_NVSTORE_ROT == 1 #include #include #include -#include "pal.h" -#include "sotp.h" +// #include "pal.h" +#include "nvstore.h" +#define NVSTORE_TYPE_ROT 4 #define DEVICE_KEY_SIZE_IN_BYTES (128/8) -/* We can get the RoT from SOTP using either sotp_probe (when ARM_UC_SOTP_PROBE_ONLY is defined to 1) - * or the "regular" sotp_get function (when ARM_UC_SOTP_PROBE_ONLY is not defined or is defined to 0) - */ -#if defined(ARM_UC_SOTP_PROBE_ONLY) && ARM_UC_SOTP_PROBE_ONLY == 1 -#define SOTP_GET_FUNCTION sotp_probe -#else -#define SOTP_GET_FUNCTION sotp_get -#endif - /** * @brief Function to get the device root of trust * @details The device root of trust should be a 128 bit value. It should never leave the device. @@ -48,34 +40,30 @@ * @return 0 on success, non-zero on failure. */ -int8_t mbed_cloud_client_get_rot_128bit(uint8_t *key_buf, uint32_t length) +extern "C" int8_t mbed_cloud_client_get_rot_128bit(uint8_t *key_buf, uint32_t length) { static bool initialized = false; uint32_t rot[DEVICE_KEY_SIZE_IN_BYTES / sizeof(uint32_t)]; uint16_t actual_len_bytes = 0; + NVStore &nvstore = NVStore::get_instance(); - if (length < DEVICE_KEY_SIZE_IN_BYTES || key_buf == NULL) - { + if (length < DEVICE_KEY_SIZE_IN_BYTES || key_buf == NULL) { return -1; } - if (!initialized) - { -#if !defined(ARM_UC_SOTP_PROBE_ONLY) || ARM_UC_SOTP_PROBE_ONLY == 0 // sotp_probe doesn't need sotp_init() - if (pal_internalFlashInit() != PAL_SUCCESS) - { + if (!initialized) { + if (nvstore.init() != NVSTORE_SUCCESS) { return -1; } -#endif initialized = true; } - sotp_result_e status = SOTP_GET_FUNCTION(SOTP_TYPE_ROT, DEVICE_KEY_SIZE_IN_BYTES, rot, &actual_len_bytes); - if (status != SOTP_SUCCESS || actual_len_bytes != DEVICE_KEY_SIZE_IN_BYTES) - { + + int status = nvstore.get(NVSTORE_TYPE_ROT, DEVICE_KEY_SIZE_IN_BYTES, rot, actual_len_bytes); + if (status != NVSTORE_SUCCESS || actual_len_bytes != DEVICE_KEY_SIZE_IN_BYTES) { return -1; } memcpy(key_buf, rot, DEVICE_KEY_SIZE_IN_BYTES); return 0; } -#endif // #if defined(ARM_UC_USE_SOTP) && ARM_UC_USE_SOTP == 1 +#endif // #if defined(ARM_BOOTLOADER_USE_NVSTORE_ROT) && ARM_BOOTLOADER_USE_NVSTORE_ROT == 1 diff --git a/source/upgrade.cpp b/source/upgrade.cpp index ae970a6..8197c3f 100755 --- a/source/upgrade.cpp +++ b/source/upgrade.cpp @@ -46,10 +46,10 @@ #define INVALID_IMAGE_INDEX 0xFFFFFFFF /* SHA256 pointer to buffer in the heap */ -uint64_t* heapVersion = NULL; +uint64_t *heapVersion = NULL; /* pointer to reboot counter in the heap */ -uint8_t* bootCounter = NULL; +uint8_t *bootCounter = NULL; /** * Verify the integrity of stored firmware @@ -64,14 +64,13 @@ uint8_t* bootCounter = NULL; * @return true if the validation succeeds. */ bool checkStoredApplication(uint32_t source, - arm_uc_firmware_details_t* details) + arm_uc_firmware_details_t *details) { tr_debug("checkStoredApplication"); bool result = false; - if (details) - { + if (details) { #if defined(BOOTLOADER_POWER_CUT_TEST) && (BOOTLOADER_POWER_CUT_TEST == 1) power_cut_test_assert_state(POWER_CUT_TEST_STATE_FIRMWARE_VALIDATION); #endif @@ -90,14 +89,13 @@ bool checkStoredApplication(uint32_t source, /* read full firmware using PAL Update API */ uint32_t offset = 0; - while (offset < details->size) - { + while (offset < details->size) { /* clear most recent UCP event */ event_callback = CLEAR_EVENT; /* set the number of bytes expected */ buffer.size = (details->size - offset) > buffer.size_max ? - buffer.size_max : (details->size - offset); + buffer.size_max : (details->size - offset); /* fill buffer using UCP */ arm_uc_error_t ucp_status = ARM_UCP_Read(source, @@ -105,25 +103,20 @@ bool checkStoredApplication(uint32_t source, &buffer); /* wait for event if the call is accepted */ - if (ucp_status.error == ERR_NONE) - { - while (event_callback == CLEAR_EVENT) - { + if (ucp_status.error == ERR_NONE) { + while (event_callback == CLEAR_EVENT) { __WFI(); } } /* check status and actual read size */ if ((event_callback == ARM_UC_PAAL_EVENT_READ_DONE) && - (buffer.size > 0)) - { + (buffer.size > 0)) { /* update hash */ mbedtls_sha256_update(&mbedtls_ctx, buffer.ptr, buffer.size); offset += buffer.size; - } - else - { + } else { tr_trace("\r\n"); tr_debug("ARM_UCP_Read returned 0 bytes"); break; @@ -134,7 +127,7 @@ bool checkStoredApplication(uint32_t source, #endif } -/* make sure buffer is large enough to contain both the SHA and HMAC */ + /* make sure buffer is large enough to contain both the SHA and HMAC */ #if BUFFER_SIZE < (2*SIZEOF_SHA256) #error "BUFFER_SIZE too small to contain SHA and HMAC" #endif @@ -156,12 +149,9 @@ bool checkStoredApplication(uint32_t source, hash_buffer.ptr, SIZEOF_SHA256); - if (diff == 0) - { + if (diff == 0) { result = true; - } - else - { + } else { printSHA256(details->hash); printSHA256(hash_buffer.ptr); } @@ -224,11 +214,9 @@ bool upgradeApplicationFromStorage(void) /* default to a fresh boot */ uint8_t localCounter = 0; - if (heapVersion && bootCounter) - { + if (heapVersion && bootCounter) { /* fresh boot */ - if (*heapVersion != imageDetails.version) - { + if (*heapVersion != imageDetails.version) { /* copy version to heap */ *heapVersion = imageDetails.version; @@ -239,8 +227,7 @@ bool upgradeApplicationFromStorage(void) tr_debug("bootCounter: %" PRIu8, *bootCounter); } /* reboot */ - else - { + else { /* increment boot counter*/ *bootCounter += 1; @@ -253,8 +240,7 @@ bool upgradeApplicationFromStorage(void) /* mark active image as valid */ if ((activeApplicationStatus == RESULT_SUCCESS) && - (localCounter < MAX_BOOT_RETRIES)) - { + (localCounter < MAX_BOOT_RETRIES)) { printSHA256(imageDetails.hash); tr_info("Version: %" PRIu64, imageDetails.version); @@ -265,18 +251,15 @@ bool upgradeApplicationFromStorage(void) bestStoredFirmwareImageDetails.version = imageDetails.version; } /* active image is empty */ - else if (activeApplicationStatus == RESULT_EMPTY) - { + else if (activeApplicationStatus == RESULT_EMPTY) { tr_info("Active firmware slot is empty"); } /* active image cannot be run */ - else if (localCounter >= MAX_BOOT_RETRIES) - { + else if (localCounter >= MAX_BOOT_RETRIES) { tr_error("Failed to boot active application %d times", MAX_BOOT_RETRIES); } /* active image failed integrity check */ - else - { + else { tr_error("Active firmware integrity check failed"); } @@ -285,8 +268,7 @@ bool upgradeApplicationFromStorage(void) /* replacement firmware for corrupted active image. */ /*************************************************************************/ - for (uint32_t index = 0; index < MAX_FIRMWARE_LOCATIONS; index++) - { + for (uint32_t index = 0; index < MAX_FIRMWARE_LOCATIONS; index++) { /* clear most recent UCP event */ event_callback = CLEAR_EVENT; @@ -295,26 +277,22 @@ bool upgradeApplicationFromStorage(void) &imageDetails); /* wait for event if the call is accepted */ - if (ucp_status.error == ERR_NONE) - { - while (event_callback == CLEAR_EVENT) - { + if (ucp_status.error == ERR_NONE) { + while (event_callback == CLEAR_EVENT) { __WFI(); } } /* check event */ - if (event_callback == ARM_UC_PAAL_EVENT_GET_FIRMWARE_DETAILS_DONE) - { + if (event_callback == ARM_UC_PAAL_EVENT_GET_FIRMWARE_DETAILS_DONE) { /* default to use firmware candidate */ bool firmwareDifferentFromActive = true; -/* disable duplicate hash check when running test */ + /* disable duplicate hash check when running test */ #if !defined(FIRMWARE_UPDATE_TEST) || (FIRMWARE_UPDATE_TEST == 0) /* compare stored firmware with the currently active one */ - if (heapVersion) - { + if (heapVersion) { firmwareDifferentFromActive = (*heapVersion != imageDetails.version); } @@ -326,9 +304,8 @@ bool upgradeApplicationFromStorage(void) bestStoredFirmwareImageDetails.version equals 0. */ if ((imageDetails.version > bestStoredFirmwareImageDetails.version) && - (imageDetails.size > 0) && - (firmwareDifferentFromActive || !activeFirmwareValid)) - { + (imageDetails.size > 0) && + (firmwareDifferentFromActive || !activeFirmwareValid)) { tr_info("Slot %" PRIu32 " firmware integrity check:", index); @@ -336,15 +313,13 @@ bool upgradeApplicationFromStorage(void) bool firmwareValid = checkStoredApplication(index, &imageDetails); - if (firmwareValid) - { + if (firmwareValid) { /* Integrity check passed */ printSHA256(imageDetails.hash); tr_info("Version: %" PRIu64, imageDetails.version); /* check firmware size fits */ - if (imageDetails.size <= MBED_CONF_APP_MAX_APPLICATION_SIZE) - { + if (imageDetails.size <= MBED_CONF_APP_MAX_APPLICATION_SIZE) { /* Update best candidate information */ bestStoredFirmwareIndex = index; bestStoredFirmwareImageDetails.version = imageDetails.version; @@ -355,25 +330,19 @@ bool upgradeApplicationFromStorage(void) memcpy(bestStoredFirmwareImageDetails.campaign, imageDetails.campaign, ARM_UC_GUID_SIZE); - } - else - { + } else { /* Firmware candidate size too large */ tr_error("Slot %" PRIu32 " firmware size too large %" PRIu32 " > %" PRIu32, index, (uint32_t) imageDetails.size, (uint32_t) MBED_CONF_APP_MAX_APPLICATION_SIZE); } - } - else - { + } else { /* Integrity check failed */ tr_error("Slot %" PRIu32 " firmware integrity check failed", index); } - } - else - { + } else { tr_info("Slot %" PRIu32 " firmware is of older date", index); /* do not print HMAC version @@ -381,9 +350,7 @@ bool upgradeApplicationFromStorage(void) */ tr_info("Version: %" PRIu64, imageDetails.version); } - } - else - { + } else { tr_info("Slot %" PRIu32 " is empty", index); } } @@ -393,11 +360,9 @@ bool upgradeApplicationFromStorage(void) /*************************************************************************/ /* only replace active image if there is a better candidate */ - if (bestStoredFirmwareIndex != INVALID_IMAGE_INDEX) - { + if (bestStoredFirmwareIndex != INVALID_IMAGE_INDEX) { /* if copy fails, retry up to MAX_COPY_RETRIES */ - for (uint32_t retries = 0; retries < MAX_COPY_RETRIES; retries++) - { + for (uint32_t retries = 0; retries < MAX_COPY_RETRIES; retries++) { tr_info("Update active firmware using slot %" PRIu32 ":", bestStoredFirmwareIndex); @@ -405,26 +370,19 @@ bool upgradeApplicationFromStorage(void) &bestStoredFirmwareImageDetails); /* if image is valid, break out from loop */ - if (activeFirmwareValid) - { + if (activeFirmwareValid) { tr_info("New active firmware is valid"); #if defined(FIRMWARE_UPDATE_TEST) && (FIRMWARE_UPDATE_TEST == 1) firmware_update_test_validate(); #endif break; - } - else - { + } else { tr_error("Firmware update failed"); } } - } - else if (activeFirmwareValid) - { + } else if (activeFirmwareValid) { tr_info("Active firmware up-to-date"); - } - else - { + } else { tr_error("Active firmware invalid"); } diff --git a/source/upgrade.h b/source/upgrade.h index 14f846f..f89bcce 100644 --- a/source/upgrade.h +++ b/source/upgrade.h @@ -22,8 +22,8 @@ #define MAX_COPY_RETRIES 1 #endif -extern uint64_t* heapVersion; -extern uint8_t* bootCounter; +extern uint64_t *heapVersion; +extern uint8_t *bootCounter; /** * Find suitable update candidate and copy firmware into active region