diff --git a/.github/.cSpellWords.txt b/.github/.cSpellWords.txt index 083a427b..10ffe359 100644 --- a/.github/.cSpellWords.txt +++ b/.github/.cSpellWords.txt @@ -168,6 +168,7 @@ NVIC ohmyzsh Onoa OPTIM +optimise OPTIMISED otaexample otapalconfig @@ -202,6 +203,7 @@ RSASSA rtrack SBCON SECP +smsc sntp Sntp SNTP @@ -219,6 +221,7 @@ suppr SYSWDOG TALGORITHMS testThing +tflite TGENERAL THEIGHT tinycbor @@ -239,11 +242,13 @@ uncrustify unusued utilises USART +utilises UYVY Vbex VCLK VECTACTIVE venv +visualisation vmean vsocket vsync diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index e6e01ea5..ae365d25 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -1,4 +1,4 @@ -# Copyright 2023-2024 Arm Limited and/or its affiliates +# Copyright 2023-2025 Arm Limited and/or its affiliates # # SPDX-License-Identifier: MIT @@ -83,10 +83,19 @@ workflow: --psa-crypto-implementation $PSA_CRYPTO_IMPLEMENTATION - | if [ $APP == "blinky" ];then - tar -czf ${TARGET}_${APP}_${TOOLCHAIN}_${INFERENCE}_${AUDIO}_${CONN_STACK}_${PSA_CRYPTO_IMPLEMENTATION}_build.tar.gz \ + tar -czf ${TARGET}_${APP}_${TOOLCHAIN}_${INFERENCE}_${AUDIO}_${CONN_STACK}_${PSA_CRYPTO_IMPLEMENTATION}_${PASS_LOG_FILE}_build.tar.gz \ build/${APP}_merged.elf + elif [[ $APP == "keyword-detection" && $TOOLCHAIN == "GNU" ]]; then + tar -czf ${TARGET}_${APP}_${TOOLCHAIN}_${INFERENCE}_${AUDIO}_${CONN_STACK}_${PSA_CRYPTO_IMPLEMENTATION}_${PASS_LOG_FILE}_build.tar.gz \ + build/${APP}_merged.elf \ + build/${APP}-update_signed.bin \ + build/${APP}-model-update_signed.bin \ + build/update-signature.txt \ + build/CMakeCache.txt \ + build/model-update-signature.txt \ + applications/${APP_UNDERSCORED}/configs/aws_configs else - tar -czf ${TARGET}_${APP}_${TOOLCHAIN}_${INFERENCE}_${AUDIO}_${CONN_STACK}_${PSA_CRYPTO_IMPLEMENTATION}_build.tar.gz \ + tar -czf ${TARGET}_${APP}_${TOOLCHAIN}_${INFERENCE}_${AUDIO}_${CONN_STACK}_${PSA_CRYPTO_IMPLEMENTATION}_${PASS_LOG_FILE}_build.tar.gz \ build/${APP}_merged.elf \ build/${APP}-update_signed.bin \ build/update-signature.txt \ @@ -112,9 +121,19 @@ build-applications-corstone320: AUDIO: [ROM] CONN_STACK: [FREERTOS_PLUS_TCP] PSA_CRYPTO_IMPLEMENTATION: [TF-M] + PASS_LOG_FILE: [corstone320_pass_output] + - + << : *pipeline_config_corstone320 + APP: [keyword-detection] + INFERENCE: [ETHOS] + AUDIO: [ROM] + CONN_STACK: [FREERTOS_PLUS_TCP] + PSA_CRYPTO_IMPLEMENTATION: [TF-M] + TOOLCHAIN: [GNU] + PASS_LOG_FILE: [corstone320_model_pass_output] artifacts: paths: - - ${TARGET}_${APP}_${TOOLCHAIN}_${INFERENCE}_${AUDIO}_${CONN_STACK}_${PSA_CRYPTO_IMPLEMENTATION}_build.tar.gz + - ${TARGET}_${APP}_${TOOLCHAIN}_${INFERENCE}_${AUDIO}_${CONN_STACK}_${PSA_CRYPTO_IMPLEMENTATION}_${PASS_LOG_FILE}_build.tar.gz expire_in: 1 week variables: GIT_SUBMODULE_STRATEGY: recursive @@ -132,9 +151,19 @@ build-applications-corstone315: AUDIO: [ROM] CONN_STACK: [FREERTOS_PLUS_TCP] PSA_CRYPTO_IMPLEMENTATION: [TF-M] + PASS_LOG_FILE: [corstone315_pass_output] + - + << : *pipeline_config_corstone315 + APP: [keyword-detection] + INFERENCE: [ETHOS] + AUDIO: [ROM] + CONN_STACK: [FREERTOS_PLUS_TCP] + PSA_CRYPTO_IMPLEMENTATION: [TF-M] + TOOLCHAIN: [GNU] + PASS_LOG_FILE: [corstone315_model_pass_output] artifacts: paths: - - ${TARGET}_${APP}_${TOOLCHAIN}_${INFERENCE}_${AUDIO}_${CONN_STACK}_${PSA_CRYPTO_IMPLEMENTATION}_build.tar.gz + - ${TARGET}_${APP}_${TOOLCHAIN}_${INFERENCE}_${AUDIO}_${CONN_STACK}_${PSA_CRYPTO_IMPLEMENTATION}_${PASS_LOG_FILE}_build.tar.gz expire_in: 1 week variables: GIT_SUBMODULE_STRATEGY: recursive @@ -152,9 +181,19 @@ build-applications-corstone310: AUDIO: [ROM] CONN_STACK: [FREERTOS_PLUS_TCP] PSA_CRYPTO_IMPLEMENTATION: [TF-M] + PASS_LOG_FILE: [corstone310_pass_output] + - + << : *pipeline_config_corstone310 + APP: [keyword-detection] + INFERENCE: [ETHOS] + AUDIO: [ROM] + CONN_STACK: [FREERTOS_PLUS_TCP] + PSA_CRYPTO_IMPLEMENTATION: [TF-M] + TOOLCHAIN: [GNU] + PASS_LOG_FILE: [corstone310_model_pass_output] artifacts: paths: - - ${TARGET}_${APP}_${TOOLCHAIN}_${INFERENCE}_${AUDIO}_${CONN_STACK}_${PSA_CRYPTO_IMPLEMENTATION}_build.tar.gz + - ${TARGET}_${APP}_${TOOLCHAIN}_${INFERENCE}_${AUDIO}_${CONN_STACK}_${PSA_CRYPTO_IMPLEMENTATION}_${PASS_LOG_FILE}_build.tar.gz expire_in: 1 week variables: GIT_SUBMODULE_STRATEGY: recursive @@ -172,9 +211,19 @@ build-applications-corstone300: AUDIO: [ROM] CONN_STACK: [FREERTOS_PLUS_TCP] PSA_CRYPTO_IMPLEMENTATION: [TF-M] + PASS_LOG_FILE: [corstone300_pass_output] + - + << : *pipeline_config_corstone300 + APP: [keyword-detection] + INFERENCE: [ETHOS] + AUDIO: [ROM] + CONN_STACK: [FREERTOS_PLUS_TCP] + PSA_CRYPTO_IMPLEMENTATION: [TF-M] + TOOLCHAIN: [GNU] + PASS_LOG_FILE: [corstone300_model_pass_output] artifacts: paths: - - ${TARGET}_${APP}_${TOOLCHAIN}_${INFERENCE}_${AUDIO}_${CONN_STACK}_${PSA_CRYPTO_IMPLEMENTATION}_build.tar.gz + - ${TARGET}_${APP}_${TOOLCHAIN}_${INFERENCE}_${AUDIO}_${CONN_STACK}_${PSA_CRYPTO_IMPLEMENTATION}_${PASS_LOG_FILE}_build.tar.gz expire_in: 1 week variables: GIT_SUBMODULE_STRATEGY: recursive @@ -227,7 +276,7 @@ test-blinky-output: - job: build-applications-corstone300 artifacts: true script: - - tar xf ${TARGET}_${APP}_${TOOLCHAIN}_${INFERENCE}_${AUDIO}_${CONN_STACK}_${PSA_CRYPTO_IMPLEMENTATION}_build.tar.gz + - tar xf ${TARGET}_${APP}_${TOOLCHAIN}_${INFERENCE}_${AUDIO}_${CONN_STACK}_${PSA_CRYPTO_IMPLEMENTATION}_${PASS_LOG_FILE}_build.tar.gz - | pytest -s tools/tests/test_blinky_output.py \ --build-artefacts-path "build" \ @@ -245,6 +294,7 @@ test-blinky-output: AUDIO: [ROM] CONN_STACK: [FREERTOS_PLUS_TCP] PSA_CRYPTO_IMPLEMENTATION: [TF-M] + PASS_LOG_FILE: [corstone320_pass_output] - << : [*pipeline_config_corstone315, *pipeline_config_toolchain] APP: [blinky] @@ -252,6 +302,7 @@ test-blinky-output: AUDIO: [ROM] CONN_STACK: [FREERTOS_PLUS_TCP] PSA_CRYPTO_IMPLEMENTATION: [TF-M] + PASS_LOG_FILE: [corstone315_pass_output] - << : [*pipeline_config_corstone310, *pipeline_config_toolchain] APP: [blinky] @@ -259,6 +310,7 @@ test-blinky-output: AUDIO: [ROM] CONN_STACK: [FREERTOS_PLUS_TCP] PSA_CRYPTO_IMPLEMENTATION: [TF-M] + PASS_LOG_FILE: [corstone310_pass_output] - << : [*pipeline_config_corstone300, *pipeline_config_toolchain] APP: [blinky] @@ -266,13 +318,14 @@ test-blinky-output: AUDIO: [ROM] CONN_STACK: [FREERTOS_PLUS_TCP] PSA_CRYPTO_IMPLEMENTATION: [TF-M] + PASS_LOG_FILE: [corstone300_pass_output] .test-applications_base: extends: .test_job script: - | - if [[ -f "${TARGET}_${APP}_${TOOLCHAIN}_${INFERENCE}_${AUDIO}_${CONN_STACK}_${PSA_CRYPTO_IMPLEMENTATION}_build.tar.gz" ]]; then - tar xf ${TARGET}_${APP}_${TOOLCHAIN}_${INFERENCE}_${AUDIO}_${CONN_STACK}_${PSA_CRYPTO_IMPLEMENTATION}_build.tar.gz + if [[ -f "${TARGET}_${APP}_${TOOLCHAIN}_${INFERENCE}_${AUDIO}_${CONN_STACK}_${PSA_CRYPTO_IMPLEMENTATION}_${PASS_LOG_FILE}_build.tar.gz" ]]; then + tar xf ${TARGET}_${APP}_${TOOLCHAIN}_${INFERENCE}_${AUDIO}_${CONN_STACK}_${PSA_CRYPTO_IMPLEMENTATION}_${PASS_LOG_FILE}_build.tar.gz fi - export APP_UNDERSCORED=$(echo ${APP} | tr '-' '_') - export SIGNING_ALGO=$(cat build/CMakeCache.txt | grep AWS_OTA_SIGNATURE_TYPE | sed s/.*=// | sed s/-.*//) @@ -287,7 +340,7 @@ test-blinky-output: --signed-update-bin-name "${APP}-update_signed.bin" \ --signing-algo ${SIGNING_ALGO} \ --timeout-seconds 2700 \ - --pass-output-file "applications/${APP_UNDERSCORED}/tests/${TARGET}_pass_output.log" \ + --pass-output-file "applications/${APP_UNDERSCORED}/tests/${PASS_LOG_FILE}.log" \ --fail-output-file "applications/${APP_UNDERSCORED}/tests/fail_output.log" \ --pythonhome-path "/opt/python/3.9.18" elif [[ $APP == "object-detection" ]]; then @@ -300,18 +353,21 @@ test-blinky-output: --signed-update-bin-name "${APP}-update_signed.bin" \ --signing-algo ${SIGNING_ALGO} \ --timeout-seconds 1800 \ - --pass-output-file "applications/${APP_UNDERSCORED}/tests/${TARGET}_pass_output.log" \ + --pass-output-file "applications/${APP_UNDERSCORED}/tests/${PASS_LOG_FILE}.log" \ --fail-output-file "applications/${APP_UNDERSCORED}/tests/fail_output.log" else + if [[ $SIGNED_UPDATE_BIN_NAME == '' ]]; then + export SIGNED_UPDATE_BIN_NAME=${APP}-update_signed + fi pytest -s tools/tests/test_applications.py \ --build-artefacts-path "build" \ --fvp $FVP_BIN \ --credentials-path "applications/${APP_UNDERSCORED}/configs/aws_configs" \ --merged-elf-name "${APP}_merged.elf" \ - --signed-update-bin-name "${APP}-update_signed.bin" \ + --signed-update-bin-name "${SIGNED_UPDATE_BIN_NAME}.bin" \ --signing-algo ${SIGNING_ALGO} \ --timeout-seconds 2700 \ - --pass-output-file "applications/${APP_UNDERSCORED}/tests/${TARGET}_pass_output.log" \ + --pass-output-file "applications/${APP_UNDERSCORED}/tests/${PASS_LOG_FILE}.log" \ --fail-output-file "applications/${APP_UNDERSCORED}/tests/fail_output.log" fi @@ -338,6 +394,7 @@ test-ml-applications-output: TOOLCHAIN: [ARMCLANG] CONN_STACK: [FREERTOS_PLUS_TCP] PSA_CRYPTO_IMPLEMENTATION: [TF-M] + PASS_LOG_FILE: [corstone320_pass_output] - << : *pipeline_config_corstone315 APP: [keyword-detection, speech-recognition, object-detection] @@ -346,6 +403,7 @@ test-ml-applications-output: TOOLCHAIN: [ARMCLANG] CONN_STACK: [FREERTOS_PLUS_TCP] PSA_CRYPTO_IMPLEMENTATION: [TF-M] + PASS_LOG_FILE: [corstone315_pass_output] - << : *pipeline_config_corstone310 APP: [keyword-detection, speech-recognition] @@ -354,6 +412,7 @@ test-ml-applications-output: TOOLCHAIN: [ARMCLANG] CONN_STACK: [FREERTOS_PLUS_TCP] PSA_CRYPTO_IMPLEMENTATION: [TF-M] + PASS_LOG_FILE: [corstone310_pass_output] - << : *pipeline_config_corstone300 APP: [keyword-detection, speech-recognition] @@ -362,6 +421,7 @@ test-ml-applications-output: TOOLCHAIN: [ARMCLANG] CONN_STACK: [FREERTOS_PLUS_TCP] PSA_CRYPTO_IMPLEMENTATION: [TF-M] + PASS_LOG_FILE: [corstone300_pass_output] unit-tests: extends: .base-job-rules @@ -486,6 +546,7 @@ sw-vsi-configs-test: TOOLCHAIN: [ARMCLANG] CONN_STACK: [FREERTOS_PLUS_TCP] PSA_CRYPTO_IMPLEMENTATION: [TF-M] + PASS_LOG_FILE: [corstone320_pass_output] - << : *pipeline_config_corstone320 APP: [keyword-detection, speech-recognition] @@ -494,6 +555,7 @@ sw-vsi-configs-test: TOOLCHAIN: [ARMCLANG] CONN_STACK: [FREERTOS_PLUS_TCP] PSA_CRYPTO_IMPLEMENTATION: [TF-M] + PASS_LOG_FILE: [corstone320_pass_output] - << : *pipeline_config_corstone320 APP: [object-detection] @@ -502,6 +564,7 @@ sw-vsi-configs-test: TOOLCHAIN: [ARMCLANG] CONN_STACK: [FREERTOS_PLUS_TCP] PSA_CRYPTO_IMPLEMENTATION: [TF-M] + PASS_LOG_FILE: [corstone320_pass_output] - << : *pipeline_config_corstone315 APP: [keyword-detection, speech-recognition] @@ -510,6 +573,7 @@ sw-vsi-configs-test: TOOLCHAIN: [ARMCLANG] CONN_STACK: [FREERTOS_PLUS_TCP] PSA_CRYPTO_IMPLEMENTATION: [TF-M] + PASS_LOG_FILE: [corstone315_pass_output] - << : *pipeline_config_corstone315 APP: [keyword-detection, speech-recognition] @@ -518,6 +582,7 @@ sw-vsi-configs-test: TOOLCHAIN: [ARMCLANG] CONN_STACK: [FREERTOS_PLUS_TCP] PSA_CRYPTO_IMPLEMENTATION: [TF-M] + PASS_LOG_FILE: [corstone315_pass_output] - << : *pipeline_config_corstone315 APP: [object-detection] @@ -526,6 +591,7 @@ sw-vsi-configs-test: TOOLCHAIN: [ARMCLANG] CONN_STACK: [FREERTOS_PLUS_TCP] PSA_CRYPTO_IMPLEMENTATION: [TF-M] + PASS_LOG_FILE: [corstone315_pass_output] - << : *pipeline_config_corstone310 APP: [keyword-detection, speech-recognition] @@ -534,6 +600,7 @@ sw-vsi-configs-test: TOOLCHAIN: [ARMCLANG] CONN_STACK: [FREERTOS_PLUS_TCP] PSA_CRYPTO_IMPLEMENTATION: [TF-M] + PASS_LOG_FILE: [corstone310_pass_output] - << : *pipeline_config_corstone310 APP: [keyword-detection, speech-recognition] @@ -542,6 +609,7 @@ sw-vsi-configs-test: TOOLCHAIN: [ARMCLANG] CONN_STACK: [FREERTOS_PLUS_TCP] PSA_CRYPTO_IMPLEMENTATION: [TF-M] + PASS_LOG_FILE: [corstone310_pass_output] - << : *pipeline_config_corstone300 APP: [keyword-detection, speech-recognition] @@ -550,6 +618,7 @@ sw-vsi-configs-test: TOOLCHAIN: [ARMCLANG] CONN_STACK: [FREERTOS_PLUS_TCP] PSA_CRYPTO_IMPLEMENTATION: [TF-M] + PASS_LOG_FILE: [corstone300_pass_output] - << : *pipeline_config_corstone300 APP: [keyword-detection, speech-recognition] @@ -558,6 +627,7 @@ sw-vsi-configs-test: TOOLCHAIN: [ARMCLANG] CONN_STACK: [FREERTOS_PLUS_TCP] PSA_CRYPTO_IMPLEMENTATION: [TF-M] + PASS_LOG_FILE: [corstone300_pass_output] retry: max: 2 when: @@ -597,6 +667,7 @@ gnu-toolchain-test: TOOLCHAIN: [GNU] CONN_STACK: [FREERTOS_PLUS_TCP] PSA_CRYPTO_IMPLEMENTATION: [TF-M] + PASS_LOG_FILE: [corstone320_pass_output] - << : *pipeline_config_corstone320 APP: [object-detection] @@ -605,6 +676,7 @@ gnu-toolchain-test: TOOLCHAIN: [GNU] CONN_STACK: [FREERTOS_PLUS_TCP] PSA_CRYPTO_IMPLEMENTATION: [TF-M] + PASS_LOG_FILE: [corstone320_pass_output] - << : *pipeline_config_corstone315 APP: [keyword-detection, speech-recognition] @@ -613,6 +685,7 @@ gnu-toolchain-test: TOOLCHAIN: [GNU] CONN_STACK: [FREERTOS_PLUS_TCP] PSA_CRYPTO_IMPLEMENTATION: [TF-M] + PASS_LOG_FILE: [corstone315_pass_output] - << : *pipeline_config_corstone315 APP: [object-detection] @@ -621,6 +694,7 @@ gnu-toolchain-test: TOOLCHAIN: [GNU] CONN_STACK: [FREERTOS_PLUS_TCP] PSA_CRYPTO_IMPLEMENTATION: [TF-M] + PASS_LOG_FILE: [corstone315_pass_output] - << : *pipeline_config_corstone310 APP: [keyword-detection, speech-recognition] @@ -629,6 +703,7 @@ gnu-toolchain-test: TOOLCHAIN: [GNU] CONN_STACK: [FREERTOS_PLUS_TCP] PSA_CRYPTO_IMPLEMENTATION: [TF-M] + PASS_LOG_FILE: [corstone310_pass_output] - << : *pipeline_config_corstone300 APP: [keyword-detection, speech-recognition] @@ -637,6 +712,7 @@ gnu-toolchain-test: TOOLCHAIN: [GNU] CONN_STACK: [FREERTOS_PLUS_TCP] PSA_CRYPTO_IMPLEMENTATION: [TF-M] + PASS_LOG_FILE: [corstone300_pass_output] retry: max: 2 when: @@ -675,6 +751,7 @@ iot-vsocket-psa-crypto-mbedtls-test: TOOLCHAIN: [GNU, ARMCLANG] CONN_STACK: [IOT_VSOCKET] PSA_CRYPTO_IMPLEMENTATION: [MBEDTLS] + PASS_LOG_FILE: [corstone320_pass_output] - << : *pipeline_config_corstone315 APP: [keyword-detection, speech-recognition, object-detection] @@ -683,6 +760,7 @@ iot-vsocket-psa-crypto-mbedtls-test: TOOLCHAIN: [GNU, ARMCLANG] CONN_STACK: [IOT_VSOCKET] PSA_CRYPTO_IMPLEMENTATION: [MBEDTLS] + PASS_LOG_FILE: [corstone315_pass_output] - << : *pipeline_config_corstone310 APP: [keyword-detection, speech-recognition] @@ -691,6 +769,7 @@ iot-vsocket-psa-crypto-mbedtls-test: TOOLCHAIN: [GNU, ARMCLANG] CONN_STACK: [IOT_VSOCKET] PSA_CRYPTO_IMPLEMENTATION: [MBEDTLS] + PASS_LOG_FILE: [corstone310_pass_output] - << : *pipeline_config_corstone300 APP: [keyword-detection, speech-recognition] @@ -699,6 +778,77 @@ iot-vsocket-psa-crypto-mbedtls-test: TOOLCHAIN: [GNU, ARMCLANG] CONN_STACK: [IOT_VSOCKET] PSA_CRYPTO_IMPLEMENTATION: [MBEDTLS] + PASS_LOG_FILE: [corstone300_pass_output] + retry: + max: 2 + when: + - script_failure + - stuck_or_timeout_failure + - runner_system_failure + variables: + GIT_SUBMODULE_STRATEGY: recursive + KUBERNETES_CPU_REQUEST: 16 + KUBERNETES_EPHEMERAL_STORAGE_REQUEST: 10Gi + KUBERNETES_MEMORY_REQUEST: 12Gi + +test-keyword-ml-model-update: + tags: + - iotmsw-amd64 + extends: .base-job-rules + rules: + - if: ( $SCHEDULED_JOB_TO_RUN == "test-keyword-ml-model-update" ) + before_script: + - !reference [.build_job, before_script] + - !reference [.build_job, script] + script: + # test_job's `before_script` section is referenced in the `script` section to set the correct value for FVP_BIN variable used in testing. + # test-applications_base job's `script` section is referenced in the `script` section of + # this job to do the testing part after the build stage is done where the build stage is inherited + # from `.build_job` + - !reference [.test_job, before_script] + - !reference [.test-applications_base, script] + parallel: + matrix: + - + << : *pipeline_config_corstone320 + APP: [keyword-detection] + INFERENCE: [ETHOS] + AUDIO: [ROM] + TOOLCHAIN: [GNU] + CONN_STACK: [FREERTOS_PLUS_TCP] + PSA_CRYPTO_IMPLEMENTATION: [TF-M] + SIGNED_UPDATE_BIN_NAME: [keyword-detection-model-update_signed] + PASS_LOG_FILE: [corstone320_model_pass_output] + - + << : *pipeline_config_corstone315 + APP: [keyword-detection] + INFERENCE: [ETHOS] + AUDIO: [ROM] + TOOLCHAIN: [GNU] + CONN_STACK: [FREERTOS_PLUS_TCP] + PSA_CRYPTO_IMPLEMENTATION: [TF-M] + SIGNED_UPDATE_BIN_NAME: [keyword-detection-model-update_signed] + PASS_LOG_FILE: [corstone315_model_pass_output] + - + << : *pipeline_config_corstone310 + APP: [keyword-detection] + INFERENCE: [ETHOS] + AUDIO: [ROM] + TOOLCHAIN: [GNU] + CONN_STACK: [FREERTOS_PLUS_TCP] + PSA_CRYPTO_IMPLEMENTATION: [TF-M] + SIGNED_UPDATE_BIN_NAME: [keyword-detection-model-update_signed] + PASS_LOG_FILE: [corstone310_model_pass_output] + - + << : *pipeline_config_corstone300 + APP: [keyword-detection] + INFERENCE: [ETHOS] + AUDIO: [ROM] + TOOLCHAIN: [GNU] + CONN_STACK: [FREERTOS_PLUS_TCP] + PSA_CRYPTO_IMPLEMENTATION: [TF-M] + SIGNED_UPDATE_BIN_NAME: [keyword-detection-model-update_signed] + PASS_LOG_FILE: [corstone300_model_pass_output] retry: max: 2 when: diff --git a/README.md b/README.md index 7f847226..84cf49f8 100644 --- a/README.md +++ b/README.md @@ -17,6 +17,10 @@ FreeRTOS kernel and libraries based software stack on top of Arm Cortex-M based platforms. All the components are put together in a modular manner to make porting of this integration across platforms easy. +## ML model update + +For details about the ML model update, see [the feature-specific readme file](docs/applications/ml_model_update/ml-model-update.md) + ## Supported Targets Arm Corstone-3xx targets includes an example subsystem based on the Cortex-M diff --git a/applications/blinky/CMakeLists.txt b/applications/blinky/CMakeLists.txt index cae66d90..f860d8ae 100644 --- a/applications/blinky/CMakeLists.txt +++ b/applications/blinky/CMakeLists.txt @@ -1,4 +1,4 @@ -# Copyright 2023-2024 Arm Limited and/or its affiliates +# Copyright 2023-2025 Arm Limited and/or its affiliates # # SPDX-License-Identifier: MIT @@ -10,6 +10,8 @@ set(APPLICATION_PATH "${IOT_REFERENCE_ARM_CORSTONE3XX_SOURCE_DIR}/applications/b set(TFM_CMAKE_APP_ARGS -DPROJECT_CONFIG_HEADER_FILE=${IOT_REFERENCE_ARM_CORSTONE3XX_SOURCE_DIR}/applications/blinky/configs/tfm_config/project_config.h ) +set(MCUBOOT_IMAGE_NUMBER 2 CACHE STRING "Total number of firmware images") +set(DEFAULT_MCUBOOT_FLASH_MAP ON) project(blinky-example LANGUAGES C) @@ -44,9 +46,27 @@ target_link_libraries(blinky set_linker_script(blinky) +list(APPEND CMAKE_MODULE_PATH ${IOT_REFERENCE_ARM_CORSTONE3XX_SOURCE_DIR}/tools/cmake) +include(ConvertElfToBin) +include(ExternalProject) +ExternalProject_Get_Property(trusted_firmware-m-build BINARY_DIR) + +extract_sections_from_axf( + blinky + SECTIONS_NAMES "ddr.bin" + OUTPUT_BIN_NAME "ns_image" +) + # The non-secure application image should be padded while being signed # Hence, passing "TRUE" as the input parameter to the pad option of sign function. -iot_reference_arm_corstone3xx_tf_m_sign_image(blinky blinky_signed 0.0.1 TRUE) +iot_reference_arm_corstone3xx_tf_m_sign_image( + blinky + "ns_image" + blinky_signed + 0.0.1 + "${BINARY_DIR}/api_ns/image_signing/layout_files/signing_layout_ns.o" + TRUE +) # A user project that consumes the ARM FRI needs to explicitly provide # addresses in order to merge images for TF-M. The addresses cannot diff --git a/applications/freertos_iot_libraries_tests/CMakeLists.txt b/applications/freertos_iot_libraries_tests/CMakeLists.txt index 1eb6d105..7e3529ad 100644 --- a/applications/freertos_iot_libraries_tests/CMakeLists.txt +++ b/applications/freertos_iot_libraries_tests/CMakeLists.txt @@ -1,4 +1,4 @@ -# Copyright 2023-2024 Arm Limited and/or its affiliates +# Copyright 2023-2025 Arm Limited and/or its affiliates # # SPDX-License-Identifier: MIT @@ -6,21 +6,9 @@ cmake_minimum_required(VERSION 3.21.0 FATAL_ERROR) set(AWS_OTA_SIGNATURE_TYPE "RSA-3072" CACHE STRING "Supported algorithms for signature validation [RSA-2048, RSA-3072, EC-P256, EC-P384]") -# From: ota-for-aws-iot-embedded-sdk/source/include/ota_appversion32.h -# struct version -# { -# uint8_t major; /*!< @brief Major version number of the firmware (X in firmware version X.Y.Z). */ -# uint8_t minor; /*!< @brief Minor version number of the firmware (Y in firmware version X.Y.Z). */ -# -# uint16_t build; /*!< @brief Build of the firmware (Z in firmware version X.Y.Z). */ -# } x; /*!< @brief Version number of the firmware. */ - -# AWS OTA client does not use the SemVer PATCH version. -# Because of this, if only PATCH version is changed then the OTA will be rejected -# due to same firmware version. -# We will therefore change the build version from TF-M. set(MCUBOOT_IMAGE_VERSION_NS "0.0.1+10") -set(MCUBOOT_IMAGE_VERSION_NS_UPDATE "0.0.1+20") +set(MCUBOOT_IMAGE_NUMBER 2 CACHE STRING "Total number of firmware images") +set(DEFAULT_MCUBOOT_FLASH_MAP ON) set(APPLICATION_PATH "${IOT_REFERENCE_ARM_CORSTONE3XX_SOURCE_DIR}/applications/freertos_iot_libraries_tests" CACHE STRING "Path to the application folder") @@ -54,7 +42,6 @@ list(APPEND CMAKE_MODULE_PATH ${IOT_REFERENCE_ARM_CORSTONE3XX_SOURCE_DIR}/compon list(APPEND CMAKE_MODULE_PATH ${IOT_REFERENCE_ARM_CORSTONE3XX_SOURCE_DIR}/components/security/trusted_firmware-m/integration/cmake) include(SetLinkerOptions) include(AWSIoTHelpers) -include(GenerateAWSUpdateDigestAndSignature) include(MergeTfmImages) include(SignTfmImage) @@ -108,7 +95,6 @@ target_link_libraries(${CMAKE_PROJECT_NAME} freertos-ota-pal-psa fri-bsp helpers-events - ota-update provisioning-lib mbedtls tfm-ns-interface @@ -116,24 +102,27 @@ target_link_libraries(${CMAKE_PROJECT_NAME} set_linker_script(${CMAKE_PROJECT_NAME}) +list(APPEND CMAKE_MODULE_PATH ${IOT_REFERENCE_ARM_CORSTONE3XX_SOURCE_DIR}/tools/cmake) +include(ConvertElfToBin) +include(ExternalProject) +ExternalProject_Get_Property(trusted_firmware-m-build BINARY_DIR) + +extract_sections_from_axf( + ${CMAKE_PROJECT_NAME} + SECTIONS_NAMES "ddr.bin" + OUTPUT_BIN_NAME "ns_image" +) + # The non-secure application image should be padded while being signed iot_reference_arm_corstone3xx_tf_m_sign_image( ${CMAKE_PROJECT_NAME} + "ns_image" ${CMAKE_PROJECT_NAME}_signed ${MCUBOOT_IMAGE_VERSION_NS} + "${BINARY_DIR}/api_ns/image_signing/layout_files/signing_layout_ns.o" TRUE ) -# The update image is not padded to fill the whole slot (no --pad), because -# 1) the image to download is smaller without padding -# 2) the trailer that keeps track of boot and update statuses should not be overwritten -iot_reference_arm_corstone3xx_tf_m_sign_image( - ${CMAKE_PROJECT_NAME} - ${CMAKE_PROJECT_NAME}-update_signed - ${MCUBOOT_IMAGE_VERSION_NS_UPDATE} - FALSE -) - # A user project that consumes the ARM FRI needs to explicitly provide # addresses in order to merge images for TF-M. The addresses cannot # be easily programmatically extracted as they are defined in the linker @@ -143,11 +132,3 @@ iot_reference_arm_corstone3xx_tf_m_merge_images( ${NS_PROVISIONING_BUNDLE_LOAD_ADDRESS} ${CMAKE_BINARY_DIR}/helpers/provisioning/provisioning_data.bin ) - -# Generate the AWS OTA update digest and signature -iot_reference_arm_corstone3xx_generate_aws_update_digest_and_signature( - ${CMAKE_PROJECT_NAME} - ${CMAKE_PROJECT_NAME}-update_signed - update-digest - update-signature -) diff --git a/applications/helpers/ota_orchestrator/CMakeLists.txt b/applications/helpers/ota_orchestrator/CMakeLists.txt index d8f77741..36a213ce 100644 --- a/applications/helpers/ota_orchestrator/CMakeLists.txt +++ b/applications/helpers/ota_orchestrator/CMakeLists.txt @@ -1,4 +1,4 @@ -# Copyright 2024 Arm Limited and/or its affiliates +# Copyright 2024-2025 Arm Limited and/or its affiliates # # SPDX-License-Identifier: MIT @@ -17,6 +17,11 @@ else() inc/ ) + target_compile_definitions(ota-update + PRIVATE + -DMCUBOOT_IMAGE_NUMBER=${MCUBOOT_IMAGE_NUMBER} + ) + target_link_libraries(ota-update PUBLIC jobs-for-aws-iot-embedded-sdk diff --git a/applications/helpers/ota_orchestrator/inc/ota_appversion32.h b/applications/helpers/ota_orchestrator/inc/ota_appversion32.h index 1e7d349b..9a445e4b 100644 --- a/applications/helpers/ota_orchestrator/inc/ota_appversion32.h +++ b/applications/helpers/ota_orchestrator/inc/ota_appversion32.h @@ -1,7 +1,7 @@ /* * AWS IoT Over-the-air Update v3.4.0 * Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved. - * Copyright 2024 Arm Limited and/or its affiliates + * Copyright 2024-2025 Arm Limited and/or its affiliates * * * SPDX-License-Identifier: MIT @@ -77,8 +77,6 @@ typedef struct } u; /*!< @brief Version based on configuration in big endian or little endian. */ } AppVersion32_t; -extern AppVersion32_t appFirmwareVersion; /*!< @brief Making the version number available globally through external linkage. */ - /* *INDENT-OFF* */ #ifdef __cplusplus } diff --git a/applications/helpers/ota_orchestrator/inc/ota_types_definitions.h b/applications/helpers/ota_orchestrator/inc/ota_types_definitions.h index 6db9ae04..c5e1e527 100644 --- a/applications/helpers/ota_orchestrator/inc/ota_types_definitions.h +++ b/applications/helpers/ota_orchestrator/inc/ota_types_definitions.h @@ -1,6 +1,6 @@ /* * Copyright Amazon.com, Inc. and its affiliates. All Rights Reserved. - * Copyright 2023-2024 Arm Limited and/or its affiliates + * Copyright 2023-2025 Arm Limited and/or its affiliates * * * SPDX-License-Identifier: MIT @@ -21,6 +21,7 @@ #include "demo_config.h" #include "MQTTFileDownloader_config.h" +#include "psa/update.h" /** * @brief The maximum time for which OTA demo waits for an MQTT operation to be complete. @@ -149,4 +150,27 @@ typedef struct OtaEventMsg OtaEvent_t eventId; /*!< Identifier for the event. */ } OtaEventMsg_t; +static struct +{ + psa_fwu_component_t id; + char * name; +} +xFwComponents[ FWU_COMPONENT_NUMBER ] = +{ + { + .id = FWU_COMPONENT_ID_SECURE, + .name = "Secure" + }, + { + .id = FWU_COMPONENT_ID_NONSECURE, + .name = "Non-Secure" + } + #if ( MCUBOOT_IMAGE_NUMBER == 3 ) + ,{ + .id = FWU_COMPONENT_ID_ML_MODEL, + .name = "ML Model" + } + #endif +}; + #endif /* OTA_TYPES_DEFINITIONS_H */ diff --git a/applications/helpers/ota_orchestrator/src/ota_orchestrator.c b/applications/helpers/ota_orchestrator/src/ota_orchestrator.c index 8cb91043..5f9c35c5 100644 --- a/applications/helpers/ota_orchestrator/src/ota_orchestrator.c +++ b/applications/helpers/ota_orchestrator/src/ota_orchestrator.c @@ -1,6 +1,6 @@ /* * Copyright Amazon.com, Inc. and its affiliates. All Rights Reserved. - * Copyright 2023-2024 Arm Limited and/or its affiliates + * Copyright 2023-2025 Arm Limited and/or its affiliates * * * SPDX-License-Identifier: MIT @@ -475,6 +475,16 @@ STATIC void sendStatusDetailsMessage( void ) char topicBuffer[ TOPIC_BUFFER_SIZE + 1 ] = { 0 }; size_t topicBufferLength = 0U; char messageBuffer[ UPDATE_JOB_MSG_LENGTH ] = { 0 }; + bool palStatus; + AppVersion32_t version; + + /* Call the platform specific code to get the image version. */ + palStatus = otaPal_GetPlatformImageVersion( &jobFields, &version ); + + if( palStatus != true ) + { + LogError( ( "Error: Couldn't fetch platform image version.\n" ) ); + } /* * AWS IoT Jobs library: @@ -500,14 +510,14 @@ STATIC void sendStatusDetailsMessage( void ) int updatedByBufferLength = snprintf( NULL, 0, "%u", - appFirmwareVersion.u.x.build ); + version.u.signedVersion32 ); char updatedByBuffer[ updatedByBufferLength + 1 ]; ( void ) snprintf( updatedByBuffer, updatedByBufferLength + 1, "%u", - appFirmwareVersion.u.x.build ); + version.u.signedVersion32 ); /* * AWS IoT Jobs library: @@ -810,6 +820,16 @@ STATIC OtaPalJobDocProcessingResult_t receivedJobDocumentHandler( OtaJobEventDat */ char updatedByBuffer[ jobStatusDetails.updatedByLen ]; char * endPtr; + bool palStatus; + AppVersion32_t version; + + /* Call the platform specific code to get the image version. */ + palStatus = otaPal_GetPlatformImageVersion( &jobFields, &version ); + + if( palStatus != true ) + { + LogError( ( "Error: Couldn't fetch platform image version.\n" ) ); + } /* * updatedBy string is not null terminated so copy it to a @@ -825,12 +845,12 @@ STATIC OtaPalJobDocProcessingResult_t receivedJobDocumentHandler( OtaJobEventDat &endPtr, 10 ); - if( updatedByVer < appFirmwareVersion.u.x.build ) + if( updatedByVer < version.u.unsignedVersion32 ) { LogInfo( ( "New image has a higher version number than the current image: " "New image version=%u" ", Previous image version=%u", - appFirmwareVersion.u.x.build, + version.u.unsignedVersion32, updatedByVer ) ); otaPal_SetPlatformImageState( &jobFields, OtaImageStateAccepted ); @@ -1295,17 +1315,27 @@ STATIC BaseType_t prvRunOTADemo( void ) STATIC void vOtaDemoTask( void * pvParam ) { ( void ) pvParam; + AppVersion32_t xComponentVersion; - if( GetImageVersionPSA( FWU_COMPONENT_ID_NONSECURE ) == 0 ) - { - LogInfo( ( "OTA over MQTT, Application version from appFirmwareVersion %u.%u.%u\n", - appFirmwareVersion.u.x.major, - appFirmwareVersion.u.x.minor, - appFirmwareVersion.u.x.build ) ); - } - else + configASSERT( ( sizeof xFwComponents / sizeof xFwComponents[ 0 ] ) == FWU_COMPONENT_NUMBER ); + + LogInfo( ( "OTA over MQTT, firmware versions:" ) ); + + for( size_t i = 0; i < FWU_COMPONENT_NUMBER; ++i ) { - LogError( ( "OTA over MQTT, unable to get application versions" ) ); + int status = GetImageVersionPSA( xFwComponents[ i ].id, &xComponentVersion ); + + if( status == 0 ) + { + LogInfo( ( "%s Component (ID %u) version=%u.%u.%u", + xFwComponents[ i ].name, xFwComponents[ i ].id, + xComponentVersion.u.x.major, xComponentVersion.u.x.minor, xComponentVersion.u.x.build ) ); + } + else + { + LogError( ( "Getting %s Component (ID %u) version failed with %d", + xFwComponents[ i ].name, xFwComponents[ i ].id, status ) ); + } } /* Initialize semaphore for buffer operations. */ diff --git a/applications/keyword_detection/CMakeLists.txt b/applications/keyword_detection/CMakeLists.txt index 3caba1f7..8fedeedc 100644 --- a/applications/keyword_detection/CMakeLists.txt +++ b/applications/keyword_detection/CMakeLists.txt @@ -1,8 +1,9 @@ -# Copyright 2023-2024 Arm Limited and/or its affiliates +# Copyright 2023-2025 Arm Limited and/or its affiliates # # SPDX-License-Identifier: MIT cmake_minimum_required(VERSION 3.21.0 FATAL_ERROR) +project(keyword-detection LANGUAGES C CXX) set(ML_INFERENCE_ENGINE "ETHOS" CACHE STRING "Machine Learning inference engine (ETHOS | SOFTWARE)") set(AUDIO_SOURCE "ROM" CACHE STRING "Source of audio data (ROM | VSI)") @@ -25,6 +26,19 @@ set(AWS_OTA_SIGNATURE_TYPE "RSA-3072" CACHE STRING "Supported algorithms for si set(MCUBOOT_IMAGE_VERSION_NS "0.0.1+10") set(MCUBOOT_IMAGE_VERSION_NS_UPDATE "0.0.1+20") +# These variables are only defined in case of GNU toolchain as it is currently the only toolchain +# that supports the ML Model component OTA update feature where these variables are needed. +if (${CMAKE_C_COMPILER_ID} STREQUAL "GNU") + set(MCUBOOT_IMAGE_VERSION_NS_ML_MODEL "0.0.1+11") + set(MCUBOOT_IMAGE_VERSION_NS_ML_MODEL_UPDATE "0.0.1+42") + set(MCUBOOT_IMAGE_NUMBER 3 CACHE STRING "Total number of firmware images") + set(MCUBOOT_NS_ML_MODEL_IMAGE_FLASH_AREA_NUM "1_0") + set(DEFAULT_MCUBOOT_FLASH_MAP OFF) +else() + set(DEFAULT_MCUBOOT_FLASH_MAP ON) + set(MCUBOOT_IMAGE_NUMBER 2 CACHE STRING "Total number of firmware images") +endif() + if (${ML_INFERENCE_ENGINE} STREQUAL "ETHOS") set(ETHOS_U_NPU_ENABLED ON) set(ETHOS_U_NPU_TIMING_ADAPTER_ENABLED OFF) @@ -43,6 +57,9 @@ set(TFM_CMAKE_APP_ARGS -DMCUBOOT_CONFIRM_IMAGE=${TFM_PLATFORM_CONFIRM_IMAGE} -DMCUBOOT_UPGRADE_STRATEGY=${TFM_PLATFORM_UPGRADE_STRATEGY} -DMCUBOOT_IMAGE_VERSION_NS=${MCUBOOT_IMAGE_VERSION_NS} + -DMCUBOOT_IMAGE_VERSION_NS_ML_MODEL=${MCUBOOT_IMAGE_VERSION_NS_ML_MODEL} + -DMCUBOOT_NS_ML_MODEL_IMAGE_FLASH_AREA_NUM=${MCUBOOT_NS_ML_MODEL_IMAGE_FLASH_AREA_NUM} + -DMCUBOOT_SECURITY_COUNTER_NS_ML_MODEL=1 -DCONFIG_TFM_HALT_ON_CORE_PANIC=ON -DMCUBOOT_DATA_SHARING=ON -DPLATFORM_HAS_FIRMWARE_UPDATE_SUPPORT=ON @@ -50,7 +67,15 @@ set(TFM_CMAKE_APP_ARGS -DTFM_PARTITION_LOG_LEVEL=TFM_PARTITION_LOG_LEVEL_INFO ) -project(keyword-detection LANGUAGES C CXX) +# These definitions are only defined in case of GNU toolchain as it is currently the only toolchain +# that supports the ML Model component OTA update feature where these definitions are needed. +if (${CMAKE_C_COMPILER_ID} STREQUAL "GNU") + list(APPEND TFM_CMAKE_APP_ARGS + -DMCUBOOT_IMAGE_VERSION_NS_ML_MODEL=${MCUBOOT_IMAGE_VERSION_NS_ML_MODEL} + -DMCUBOOT_NS_ML_MODEL_IMAGE_FLASH_AREA_NUM=${MCUBOOT_NS_ML_MODEL_IMAGE_FLASH_AREA_NUM} + -DMCUBOOT_SECURITY_COUNTER_NS_ML_MODEL=1 + ) +endif() # Set global optimization level to reduce code size while keeping the debug experience. if(${CMAKE_C_COMPILER_ID} STREQUAL "GNU") @@ -82,6 +107,17 @@ add_executable(keyword-detection model_config.cc ) +# These definitions are only defined in case of GNU toolchain as it is currently the only toolchain +# that supports the ML Model component OTA update feature where these definitions are needed. +if (${CMAKE_C_COMPILER_ID} STREQUAL "GNU") + target_compile_definitions(keyword-detection + PRIVATE + -DNS_ML_MODEL_IMAGE_LOAD_ADDRESS=${NS_ML_MODEL_IMAGE_LOAD_ADDRESS} + -DNS_ML_MODEL_IMAGE_SIZE=${NS_ML_MODEL_IMAGE_SIZE} + -DNS_ML_MODEL_IMAGE_EXECUTION_ADDRESS=${NS_ML_MODEL_IMAGE_EXECUTION_ADDRESS} + ) +endif() + target_include_directories(keyword-detection PUBLIC ../helpers/provisioning @@ -165,26 +201,74 @@ endif() include(${IOT_REFERENCE_ARM_CORSTONE3XX_SOURCE_DIR}/bsp/cmake/SetLinkerOptions.cmake) set_linker_script(keyword-detection) -# The non-secure application image should be padded while being signed +list(APPEND CMAKE_MODULE_PATH ${IOT_REFERENCE_ARM_CORSTONE3XX_SOURCE_DIR}/tools/cmake) +include(ConvertElfToBin) +include(ExternalProject) +ExternalProject_Get_Property(trusted_firmware-m-build BINARY_DIR) + +# The ML Model is only extracted in case of GNU toolchain as it is currently the only toolchain +# that supports the ML Model component OTA update feature. +if (${CMAKE_C_COMPILER_ID} STREQUAL "GNU") + set(SECTIONS_NAMES "ddr.bin" "model.bin") +else() + set(SECTIONS_NAMES "ddr.bin") +endif() + +extract_sections_from_axf( + keyword-detection + SECTIONS_NAMES ${SECTIONS_NAMES} + OUTPUT_BIN_NAME "ns_image" +) + +# The non-secure application, and ML model images should be padded while being signed # Hence, passing "TRUE" as the input parameter to the pad option of sign function. iot_reference_arm_corstone3xx_tf_m_sign_image( keyword-detection + "ns_image" keyword-detection_signed ${MCUBOOT_IMAGE_VERSION_NS} + "${BINARY_DIR}/api_ns/image_signing/layout_files/signing_layout_ns.o" TRUE ) -# The update image is not padded to fill the whole slot (no --pad), because +# The ML Model image is only signed in case of GNU toolchain as it is currently the only toolchain +# that supports the ML Model component OTA update feature. +if (${CMAKE_C_COMPILER_ID} STREQUAL "GNU") + iot_reference_arm_corstone3xx_tf_m_sign_image( + keyword-detection + "model" + keyword-detection-model_signed + ${MCUBOOT_IMAGE_VERSION_NS_ML_MODEL} + "${BINARY_DIR}/api_ns/image_signing/layout_files/signing_layout_ns_ml_model.o" + TRUE + ) +endif() + +# The non-secure application, and ML model update images are not padded to fill the whole slot (no --pad), because # 1) the image to download is smaller without padding # 2) the trailer that keeps track of boot and update statuses should not be overwritten # Hence, passing "FALSE" as the input parameter for the pad option to the sign function. iot_reference_arm_corstone3xx_tf_m_sign_image( keyword-detection + "ns_image" keyword-detection-update_signed ${MCUBOOT_IMAGE_VERSION_NS_UPDATE} + "${BINARY_DIR}/api_ns/image_signing/layout_files/signing_layout_ns.o" FALSE ) +# The ML Model update image is only extracted in case of GNU toolchain as it is +# currently the only toolchain that supports the ML Model component OTA update feature. +if (${CMAKE_C_COMPILER_ID} STREQUAL "GNU") + iot_reference_arm_corstone3xx_tf_m_sign_image( + keyword-detection + "model" + keyword-detection-model-update_signed + ${MCUBOOT_IMAGE_VERSION_NS_ML_MODEL_UPDATE} + "${BINARY_DIR}/api_ns/image_signing/layout_files/signing_layout_ns_ml_model.o" + FALSE + ) +endif() # A user project that consumes the ARM FIR needs to explicitly provide # addresses in order to merge images for TF-M. The addresses cannot @@ -196,6 +280,8 @@ iot_reference_arm_corstone3xx_tf_m_merge_images( ${CMAKE_BINARY_DIR}/helpers/provisioning/provisioning_data.bin ${NS_DDR4_IMAGE_LOAD_ADDRESS} ${SECTORS_BIN_DIR}/ddr.bin + ${NS_ML_MODEL_IMAGE_LOAD_ADDRESS} + ${CMAKE_BINARY_DIR}/keyword-detection-model_signed.bin ) iot_reference_arm_corstone3xx_generate_aws_update_digest_and_signature( @@ -204,3 +290,14 @@ iot_reference_arm_corstone3xx_generate_aws_update_digest_and_signature( update-digest update-signature ) + +# The AWS update digest and signature are only extracted in case of GNU toolchain as it is +# currently the only toolchain that supports the ML Model component OTA update feature. +if (${CMAKE_C_COMPILER_ID} STREQUAL "GNU") + iot_reference_arm_corstone3xx_generate_aws_update_digest_and_signature( + keyword-detection + keyword-detection-model-update_signed + model-update-digest + model-update-signature + ) +endif() diff --git a/applications/keyword_detection/ml-model-update-demo/faulty_kws_micronet_m.tflite b/applications/keyword_detection/ml-model-update-demo/faulty_kws_micronet_m.tflite new file mode 100644 index 00000000..6915186a Binary files /dev/null and b/applications/keyword_detection/ml-model-update-demo/faulty_kws_micronet_m.tflite differ diff --git a/applications/keyword_detection/ml-model-update-demo/kws_micronet_m.tflite b/applications/keyword_detection/ml-model-update-demo/kws_micronet_m.tflite new file mode 100644 index 00000000..924edd77 Binary files /dev/null and b/applications/keyword_detection/ml-model-update-demo/kws_micronet_m.tflite differ diff --git a/applications/keyword_detection/ml_interface.cc b/applications/keyword_detection/ml_interface.cc index 1bd83d0a..fe6f5de4 100644 --- a/applications/keyword_detection/ml_interface.cc +++ b/applications/keyword_detection/ml_interface.cc @@ -1,4 +1,4 @@ -/* Copyright 2021-2024 Arm Limited and/or its affiliates +/* Copyright 2021-2025 Arm Limited and/or its affiliates * * SPDX-License-Identifier: MIT */ @@ -1061,6 +1061,12 @@ void vMlTask( void * arg ) { ( void ) arg; + #if defined( NS_ML_MODEL_IMAGE_LOAD_ADDRESS ) + /* Copy the entire model from the boot image @ 0x28280000 to execution area in DDR @ 0x60000000. */ + LogInfo( ( "Copying the ML model data from FLASH to DDR memory" ) ); + memcpy( reinterpret_cast( NS_ML_MODEL_IMAGE_EXECUTION_ADDRESS ), reinterpret_cast( NS_ML_MODEL_IMAGE_LOAD_ADDRESS ), static_cast( NS_ML_MODEL_IMAGE_SIZE ) ); + #endif + EventBits_t flags = xEventGroupWaitBits( xSystemEvents, ( EventBits_t ) EVENT_MASK_ML_START, pdTRUE, pdFAIL, portMAX_DELAY ); if( flags & EVENT_MASK_ML_START ) diff --git a/applications/keyword_detection/tests/corstone300_model_pass_output.log b/applications/keyword_detection/tests/corstone300_model_pass_output.log new file mode 100644 index 00000000..83512f37 --- /dev/null +++ b/applications/keyword_detection/tests/corstone300_model_pass_output.log @@ -0,0 +1,18 @@ +Waiting for provisioning bundle +Running provisioning bundle +Secure Component (ID 0) version=2.1.0 +Non-Secure Component (ID 1) version=0.0.10 +ML Model Component (ID 2) version=0.0.11 +Starting bootloader +Booting TF-M v2.1.0 +PSA Framework version is: 257 +Secure Component (ID 0) version=2.1.0 +Non-Secure Component (ID 1) version=0.0.10 +ML Model Component (ID 2) version=0.0.42 +ML interface initialised +ML_HEARD_ON +ML UNKNOWN +ML_HEARD_OFF +ML UNKNOWN +ML_HEARD_GO +ML UNKNOWN diff --git a/applications/keyword_detection/tests/corstone300_pass_output.log b/applications/keyword_detection/tests/corstone300_pass_output.log index 3230c094..efec65fa 100644 --- a/applications/keyword_detection/tests/corstone300_pass_output.log +++ b/applications/keyword_detection/tests/corstone300_pass_output.log @@ -1,10 +1,12 @@ Waiting for provisioning bundle Running provisioning bundle -Application version from appFirmwareVersion 0.0.10 +Secure Component (ID 0) version=2.1.0 +Non-Secure Component (ID 1) version=0.0.10 Starting bootloader Booting TF-M v2.1.0 PSA Framework version is: 257 -Application version from appFirmwareVersion 0.0.20 +Secure Component (ID 0) version=2.1.0 +Non-Secure Component (ID 1) version=0.0.20 ML interface initialised ML_HEARD_ON ML UNKNOWN diff --git a/applications/keyword_detection/tests/corstone310_model_pass_output.log b/applications/keyword_detection/tests/corstone310_model_pass_output.log new file mode 100644 index 00000000..83512f37 --- /dev/null +++ b/applications/keyword_detection/tests/corstone310_model_pass_output.log @@ -0,0 +1,18 @@ +Waiting for provisioning bundle +Running provisioning bundle +Secure Component (ID 0) version=2.1.0 +Non-Secure Component (ID 1) version=0.0.10 +ML Model Component (ID 2) version=0.0.11 +Starting bootloader +Booting TF-M v2.1.0 +PSA Framework version is: 257 +Secure Component (ID 0) version=2.1.0 +Non-Secure Component (ID 1) version=0.0.10 +ML Model Component (ID 2) version=0.0.42 +ML interface initialised +ML_HEARD_ON +ML UNKNOWN +ML_HEARD_OFF +ML UNKNOWN +ML_HEARD_GO +ML UNKNOWN diff --git a/applications/keyword_detection/tests/corstone310_pass_output.log b/applications/keyword_detection/tests/corstone310_pass_output.log index 3230c094..efec65fa 100644 --- a/applications/keyword_detection/tests/corstone310_pass_output.log +++ b/applications/keyword_detection/tests/corstone310_pass_output.log @@ -1,10 +1,12 @@ Waiting for provisioning bundle Running provisioning bundle -Application version from appFirmwareVersion 0.0.10 +Secure Component (ID 0) version=2.1.0 +Non-Secure Component (ID 1) version=0.0.10 Starting bootloader Booting TF-M v2.1.0 PSA Framework version is: 257 -Application version from appFirmwareVersion 0.0.20 +Secure Component (ID 0) version=2.1.0 +Non-Secure Component (ID 1) version=0.0.20 ML interface initialised ML_HEARD_ON ML UNKNOWN diff --git a/applications/keyword_detection/tests/corstone315_model_pass_output.log b/applications/keyword_detection/tests/corstone315_model_pass_output.log new file mode 100644 index 00000000..b71ac69e --- /dev/null +++ b/applications/keyword_detection/tests/corstone315_model_pass_output.log @@ -0,0 +1,18 @@ +Waiting for DM provisioning bundle +Running DM provisioning bundle +Secure Component (ID 0) version=2.1.0 +Non-Secure Component (ID 1) version=0.0.10 +ML Model Component (ID 2) version=0.0.11 +Starting bootloader +Booting TF-M v2.1.0 +PSA Framework version is: 257 +Secure Component (ID 0) version=2.1.0 +Non-Secure Component (ID 1) version=0.0.10 +ML Model Component (ID 2) version=0.0.42 +ML interface initialised +ML_HEARD_ON +ML UNKNOWN +ML_HEARD_OFF +ML UNKNOWN +ML_HEARD_GO +ML UNKNOWN diff --git a/applications/keyword_detection/tests/corstone315_pass_output.log b/applications/keyword_detection/tests/corstone315_pass_output.log index 5f8021b2..07ea45ea 100644 --- a/applications/keyword_detection/tests/corstone315_pass_output.log +++ b/applications/keyword_detection/tests/corstone315_pass_output.log @@ -1,10 +1,12 @@ Waiting for DM provisioning bundle Running DM provisioning bundle -Application version from appFirmwareVersion 0.0.10 +Secure Component (ID 0) version=2.1.0 +Non-Secure Component (ID 1) version=0.0.10 Starting bootloader Booting TF-M v2.1.0 PSA Framework version is: 257 -Application version from appFirmwareVersion 0.0.20 +Secure Component (ID 0) version=2.1.0 +Non-Secure Component (ID 1) version=0.0.20 ML interface initialised ML_HEARD_ON ML UNKNOWN diff --git a/applications/keyword_detection/tests/corstone320_model_pass_output.log b/applications/keyword_detection/tests/corstone320_model_pass_output.log new file mode 100644 index 00000000..b71ac69e --- /dev/null +++ b/applications/keyword_detection/tests/corstone320_model_pass_output.log @@ -0,0 +1,18 @@ +Waiting for DM provisioning bundle +Running DM provisioning bundle +Secure Component (ID 0) version=2.1.0 +Non-Secure Component (ID 1) version=0.0.10 +ML Model Component (ID 2) version=0.0.11 +Starting bootloader +Booting TF-M v2.1.0 +PSA Framework version is: 257 +Secure Component (ID 0) version=2.1.0 +Non-Secure Component (ID 1) version=0.0.10 +ML Model Component (ID 2) version=0.0.42 +ML interface initialised +ML_HEARD_ON +ML UNKNOWN +ML_HEARD_OFF +ML UNKNOWN +ML_HEARD_GO +ML UNKNOWN diff --git a/applications/keyword_detection/tests/corstone320_pass_output.log b/applications/keyword_detection/tests/corstone320_pass_output.log index 5f8021b2..07ea45ea 100644 --- a/applications/keyword_detection/tests/corstone320_pass_output.log +++ b/applications/keyword_detection/tests/corstone320_pass_output.log @@ -1,10 +1,12 @@ Waiting for DM provisioning bundle Running DM provisioning bundle -Application version from appFirmwareVersion 0.0.10 +Secure Component (ID 0) version=2.1.0 +Non-Secure Component (ID 1) version=0.0.10 Starting bootloader Booting TF-M v2.1.0 PSA Framework version is: 257 -Application version from appFirmwareVersion 0.0.20 +Secure Component (ID 0) version=2.1.0 +Non-Secure Component (ID 1) version=0.0.20 ML interface initialised ML_HEARD_ON ML UNKNOWN diff --git a/applications/object_detection/CMakeLists.txt b/applications/object_detection/CMakeLists.txt index 5bb03ace..82a271f8 100644 --- a/applications/object_detection/CMakeLists.txt +++ b/applications/object_detection/CMakeLists.txt @@ -1,4 +1,4 @@ -# Copyright 2023-2024 Arm Limited and/or its affiliates +# Copyright 2023-2025 Arm Limited and/or its affiliates # # SPDX-License-Identifier: MIT @@ -24,6 +24,8 @@ set(AWS_OTA_SIGNATURE_TYPE "RSA-3072" CACHE STRING "Supported algorithms for si # We will therefore change the build version from TF-M. set(MCUBOOT_IMAGE_VERSION_NS "0.0.1+10") set(MCUBOOT_IMAGE_VERSION_NS_UPDATE "0.0.1+20") +set(MCUBOOT_IMAGE_NUMBER 2 CACHE STRING "Total number of firmware images") +set(DEFAULT_MCUBOOT_FLASH_MAP ON) if (${ML_INFERENCE_ENGINE} STREQUAL "ETHOS") set(ETHOS_U_NPU_ENABLED ON) @@ -140,12 +142,25 @@ target_link_libraries(object-detection include(${IOT_REFERENCE_ARM_CORSTONE3XX_SOURCE_DIR}/bsp/cmake/SetLinkerOptions.cmake) set_linker_script(object-detection) +list(APPEND CMAKE_MODULE_PATH ${IOT_REFERENCE_ARM_CORSTONE3XX_SOURCE_DIR}/tools/cmake) +include(ConvertElfToBin) +include(ExternalProject) +ExternalProject_Get_Property(trusted_firmware-m-build BINARY_DIR) + +extract_sections_from_axf( + object-detection + SECTIONS_NAMES "ddr.bin" + OUTPUT_BIN_NAME "ns_image" +) + # The non-secure application image should be padded while being signed # Hence, passing "TRUE" as the input parameter to the pad option of sign function. iot_reference_arm_corstone3xx_tf_m_sign_image( object-detection + "ns_image" object-detection_signed ${MCUBOOT_IMAGE_VERSION_NS} + "${BINARY_DIR}/api_ns/image_signing/layout_files/signing_layout_ns.o" TRUE ) @@ -155,8 +170,10 @@ iot_reference_arm_corstone3xx_tf_m_sign_image( # Hence, passing "FALSE" as the input parameter for the pad option to the sign function. iot_reference_arm_corstone3xx_tf_m_sign_image( object-detection + "ns_image" object-detection-update_signed ${MCUBOOT_IMAGE_VERSION_NS_UPDATE} + "${BINARY_DIR}/api_ns/image_signing/layout_files/signing_layout_ns.o" FALSE ) diff --git a/applications/object_detection/tests/corstone300_pass_output.log b/applications/object_detection/tests/corstone300_pass_output.log index 2a39f0a9..b1c3f71d 100644 --- a/applications/object_detection/tests/corstone300_pass_output.log +++ b/applications/object_detection/tests/corstone300_pass_output.log @@ -1,10 +1,12 @@ Waiting for provisioning bundle Running provisioning bundle -Application version from appFirmwareVersion 0.0.10 +Secure Component (ID 0) version=2.1.0 +Non-Secure Component (ID 1) version=0.0.10 Starting bootloader Booting TF-M v2.1.0 PSA Framework version is: 257 -Application version from appFirmwareVersion 0.0.20 +Secure Component (ID 0) version=2.1.0 +Non-Secure Component (ID 1) version=0.0.20 Complete recognition: Detected faces: 2 Complete recognition: Detected faces: 2 Complete recognition: Detected faces: 2 diff --git a/applications/object_detection/tests/corstone310_pass_output.log b/applications/object_detection/tests/corstone310_pass_output.log index 2a39f0a9..b1c3f71d 100644 --- a/applications/object_detection/tests/corstone310_pass_output.log +++ b/applications/object_detection/tests/corstone310_pass_output.log @@ -1,10 +1,12 @@ Waiting for provisioning bundle Running provisioning bundle -Application version from appFirmwareVersion 0.0.10 +Secure Component (ID 0) version=2.1.0 +Non-Secure Component (ID 1) version=0.0.10 Starting bootloader Booting TF-M v2.1.0 PSA Framework version is: 257 -Application version from appFirmwareVersion 0.0.20 +Secure Component (ID 0) version=2.1.0 +Non-Secure Component (ID 1) version=0.0.20 Complete recognition: Detected faces: 2 Complete recognition: Detected faces: 2 Complete recognition: Detected faces: 2 diff --git a/applications/object_detection/tests/corstone315_pass_output.log b/applications/object_detection/tests/corstone315_pass_output.log index f4e53709..7e8fe031 100644 --- a/applications/object_detection/tests/corstone315_pass_output.log +++ b/applications/object_detection/tests/corstone315_pass_output.log @@ -1,10 +1,12 @@ Waiting for DM provisioning bundle Running DM provisioning bundle -Application version from appFirmwareVersion 0.0.10 +Secure Component (ID 0) version=2.1.0 +Non-Secure Component (ID 1) version=0.0.10 Starting bootloader Booting TF-M v2.1.0 PSA Framework version is: 257 -Application version from appFirmwareVersion 0.0.20 +Secure Component (ID 0) version=2.1.0 +Non-Secure Component (ID 1) version=0.0.20 Complete recognition: Detected faces: 2 Complete recognition: Detected faces: 2 Complete recognition: Detected faces: 2 diff --git a/applications/object_detection/tests/corstone320_pass_output.log b/applications/object_detection/tests/corstone320_pass_output.log index f4e53709..7e8fe031 100644 --- a/applications/object_detection/tests/corstone320_pass_output.log +++ b/applications/object_detection/tests/corstone320_pass_output.log @@ -1,10 +1,12 @@ Waiting for DM provisioning bundle Running DM provisioning bundle -Application version from appFirmwareVersion 0.0.10 +Secure Component (ID 0) version=2.1.0 +Non-Secure Component (ID 1) version=0.0.10 Starting bootloader Booting TF-M v2.1.0 PSA Framework version is: 257 -Application version from appFirmwareVersion 0.0.20 +Secure Component (ID 0) version=2.1.0 +Non-Secure Component (ID 1) version=0.0.20 Complete recognition: Detected faces: 2 Complete recognition: Detected faces: 2 Complete recognition: Detected faces: 2 diff --git a/applications/speech_recognition/CMakeLists.txt b/applications/speech_recognition/CMakeLists.txt index 0ab79754..9ed0546c 100644 --- a/applications/speech_recognition/CMakeLists.txt +++ b/applications/speech_recognition/CMakeLists.txt @@ -1,4 +1,4 @@ -# Copyright 2023-2024 Arm Limited and/or its affiliates +# Copyright 2023-2025 Arm Limited and/or its affiliates # # SPDX-License-Identifier: MIT @@ -24,6 +24,8 @@ set(AWS_OTA_SIGNATURE_TYPE "RSA-3072" CACHE STRING "Supported algorithms for si # We will therefore change the build version from TF-M. set(MCUBOOT_IMAGE_VERSION_NS "0.0.1+10") set(MCUBOOT_IMAGE_VERSION_NS_UPDATE "0.0.1+20") +set(MCUBOOT_IMAGE_NUMBER 2 CACHE STRING "Total number of firmware images") +set(DEFAULT_MCUBOOT_FLASH_MAP ON) if (${ML_INFERENCE_ENGINE} STREQUAL "ETHOS") set(ETHOS_U_NPU_ENABLED ON) @@ -167,12 +169,25 @@ target_link_libraries(speech-recognition include(${IOT_REFERENCE_ARM_CORSTONE3XX_SOURCE_DIR}/bsp/cmake/SetLinkerOptions.cmake) set_linker_script(speech-recognition) +list(APPEND CMAKE_MODULE_PATH ${IOT_REFERENCE_ARM_CORSTONE3XX_SOURCE_DIR}/tools/cmake) +include(ConvertElfToBin) +include(ExternalProject) +ExternalProject_Get_Property(trusted_firmware-m-build BINARY_DIR) + +extract_sections_from_axf( + speech-recognition + SECTIONS_NAMES "ddr.bin" + OUTPUT_BIN_NAME "ns_image" +) + # The non-secure application image should be padded while being signed # Hence, passing "TRUE" as the input parameter to the pad option of sign function. iot_reference_arm_corstone3xx_tf_m_sign_image( speech-recognition + "ns_image" speech-recognition_signed ${MCUBOOT_IMAGE_VERSION_NS} + "${BINARY_DIR}/api_ns/image_signing/layout_files/signing_layout_ns.o" TRUE ) @@ -182,8 +197,10 @@ iot_reference_arm_corstone3xx_tf_m_sign_image( # Hence, passing "FALSE" as the input parameter for the pad option to the sign function. iot_reference_arm_corstone3xx_tf_m_sign_image( speech-recognition + "ns_image" speech-recognition-update_signed ${MCUBOOT_IMAGE_VERSION_NS_UPDATE} + "${BINARY_DIR}/api_ns/image_signing/layout_files/signing_layout_ns.o" FALSE ) diff --git a/applications/speech_recognition/tests/corstone300_pass_output.log b/applications/speech_recognition/tests/corstone300_pass_output.log index bea8cc05..3788b1c5 100644 --- a/applications/speech_recognition/tests/corstone300_pass_output.log +++ b/applications/speech_recognition/tests/corstone300_pass_output.log @@ -1,10 +1,12 @@ Waiting for provisioning bundle Running provisioning bundle -Application version from appFirmwareVersion 0.0.10 +Secure Component (ID 0) version=2.1.0 +Non-Secure Component (ID 1) version=0.0.10 Starting bootloader Booting TF-M v2.1.0 PSA Framework version is: 257 -Application version from appFirmwareVersion 0.0.20 +Secure Component (ID 0) version=2.1.0 +Non-Secure Component (ID 1) version=0.0.20 Init speex ML interface initialised Complete recognition: turn down the temperature in the bedroom diff --git a/applications/speech_recognition/tests/corstone310_pass_output.log b/applications/speech_recognition/tests/corstone310_pass_output.log index bea8cc05..3788b1c5 100644 --- a/applications/speech_recognition/tests/corstone310_pass_output.log +++ b/applications/speech_recognition/tests/corstone310_pass_output.log @@ -1,10 +1,12 @@ Waiting for provisioning bundle Running provisioning bundle -Application version from appFirmwareVersion 0.0.10 +Secure Component (ID 0) version=2.1.0 +Non-Secure Component (ID 1) version=0.0.10 Starting bootloader Booting TF-M v2.1.0 PSA Framework version is: 257 -Application version from appFirmwareVersion 0.0.20 +Secure Component (ID 0) version=2.1.0 +Non-Secure Component (ID 1) version=0.0.20 Init speex ML interface initialised Complete recognition: turn down the temperature in the bedroom diff --git a/applications/speech_recognition/tests/corstone315_pass_output.log b/applications/speech_recognition/tests/corstone315_pass_output.log index 7ff46e8e..cb995a04 100644 --- a/applications/speech_recognition/tests/corstone315_pass_output.log +++ b/applications/speech_recognition/tests/corstone315_pass_output.log @@ -1,10 +1,12 @@ Waiting for DM provisioning bundle Running DM provisioning bundle -Application version from appFirmwareVersion 0.0.10 +Secure Component (ID 0) version=2.1.0 +Non-Secure Component (ID 1) version=0.0.10 Starting bootloader Booting TF-M v2.1.0 PSA Framework version is: 257 -Application version from appFirmwareVersion 0.0.20 +Secure Component (ID 0) version=2.1.0 +Non-Secure Component (ID 1) version=0.0.20 Init speex ML interface initialised Complete recognition: turn down the temperature in the bedroom diff --git a/applications/speech_recognition/tests/corstone320_pass_output.log b/applications/speech_recognition/tests/corstone320_pass_output.log index 7ff46e8e..cb995a04 100644 --- a/applications/speech_recognition/tests/corstone320_pass_output.log +++ b/applications/speech_recognition/tests/corstone320_pass_output.log @@ -1,10 +1,12 @@ Waiting for DM provisioning bundle Running DM provisioning bundle -Application version from appFirmwareVersion 0.0.10 +Secure Component (ID 0) version=2.1.0 +Non-Secure Component (ID 1) version=0.0.10 Starting bootloader Booting TF-M v2.1.0 PSA Framework version is: 257 -Application version from appFirmwareVersion 0.0.20 +Secure Component (ID 0) version=2.1.0 +Non-Secure Component (ID 1) version=0.0.20 Init speex ML interface initialised Complete recognition: turn down the temperature in the bedroom diff --git a/bsp/CMakeLists.txt b/bsp/CMakeLists.txt index eb101ada..574fa268 100644 --- a/bsp/CMakeLists.txt +++ b/bsp/CMakeLists.txt @@ -1,4 +1,4 @@ -# Copyright 2023-2024 Arm Limited and/or its affiliates +# Copyright 2023-2025 Arm Limited and/or its affiliates # # SPDX-License-Identifier: Apache-2.0 @@ -45,14 +45,25 @@ target_compile_definitions(arm-corstone-platform-bsp if(ARM_CORSTONE_BSP_TARGET_PLATFORM STREQUAL "corstone300") set(TFM_PLATFORM_LOCAL_PATH "arm/mps3/corstone300/fvp" CACHE STRING "TFM Platform local path") set(TFM_FLASH_S_PARTITION_SIZE "0x40000") - set(TFM_FLASH_NS_PARTITION_SIZE "0x340000") - + # These variables are only defined in case of building keyword_detection application with GNU toolchain + # as it is currently the only application that utilises the ML Model component OTA update feature + # where these variables are needed. + if((${APPLICATION_PATH} MATCHES ".*keyword_detection") AND (${CMAKE_C_COMPILER_ID} STREQUAL "GNU")) + set(TFM_FLASH_NS_PARTITION_SIZE "0x240000") + set(TFM_FLASH_NS_ML_MODEL_PARTITION_SIZE "0x100000") + set(NS_DDR4_IMAGE_LOAD_ADDRESS 0x60100000 CACHE STRING "Non-Secure Double Data Rate RAM image loading address") + set(NS_ML_MODEL_IMAGE_LOAD_ADDRESS 0x28280000 CACHE STRING "Non-Secure ML model image loading address") + set(NS_ML_MODEL_IMAGE_EXECUTION_ADDRESS 0x60000000 CACHE STRING "Non-Secure ML model image runtime address") + set(NS_ML_MODEL_IMAGE_SIZE 0x100000 CACHE STRING "Non-Secure ML model image size") + else() + set(TFM_FLASH_NS_PARTITION_SIZE "0x340000") + set(NS_DDR4_IMAGE_LOAD_ADDRESS 0x60000000 CACHE STRING "Non-Secure Double Data Rate RAM image loading address") + endif() set(BL2_IMAGE_LOAD_ADDRESS 0x00000000 CACHE STRING "Bootload image loading address") set(S_IMAGE_LOAD_ADDRESS 0x38000000 CACHE STRING "Secure TF-M firmware loading address") set(NS_IMAGE_LOAD_ADDRESS 0x28040000 CACHE STRING "Non-secure user application loading address") set(S_PROVISIONING_BUNDLE_LOAD_ADDRESS 0x10022000 CACHE STRING "Secure provisioning bundle loading address") set(NS_PROVISIONING_BUNDLE_LOAD_ADDRESS 0x211FF000 CACHE STRING "Non-Secure provisioning bundle loading address") - set(NS_DDR4_IMAGE_LOAD_ADDRESS 0x60000000 CACHE STRING "Non-Secure Double Data Rate RAM image loading address") set(ETHOS_U_BASE_ADDR "0x48102000" CACHE STRING "Ethos-U NPU base address" FORCE) set(ETHOS_U_IRQN "56" CACHE STRING "Ethos-U NPU Interrupt" FORCE) @@ -73,14 +84,26 @@ if(ARM_CORSTONE_BSP_TARGET_PLATFORM STREQUAL "corstone300") elseif(ARM_CORSTONE_BSP_TARGET_PLATFORM STREQUAL "corstone310") set(TFM_PLATFORM_LOCAL_PATH "arm/mps3/corstone310/fvp" CACHE STRING "TFM Platform local path") set(TFM_FLASH_S_PARTITION_SIZE "0x40000") - set(TFM_FLASH_NS_PARTITION_SIZE "0x340000") + # These variables are only defined in case of building keyword_detection application with GNU toolchain + # as it is currently the only application that utilises the ML Model component OTA update feature + # where these variables are needed. + if((${APPLICATION_PATH} MATCHES ".*keyword_detection") AND (${CMAKE_C_COMPILER_ID} STREQUAL "GNU")) + set(TFM_FLASH_NS_PARTITION_SIZE "0x240000") + set(TFM_FLASH_NS_ML_MODEL_PARTITION_SIZE "0x100000") + set(NS_DDR4_IMAGE_LOAD_ADDRESS 0x60100000 CACHE STRING "Non-Secure Double Data Rate RAM image loading address") + set(NS_ML_MODEL_IMAGE_LOAD_ADDRESS 0x28280000 CACHE STRING "Non-Secure ML model image loading address") + set(NS_ML_MODEL_IMAGE_EXECUTION_ADDRESS 0x60000000 CACHE STRING "Non-Secure ML model image runtime address") + set(NS_ML_MODEL_IMAGE_SIZE 0x100000 CACHE STRING "Non-Secure ML model image size") + else() + set(TFM_FLASH_NS_PARTITION_SIZE "0x340000") + set(NS_DDR4_IMAGE_LOAD_ADDRESS 0x60000000 CACHE STRING "Non-Secure Double Data Rate RAM image loading address") + endif() set(BL2_IMAGE_LOAD_ADDRESS 0x11000000 CACHE STRING "Bootload image loading address") set(S_IMAGE_LOAD_ADDRESS 0x38000000 CACHE STRING "Secure TF-M firmware loading address") set(NS_IMAGE_LOAD_ADDRESS 0x28040000 CACHE STRING "Non-secure user application loading address") set(S_PROVISIONING_BUNDLE_LOAD_ADDRESS 0x11022000 CACHE STRING "Secure provisioning bundle loading address") set(NS_PROVISIONING_BUNDLE_LOAD_ADDRESS 0x213FF000 CACHE STRING "Non-Secure provisioning bundle loading address") - set(NS_DDR4_IMAGE_LOAD_ADDRESS 0x60000000 CACHE STRING "Non-Secure Double Data Rate RAM image loading address") set(ETHOS_U_BASE_ADDR "0x40004000" CACHE STRING "Ethos-U NPU base address" FORCE) set(ETHOS_U_IRQN "16" CACHE STRING "Ethos-U NPU Interrupt" FORCE) @@ -101,7 +124,20 @@ elseif(ARM_CORSTONE_BSP_TARGET_PLATFORM STREQUAL "corstone310") elseif(ARM_CORSTONE_BSP_TARGET_PLATFORM STREQUAL "corstone315") set(TFM_PLATFORM_LOCAL_PATH "arm/mps4/corstone315" CACHE STRING "TFM Platform local path") set(TFM_FLASH_S_PARTITION_SIZE "0x40000") - set(TFM_FLASH_NS_PARTITION_SIZE "0x340000") + # These variables are only defined in case of building keyword_detection application with GNU toolchain + # as it is currently the only application that utilises the ML Model component OTA update feature + # where these variables are needed. + if((${APPLICATION_PATH} MATCHES ".*keyword_detection") AND (${CMAKE_C_COMPILER_ID} STREQUAL "GNU")) + set(TFM_FLASH_NS_PARTITION_SIZE "0x240000") + set(TFM_FLASH_NS_ML_MODEL_PARTITION_SIZE "0x100000") + set(NS_DDR4_IMAGE_LOAD_ADDRESS 0x60100000 CACHE STRING "Non-Secure Double Data Rate RAM image loading address") + set(NS_ML_MODEL_IMAGE_LOAD_ADDRESS 0x28280000 CACHE STRING "Non-Secure ML model image loading address") + set(NS_ML_MODEL_IMAGE_EXECUTION_ADDRESS 0x60000000 CACHE STRING "Non-Secure ML model image runtime address") + set(NS_ML_MODEL_IMAGE_SIZE 0x100000 CACHE STRING "Non-Secure ML model image size") + else() + set(TFM_FLASH_NS_PARTITION_SIZE "0x340000") + set(NS_DDR4_IMAGE_LOAD_ADDRESS 0x60000000 CACHE STRING "Non-Secure Double Data Rate RAM image loading address") + endif() set(BL1_IMAGE_LOAD_ADDRESS 0x11000000 CACHE STRING "Bootload stage 1 image loading address") set(BL2_IMAGE_LOAD_ADDRESS 0x12031400 CACHE STRING "Bootload image loading address") @@ -110,7 +146,6 @@ elseif(ARM_CORSTONE_BSP_TARGET_PLATFORM STREQUAL "corstone315") set(S_CM_PROVISIONING_BUNDLE_LOAD_ADDRESS 0x12024000 CACHE STRING "Secure CM provisioning bundle loading address") set(S_DM_PROVISIONING_BUNDLE_LOAD_ADDRESS 0x1202aa00 CACHE STRING "Secure DM provisioning bundle loading address") set(NS_PROVISIONING_BUNDLE_LOAD_ADDRESS 0x213FF000 CACHE STRING "Non-Secure provisioning bundle loading address") - set(NS_DDR4_IMAGE_LOAD_ADDRESS 0x60000000 CACHE STRING "Non-Secure Double Data Rate RAM image loading address") set(ETHOS_U_BASE_ADDR "0x40004000" CACHE STRING "Ethos-U NPU base address" FORCE) set(ETHOS_U_IRQN "16" CACHE STRING "Ethos-U NPU Interrupt" FORCE) @@ -133,7 +168,20 @@ elseif(ARM_CORSTONE_BSP_TARGET_PLATFORM STREQUAL "corstone315") elseif(ARM_CORSTONE_BSP_TARGET_PLATFORM STREQUAL "corstone320") set(TFM_PLATFORM_LOCAL_PATH "arm/mps4/corstone320" CACHE STRING "TFM Platform local path") set(TFM_FLASH_S_PARTITION_SIZE "0x40000") - set(TFM_FLASH_NS_PARTITION_SIZE "0x340000") + # These variables are only defined in case of building keyword_detection application with GNU toolchain + # as it is currently the only application that utilises the ML Model component OTA update feature + # where these variables are needed. + if((${APPLICATION_PATH} MATCHES ".*keyword_detection") AND (${CMAKE_C_COMPILER_ID} STREQUAL "GNU")) + set(TFM_FLASH_NS_PARTITION_SIZE "0x240000") + set(TFM_FLASH_NS_ML_MODEL_PARTITION_SIZE "0x100000") + set(NS_DDR4_IMAGE_LOAD_ADDRESS 0x60100000 CACHE STRING "Non-Secure Double Data Rate RAM image loading address") + set(NS_ML_MODEL_IMAGE_LOAD_ADDRESS 0x28280000 CACHE STRING "Non-Secure ML model image loading address") + set(NS_ML_MODEL_IMAGE_EXECUTION_ADDRESS 0x60000000 CACHE STRING "Non-Secure ML model image runtime address") + set(NS_ML_MODEL_IMAGE_SIZE 0x100000 CACHE STRING "Non-Secure ML model image size") + else() + set(TFM_FLASH_NS_PARTITION_SIZE "0x340000") + set(NS_DDR4_IMAGE_LOAD_ADDRESS 0x60000000 CACHE STRING "Non-Secure Double Data Rate RAM image loading address") + endif() set(BL1_IMAGE_LOAD_ADDRESS 0x11000000 CACHE STRING "Bootload stage 1 image loading address") set(BL2_IMAGE_LOAD_ADDRESS 0x12031400 CACHE STRING "Bootload image loading address") @@ -142,7 +190,6 @@ elseif(ARM_CORSTONE_BSP_TARGET_PLATFORM STREQUAL "corstone320") set(S_CM_PROVISIONING_BUNDLE_LOAD_ADDRESS 0x12024000 CACHE STRING "Secure CM provisioning bundle loading address") set(S_DM_PROVISIONING_BUNDLE_LOAD_ADDRESS 0x1202aa00 CACHE STRING "Secure DM provisioning bundle loading address") set(NS_PROVISIONING_BUNDLE_LOAD_ADDRESS 0x213FF000 CACHE STRING "Non-Secure provisioning bundle loading address") - set(NS_DDR4_IMAGE_LOAD_ADDRESS 0x60000000 CACHE STRING "Non-Secure Double Data Rate RAM image loading address") set(ETHOS_U_BASE_ADDR "0x40004000" CACHE STRING "Ethos-U NPU base address" FORCE) set(ETHOS_U_IRQN "16" CACHE STRING "Ethos-U NPU Interrupt" FORCE) @@ -196,10 +243,21 @@ set(ARM_CORSTONE_BSP_TARGET_PLATFORM_TFM_CMAKE_ARGS -DTFM_PLATFORM=${TFM_PLATFORM_LOCAL_PATH} -DFLASH_S_PARTITION_SIZE=${TFM_FLASH_S_PARTITION_SIZE} -DFLASH_NS_PARTITION_SIZE=${TFM_FLASH_NS_PARTITION_SIZE} + -DMCUBOOT_IMAGE_NUMBER=${MCUBOOT_IMAGE_NUMBER} + -DDEFAULT_MCUBOOT_FLASH_MAP=${DEFAULT_MCUBOOT_FLASH_MAP} ${TFM_CMAKE_APP_ARGS} CACHE STRING "TFM CMake arguments" FORCE ) +# This variable is only defined in case of building keyword_detection application with GNU toolchain +# as it is currently the only application that utilises the ML Model component OTA update feature +# where this variable is needed. +if((${APPLICATION_PATH} MATCHES ".*keyword_detection") AND (${CMAKE_C_COMPILER_ID} STREQUAL "GNU")) + list(APPEND ARM_CORSTONE_BSP_TARGET_PLATFORM_TFM_CMAKE_ARGS + -DFLASH_NS_ML_MODEL_PARTITION_SIZE=${TFM_FLASH_NS_ML_MODEL_PARTITION_SIZE} + ) +endif() + if(${CMAKE_C_COMPILER_ID} STREQUAL "GNU") # Execute the command as CMAKE_C_COMPILER_VERSION is not guaranteed to be defined. EXECUTE_PROCESS( COMMAND ${CMAKE_C_COMPILER} -dumpversion OUTPUT_VARIABLE ARM_GNU_TOOLCHAIN_VERSION ) diff --git a/bsp/cmake/SetLinkerOptions.cmake b/bsp/cmake/SetLinkerOptions.cmake index 19567743..60ee3a43 100644 --- a/bsp/cmake/SetLinkerOptions.cmake +++ b/bsp/cmake/SetLinkerOptions.cmake @@ -1,18 +1,29 @@ -# Copyright 2023-2024, Arm Limited and/or its affiliates +# Copyright 2023-2025, Arm Limited and/or its affiliates # # SPDX-License-Identifier: Apache-2.0 # Set the linker script for the target specified macro(set_linker_script executable_target) if(${CMAKE_C_COMPILER_ID} STREQUAL "GNU") - target_link_options(${executable_target} - PRIVATE - $<$:-T ${IOT_REFERENCE_ARM_CORSTONE3XX_SOURCE_DIR}/bsp/corstone300/an552_ns.ld> - $<$:-T ${IOT_REFERENCE_ARM_CORSTONE3XX_SOURCE_DIR}/bsp/corstone310/an555_ns.ld> - $<$:-T ${IOT_REFERENCE_ARM_CORSTONE3XX_SOURCE_DIR}/bsp/corstone315/corstone_315_ns.ld> - $<$:-T ${IOT_REFERENCE_ARM_CORSTONE3XX_SOURCE_DIR}/bsp/corstone320/corstone_320_ns.ld> - -Wl,--gc-sections,-Map=${executable_target}.map - ) + if((${APPLICATION_PATH} MATCHES ".*keyword_detection") AND (${CMAKE_C_COMPILER_ID} STREQUAL "GNU")) + target_link_options(${executable_target} + PRIVATE + $<$:-T ${IOT_REFERENCE_ARM_CORSTONE3XX_SOURCE_DIR}/bsp/corstone300/an552_ns_keyword_ml_model_update.ld> + $<$:-T ${IOT_REFERENCE_ARM_CORSTONE3XX_SOURCE_DIR}/bsp/corstone310/an555_ns_keyword_ml_model_update.ld> + $<$:-T ${IOT_REFERENCE_ARM_CORSTONE3XX_SOURCE_DIR}/bsp/corstone315/corstone_315_ns_keyword_ml_model_update.ld> + $<$:-T ${IOT_REFERENCE_ARM_CORSTONE3XX_SOURCE_DIR}/bsp/corstone320/corstone_320_ns_keyword_ml_model_update.ld> + -Wl,--gc-sections,-Map=${executable_target}.map + ) + else() + target_link_options(${executable_target} + PRIVATE + $<$:-T ${IOT_REFERENCE_ARM_CORSTONE3XX_SOURCE_DIR}/bsp/corstone300/an552_ns.ld> + $<$:-T ${IOT_REFERENCE_ARM_CORSTONE3XX_SOURCE_DIR}/bsp/corstone310/an555_ns.ld> + $<$:-T ${IOT_REFERENCE_ARM_CORSTONE3XX_SOURCE_DIR}/bsp/corstone315/corstone_315_ns.ld> + $<$:-T ${IOT_REFERENCE_ARM_CORSTONE3XX_SOURCE_DIR}/bsp/corstone320/corstone_320_ns.ld> + -Wl,--gc-sections,-Map=${executable_target}.map + ) + endif() else() target_link_options(${executable_target} PRIVATE diff --git a/bsp/corstone300/an552_ns.sct b/bsp/corstone300/an552_ns.sct index 27beb96b..93abfe36 100644 --- a/bsp/corstone300/an552_ns.sct +++ b/bsp/corstone300/an552_ns.sct @@ -1,6 +1,6 @@ #! armclang --target=arm-arm-none-eabi -march=armv8.1-m.main+mve.fp+fp.dp -E -x c /* - * Copyright (c) 2023-2024, Arm Limited. All rights reserved. + * Copyright (c) 2023-2025, Arm Limited. All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -30,7 +30,7 @@ LOAD_REGION_0 (ROM_START + ((((0) + (FLASH_S_PARTITION_SIZE)) + (BL2_HEADER_SIZE)))) { - flash.bin (ROM_START + ((((0) + (FLASH_S_PARTITION_SIZE)) + (BL2_HEADER_SIZE)))) (((FLASH_NS_PARTITION_SIZE) - (BL2_HEADER_SIZE) - (BL2_TRAILER_SIZE))) { + ns_image.bin (ROM_START + ((((0) + (FLASH_S_PARTITION_SIZE)) + (BL2_HEADER_SIZE)))) (((FLASH_NS_PARTITION_SIZE) - (BL2_HEADER_SIZE) - (BL2_TRAILER_SIZE))) { *.o (RESET +First) * (InRoot$$Sections) * (+RO) diff --git a/bsp/corstone300/an552_ns_keyword_ml_model_update.ld b/bsp/corstone300/an552_ns_keyword_ml_model_update.ld new file mode 100644 index 00000000..da9a65bc --- /dev/null +++ b/bsp/corstone300/an552_ns_keyword_ml_model_update.ld @@ -0,0 +1,265 @@ +/* Copyright 2009-2025 Arm Limited and/or its affiliates + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/* + * Note: This file is based on Device/ARM/ARMCM55/Source/GCC/gcc_arm.ld from + * the git tag 5.8.0 of the CMSIS_5 repository. + */ + +/* + *-------- <<< Use Configuration Wizard in Context Menu >>> ------------------- + */ + +/*---------------------- Flash Configuration ---------------------------------- + Flash Configuration + Flash Base Address <0x0-0xFFFFFFFF:8> + Flash Size (in Bytes) <0x0-0xFFFFFFFF:8> + + -----------------------------------------------------------------------------*/ +FLASH_NS_ML_MODEL_PARTITION_SIZE = 0x100000; +FLASH_NS_PARTITION_SIZE = 0x240000; +FLASH_S_PARTITION_SIZE = 0x40000; +ROM_START = 0x28000000; +BL2_HEADER_SIZE = 0x400; +BL2_TRAILER_SIZE = 0xC00; +DDR_START = 0x60000000; +DDR_SIZE = 0x10000000; + +__ROM_BASE = (ROM_START + FLASH_S_PARTITION_SIZE + BL2_HEADER_SIZE); +__ROM_SIZE = (FLASH_NS_PARTITION_SIZE - BL2_HEADER_SIZE - BL2_TRAILER_SIZE); + +__MODEL_BASE = (DDR_START + BL2_HEADER_SIZE); +__MODEL_SIZE = (FLASH_NS_ML_MODEL_PARTITION_SIZE - BL2_HEADER_SIZE - BL2_TRAILER_SIZE); + +__DDR_NS_PARTITION_BASE = (DDR_START + FLASH_NS_ML_MODEL_PARTITION_SIZE); +__DDR_NS_PARTITION_SIZE = (DDR_SIZE - FLASH_NS_ML_MODEL_PARTITION_SIZE); + +/*--------------------- Embedded RAM Configuration ---------------------------- + RAM Configuration + RAM Base Address <0x0-0xFFFFFFFF:8> + RAM Size (in Bytes) <0x0-0xFFFFFFFF:8> + + -----------------------------------------------------------------------------*/ +PROVISIONING_SIZE = 0x1000; +__RAM_BASE = 0x21000000; +__RAM_SIZE = 0x00200000; +__RAM_S_SIZE = 0x20000; +__RAM_NS_BASE = __RAM_BASE + __RAM_S_SIZE; +__RAM_NS_SIZE = (__RAM_SIZE - __RAM_S_SIZE - PROVISIONING_SIZE); + +/*--------------------- Stack / Heap Configuration ---------------------------- + Stack / Heap Configuration + Stack Size (in Bytes) <0x0-0xFFFFFFFF:8> + Heap Size (in Bytes) <0x0-0xFFFFFFFF:8> + + -----------------------------------------------------------------------------*/ +__STACK_SIZE = 0x00002000; +__HEAP_SIZE = 0x000C0000; + +/* + *-------------------- <<< end of configuration section >>> ------------------- + */ + +MEMORY +{ + FLASH (rx) : ORIGIN = __ROM_BASE, LENGTH = __ROM_SIZE + RAM (rwx) : ORIGIN = __RAM_NS_BASE, LENGTH = __RAM_NS_SIZE + DDR (rwx) : ORIGIN = __DDR_NS_PARTITION_BASE, LENGTH = __DDR_NS_PARTITION_SIZE + MODEL (rwx) : ORIGIN = __MODEL_BASE, LENGTH = __MODEL_SIZE +} + +/* Linker script to place sections and symbol values. + * It references following symbols, which must be defined in code: + * Reset_Handler : Entry of reset handler + * + * It defines following symbols, which code can use without definition: + * __exidx_start + * __exidx_end + * __copy_table_start__ + * __copy_table_end__ + * __zero_table_start__ + * __zero_table_end__ + * __etext + * __data_start__ + * __preinit_array_start + * __preinit_array_end + * __init_array_start + * __init_array_end + * __fini_array_start + * __fini_array_end + * __data_end__ + * __bss_start__ + * __bss_end__ + * __end__ + * end + * __HeapLimit + * __StackLimit + * __StackTop + * __stack + */ +ENTRY(Reset_Handler) + +SECTIONS +{ + .text : + { + _vectors = .; + KEEP(*(.vectors)) + *(.text*) + + . = ALIGN(4); + __copy_table_start__ = .; + LONG (LOADADDR(.data)) + LONG (ADDR(.data)) + LONG (SIZEOF(.data) / 4) + __copy_table_end__ = .; + + /* .zero.table */ + . = ALIGN(4); + __zero_table_start__ = .; + LONG (ADDR(.bss)) + LONG (SIZEOF(.bss) / 4) + __zero_table_end__ = .; + + KEEP(*(.init)) + KEEP(*(.fini)) + + /* .ctors */ + *crtbegin.o(.ctors) + *crtbegin?.o(.ctors) + *(EXCLUDE_FILE(*crtend?.o *crtend.o) .ctors) + *(SORT(.ctors.*)) + *(.ctors) + + /* .dtors */ + *crtbegin.o(.dtors) + *crtbegin?.o(.dtors) + *(EXCLUDE_FILE(*crtend?.o *crtend.o) .dtors) + *(SORT(.dtors.*)) + *(.dtors) + + *(.rodata*) + + KEEP(*(.eh_frame*)) + } > FLASH + + .ARM.extab : + { + *(.ARM.extab* .gnu.linkonce.armextab.*) + } > FLASH + + __exidx_start = .; + .ARM.exidx : + { + *(.ARM.exidx* .gnu.linkonce.armexidx.*) + } > FLASH + __exidx_end = .; + + /** + * Location counter can end up 2byte aligned with narrow Thumb code but + * __etext is assumed by startup code to be the LMA of a section in RAM + * which must be 4byte aligned + */ + __etext = ALIGN (4); + + .data : AT (__etext) + { + __data_start__ = .; + *(vtable) + *(.data) + *(.data.*) + + . = ALIGN(4); + /* preinit data */ + PROVIDE_HIDDEN (__preinit_array_start = .); + KEEP(*(.preinit_array)) + PROVIDE_HIDDEN (__preinit_array_end = .); + + . = ALIGN(4); + /* init data */ + PROVIDE_HIDDEN (__init_array_start = .); + KEEP(*(SORT(.init_array.*))) + KEEP(*(.init_array)) + PROVIDE_HIDDEN (__init_array_end = .); + + . = ALIGN(4); + /* finit data */ + PROVIDE_HIDDEN (__fini_array_start = .); + KEEP(*(SORT(.fini_array.*))) + KEEP(*(.fini_array)) + PROVIDE_HIDDEN (__fini_array_end = .); + + KEEP(*(.jcr*)) + . = ALIGN(4); + *(tasks_share) + /* All data end */ + __data_end__ = .; + + } > RAM + + model.bin : + { + . = ALIGN (16); + __nn_model_start__ = .; + /* nn model's default space */ + *(nn_model) + __nn_model_end__ = .; + } > MODEL + + ddr.bin : + { + __ddr_start__ = .; + . = ALIGN(16); + /* nn model's baked in input matrices */ + *(ifm) + . = ALIGN (16); + /* labels */ + *(labels) + . = ALIGN (16); + *(.bss.NoInit.activation_buf_sram) + *(activation_buf_dram) + . = ALIGN (4); + /* Buffer for transferring VSI audio data from S to NS */ + *(.bss.NoInit.vsi_audio_buffer) + . = ALIGN (16); + *(.bss.NoInit.ethos_u_cache) + __ddr_end__ = .; + } > DDR + + .bss : + { + . = ALIGN(4); + __bss_start__ = .; + *(.bss) + *(.bss.*) + *(COMMON) + . = ALIGN(4); + __bss_end__ = .; + } > RAM AT > RAM + + .heap (COPY) : + { + . = ALIGN(8); + __end__ = .; + PROVIDE(end = .); + . = . + __HEAP_SIZE; + . = ALIGN(8); + __HeapLimit = .; + } > RAM + PROVIDE(__RAM_segment_used_end__ = __HeapLimit); + + .stack (ORIGIN(RAM) + LENGTH(RAM) - __STACK_SIZE) (COPY) : + { + . = ALIGN(8); + __StackLimit = .; + . = . + __STACK_SIZE; + . = ALIGN(8); + __StackTop = .; + } > RAM + PROVIDE(__stack = __StackTop); + + /* Check if data + heap + stack exceeds RAM limit */ + ASSERT(__StackLimit >= __HeapLimit, "region RAM overflowed with stack") +} diff --git a/bsp/corstone310/an555_ns.sct b/bsp/corstone310/an555_ns.sct index 13c7cdd9..e10b1673 100644 --- a/bsp/corstone310/an555_ns.sct +++ b/bsp/corstone310/an555_ns.sct @@ -1,6 +1,6 @@ #! armclang --target=arm-arm-none-eabi -march=armv8.1-m.main+mve.fp+fp.dp -E -x c /* - * Copyright (c) 2021-2024 Arm Limited. All rights reserved. + * Copyright (c) 2021-2025 Arm Limited. All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -29,7 +29,7 @@ LOAD_REGION_0 (ROM_START + ((((0) + (FLASH_S_PARTITION_SIZE)) + BL2_HEADER_SIZE))) { - flash.bin (ROM_START + ((((0) + (FLASH_S_PARTITION_SIZE)) + BL2_HEADER_SIZE))) (((FLASH_NS_PARTITION_SIZE) - BL2_HEADER_SIZE - BL2_TRAILER_SIZE)) { + ns_image.bin (ROM_START + ((((0) + (FLASH_S_PARTITION_SIZE)) + BL2_HEADER_SIZE))) (((FLASH_NS_PARTITION_SIZE) - BL2_HEADER_SIZE - BL2_TRAILER_SIZE)) { *.o (RESET +First) * (+RO) } diff --git a/bsp/corstone310/an555_ns_keyword_ml_model_update.ld b/bsp/corstone310/an555_ns_keyword_ml_model_update.ld new file mode 100644 index 00000000..895d1a17 --- /dev/null +++ b/bsp/corstone310/an555_ns_keyword_ml_model_update.ld @@ -0,0 +1,279 @@ +/* + * Copyright (c) 2009-2025 Arm Limited. All rights reserved. + * + * 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 + * + * 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. + */ + +/* + * Note: This file is based on Device/ARM/ARMCM55/Source/GCC/gcc_arm.ld from + * the git tag 5.8.0 of the CMSIS_5 repository. + */ + +/* + *-------- <<< Use Configuration Wizard in Context Menu >>> ------------------- + */ + +/*---------------------- Flash Configuration ---------------------------------- + Flash Configuration + Flash Base Address <0x0-0xFFFFFFFF:8> + Flash Size (in Bytes) <0x0-0xFFFFFFFF:8> + + -----------------------------------------------------------------------------*/ +FLASH_NS_ML_MODEL_PARTITION_SIZE = 0x100000; +FLASH_NS_PARTITION_SIZE = 0x240000; +FLASH_S_PARTITION_SIZE = 0x40000; +ROM_START = 0x28000000; +BL2_HEADER_SIZE = 0x400; +BL2_TRAILER_SIZE = 0xC00; +DDR_START = 0x60000000; +DDR_SIZE = 0x10000000; +ISRAM0_BASE_ADDRESS = 0x21000000; +ISRAM1_OFFSET = 0x00200000; +ISRAM1_SIZE = 0x00200000; + +__ROM_BASE = (ROM_START + FLASH_S_PARTITION_SIZE + BL2_HEADER_SIZE); +__ROM_SIZE = (FLASH_NS_PARTITION_SIZE - BL2_HEADER_SIZE - BL2_TRAILER_SIZE); + +__MODEL_BASE = (DDR_START + BL2_HEADER_SIZE); +__MODEL_SIZE = (FLASH_NS_ML_MODEL_PARTITION_SIZE - BL2_HEADER_SIZE - BL2_TRAILER_SIZE); + +__DDR_NS_PARTITION_BASE = (DDR_START + FLASH_NS_ML_MODEL_PARTITION_SIZE); +__DDR_NS_PARTITION_SIZE = (DDR_SIZE - FLASH_NS_ML_MODEL_PARTITION_SIZE); + +/*--------------------- Embedded RAM Configuration ---------------------------- + RAM Configuration + RAM Base Address <0x0-0xFFFFFFFF:8> + RAM Size (in Bytes) <0x0-0xFFFFFFFF:8> + + -----------------------------------------------------------------------------*/ +PROVISIONING_SIZE = 0x1000; +__RAM_BASE = (ISRAM0_BASE_ADDRESS + ISRAM1_OFFSET); +__RAM_SIZE = (ISRAM1_SIZE - PROVISIONING_SIZE); + +/*--------------------- Stack / Heap Configuration ---------------------------- + Stack / Heap Configuration + Stack Size (in Bytes) <0x0-0xFFFFFFFF:8> + Heap Size (in Bytes) <0x0-0xFFFFFFFF:8> + + -----------------------------------------------------------------------------*/ +__STACK_SIZE = 0x00002000; +__HEAP_SIZE = 0x000C0000; + +/* + *-------------------- <<< end of configuration section >>> ------------------- + */ + +MEMORY +{ + FLASH (rx) : ORIGIN = __ROM_BASE, LENGTH = __ROM_SIZE + RAM (rwx) : ORIGIN = __RAM_BASE, LENGTH = __RAM_SIZE + DDR (rwx) : ORIGIN = __DDR_NS_PARTITION_BASE, LENGTH = __DDR_NS_PARTITION_SIZE + MODEL (rwx) : ORIGIN = __MODEL_BASE, LENGTH = __MODEL_SIZE + DMA (rwx) : ORIGIN = 0x80000000, LENGTH = 0x02000000 +} + +/* Linker script to place sections and symbol values. + * It references following symbols, which must be defined in code: + * Reset_Handler : Entry of reset handler + * + * It defines following symbols, which code can use without definition: + * __exidx_start + * __exidx_end + * __copy_table_start__ + * __copy_table_end__ + * __zero_table_start__ + * __zero_table_end__ + * __etext + * __data_start__ + * __preinit_array_start + * __preinit_array_end + * __init_array_start + * __init_array_end + * __fini_array_start + * __fini_array_end + * __data_end__ + * __bss_start__ + * __bss_end__ + * __end__ + * end + * __HeapLimit + * __StackLimit + * __StackTop + * __stack + */ +ENTRY(Reset_Handler) + +SECTIONS +{ + .text : + { + _vectors = .; + KEEP(*(.vectors)) + *(.text*) + + . = ALIGN(4); + __copy_table_start__ = .; + LONG (LOADADDR(.data)) + LONG (ADDR(.data)) + LONG (SIZEOF(.data) / 4) + __copy_table_end__ = .; + + /* .zero.table */ + . = ALIGN(4); + __zero_table_start__ = .; + LONG (ADDR(.bss)) + LONG (SIZEOF(.bss) / 4) + __zero_table_end__ = .; + + KEEP(*(.init)) + KEEP(*(.fini)) + + /* .ctors */ + *crtbegin.o(.ctors) + *crtbegin?.o(.ctors) + *(EXCLUDE_FILE(*crtend?.o *crtend.o) .ctors) + *(SORT(.ctors.*)) + *(.ctors) + + /* .dtors */ + *crtbegin.o(.dtors) + *crtbegin?.o(.dtors) + *(EXCLUDE_FILE(*crtend?.o *crtend.o) .dtors) + *(SORT(.dtors.*)) + *(.dtors) + + *(.rodata*) + + KEEP(*(.eh_frame*)) + } > FLASH + + .ARM.extab : + { + *(.ARM.extab* .gnu.linkonce.armextab.*) + } > FLASH + + __exidx_start = .; + .ARM.exidx : + { + *(.ARM.exidx* .gnu.linkonce.armexidx.*) + } > FLASH + __exidx_end = .; + + /** + * Location counter can end up 2byte aligned with narrow Thumb code but + * __etext is assumed by startup code to be the LMA of a section in RAM + * which must be 4byte aligned + */ + __etext = ALIGN (4); + + .data : AT (__etext) + { + __data_start__ = .; + *(vtable) + *(.data) + *(.data.*) + + . = ALIGN(4); + /* preinit data */ + PROVIDE_HIDDEN (__preinit_array_start = .); + KEEP(*(.preinit_array)) + PROVIDE_HIDDEN (__preinit_array_end = .); + + . = ALIGN(4); + /* init data */ + PROVIDE_HIDDEN (__init_array_start = .); + KEEP(*(SORT(.init_array.*))) + KEEP(*(.init_array)) + PROVIDE_HIDDEN (__init_array_end = .); + + . = ALIGN(4); + /* finit data */ + PROVIDE_HIDDEN (__fini_array_start = .); + KEEP(*(SORT(.fini_array.*))) + KEEP(*(.fini_array)) + PROVIDE_HIDDEN (__fini_array_end = .); + + KEEP(*(.jcr*)) + . = ALIGN(4); + *(tasks_share) + /* All data end */ + __data_end__ = .; + + } > RAM + + model.bin : + { + . = ALIGN (16); + __nn_model_start__ = .; + /* nn model's default space */ + *(nn_model) + __nn_model_end__ = .; + } > MODEL + + ddr.bin : + { + __ddr_start__ = .; + . = ALIGN(16); + /* nn model's baked in input matrices */ + *(ifm) + . = ALIGN (16); + /* labels */ + *(labels) + . = ALIGN (16); + *(.bss.NoInit.activation_buf_sram) + *(activation_buf_dram) + . = ALIGN (4); + /* Buffer for transferring VSI audio data from S to NS */ + *(.bss.NoInit.vsi_audio_buffer) + . = ALIGN (16); + *(.bss.NoInit.ethos_u_cache) + __ddr_end__ = .; + } > DDR + + .bss : + { + . = ALIGN(4); + __bss_start__ = .; + *(.bss) + *(.bss.*) + *(COMMON) + . = ALIGN(4); + __bss_end__ = .; + } > RAM AT > RAM + + .heap (COPY) : + { + . = ALIGN(8); + __end__ = .; + PROVIDE(end = .); + . = . + __HEAP_SIZE; + . = ALIGN(8); + __HeapLimit = .; + } > RAM + PROVIDE(__RAM_segment_used_end__ = __HeapLimit); + + .stack (ORIGIN(RAM) + LENGTH(RAM) - __STACK_SIZE) (COPY) : + { + . = ALIGN(8); + __StackLimit = .; + . = . + __STACK_SIZE; + . = ALIGN(8); + __StackTop = .; + } > RAM + PROVIDE(__stack = __StackTop); + + /* Check if data + heap + stack exceeds RAM limit */ + ASSERT(__StackLimit >= __HeapLimit, "region RAM overflowed with stack") +} diff --git a/bsp/corstone315/corstone_315_ns.sct b/bsp/corstone315/corstone_315_ns.sct index 8588152f..3e8fe302 100644 --- a/bsp/corstone315/corstone_315_ns.sct +++ b/bsp/corstone315/corstone_315_ns.sct @@ -1,6 +1,6 @@ #! armclang --target=arm-arm-none-eabi -march=armv8.1-m.main+mve.fp+fp.dp -E -x c /* - * Copyright (c) 2021-2024, Arm Limited. All rights reserved. + * Copyright (c) 2021-2025, Arm Limited. All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -29,7 +29,7 @@ LOAD_REGION_0 (ROM_START + ((((0) + (FLASH_S_PARTITION_SIZE)) + BL2_HEADER_SIZE))) { - flash.bin (ROM_START + ((((0) + (FLASH_S_PARTITION_SIZE)) + BL2_HEADER_SIZE))) (((FLASH_NS_PARTITION_SIZE) - BL2_HEADER_SIZE - BL2_TRAILER_SIZE)) { + ns_image.bin (ROM_START + ((((0) + (FLASH_S_PARTITION_SIZE)) + BL2_HEADER_SIZE))) (((FLASH_NS_PARTITION_SIZE) - BL2_HEADER_SIZE - BL2_TRAILER_SIZE)) { *.o (RESET +First) * (+RO) } diff --git a/bsp/corstone315/corstone_315_ns_keyword_ml_model_update.ld b/bsp/corstone315/corstone_315_ns_keyword_ml_model_update.ld new file mode 100644 index 00000000..e99a0039 --- /dev/null +++ b/bsp/corstone315/corstone_315_ns_keyword_ml_model_update.ld @@ -0,0 +1,279 @@ +/* + * Copyright (c) 2009-2025, Arm Limited. All rights reserved. + * + * 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 + * + * 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. + */ + +/* + * Note: This file is based on Device/ARM/ARMCM55/Source/GCC/gcc_arm.ld from + * the git tag 5.8.0 of the CMSIS_5 repository. + */ + +/* + *-------- <<< Use Configuration Wizard in Context Menu >>> ------------------- + */ + +/*---------------------- Flash Configuration ---------------------------------- + Flash Configuration + Flash Base Address <0x0-0xFFFFFFFF:8> + Flash Size (in Bytes) <0x0-0xFFFFFFFF:8> + + -----------------------------------------------------------------------------*/ +FLASH_NS_ML_MODEL_PARTITION_SIZE = 0x100000; +FLASH_NS_PARTITION_SIZE = 0x240000; +FLASH_S_PARTITION_SIZE = 0x40000; +ROM_START = 0x28000000; +BL2_HEADER_SIZE = 0x400; +BL2_TRAILER_SIZE = 0xC00; +DDR_START = 0x60000000; +DDR_SIZE = 0x10000000; +ISRAM0_BASE_ADDRESS = 0x21000000; +ISRAM1_OFFSET = 0x00200000; +ISRAM1_SIZE = 0x00200000; + +__ROM_BASE = (ROM_START + FLASH_S_PARTITION_SIZE + BL2_HEADER_SIZE); +__ROM_SIZE = (FLASH_NS_PARTITION_SIZE - BL2_HEADER_SIZE - BL2_TRAILER_SIZE); + +__MODEL_BASE = (DDR_START + BL2_HEADER_SIZE); +__MODEL_SIZE = (FLASH_NS_ML_MODEL_PARTITION_SIZE - BL2_HEADER_SIZE - BL2_TRAILER_SIZE); + +__DDR_NS_PARTITION_BASE = (DDR_START + FLASH_NS_ML_MODEL_PARTITION_SIZE); +__DDR_NS_PARTITION_SIZE = (DDR_SIZE - FLASH_NS_ML_MODEL_PARTITION_SIZE); + +/*--------------------- Embedded RAM Configuration ---------------------------- + RAM Configuration + RAM Base Address <0x0-0xFFFFFFFF:8> + RAM Size (in Bytes) <0x0-0xFFFFFFFF:8> + + -----------------------------------------------------------------------------*/ +PROVISIONING_SIZE = 0x1000; +__RAM_BASE = (ISRAM0_BASE_ADDRESS + ISRAM1_OFFSET); +__RAM_SIZE = (ISRAM1_SIZE - PROVISIONING_SIZE); + +/*--------------------- Stack / Heap Configuration ---------------------------- + Stack / Heap Configuration + Stack Size (in Bytes) <0x0-0xFFFFFFFF:8> + Heap Size (in Bytes) <0x0-0xFFFFFFFF:8> + + -----------------------------------------------------------------------------*/ +__STACK_SIZE = 0x00002000; +__HEAP_SIZE = 0x000C0000; + +/* + *-------------------- <<< end of configuration section >>> ------------------- + */ + +MEMORY +{ + FLASH (rx) : ORIGIN = __ROM_BASE, LENGTH = __ROM_SIZE + RAM (rwx) : ORIGIN = __RAM_BASE, LENGTH = __RAM_SIZE + DDR (rwx) : ORIGIN = __DDR_NS_PARTITION_BASE, LENGTH = __DDR_NS_PARTITION_SIZE + MODEL (rwx) : ORIGIN = __MODEL_BASE, LENGTH = __MODEL_SIZE + DMA (rwx) : ORIGIN = 0x80000000, LENGTH = 0x02000000 +} + +/* Linker script to place sections and symbol values. + * It references following symbols, which must be defined in code: + * Reset_Handler : Entry of reset handler + * + * It defines following symbols, which code can use without definition: + * __exidx_start + * __exidx_end + * __copy_table_start__ + * __copy_table_end__ + * __zero_table_start__ + * __zero_table_end__ + * __etext + * __data_start__ + * __preinit_array_start + * __preinit_array_end + * __init_array_start + * __init_array_end + * __fini_array_start + * __fini_array_end + * __data_end__ + * __bss_start__ + * __bss_end__ + * __end__ + * end + * __HeapLimit + * __StackLimit + * __StackTop + * __stack + */ +ENTRY(Reset_Handler) + +SECTIONS +{ + .text : + { + _vectors = .; + KEEP(*(.vectors)) + *(.text*) + + . = ALIGN(4); + __copy_table_start__ = .; + LONG (LOADADDR(.data)) + LONG (ADDR(.data)) + LONG (SIZEOF(.data) / 4) + __copy_table_end__ = .; + + /* .zero.table */ + . = ALIGN(4); + __zero_table_start__ = .; + LONG (ADDR(.bss)) + LONG (SIZEOF(.bss) / 4) + __zero_table_end__ = .; + + KEEP(*(.init)) + KEEP(*(.fini)) + + /* .ctors */ + *crtbegin.o(.ctors) + *crtbegin?.o(.ctors) + *(EXCLUDE_FILE(*crtend?.o *crtend.o) .ctors) + *(SORT(.ctors.*)) + *(.ctors) + + /* .dtors */ + *crtbegin.o(.dtors) + *crtbegin?.o(.dtors) + *(EXCLUDE_FILE(*crtend?.o *crtend.o) .dtors) + *(SORT(.dtors.*)) + *(.dtors) + + *(.rodata*) + + KEEP(*(.eh_frame*)) + } > FLASH + + .ARM.extab : + { + *(.ARM.extab* .gnu.linkonce.armextab.*) + } > FLASH + + __exidx_start = .; + .ARM.exidx : + { + *(.ARM.exidx* .gnu.linkonce.armexidx.*) + } > FLASH + __exidx_end = .; + + /** + * Location counter can end up 2byte aligned with narrow Thumb code but + * __etext is assumed by startup code to be the LMA of a section in RAM + * which must be 4byte aligned + */ + __etext = ALIGN (4); + + .data : AT (__etext) + { + __data_start__ = .; + *(vtable) + *(.data) + *(.data.*) + + . = ALIGN(4); + /* preinit data */ + PROVIDE_HIDDEN (__preinit_array_start = .); + KEEP(*(.preinit_array)) + PROVIDE_HIDDEN (__preinit_array_end = .); + + . = ALIGN(4); + /* init data */ + PROVIDE_HIDDEN (__init_array_start = .); + KEEP(*(SORT(.init_array.*))) + KEEP(*(.init_array)) + PROVIDE_HIDDEN (__init_array_end = .); + + . = ALIGN(4); + /* finit data */ + PROVIDE_HIDDEN (__fini_array_start = .); + KEEP(*(SORT(.fini_array.*))) + KEEP(*(.fini_array)) + PROVIDE_HIDDEN (__fini_array_end = .); + + KEEP(*(.jcr*)) + . = ALIGN(4); + *(tasks_share) + /* All data end */ + __data_end__ = .; + + } > RAM + + model.bin : + { + . = ALIGN (16); + __nn_model_start__ = .; + /* nn model's default space */ + *(nn_model) + __nn_model_end__ = .; + } > MODEL + + ddr.bin : + { + __ddr_start__ = .; + . = ALIGN(16); + /* nn model's baked in input matrices */ + *(ifm) + . = ALIGN (16); + /* labels */ + *(labels) + . = ALIGN (16); + *(.bss.NoInit.activation_buf_sram) + *(activation_buf_dram) + . = ALIGN (4); + /* Buffer for transferring VSI audio data from S to NS */ + *(.bss.NoInit.vsi_audio_buffer) + . = ALIGN (16); + *(.bss.NoInit.ethos_u_cache) + __ddr_end__ = .; + } > DDR + + .bss : + { + . = ALIGN(4); + __bss_start__ = .; + *(.bss) + *(.bss.*) + *(COMMON) + . = ALIGN(4); + __bss_end__ = .; + } > RAM AT > RAM + + .heap (COPY) : + { + . = ALIGN(8); + __end__ = .; + PROVIDE(end = .); + . = . + __HEAP_SIZE; + . = ALIGN(8); + __HeapLimit = .; + } > RAM + PROVIDE(__RAM_segment_used_end__ = __HeapLimit); + + .stack (ORIGIN(RAM) + LENGTH(RAM) - __STACK_SIZE) (COPY) : + { + . = ALIGN(8); + __StackLimit = .; + . = . + __STACK_SIZE; + . = ALIGN(8); + __StackTop = .; + } > RAM + PROVIDE(__stack = __StackTop); + + /* Check if data + heap + stack exceeds RAM limit */ + ASSERT(__StackLimit >= __HeapLimit, "region RAM overflowed with stack") +} diff --git a/bsp/corstone320/corstone_320_ns.sct b/bsp/corstone320/corstone_320_ns.sct index 8588152f..3e8fe302 100644 --- a/bsp/corstone320/corstone_320_ns.sct +++ b/bsp/corstone320/corstone_320_ns.sct @@ -1,6 +1,6 @@ #! armclang --target=arm-arm-none-eabi -march=armv8.1-m.main+mve.fp+fp.dp -E -x c /* - * Copyright (c) 2021-2024, Arm Limited. All rights reserved. + * Copyright (c) 2021-2025, Arm Limited. All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -29,7 +29,7 @@ LOAD_REGION_0 (ROM_START + ((((0) + (FLASH_S_PARTITION_SIZE)) + BL2_HEADER_SIZE))) { - flash.bin (ROM_START + ((((0) + (FLASH_S_PARTITION_SIZE)) + BL2_HEADER_SIZE))) (((FLASH_NS_PARTITION_SIZE) - BL2_HEADER_SIZE - BL2_TRAILER_SIZE)) { + ns_image.bin (ROM_START + ((((0) + (FLASH_S_PARTITION_SIZE)) + BL2_HEADER_SIZE))) (((FLASH_NS_PARTITION_SIZE) - BL2_HEADER_SIZE - BL2_TRAILER_SIZE)) { *.o (RESET +First) * (+RO) } diff --git a/bsp/corstone320/corstone_320_ns_keyword_ml_model_update.ld b/bsp/corstone320/corstone_320_ns_keyword_ml_model_update.ld new file mode 100644 index 00000000..e99a0039 --- /dev/null +++ b/bsp/corstone320/corstone_320_ns_keyword_ml_model_update.ld @@ -0,0 +1,279 @@ +/* + * Copyright (c) 2009-2025, Arm Limited. All rights reserved. + * + * 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 + * + * 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. + */ + +/* + * Note: This file is based on Device/ARM/ARMCM55/Source/GCC/gcc_arm.ld from + * the git tag 5.8.0 of the CMSIS_5 repository. + */ + +/* + *-------- <<< Use Configuration Wizard in Context Menu >>> ------------------- + */ + +/*---------------------- Flash Configuration ---------------------------------- + Flash Configuration + Flash Base Address <0x0-0xFFFFFFFF:8> + Flash Size (in Bytes) <0x0-0xFFFFFFFF:8> + + -----------------------------------------------------------------------------*/ +FLASH_NS_ML_MODEL_PARTITION_SIZE = 0x100000; +FLASH_NS_PARTITION_SIZE = 0x240000; +FLASH_S_PARTITION_SIZE = 0x40000; +ROM_START = 0x28000000; +BL2_HEADER_SIZE = 0x400; +BL2_TRAILER_SIZE = 0xC00; +DDR_START = 0x60000000; +DDR_SIZE = 0x10000000; +ISRAM0_BASE_ADDRESS = 0x21000000; +ISRAM1_OFFSET = 0x00200000; +ISRAM1_SIZE = 0x00200000; + +__ROM_BASE = (ROM_START + FLASH_S_PARTITION_SIZE + BL2_HEADER_SIZE); +__ROM_SIZE = (FLASH_NS_PARTITION_SIZE - BL2_HEADER_SIZE - BL2_TRAILER_SIZE); + +__MODEL_BASE = (DDR_START + BL2_HEADER_SIZE); +__MODEL_SIZE = (FLASH_NS_ML_MODEL_PARTITION_SIZE - BL2_HEADER_SIZE - BL2_TRAILER_SIZE); + +__DDR_NS_PARTITION_BASE = (DDR_START + FLASH_NS_ML_MODEL_PARTITION_SIZE); +__DDR_NS_PARTITION_SIZE = (DDR_SIZE - FLASH_NS_ML_MODEL_PARTITION_SIZE); + +/*--------------------- Embedded RAM Configuration ---------------------------- + RAM Configuration + RAM Base Address <0x0-0xFFFFFFFF:8> + RAM Size (in Bytes) <0x0-0xFFFFFFFF:8> + + -----------------------------------------------------------------------------*/ +PROVISIONING_SIZE = 0x1000; +__RAM_BASE = (ISRAM0_BASE_ADDRESS + ISRAM1_OFFSET); +__RAM_SIZE = (ISRAM1_SIZE - PROVISIONING_SIZE); + +/*--------------------- Stack / Heap Configuration ---------------------------- + Stack / Heap Configuration + Stack Size (in Bytes) <0x0-0xFFFFFFFF:8> + Heap Size (in Bytes) <0x0-0xFFFFFFFF:8> + + -----------------------------------------------------------------------------*/ +__STACK_SIZE = 0x00002000; +__HEAP_SIZE = 0x000C0000; + +/* + *-------------------- <<< end of configuration section >>> ------------------- + */ + +MEMORY +{ + FLASH (rx) : ORIGIN = __ROM_BASE, LENGTH = __ROM_SIZE + RAM (rwx) : ORIGIN = __RAM_BASE, LENGTH = __RAM_SIZE + DDR (rwx) : ORIGIN = __DDR_NS_PARTITION_BASE, LENGTH = __DDR_NS_PARTITION_SIZE + MODEL (rwx) : ORIGIN = __MODEL_BASE, LENGTH = __MODEL_SIZE + DMA (rwx) : ORIGIN = 0x80000000, LENGTH = 0x02000000 +} + +/* Linker script to place sections and symbol values. + * It references following symbols, which must be defined in code: + * Reset_Handler : Entry of reset handler + * + * It defines following symbols, which code can use without definition: + * __exidx_start + * __exidx_end + * __copy_table_start__ + * __copy_table_end__ + * __zero_table_start__ + * __zero_table_end__ + * __etext + * __data_start__ + * __preinit_array_start + * __preinit_array_end + * __init_array_start + * __init_array_end + * __fini_array_start + * __fini_array_end + * __data_end__ + * __bss_start__ + * __bss_end__ + * __end__ + * end + * __HeapLimit + * __StackLimit + * __StackTop + * __stack + */ +ENTRY(Reset_Handler) + +SECTIONS +{ + .text : + { + _vectors = .; + KEEP(*(.vectors)) + *(.text*) + + . = ALIGN(4); + __copy_table_start__ = .; + LONG (LOADADDR(.data)) + LONG (ADDR(.data)) + LONG (SIZEOF(.data) / 4) + __copy_table_end__ = .; + + /* .zero.table */ + . = ALIGN(4); + __zero_table_start__ = .; + LONG (ADDR(.bss)) + LONG (SIZEOF(.bss) / 4) + __zero_table_end__ = .; + + KEEP(*(.init)) + KEEP(*(.fini)) + + /* .ctors */ + *crtbegin.o(.ctors) + *crtbegin?.o(.ctors) + *(EXCLUDE_FILE(*crtend?.o *crtend.o) .ctors) + *(SORT(.ctors.*)) + *(.ctors) + + /* .dtors */ + *crtbegin.o(.dtors) + *crtbegin?.o(.dtors) + *(EXCLUDE_FILE(*crtend?.o *crtend.o) .dtors) + *(SORT(.dtors.*)) + *(.dtors) + + *(.rodata*) + + KEEP(*(.eh_frame*)) + } > FLASH + + .ARM.extab : + { + *(.ARM.extab* .gnu.linkonce.armextab.*) + } > FLASH + + __exidx_start = .; + .ARM.exidx : + { + *(.ARM.exidx* .gnu.linkonce.armexidx.*) + } > FLASH + __exidx_end = .; + + /** + * Location counter can end up 2byte aligned with narrow Thumb code but + * __etext is assumed by startup code to be the LMA of a section in RAM + * which must be 4byte aligned + */ + __etext = ALIGN (4); + + .data : AT (__etext) + { + __data_start__ = .; + *(vtable) + *(.data) + *(.data.*) + + . = ALIGN(4); + /* preinit data */ + PROVIDE_HIDDEN (__preinit_array_start = .); + KEEP(*(.preinit_array)) + PROVIDE_HIDDEN (__preinit_array_end = .); + + . = ALIGN(4); + /* init data */ + PROVIDE_HIDDEN (__init_array_start = .); + KEEP(*(SORT(.init_array.*))) + KEEP(*(.init_array)) + PROVIDE_HIDDEN (__init_array_end = .); + + . = ALIGN(4); + /* finit data */ + PROVIDE_HIDDEN (__fini_array_start = .); + KEEP(*(SORT(.fini_array.*))) + KEEP(*(.fini_array)) + PROVIDE_HIDDEN (__fini_array_end = .); + + KEEP(*(.jcr*)) + . = ALIGN(4); + *(tasks_share) + /* All data end */ + __data_end__ = .; + + } > RAM + + model.bin : + { + . = ALIGN (16); + __nn_model_start__ = .; + /* nn model's default space */ + *(nn_model) + __nn_model_end__ = .; + } > MODEL + + ddr.bin : + { + __ddr_start__ = .; + . = ALIGN(16); + /* nn model's baked in input matrices */ + *(ifm) + . = ALIGN (16); + /* labels */ + *(labels) + . = ALIGN (16); + *(.bss.NoInit.activation_buf_sram) + *(activation_buf_dram) + . = ALIGN (4); + /* Buffer for transferring VSI audio data from S to NS */ + *(.bss.NoInit.vsi_audio_buffer) + . = ALIGN (16); + *(.bss.NoInit.ethos_u_cache) + __ddr_end__ = .; + } > DDR + + .bss : + { + . = ALIGN(4); + __bss_start__ = .; + *(.bss) + *(.bss.*) + *(COMMON) + . = ALIGN(4); + __bss_end__ = .; + } > RAM AT > RAM + + .heap (COPY) : + { + . = ALIGN(8); + __end__ = .; + PROVIDE(end = .); + . = . + __HEAP_SIZE; + . = ALIGN(8); + __HeapLimit = .; + } > RAM + PROVIDE(__RAM_segment_used_end__ = __HeapLimit); + + .stack (ORIGIN(RAM) + LENGTH(RAM) - __STACK_SIZE) (COPY) : + { + . = ALIGN(8); + __StackLimit = .; + . = . + __STACK_SIZE; + . = ALIGN(8); + __StackTop = .; + } > RAM + PROVIDE(__stack = __StackTop); + + /* Check if data + heap + stack exceeds RAM limit */ + ASSERT(__StackLimit >= __HeapLimit, "region RAM overflowed with stack") +} diff --git a/components/ai/ml_embedded_evaluation_kit/CMakeLists.txt b/components/ai/ml_embedded_evaluation_kit/CMakeLists.txt index 92c43c77..1d18c562 100644 --- a/components/ai/ml_embedded_evaluation_kit/CMakeLists.txt +++ b/components/ai/ml_embedded_evaluation_kit/CMakeLists.txt @@ -1,4 +1,4 @@ -# Copyright 2021-2024 Arm Limited and/or its affiliates +# Copyright 2021-2025 Arm Limited and/or its affiliates # # SPDX-License-Identifier: MIT @@ -15,10 +15,11 @@ set(PATCH_FILES "${PATCH_FILES_DIRECTORY}/0001-User-defined-resources-download-path.patch" "${PATCH_FILES_DIRECTORY}/0002-Use-CMSIS_device_header-instead-of-RTE_Components.h.patch" "${PATCH_FILES_DIRECTORY}/0003-Make-ETHOSU_ARCH-configurable-in-TensorFlow-CMake.patch" + "${PATCH_FILES_DIRECTORY}/0004-Override-EthosU55-NPU-default-IRQ-handler.patch" ) iot_reference_arm_corstone3xx_apply_patches("${ml_embedded_evaluation_kit_SOURCE_DIR}" "${PATCH_FILES}") set(PATCH_FILES - "${PATCH_FILES_DIRECTORY}/0004-Patch-tensorflow.patch" + "${PATCH_FILES_DIRECTORY}/0005-Patch-tensorflow.patch" ) iot_reference_arm_corstone3xx_apply_patches("${ml_embedded_evaluation_kit_SOURCE_DIR}/dependencies/tensorflow/" "${PATCH_FILES}") diff --git a/components/ai/ml_embedded_evaluation_kit/integration/patches/0001-User-defined-resources-download-path.patch b/components/ai/ml_embedded_evaluation_kit/integration/patches/0001-User-defined-resources-download-path.patch index 62c13900..bfebac70 100644 --- a/components/ai/ml_embedded_evaluation_kit/integration/patches/0001-User-defined-resources-download-path.patch +++ b/components/ai/ml_embedded_evaluation_kit/integration/patches/0001-User-defined-resources-download-path.patch @@ -1,7 +1,7 @@ -From a7ad534ccceb84df589417feb5272b9f4cd3aeaa Mon Sep 17 00:00:00 2001 +From ef81e4d5aa2392c7b0558923932894c8117831d9 Mon Sep 17 00:00:00 2001 From: Ahmed Ismail -Date: Fri, 28 Jun 2024 15:49:31 +0100 -Subject: [PATCH 1/2] User defined resources download path +Date: Thu, 28 Nov 2024 16:11:58 +0000 +Subject: [PATCH 1/4] User defined resources download path The location of the downloaded resources can be specified to allow users to place them wherever they require. Such location @@ -10,11 +10,11 @@ is required if different model resources need to be downloaded. Signed-off-by: Ahmed Ismail --- - set_up_default_resources.py | 21 ++++++++++++++------- - 1 file changed, 14 insertions(+), 7 deletions(-) + set_up_default_resources.py | 19 ++++++++++++++----- + 1 file changed, 14 insertions(+), 5 deletions(-) diff --git a/set_up_default_resources.py b/set_up_default_resources.py -index 2ce972a..85c02ea 100755 +index a33c8f3..e4518ec 100755 --- a/set_up_default_resources.py +++ b/set_up_default_resources.py @@ -157,12 +157,14 @@ class PathsConfig: diff --git a/components/ai/ml_embedded_evaluation_kit/integration/patches/0002-Use-CMSIS_device_header-instead-of-RTE_Components.h.patch b/components/ai/ml_embedded_evaluation_kit/integration/patches/0002-Use-CMSIS_device_header-instead-of-RTE_Components.h.patch index a2dbc692..709068be 100644 --- a/components/ai/ml_embedded_evaluation_kit/integration/patches/0002-Use-CMSIS_device_header-instead-of-RTE_Components.h.patch +++ b/components/ai/ml_embedded_evaluation_kit/integration/patches/0002-Use-CMSIS_device_header-instead-of-RTE_Components.h.patch @@ -1,7 +1,7 @@ -From 6d9a4a9faac936d197a0e2dcb6bf4743acd3d28b Mon Sep 17 00:00:00 2001 +From 8e928e600322eb550d96e41244f6b29463bc75ef Mon Sep 17 00:00:00 2001 From: Ahmed Ismail -Date: Fri, 28 Jun 2024 15:49:47 +0100 -Subject: [PATCH 2/2] Use CMSIS_device_header instead of RTE_Components.h +Date: Thu, 28 Nov 2024 16:13:09 +0000 +Subject: [PATCH 2/4] Use CMSIS_device_header instead of RTE_Components.h Signed-off-by: Gabor Abonyi --- diff --git a/components/ai/ml_embedded_evaluation_kit/integration/patches/0003-Make-ETHOSU_ARCH-configurable-in-TensorFlow-CMake.patch b/components/ai/ml_embedded_evaluation_kit/integration/patches/0003-Make-ETHOSU_ARCH-configurable-in-TensorFlow-CMake.patch index e321956d..b8bb91a0 100644 --- a/components/ai/ml_embedded_evaluation_kit/integration/patches/0003-Make-ETHOSU_ARCH-configurable-in-TensorFlow-CMake.patch +++ b/components/ai/ml_embedded_evaluation_kit/integration/patches/0003-Make-ETHOSU_ARCH-configurable-in-TensorFlow-CMake.patch @@ -1,7 +1,9 @@ -From c5c0bdff764cde7db2c97761a5eff15f55a09dbb Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Gergely=20Korcs=C3=A1k?= -Date: Thu, 8 Aug 2024 17:47:54 +0200 -Subject: [PATCH] Make ETHOSU_ARCH configurable in TensorFlow CMake +From 2f6ec81d61c885b2e36af47d2cc223b4d4761904 Mon Sep 17 00:00:00 2001 +From: Ahmed Ismail +Date: Thu, 28 Nov 2024 16:13:50 +0000 +Subject: [PATCH 3/4] Make ETHOSU_ARCH configurable in TensorFlow CMake + MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 + Content-Transfer-Encoding: 8bit MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit @@ -12,10 +14,10 @@ Signed-off-by: Gergely Korcsák 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/scripts/cmake/tensorflow_lite_micro.cmake b/scripts/cmake/tensorflow_lite_micro.cmake -index 4a988aa..1640626 100644 +index 734c713..c06854a 100644 --- a/scripts/cmake/tensorflow_lite_micro.cmake +++ b/scripts/cmake/tensorflow_lite_micro.cmake -@@ -75,11 +75,7 @@ else() +@@ -130,11 +130,7 @@ else() if(ETHOS_U_NPU_ENABLED) # Arm Ethos-U55 NPU is the co-processor for ML workload: set(TENSORFLOW_LITE_MICRO_CO_PROCESSOR "ethos_u") diff --git a/components/ai/ml_embedded_evaluation_kit/integration/patches/0004-Override-EthosU55-NPU-default-IRQ-handler.patch b/components/ai/ml_embedded_evaluation_kit/integration/patches/0004-Override-EthosU55-NPU-default-IRQ-handler.patch new file mode 100644 index 00000000..9139486d --- /dev/null +++ b/components/ai/ml_embedded_evaluation_kit/integration/patches/0004-Override-EthosU55-NPU-default-IRQ-handler.patch @@ -0,0 +1,69 @@ +From 1a047cff83badc2f6a95e3e78af735abef51ef8a Mon Sep 17 00:00:00 2001 +From: Ahmed Ismail +Date: Thu, 28 Nov 2024 16:14:38 +0000 +Subject: [PATCH 4/4] Override EthosU55 NPU default IRQ handler + +This change is done to avoid modifying the +vector table by setting the Ethos U55 IRQ handler +to `arm_ethosu_npu_irq_handler` in the run-time +using the `NVIC_SetVector()` function where in this +case, the checksum of the non-secure image +is altered which result into failure of MCUBoot non-secure +image validation after ML Model OTA update. + +Now, we are using the default IRQ handler name +`ETHOS_U55_Handler` which is defined as weak inside +the startup file for the platform. This way the vector table +is not altered because we are setting the same IRQ handler function +in the `NVIC_SetVector()` so techincally it has no effect. + +Signed-off-by: Ahmed Ismail +--- + source/hal/source/components/npu/ethosu_npu_init.c | 6 +++--- + source/hal/source/components/npu/include/ethosu_npu_init.h | 2 +- + 2 files changed, 4 insertions(+), 4 deletions(-) + +diff --git a/source/hal/source/components/npu/ethosu_npu_init.c b/source/hal/source/components/npu/ethosu_npu_init.c +index 2cbdb1e..1c8b4f6 100644 +--- a/source/hal/source/components/npu/ethosu_npu_init.c ++++ b/source/hal/source/components/npu/ethosu_npu_init.c +@@ -71,20 +71,20 @@ static void arm_ethosu_npu_irq_init(void) + + /* Register the EthosU IRQ handler in our vector table. + * Note, this handler comes from the EthosU driver */ +- NVIC_SetVector(ethosu_irqnum, (uint32_t)arm_ethosu_npu_irq_handler); ++ NVIC_SetVector(ethosu_irqnum, (uint32_t)ETHOS_U55_Handler); + + /* Enable the IRQ */ + NVIC_EnableIRQ(ethosu_irqnum); + + debug("EthosU IRQ#: %u, Handler: 0x%p\n", +- ethosu_irqnum, arm_ethosu_npu_irq_handler); ++ ethosu_irqnum, ETHOS_U55_Handler); + } + + /** + * @brief Defines the Ethos-U interrupt handler: just a wrapper around the default + * implementation. + **/ +-void arm_ethosu_npu_irq_handler(void) ++void ETHOS_U55_Handler(void) + { + /* Call the default interrupt handler from the NPU driver */ + ethosu_irq_handler(ðosu_drv); +diff --git a/source/hal/source/components/npu/include/ethosu_npu_init.h b/source/hal/source/components/npu/include/ethosu_npu_init.h +index b82386f..243c4a0 100644 +--- a/source/hal/source/components/npu/include/ethosu_npu_init.h ++++ b/source/hal/source/components/npu/include/ethosu_npu_init.h +@@ -29,7 +29,7 @@ int arm_ethosu_npu_init(void); + * @brief Defines the Arm Ethos-U NPU interrupt handler: just a wrapper + * around the default implementation. + **/ +-void arm_ethosu_npu_irq_handler(void); ++void ETHOS_U55_Handler(void); + + #endif /* ARM_NPU */ + +-- +2.34.1 + diff --git a/components/ai/ml_embedded_evaluation_kit/integration/patches/0004-Patch-tensorflow.patch b/components/ai/ml_embedded_evaluation_kit/integration/patches/0005-Patch-tensorflow.patch similarity index 67% rename from components/ai/ml_embedded_evaluation_kit/integration/patches/0004-Patch-tensorflow.patch rename to components/ai/ml_embedded_evaluation_kit/integration/patches/0005-Patch-tensorflow.patch index 162b15de..c150ca89 100644 --- a/components/ai/ml_embedded_evaluation_kit/integration/patches/0004-Patch-tensorflow.patch +++ b/components/ai/ml_embedded_evaluation_kit/integration/patches/0005-Patch-tensorflow.patch @@ -1,7 +1,8 @@ -From 2352b60b03042fc9ea2d9cf9ce861d8e87341e32 Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Gergely=20Korcs=C3=A1k?= -Date: Mon, 12 Aug 2024 15:43:48 +0200 -Subject: [PATCH] Patch tensorflow +From 15c53b15b6588c104081656a98be986e3f91670a Mon Sep 17 00:00:00 2001 +From: Ahmed Ismail +Date: Thu, 28 Nov 2024 16:16:01 +0000 +Subject: [PATCH] Patch tensorflow MIME-Version: 1.0 Content-Type: text/plain; + charset=UTF-8 Content-Transfer-Encoding: 8bit MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit @@ -12,10 +13,10 @@ Signed-off-by: Gergely Korcsák 1 file changed, 4 insertions(+) diff --git a/tensorflow/lite/micro/tools/make/ext_libs/ethos_u.inc b/tensorflow/lite/micro/tools/make/ext_libs/ethos_u.inc -index c61aaff3..81066237 100644 +index 73447cd7..4ef80aec 100644 --- a/tensorflow/lite/micro/tools/make/ext_libs/ethos_u.inc +++ b/tensorflow/lite/micro/tools/make/ext_libs/ethos_u.inc -@@ -64,6 +64,10 @@ else ifeq ($(ETHOSU_ARCH), u65) +@@ -74,6 +74,10 @@ else ifeq ($(ETHOSU_ARCH), u65) ETHOSU_FLAGS += \ -DETHOSU_ARCH=u65 \ -DETHOSU65 diff --git a/components/security/freertos_ota_pal_psa/CMakeLists.txt b/components/security/freertos_ota_pal_psa/CMakeLists.txt index dc54dbe1..fc55240d 100644 --- a/components/security/freertos_ota_pal_psa/CMakeLists.txt +++ b/components/security/freertos_ota_pal_psa/CMakeLists.txt @@ -1,4 +1,4 @@ -# Copyright 2023-2024 Arm Limited and/or its affiliates +# Copyright 2023-2025 Arm Limited and/or its affiliates # # SPDX-License-Identifier: MIT @@ -15,6 +15,9 @@ if(CMAKE_CROSSCOMPILING) set(PATCH_FILES "${PATCH_FILES_DIRECTORY}/0001-ota-abort-Fix-successful-abortion-check.patch" "${PATCH_FILES_DIRECTORY}/0002-Update-FreeRTOS-OTA-PAL-PSA-to-work-with-new-modular.patch" + "${PATCH_FILES_DIRECTORY}/0003-component-ID-Add-ML-model-file-path.patch" + "${PATCH_FILES_DIRECTORY}/0004-app-version-Do-not-store-version-in-a-global-var.patch" + "${PATCH_FILES_DIRECTORY}/0005-PAL-Implement-component-version-getter.patch" ) iot_reference_arm_corstone3xx_apply_patches("${freertos_ota_pal_psa_SOURCE_DIR}" "${PATCH_FILES}") diff --git a/components/security/freertos_ota_pal_psa/integration/patches/0001-ota-abort-Fix-successful-abortion-check.patch b/components/security/freertos_ota_pal_psa/integration/patches/0001-ota-abort-Fix-successful-abortion-check.patch index 4a629374..f0dd898f 100644 --- a/components/security/freertos_ota_pal_psa/integration/patches/0001-ota-abort-Fix-successful-abortion-check.patch +++ b/components/security/freertos_ota_pal_psa/integration/patches/0001-ota-abort-Fix-successful-abortion-check.patch @@ -1,7 +1,7 @@ -From 70721e0c00a9e698df467e81e1ad3b54cf76edf4 Mon Sep 17 00:00:00 2001 +From 2afe0bd72fc141a4122647e94ae73b8465b6da0e Mon Sep 17 00:00:00 2001 From: Ahmed Ismail -Date: Wed, 17 Jan 2024 11:00:09 +0000 -Subject: [PATCH] ota-abort: Fix successful abortion check +Date: Tue, 14 Jan 2025 17:14:24 +0000 +Subject: [PATCH 1/5] ota-abort: Fix successful abortion check PsaStatus variable should be initialized before being accessed as in the happy path scenario the diff --git a/components/security/freertos_ota_pal_psa/integration/patches/0002-Update-FreeRTOS-OTA-PAL-PSA-to-work-with-new-modular.patch b/components/security/freertos_ota_pal_psa/integration/patches/0002-Update-FreeRTOS-OTA-PAL-PSA-to-work-with-new-modular.patch index 4e676bb7..d32227c6 100644 --- a/components/security/freertos_ota_pal_psa/integration/patches/0002-Update-FreeRTOS-OTA-PAL-PSA-to-work-with-new-modular.patch +++ b/components/security/freertos_ota_pal_psa/integration/patches/0002-Update-FreeRTOS-OTA-PAL-PSA-to-work-with-new-modular.patch @@ -1,7 +1,7 @@ -From 45ee1cd5754d0c445bc500ed137adb896e33497a Mon Sep 17 00:00:00 2001 -From: Chuyue Luo -Date: Thu, 5 Dec 2024 10:53:50 +0000 -Subject: [PATCH 2/2] Update FreeRTOS OTA PAL PSA to work with new modular OTA +From e18baace8db06e3c74373dd7efe09f85f41a6770 Mon Sep 17 00:00:00 2001 +From: Ahmed Ismail +Date: Tue, 14 Jan 2025 17:19:43 +0000 +Subject: [PATCH 2/5] Update FreeRTOS OTA PAL PSA to work with new modular OTA This patch is taken from https://github.com/Linaro/freertos-ota-pal-psa/commit/bfef9705b92badfa5bcb388f4d1cf512b27c5a5f.patch @@ -17,11 +17,9 @@ Jobs-for-AWS-IoT-embedded-sdk library. Signed-off-by: Chuyue Luo --- - ota_pal.c | 172 +++++++++++++++++----------------- - ota_pal.h | 77 +++++++++++++-- - version/application_version.c | 38 +++++++- - version/application_version.h | 3 +- - 4 files changed, 192 insertions(+), 98 deletions(-) + ota_pal.c | 172 +++++++++++++++++++++++++++--------------------------- + ota_pal.h | 77 ++++++++++++++++++++---- + 2 files changed, 154 insertions(+), 95 deletions(-) diff --git a/ota_pal.c b/ota_pal.c index 165c146..9b7e6f4 100644 @@ -688,79 +686,6 @@ index c530620..4c95bda 100644 -OtaPalStatus_t otaPal_ResetDevice( OtaFileContext_t * const pFileContext ); +bool otaPal_ResetDevice( AfrOtaJobDocumentFields_t * const pFileContext ); #endif /* ifndef OTA_PAL_H_ */ -diff --git a/version/application_version.c b/version/application_version.c -index 7b38c6a..68c715f 100644 ---- a/version/application_version.c -+++ b/version/application_version.c -@@ -1,5 +1,5 @@ - /* -- * Copyright (c) 2020-2022 Arm Limited. All rights reserved. -+ * Copyright (c) 2020-2024 Arm Limited. All rights reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a copy of - * this software and associated documentation files (the "Software"), to deal in -@@ -33,6 +33,42 @@ - #include "FreeRTOS.h" - #include "application_version.h" - -+/** -+ * @ingroup ota_struct_types -+ * @brief Application version structure. -+ * -+ */ -+typedef struct -+{ -+ /* MISRA Ref 19.2.1 [Unions] */ -+ /* More details at: https://github.com/aws/ota-for-aws-iot-embedded-sdk/blob/main/MISRA.md#rule-192 */ -+ /* coverity[misra_c_2012_rule_19_2_violation] */ -+ union -+ { -+ #if ( defined( __BYTE_ORDER__ ) && defined( __ORDER_LITTLE_ENDIAN__ ) && ( __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ ) ) || ( __little_endian__ == 1 ) || WIN32 || ( __BYTE_ORDER == __LITTLE_ENDIAN ) -+ struct version -+ { -+ uint16_t build; /*!< @brief Build of the firmware (Z in firmware version Z.Y.X). */ -+ uint8_t minor; /*!< @brief Minor version number of the firmware (Y in firmware version Z.Y.X). */ -+ -+ uint8_t major; /*!< @brief Major version number of the firmware (X in firmware version Z.Y.X). */ -+ } x; /*!< @brief Version number of the firmware. */ -+ #elif ( defined( __BYTE_ORDER__ ) && defined( __ORDER_BIG_ENDIAN__ ) && __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__ ) || ( __big_endian__ == 1 ) || ( __BYTE_ORDER == __BIG_ENDIAN ) -+ struct version -+ { -+ uint8_t major; /*!< @brief Major version number of the firmware (X in firmware version X.Y.Z). */ -+ uint8_t minor; /*!< @brief Minor version number of the firmware (Y in firmware version X.Y.Z). */ -+ -+ uint16_t build; /*!< @brief Build of the firmware (Z in firmware version X.Y.Z). */ -+ } x; /*!< @brief Version number of the firmware. */ -+ #else /* if ( defined( __BYTE_ORDER__ ) && defined( __ORDER_LITTLE_ENDIAN__ ) && __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ ) || ( __little_endian__ == 1 ) || WIN32 || ( __BYTE_ORDER == __LITTLE_ENDIAN ) */ -+ #error "Unable to determine byte order!" -+ #endif /* if ( defined( __BYTE_ORDER__ ) && defined( __ORDER_LITTLE_ENDIAN__ ) && __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ ) || ( __little_endian__ == 1 ) || WIN32 || ( __BYTE_ORDER == __LITTLE_ENDIAN ) */ -+ uint32_t unsignedVersion32; -+ int32_t signedVersion32; -+ } u; /*!< @brief Version based on configuration in big endian or little endian. */ -+} AppVersion32_t; -+ - AppVersion32_t appFirmwareVersion; - - int GetImageVersionPSA( psa_fwu_component_t uxComponent ) -diff --git a/version/application_version.h b/version/application_version.h -index 7775910..a790df7 100644 ---- a/version/application_version.h -+++ b/version/application_version.h -@@ -1,5 +1,5 @@ - /* -- * Copyright (c) 2020-2022 Arm Limited. All rights reserved. -+ * Copyright (c) 2020-2024 Arm Limited. All rights reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a copy of - * this software and associated documentation files (the "Software"), to deal in -@@ -24,7 +24,6 @@ - #define APPLICATION_VERSION_H_ - - #include "ota_config.h" --#include "ota_appversion32.h" - #include "psa/update.h" - - /** -- -2.47.0 +2.34.1 diff --git a/components/security/freertos_ota_pal_psa/integration/patches/0003-component-ID-Add-ML-model-file-path.patch b/components/security/freertos_ota_pal_psa/integration/patches/0003-component-ID-Add-ML-model-file-path.patch new file mode 100644 index 00000000..d81d3586 --- /dev/null +++ b/components/security/freertos_ota_pal_psa/integration/patches/0003-component-ID-Add-ML-model-file-path.patch @@ -0,0 +1,34 @@ +From abc28629fb60834dd85bc9065132d413e416a4c0 Mon Sep 17 00:00:00 2001 +From: Ahmed Ismail +Date: Tue, 14 Jan 2025 17:20:31 +0000 +Subject: [PATCH 3/5] component ID: Add ML model file path + +Update the PortConvertFilePathtoPSAComponentID function to support the +ML model image file path, to enable the model-only OTA update. + +Signed-off-by: Filip Jagodzinski +--- + ota_pal.c | 7 +++++++ + 1 file changed, 7 insertions(+) + +diff --git a/ota_pal.c b/ota_pal.c +index 9b7e6f4..9641106 100644 +--- a/ota_pal.c ++++ b/ota_pal.c +@@ -228,6 +228,13 @@ static bool PortConvertFilePathtoPSAComponentID ( AfrOtaJobDocumentFields_t * co + return true; + } + #endif ++#ifdef FWU_COMPONENT_ID_ML_MODEL ++ if( memcmp( pFileContext->filepath, "ml_model image", strlen("ml_model image") ) == 0 ) ++ { ++ *pxComponent = FWU_COMPONENT_ID_ML_MODEL; ++ return true; ++ } ++#endif + #ifdef FWU_COMPONENT_ID_FULL + if( memcmp( pFileContext->filepath, "combined image", strlen("combined image") ) == 0 ) + { +-- +2.34.1 + diff --git a/components/security/freertos_ota_pal_psa/integration/patches/0004-app-version-Do-not-store-version-in-a-global-var.patch b/components/security/freertos_ota_pal_psa/integration/patches/0004-app-version-Do-not-store-version-in-a-global-var.patch new file mode 100644 index 00000000..7a49bd33 --- /dev/null +++ b/components/security/freertos_ota_pal_psa/integration/patches/0004-app-version-Do-not-store-version-in-a-global-var.patch @@ -0,0 +1,98 @@ +From 61b9e8cc2595a551d6bedd0f50fa87d78e1dc63d Mon Sep 17 00:00:00 2001 +From: Ahmed Ismail +Date: Tue, 14 Jan 2025 17:22:04 +0000 +Subject: [PATCH 4/5] app-version: Do not store version in a global var + +Storing the component image version in a single variable makes +multi-component setup impossible to handle correctly. + +Update the image version getter to write the component version to an +output param. + +Signed-off-by: Filip Jagodzinski +--- + version/application_version.c | 16 ++++++++-------- + version/application_version.h | 25 ++++++++++++------------- + 2 files changed, 20 insertions(+), 21 deletions(-) + +diff --git a/version/application_version.c b/version/application_version.c +index 7b38c6a..a44d284 100644 +--- a/version/application_version.c ++++ b/version/application_version.c +@@ -1,5 +1,5 @@ + /* +- * Copyright (c) 2020-2022 Arm Limited. All rights reserved. ++ * Copyright (c) 2020-2024 Arm Limited. All rights reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of + * this software and associated documentation files (the "Software"), to deal in +@@ -33,24 +33,24 @@ + #include "FreeRTOS.h" + #include "application_version.h" + +-AppVersion32_t appFirmwareVersion; +- +-int GetImageVersionPSA( psa_fwu_component_t uxComponent ) ++int GetImageVersionPSA( psa_fwu_component_t uxComponent, AppVersion32_t *pxVersion ) + { + psa_fwu_component_info_t xComponentInfo = { 0 }; + psa_status_t uxStatus; + ++ configASSERT( pxVersion != NULL ); ++ + uxStatus = psa_fwu_query( uxComponent, &xComponentInfo ); + if( uxStatus == PSA_SUCCESS ) + { +- appFirmwareVersion.u.x.major = xComponentInfo.version.major; +- appFirmwareVersion.u.x.minor = xComponentInfo.version.minor; +- appFirmwareVersion.u.x.build = (uint16_t)xComponentInfo.version.build; ++ pxVersion->u.x.major = xComponentInfo.version.major; ++ pxVersion->u.x.minor = xComponentInfo.version.minor; ++ pxVersion->u.x.build = (uint16_t)xComponentInfo.version.build; + return 0; + } + else + { +- appFirmwareVersion.u.signedVersion32 = 0; ++ pxVersion->u.signedVersion32 = 0; + return -1; + } + } +diff --git a/version/application_version.h b/version/application_version.h +index 7775910..fcd8b85 100644 +--- a/version/application_version.h ++++ b/version/application_version.h +@@ -28,18 +28,17 @@ + #include "psa/update.h" + + /** +- * @brief Get the running image version of the given component. +- * +- * Get the image version by PSA Firmware update service API and assign it to xAppFirmwareVersion +- * which is use in the ota agent. +- * +- * @note portALLOCATE_SECURE_CONTEXT( 0 ) should be called before this function, otherwise this function +- * will always fail. +- * @param[in] N/A. +- * +- * @return 0 on success and the xAppFirmwareVersion is assigned with the value read from the Firmware +- * update service. -1 on failure and the xAppFirmwareVersion is 0. +- */ +-int GetImageVersionPSA( psa_fwu_component_t uxComponent ); ++* @brief Get the running image version of the given component. ++* ++* Get the image version by PSA Firmware update service API and assign it to pxVersion. ++* ++* @note portALLOCATE_SECURE_CONTEXT( 0 ) should be called before this function, otherwise this function ++* will always fail. ++* @param[in] uxComponent Firmware component for which information is requested. ++* @param[out] pxVersion Output parameter for version information. On failure this is set to 0. ++* ++* @return 0 on success and -1 on failure. ++*/ ++int GetImageVersionPSA( psa_fwu_component_t uxComponent, AppVersion32_t *pxVersion ); + + #endif +-- +2.34.1 + diff --git a/components/security/freertos_ota_pal_psa/integration/patches/0005-PAL-Implement-component-version-getter.patch b/components/security/freertos_ota_pal_psa/integration/patches/0005-PAL-Implement-component-version-getter.patch new file mode 100644 index 00000000..e93b1b74 --- /dev/null +++ b/components/security/freertos_ota_pal_psa/integration/patches/0005-PAL-Implement-component-version-getter.patch @@ -0,0 +1,100 @@ +From 3c82d8c479d0690815cfeb63aaa2c27a8ec406a3 Mon Sep 17 00:00:00 2001 +From: Ahmed Ismail +Date: Tue, 14 Jan 2025 17:22:46 +0000 +Subject: [PATCH 5/5] PAL: Implement component version getter + +Multi-component setup requires independent version handling for each +component. Add an implementation for the extended API used for reading +OTA update image version. + +Signed-off-by: Filip Jagodzinski +--- + ota_pal.c | 40 ++++++++++++++++++++++++++++++++++++++++ + ota_pal.h | 13 +++++++++++++ + 2 files changed, 53 insertions(+) + +diff --git a/ota_pal.c b/ota_pal.c +index 9641106..7dc9574 100644 +--- a/ota_pal.c ++++ b/ota_pal.c +@@ -747,6 +747,46 @@ OtaPalImageState_t otaPal_GetPlatformImageState( AfrOtaJobDocumentFields_t * con + /* It should never goes here. But just for coding safety. */ + return OtaPalImageStateInvalid; + } ++ ++/** ++ * @brief Get the version of the OTA update image. ++ * ++ * @param[in] pFileContext File context of type AfrOtaJobDocumentFields_t. ++ * @param[out] pxVersion Output parameter for version information. ++ * ++ * @return true in case the platform image version is fetched successfully. ++ * false in case the platform image version is not fetched successfully. ++ */ ++bool otaPal_GetPlatformImageVersion( AfrOtaJobDocumentFields_t * const pFileContext, ++ AppVersion32_t * pxVersion ) ++{ ++ psa_fwu_component_t uxComponent; ++ psa_status_t uxStatus; ++ psa_fwu_component_info_t xComponentInfo = { 0 }; ++ ++ if( pFileContext == NULL || pxVersion == NULL ) ++ { ++ return false; ++ } ++ ++ if( PortConvertFilePathtoPSAComponentID( pFileContext, &uxComponent ) != true ) ++ { ++ return false; ++ } ++ ++ uxStatus = psa_fwu_query( uxComponent, &xComponentInfo ); ++ if( uxStatus != PSA_SUCCESS ) ++ { ++ return false; ++ } ++ ++ pxVersion->u.x.major = xComponentInfo.version.major; ++ pxVersion->u.x.minor = xComponentInfo.version.minor; ++ pxVersion->u.x.build = (uint16_t)xComponentInfo.version.build; ++ ++ return true; ++} ++ + /** + * @brief Reset the device. + * +diff --git a/ota_pal.h b/ota_pal.h +index 4c95bda..724cf77 100644 +--- a/ota_pal.h ++++ b/ota_pal.h +@@ -34,6 +34,7 @@ + #define OTA_PAL_H_ + + #include "job_parser.h" ++#include "ota_appversion32.h" + + /* OTA PAL signing algorithm configurations. */ + #define OTA_PAL_CODE_SIGNING_RSA ( 0 ) +@@ -288,6 +289,18 @@ bool otaPal_SetPlatformImageState( AfrOtaJobDocumentFields_t * const pFileContex + */ + OtaPalImageState_t otaPal_GetPlatformImageState( AfrOtaJobDocumentFields_t * const pFileContext ); + ++/** ++ * @brief Get the version of the OTA update image. ++ * ++ * @param[in] pFileContext File context of type AfrOtaJobDocumentFields_t. ++ * @param[out] pxVersion Output parameter for version information. ++ * ++ * @return true in case the platform image version is fetched successfully. ++ * false in case the platform image version is not fetched successfully. ++ */ ++bool otaPal_GetPlatformImageVersion( AfrOtaJobDocumentFields_t * const pFileContext, ++ AppVersion32_t * pxVersion ); ++ + /** + * @brief Reset the device. + * +-- +2.34.1 + diff --git a/components/security/trusted_firmware-m/CMakeLists.txt b/components/security/trusted_firmware-m/CMakeLists.txt index 9a259c67..4754cec2 100644 --- a/components/security/trusted_firmware-m/CMakeLists.txt +++ b/components/security/trusted_firmware-m/CMakeLists.txt @@ -1,4 +1,4 @@ -# Copyright 2023-2024, Arm Limited and/or its affiliates +# Copyright 2023-2025, Arm Limited and/or its affiliates # # SPDX-License-Identifier: MIT @@ -12,5 +12,19 @@ set(trusted_firmware-m_SOURCE_DIR if(BUILD_TESTING AND NOT CMAKE_CROSSCOMPILING) add_subdirectory(library_mocks) else() + # This patch is only applied in case of building keyword_detection application with GNU toolchain + # as it is currently the only application that utilises the ML Model component OTA update feature + # where this patch is needed. + if((${APPLICATION_PATH} MATCHES ".*keyword_detection") AND (${CMAKE_C_COMPILER_ID} STREQUAL "GNU")) + include(ApplyPatches) + + set(PATCH_FILES_DIRECTORY "${CMAKE_CURRENT_LIST_DIR}/integration/patches") + set(PATCH_FILES + "${PATCH_FILES_DIRECTORY}/0001-corstone300-Add-ML-model-component.patch" + "${PATCH_FILES_DIRECTORY}/0002-corstone310-Add-ML-model-component.patch" + "${PATCH_FILES_DIRECTORY}/0003-mps4-Add-ML-model-component.patch" + ) + iot_reference_arm_corstone3xx_apply_patches("${trusted_firmware-m_SOURCE_DIR}" "${PATCH_FILES}") + endif() add_subdirectory(integration) endif() diff --git a/components/security/trusted_firmware-m/integration/CMakeLists.txt b/components/security/trusted_firmware-m/integration/CMakeLists.txt index 4b46a510..699040d3 100644 --- a/components/security/trusted_firmware-m/integration/CMakeLists.txt +++ b/components/security/trusted_firmware-m/integration/CMakeLists.txt @@ -1,4 +1,4 @@ -# Copyright 2021-2024, Arm Limited and/or its affiliates +# Copyright 2021-2025, Arm Limited and/or its affiliates # # SPDX-License-Identifier: MIT @@ -31,7 +31,6 @@ target_compile_definitions(tfm-ns-interface # Corstone-315 is not using the default crypto keys, it is defined in the TF-M platform port $<$:PLATFORM_DEFAULT_CRYPTO_KEYS> $<$:PLATFORM_DEFAULT_CRYPTO_KEYS> - MCUBOOT_IMAGE_NUMBER=2 ) add_library(tfm-ns-interface-mbedtls-config INTERFACE) diff --git a/components/security/trusted_firmware-m/integration/cmake/MergeTfmImages.cmake b/components/security/trusted_firmware-m/integration/cmake/MergeTfmImages.cmake index 72fd0c6b..1d9404cb 100644 --- a/components/security/trusted_firmware-m/integration/cmake/MergeTfmImages.cmake +++ b/components/security/trusted_firmware-m/integration/cmake/MergeTfmImages.cmake @@ -1,4 +1,4 @@ -# Copyright 2023-2024, Arm Limited and/or its affiliates +# Copyright 2023-2025, Arm Limited and/or its affiliates # # SPDX-License-Identifier: MIT @@ -29,6 +29,11 @@ function(iot_reference_arm_corstone3xx_tf_m_merge_images target) else() set(ddr_binary_param "") endif() + if(DEFINED ARGV5 AND DEFINED ARGV6) + set(model_binary_param ${ARGV6} -Binary -offset ${ARGV5}) + else() + set(model_binary_param "") + endif() find_program(srec_cat NAMES srec_cat REQUIRED) find_program(objcopy NAMES arm-none-eabi-objcopy objcopy REQUIRED) if(ARM_CORSTONE_BSP_TARGET_PLATFORM STREQUAL "corstone300" OR ARM_CORSTONE_BSP_TARGET_PLATFORM STREQUAL "corstone310") @@ -44,6 +49,7 @@ function(iot_reference_arm_corstone3xx_tf_m_merge_images target) $/${target}_signed.bin -Binary -offset ${NS_IMAGE_LOAD_ADDRESS} ${ddr_binary_param} ${ns_provisioning_data_param} + ${model_binary_param} ${BINARY_DIR}/api_ns/bin/provisioning_bundle.bin -Binary -offset ${S_PROVISIONING_BUNDLE_LOAD_ADDRESS} -o $/${target}_merged.hex COMMAND @@ -68,6 +74,7 @@ function(iot_reference_arm_corstone3xx_tf_m_merge_images target) ${BINARY_DIR}/api_ns/bin/bl2_signed.bin -Binary -offset ${BL2_IMAGE_LOAD_ADDRESS} ${BINARY_DIR}/api_ns/bin/tfm_s_signed.bin -Binary -offset ${S_IMAGE_LOAD_ADDRESS} $/${target}_signed.bin -Binary -offset ${NS_IMAGE_LOAD_ADDRESS} + ${model_binary_param} ${ddr_binary_param} ${ns_provisioning_data_param} -o $/${target}_merged.hex diff --git a/components/security/trusted_firmware-m/integration/cmake/SignTfmImage.cmake b/components/security/trusted_firmware-m/integration/cmake/SignTfmImage.cmake index d1df1e48..e74fa932 100644 --- a/components/security/trusted_firmware-m/integration/cmake/SignTfmImage.cmake +++ b/components/security/trusted_firmware-m/integration/cmake/SignTfmImage.cmake @@ -1,4 +1,4 @@ -# Copyright 2023-2024 Arm Limited and/or its affiliates +# Copyright 2023-2025 Arm Limited and/or its affiliates # # SPDX-License-Identifier: MIT @@ -8,22 +8,15 @@ include(ExternalProject) ExternalProject_Get_Property(trusted_firmware-m-build BINARY_DIR) -function(iot_reference_arm_corstone3xx_tf_m_sign_image target signed_target_name version pad) +# This function is documented under `Image signing` section in `trusted_firmware-m.md` document located at +# `${IOT_REFERENCE_ARM_CORSTONE3XX_SOURCE_DIR}/docs/components/security/` directory. +function(iot_reference_arm_corstone3xx_tf_m_sign_image target unsigned_image_bin_name signed_bin_name signed_bin_version signature_layout_file pad) if(${pad}) set(pad_option "--pad") else() set(pad_option "") endif() - set(LINKER_SECTION_NAMES "ddr.bin") - set(OUTPUT_BINARY_NAME "flash") - - extract_sections_from_axf( - ${target} - SECTIONS_NAMES "${LINKER_SECTION_NAMES}" - OUTPUT_BIN_NAME "${OUTPUT_BINARY_NAME}" - ) - add_custom_command( TARGET ${target} @@ -33,17 +26,17 @@ function(iot_reference_arm_corstone3xx_tf_m_sign_image target signed_target_name COMMAND # Sign the non-secure (application) image for TF-M bootloader (BL2) python3 ${BINARY_DIR}/api_ns/image_signing/scripts/wrapper/wrapper.py - -v ${version} - --layout ${BINARY_DIR}/api_ns/image_signing/layout_files/signing_layout_ns.o + -v ${signed_bin_version} + --layout ${signature_layout_file} -k ${BINARY_DIR}/api_ns/image_signing/keys/image_ns_signing_private_key.pem --public-key-format full --align 1 --pad-header ${pad_option} -H 0x400 -s auto --measured-boot-record --confirm - ${SECTORS_BIN_DIR}/${OUTPUT_BINARY_NAME}.bin - $/${signed_target_name}.bin + ${SECTORS_BIN_DIR}/${unsigned_image_bin_name}.bin + $/${signed_bin_name}.bin COMMAND - ${CMAKE_COMMAND} -E echo "-- signed: $/${signed_target_name}.bin" + ${CMAKE_COMMAND} -E echo "-- signed: $/${signed_bin_name}.bin" VERBATIM ) endfunction() diff --git a/components/security/trusted_firmware-m/integration/patches/0001-corstone300-Add-ML-model-component.patch b/components/security/trusted_firmware-m/integration/patches/0001-corstone300-Add-ML-model-component.patch new file mode 100644 index 00000000..d86407a3 --- /dev/null +++ b/components/security/trusted_firmware-m/integration/patches/0001-corstone300-Add-ML-model-component.patch @@ -0,0 +1,507 @@ +From 6128f015c59483f6c6e02b8c62df0f8fb00a3995 Mon Sep 17 00:00:00 2001 +From: Ahmed Ismail +Date: Thu, 5 Dec 2024 10:56:59 +0000 +Subject: [PATCH 1/3] corstone300: Add ML model component + +As the TF-M is currently configured to enable a 2 image operation (for +the Secure and Non-Secure components), an update is required to enable +an ML-model-only OTA update, with the use of a new, third TF-M +component. + +Enable a 3-component TF-M setup. Apart from the standard Secure and +Non-Secure images, a third, Non-Secure ML model image is added to the +mix. To keep changes minimal, the NS partition is re-sized from 0x340000 +B to 0x240000 B, and the remaining 0x100000 B are used for the ML model. + +- Enable MCUBoot to support a 3 image setup. +- Add signing layout for the ML model image. +- Add provisioning data and SPE config for the ML model image. +- Add a custom, 3-image flash map, where the ML model image partition is +created at the cost of reduced NS partition size. +- Keep addresses of the Secure, Non-Secure and Scratch partitions +unchanged. +- Keep sizes of the Secure and Scratch partitions unchanged. + +Signed-off-by: Filip Jagodzinski +Signed-off-by: Ahmed Ismail +--- + bl2/ext/mcuboot/CMakeLists.txt | 24 +++ + bl2/ext/mcuboot/include/sysflash/sysflash.h | 9 ++ + cmake/install.cmake | 5 + + config/spe_config.cmake.in | 5 + + interface/include/psa/fwu_config.h.in | 1 + + .../common/provisioning_bundle/CMakeLists.txt | 1 + + .../arm/mps3/corstone300/an552/config.cmake | 1 + + .../corstone300/common/bl2/flash_map_bl2.c | 144 ++++++++++++++++++ + .../arm/mps3/corstone300/common/common.cmake | 16 +- + .../arm/mps3/corstone300/common/config.cmake | 3 +- + .../common/partition/flash_layout.h | 86 ++++++++++- + .../common/partition/region_defs.h | 10 +- + 12 files changed, 300 insertions(+), 5 deletions(-) + create mode 100644 platform/ext/target/arm/mps3/corstone300/common/bl2/flash_map_bl2.c + +diff --git a/bl2/ext/mcuboot/CMakeLists.txt b/bl2/ext/mcuboot/CMakeLists.txt +index 795bfc618..deb733935 100644 +--- a/bl2/ext/mcuboot/CMakeLists.txt ++++ b/bl2/ext/mcuboot/CMakeLists.txt +@@ -234,6 +234,30 @@ if (PLATFORM_DEFAULT_IMAGE_SIGNING) + platform_bl2 + ) + ++ if(MCUBOOT_IMAGE_NUMBER GREATER 2) ++ set(IMAGE_TYPE "NS_ML_MODEL_IMAGE") ++ set(FLASH_AREA_NUM ${MCUBOOT_NS_ML_MODEL_IMAGE_FLASH_AREA_NUM}) ++ configure_file(signing_layout.c.in signing_layout_ns_ml_model.c @ONLY) ++ ++ add_library(signing_layout_ns_ml_model OBJECT ${CMAKE_CURRENT_BINARY_DIR}/signing_layout_ns_ml_model.c) ++ target_compile_options(signing_layout_ns_ml_model ++ PRIVATE ++ $<$:-E\;-xc> ++ $<$:-E\;-xc> ++ $<$:--preprocess=ns\;$> ++ ) ++ target_compile_definitions(signing_layout_ns_ml_model ++ PRIVATE ++ $<$:BL2> ++ $<$:MCUBOOT_IMAGE_NUMBER=${MCUBOOT_IMAGE_NUMBER}> ++ $<$:IMAGE_ROM_FIXED> ++ ) ++ target_link_libraries(signing_layout_ns_ml_model ++ PRIVATE ++ platform_bl2 ++ ) ++ endif() ++ + add_custom_target(signed_images + ALL + DEPENDS tfm_s_signed_bin +diff --git a/bl2/ext/mcuboot/include/sysflash/sysflash.h b/bl2/ext/mcuboot/include/sysflash/sysflash.h +index b5d166dc4..af13275bd 100644 +--- a/bl2/ext/mcuboot/include/sysflash/sysflash.h ++++ b/bl2/ext/mcuboot/include/sysflash/sysflash.h +@@ -39,6 +39,15 @@ extern "C" { + #define FLASH_AREA_IMAGE_SECONDARY(x) (((x) == 0) ? FLASH_AREA_2_ID : \ + ((x) == 1) ? FLASH_AREA_3_ID : \ + 255 ) ++#elif (MCUBOOT_IMAGE_NUMBER == 3) ++#define FLASH_AREA_IMAGE_PRIMARY(x) (((x) == 0) ? FLASH_AREA_0_ID : \ ++ ((x) == 1) ? FLASH_AREA_1_ID : \ ++ ((x) == 2) ? FLASH_AREA_1_0_ID : \ ++ 255 ) ++#define FLASH_AREA_IMAGE_SECONDARY(x) (((x) == 0) ? FLASH_AREA_2_ID : \ ++ ((x) == 1) ? FLASH_AREA_3_ID : \ ++ ((x) == 2) ? FLASH_AREA_3_0_ID : \ ++ 255 ) + #else + #error "Image slot and flash area mapping is not defined" + #endif +diff --git a/cmake/install.cmake b/cmake/install.cmake +index d98bef1a7..6fcd11b9b 100644 +--- a/cmake/install.cmake ++++ b/cmake/install.cmake +@@ -223,6 +223,11 @@ if(BL2 AND PLATFORM_DEFAULT_IMAGE_SIGNING) + install(FILES $/image_ns_signing_public_key.pem + DESTINATION ${INSTALL_IMAGE_SIGNING_DIR}/keys) + endif() ++ ++ if(MCUBOOT_IMAGE_NUMBER GREATER 2) ++ install(FILES $ ++ DESTINATION ${INSTALL_IMAGE_SIGNING_DIR}/layout_files) ++ endif() + endif() + + if(TFM_PARTITION_FIRMWARE_UPDATE) +diff --git a/config/spe_config.cmake.in b/config/spe_config.cmake.in +index 5ca964003..3731facd9 100644 +--- a/config/spe_config.cmake.in ++++ b/config/spe_config.cmake.in +@@ -43,6 +43,11 @@ set(MCUBOOT_KEY_S @MCUBOOT_INSTALL_KEY_S@) + set(MCUBOOT_SECURITY_COUNTER_NS @MCUBOOT_SECURITY_COUNTER_NS@) + set(MCUBOOT_IMAGE_VERSION_NS @MCUBOOT_IMAGE_VERSION_NS@) + set(MCUBOOT_KEY_NS @MCUBOOT_INSTALL_KEY_NS@) ++ ++set(MCUBOOT_SECURITY_COUNTER_NS_ML_MODEL @MCUBOOT_SECURITY_COUNTER_NS_ML_MODEL@) ++set(MCUBOOT_IMAGE_VERSION_NS_ML_MODEL @MCUBOOT_IMAGE_VERSION_NS_ML_MODEL@) ++set(MCUBOOT_KEY_NS_ML_MODEL @MCUBOOT_INSTALL_KEY_NS_ML_MODEL@) ++ + set(PLATFORM_DEFAULT_IMAGE_SIGNING @PLATFORM_DEFAULT_IMAGE_SIGNING@) + + # The common options describing a platform configuration +diff --git a/interface/include/psa/fwu_config.h.in b/interface/include/psa/fwu_config.h.in +index 1e3eca65b..81ac9f2e8 100644 +--- a/interface/include/psa/fwu_config.h.in ++++ b/interface/include/psa/fwu_config.h.in +@@ -20,6 +20,7 @@ + #if FWU_COMPONENT_NUMBER > 1 + #define FWU_COMPONENT_ID_SECURE 0x00U + #define FWU_COMPONENT_ID_NONSECURE 0x01U ++#define FWU_COMPONENT_ID_ML_MODEL 0x02U + #else + #define FWU_COMPONENT_ID_FULL 0x00U + #endif +diff --git a/platform/ext/common/provisioning_bundle/CMakeLists.txt b/platform/ext/common/provisioning_bundle/CMakeLists.txt +index 915b99238..39364218d 100644 +--- a/platform/ext/common/provisioning_bundle/CMakeLists.txt ++++ b/platform/ext/common/provisioning_bundle/CMakeLists.txt +@@ -124,6 +124,7 @@ add_custom_command(OUTPUT provisioning_data.c + ${CMAKE_CURRENT_BINARY_DIR}/provisioning_data.c + --bl2_rot_priv_key_0=${MCUBOOT_KEY_S} + --bl2_rot_priv_key_1=${MCUBOOT_KEY_NS} ++ --bl2_rot_priv_key_2=${MCUBOOT_KEY_NS} + --bl2_mcuboot_hw_key=${MCUBOOT_HW_KEY} + --template_path=${CMAKE_CURRENT_SOURCE_DIR} + --secure_debug_pk=${SECURE_DEBUG_PK} +diff --git a/platform/ext/target/arm/mps3/corstone300/an552/config.cmake b/platform/ext/target/arm/mps3/corstone300/an552/config.cmake +index bfad1ed35..14aa0c97c 100644 +--- a/platform/ext/target/arm/mps3/corstone300/an552/config.cmake ++++ b/platform/ext/target/arm/mps3/corstone300/an552/config.cmake +@@ -12,3 +12,4 @@ include(${CORSTONE300_COMMON_DIR}/config.cmake) + set(PROVISIONING_CODE_PADDED_SIZE "0x2400" CACHE STRING "") + set(PROVISIONING_VALUES_PADDED_SIZE "0x400" CACHE STRING "") + set(PROVISIONING_DATA_PADDED_SIZE "0x400" CACHE STRING "") ++set(DEFAULT_MCUBOOT_FLASH_MAP OFF CACHE BOOL "Whether to use the default flash map defined by TF-M project") +diff --git a/platform/ext/target/arm/mps3/corstone300/common/bl2/flash_map_bl2.c b/platform/ext/target/arm/mps3/corstone300/common/bl2/flash_map_bl2.c +new file mode 100644 +index 000000000..398222b26 +--- /dev/null ++++ b/platform/ext/target/arm/mps3/corstone300/common/bl2/flash_map_bl2.c +@@ -0,0 +1,144 @@ ++/* ++ * Copyright (c) 2021, 2024, Arm Limited. All rights reserved. ++ * ++ * SPDX-License-Identifier: BSD-3-Clause ++ * ++ */ ++ ++#include ++#include "flash_map/flash_map.h" ++#include "target.h" ++#include "Driver_Flash.h" ++ ++/* When undefined FLASH_DEV_NAME_0 or FLASH_DEVICE_ID_0 , default */ ++#if !defined(FLASH_DEV_NAME_0) || !defined(FLASH_DEVICE_ID_0) ++#define FLASH_DEV_NAME_0 FLASH_DEV_NAME ++#define FLASH_DEVICE_ID_0 FLASH_DEVICE_ID ++#endif ++ ++/* When undefined FLASH_DEV_NAME_1 or FLASH_DEVICE_ID_1 , default */ ++#if !defined(FLASH_DEV_NAME_1) || !defined(FLASH_DEVICE_ID_1) ++#define FLASH_DEV_NAME_1 FLASH_DEV_NAME ++#define FLASH_DEVICE_ID_1 FLASH_DEVICE_ID ++#endif ++ ++/* When undefined FLASH_DEV_NAME_2 or FLASH_DEVICE_ID_2 , default */ ++#if !defined(FLASH_DEV_NAME_2) || !defined(FLASH_DEVICE_ID_2) ++#define FLASH_DEV_NAME_2 FLASH_DEV_NAME ++#define FLASH_DEVICE_ID_2 FLASH_DEVICE_ID ++#endif ++ ++/* When undefined FLASH_DEV_NAME_3 or FLASH_DEVICE_ID_3 , default */ ++#if !defined(FLASH_DEV_NAME_3) || !defined(FLASH_DEVICE_ID_3) ++#define FLASH_DEV_NAME_3 FLASH_DEV_NAME ++#define FLASH_DEVICE_ID_3 FLASH_DEVICE_ID ++#endif ++ ++#if defined(MCUBOOT_SWAP_USING_SCRATCH) ++/* When undefined FLASH_DEV_NAME_SCRATCH or FLASH_DEVICE_ID_SCRATCH , default */ ++#if !defined(FLASH_DEV_NAME_SCRATCH) || !defined(FLASH_DEVICE_ID_SCRATCH) ++#define FLASH_DEV_NAME_SCRATCH FLASH_DEV_NAME ++#define FLASH_DEVICE_ID_SCRATCH FLASH_DEVICE_ID ++#endif ++#endif /* defined(MCUBOOT_SWAP_USING_SCRATCH) */ ++ ++#define ARRAY_SIZE(arr) (sizeof(arr)/sizeof((arr)[0])) ++ ++/* Flash device names must be specified by target */ ++extern ARM_DRIVER_FLASH FLASH_DEV_NAME_0; ++extern ARM_DRIVER_FLASH FLASH_DEV_NAME_1; ++extern ARM_DRIVER_FLASH FLASH_DEV_NAME_2; ++extern ARM_DRIVER_FLASH FLASH_DEV_NAME_3; ++extern ARM_DRIVER_FLASH FLASH_DEV_NAME_SCRATCH; ++ ++#if !defined(FLASH_DRIVER_LIST) ++/* Default Drivers list */ ++const ARM_DRIVER_FLASH *flash_driver[] = { ++ &FLASH_DEV_NAME, ++#if FLASH_DEV_NAME_0 != FLASH_DEV_NAME ++ &FLASH_DEV_NAME_0, ++#endif ++#if FLASH_DEV_NAME_1 != FLASH_DEV_NAME ++ &FLASH_DEV_NAME_1, ++#endif ++#if FLASH_DEV_NAME_2 != FLASH_DEV_NAME ++ &FLASH_DEV_NAME_2, ++#endif ++#if (MCUBOOT_IMAGE_NUMBER == 2) ++#if FLASH_DEV_NAME_1 != FLASH_DEV_NAME ++ &FLASH_DEV_NAME_1, ++#endif ++#if FLASH_DEV_NAME_3 != FLASH_DEV_NAME ++ &FLASH_DEV_NAME_3, ++#endif ++#endif /* (MCUBOOT_IMAGE_NUMBER == 2) */ ++#if defined(MCUBOOT_SWAP_USING_SCRATCH) && \ ++ defined(FLASH_DEV_NAME_SCRATCH) && FLASH_DEV_NAME_SCRATCH != FLASH_DEV_NAME ++ &FLASH_DEV_NAME_SCRATCH ++#endif ++}; ++#else ++/* Platform driver list */ ++const ARM_DRIVER_FLASH *flash_driver[] = FLASH_DRIVER_LIST; ++#endif /* !defined(FLASH_DRIVER_LIST) */ ++const int flash_driver_entry_num = ARRAY_SIZE(flash_driver); ++ ++const struct flash_area flash_map[] = { ++ { ++ .fa_id = FLASH_AREA_0_ID, ++ .fa_device_id = FLASH_DEVICE_ID_0, ++ .fa_driver = &FLASH_DEV_NAME_0, ++ .fa_off = FLASH_AREA_0_OFFSET, ++ .fa_size = FLASH_AREA_0_SIZE, ++ }, ++ { ++ .fa_id = FLASH_AREA_2_ID, ++ .fa_device_id = FLASH_DEVICE_ID_2, ++ .fa_driver = &FLASH_DEV_NAME_2, ++ .fa_off = FLASH_AREA_2_OFFSET, ++ .fa_size = FLASH_AREA_2_SIZE, ++ }, ++#if (MCUBOOT_IMAGE_NUMBER >= 2) ++ { ++ .fa_id = FLASH_AREA_1_ID, ++ .fa_device_id = FLASH_DEVICE_ID_1, ++ .fa_driver = &FLASH_DEV_NAME_1, ++ .fa_off = FLASH_AREA_1_OFFSET, ++ .fa_size = FLASH_AREA_1_SIZE, ++ }, ++ { ++ .fa_id = FLASH_AREA_3_ID, ++ .fa_device_id = FLASH_DEVICE_ID_3, ++ .fa_driver = &FLASH_DEV_NAME_3, ++ .fa_off = FLASH_AREA_3_OFFSET, ++ .fa_size = FLASH_AREA_3_SIZE, ++ }, ++#endif ++#if (MCUBOOT_IMAGE_NUMBER >= 3) ++ { ++ .fa_id = FLASH_AREA_1_0_ID, ++ .fa_device_id = FLASH_DEVICE_ID_1, ++ .fa_driver = &FLASH_DEV_NAME_1, ++ .fa_off = FLASH_AREA_1_0_OFFSET, ++ .fa_size = FLASH_AREA_1_0_SIZE, ++ }, ++ { ++ .fa_id = FLASH_AREA_3_0_ID, ++ .fa_device_id = FLASH_DEVICE_ID_3, ++ .fa_driver = &FLASH_DEV_NAME_3, ++ .fa_off = FLASH_AREA_3_0_OFFSET, ++ .fa_size = FLASH_AREA_3_0_SIZE, ++ }, ++#endif ++#if defined(MCUBOOT_SWAP_USING_SCRATCH) ++ { ++ .fa_id = FLASH_AREA_SCRATCH_ID, ++ .fa_device_id = FLASH_DEVICE_ID_SCRATCH, ++ .fa_driver = &FLASH_DEV_NAME_SCRATCH, ++ .fa_off = FLASH_AREA_SCRATCH_OFFSET, ++ .fa_size = FLASH_AREA_SCRATCH_SIZE, ++ }, ++#endif /* defined(MCUBOOT_SWAP_USING_SCRATCH) */ ++}; ++ ++const int flash_map_entry_num = ARRAY_SIZE(flash_map); +diff --git a/platform/ext/target/arm/mps3/corstone300/common/common.cmake b/platform/ext/target/arm/mps3/corstone300/common/common.cmake +index e6a3a53a2..f7779fe3b 100644 +--- a/platform/ext/target/arm/mps3/corstone300/common/common.cmake ++++ b/platform/ext/target/arm/mps3/corstone300/common/common.cmake +@@ -152,6 +152,13 @@ if(BL2) + ${CORSTONE300_COMMON_DIR}/bl2/boot_hal_bl2.c + ) + ++ if(MCUBOOT_IMAGE_NUMBER GREATER 2) ++ target_sources(bl2 ++ PRIVATE ++ ${CORSTONE300_COMMON_DIR}/bl2/flash_map_bl2.c ++ ) ++ endif() ++ + target_compile_options(bl2 + PUBLIC + ${BL2_COMPILER_CP_FLAG} +@@ -205,7 +212,12 @@ if(BL2) + $<$,$>:tfm_boot_status> + device_definition + ) +- ++ if(MCUBOOT_IMAGE_NUMBER GREATER 2) ++ target_sources(tfm_fwu_mcuboot_util ++ INTERFACE ++ ${CORSTONE300_COMMON_DIR}/bl2/flash_map_bl2.c ++ ) ++ endif() + endif() + + #========================= tfm_spm ============================================# +@@ -233,6 +245,7 @@ target_compile_definitions(platform_region_defs + S_DATA_OVERALL_SIZE=${S_DATA_OVERALL_SIZE} + FLASH_S_PARTITION_SIZE=${FLASH_S_PARTITION_SIZE} + FLASH_NS_PARTITION_SIZE=${FLASH_NS_PARTITION_SIZE} ++ FLASH_NS_ML_MODEL_PARTITION_SIZE=${FLASH_NS_ML_MODEL_PARTITION_SIZE} + PROVISIONING_CODE_PADDED_SIZE=${PROVISIONING_CODE_PADDED_SIZE} + PROVISIONING_VALUES_PADDED_SIZE=${PROVISIONING_VALUES_PADDED_SIZE} + PROVISIONING_DATA_PADDED_SIZE=${PROVISIONING_DATA_PADDED_SIZE} +@@ -249,6 +262,7 @@ target_compile_definitions(tfm_config + S_DATA_OVERALL_SIZE=${S_DATA_OVERALL_SIZE} + FLASH_S_PARTITION_SIZE=${FLASH_S_PARTITION_SIZE} + FLASH_NS_PARTITION_SIZE=${FLASH_NS_PARTITION_SIZE} ++ FLASH_NS_ML_MODEL_PARTITION_SIZE=${FLASH_NS_ML_MODEL_PARTITION_SIZE} + PROVISIONING_CODE_PADDED_SIZE=${PROVISIONING_CODE_PADDED_SIZE} + PROVISIONING_VALUES_PADDED_SIZE=${PROVISIONING_VALUES_PADDED_SIZE} + PROVISIONING_DATA_PADDED_SIZE=${PROVISIONING_DATA_PADDED_SIZE} +diff --git a/platform/ext/target/arm/mps3/corstone300/common/config.cmake b/platform/ext/target/arm/mps3/corstone300/common/config.cmake +index 027e64c71..328965b21 100644 +--- a/platform/ext/target/arm/mps3/corstone300/common/config.cmake ++++ b/platform/ext/target/arm/mps3/corstone300/common/config.cmake +@@ -13,7 +13,8 @@ set(PROVISIONING_KEYS_CONFIG "" CACHE FILEPATH "The config file whi + + set(S_DATA_OVERALL_SIZE "0x20000" CACHE STRING "Secure data size") + set(FLASH_S_PARTITION_SIZE "0x80000" CACHE STRING "Secure code size") +-set(FLASH_NS_PARTITION_SIZE "0x300000" CACHE STRING "Non-secure code size") ++set(FLASH_NS_PARTITION_SIZE "0x240000" CACHE STRING "Non-secure code size") ++set(FLASH_NS_ML_MODEL_PARTITION_SIZE "0x100000" CACHE STRING "Non-secure ML model size") + + if(BL2) + set(BL2_TRAILER_SIZE 0x800 CACHE STRING "Trailer size") +diff --git a/platform/ext/target/arm/mps3/corstone300/common/partition/flash_layout.h b/platform/ext/target/arm/mps3/corstone300/common/partition/flash_layout.h +index 1923f91bb..fc1e589bd 100644 +--- a/platform/ext/target/arm/mps3/corstone300/common/partition/flash_layout.h ++++ b/platform/ext/target/arm/mps3/corstone300/common/partition/flash_layout.h +@@ -143,8 +143,53 @@ + /* Maximum number of image sectors supported by the bootloader. */ + #define MCUBOOT_MAX_IMG_SECTORS (FLASH_MAX_PARTITION_SIZE / \ + FLASH_AREA_IMAGE_SECTOR_SIZE) +-#else /* MCUBOOT_IMAGE_NUMBER > 2 */ +-#error "Only MCUBOOT_IMAGE_NUMBER 1 and 2 are supported!" ++#elif (MCUBOOT_IMAGE_NUMBER == 3) ++ ++/* Secure image primary slot */ ++#define FLASH_AREA_0_ID (1) ++#define FLASH_AREA_0_OFFSET (0) ++#define FLASH_AREA_0_SIZE (FLASH_S_PARTITION_SIZE) ++ ++/* Non-secure image primary slot */ ++#define FLASH_AREA_1_ID (FLASH_AREA_0_ID + 1) ++#define FLASH_AREA_1_OFFSET (FLASH_AREA_0_OFFSET + FLASH_AREA_0_SIZE) ++#define FLASH_AREA_1_SIZE (FLASH_NS_PARTITION_SIZE) ++ ++/* Non-secure ML model image primary slot */ /* Use a _0 suffix to keep other slot names unchanged. */ ++#define FLASH_AREA_1_0_ID (FLASH_AREA_1_ID + 1) ++#define FLASH_AREA_1_0_OFFSET (FLASH_AREA_1_OFFSET + FLASH_AREA_1_SIZE) ++#define FLASH_AREA_1_0_SIZE (FLASH_NS_ML_MODEL_PARTITION_SIZE) ++ ++/* Secure image secondary slot */ ++#define FLASH_AREA_2_ID (FLASH_AREA_1_0_ID + 1) ++#define FLASH_AREA_2_OFFSET (FLASH_AREA_1_0_OFFSET + FLASH_AREA_1_0_SIZE) ++#define FLASH_AREA_2_SIZE (FLASH_S_PARTITION_SIZE) ++ ++/* Non-secure image secondary slot */ ++#define FLASH_AREA_3_ID (FLASH_AREA_2_ID + 1) ++#define FLASH_AREA_3_OFFSET (FLASH_AREA_2_OFFSET + FLASH_AREA_2_SIZE) ++#define FLASH_AREA_3_SIZE (FLASH_NS_PARTITION_SIZE) ++ ++/* Non-secure ML model image secondary slot */ /* Use a _0 suffix to keep other slot names unchanged. */ ++#define FLASH_AREA_3_0_ID (FLASH_AREA_3_ID + 1) ++#define FLASH_AREA_3_0_OFFSET (FLASH_AREA_3_OFFSET + FLASH_AREA_3_SIZE) ++#define FLASH_AREA_3_0_SIZE (FLASH_NS_ML_MODEL_PARTITION_SIZE) ++ ++/* Scratch area */ ++#define FLASH_AREA_SCRATCH_ID (FLASH_AREA_3_0_ID + 1) ++#define FLASH_AREA_SCRATCH_OFFSET (FLASH_AREA_3_0_OFFSET + FLASH_AREA_3_0_SIZE) ++#define FLASH_AREA_SCRATCH_SIZE (0x80000) /* 512 kB */ ++ ++/* The maximum number of status entries supported by the bootloader. */ ++#define MCUBOOT_STATUS_MAX_ENTRIES (FLASH_MAX_PARTITION_SIZE / \ ++ FLASH_AREA_SCRATCH_SIZE) ++ ++/* Maximum number of image sectors supported by the bootloader. */ ++#define MCUBOOT_MAX_IMG_SECTORS (FLASH_MAX_PARTITION_SIZE / \ ++ FLASH_AREA_IMAGE_SECTOR_SIZE) ++ ++#else /* MCUBOOT_IMAGE_NUMBER > 3 */ ++#error "Only MCUBOOT_IMAGE_NUMBER 1, 2 and 3 are supported!" + #endif /* MCUBOOT_IMAGE_NUMBER */ + + /* Protected Storage (PS) Service definitions */ +@@ -254,4 +299,41 @@ + #define TFM_OTP_NV_COUNTERS_BACKUP_AREA_ADDR (TFM_OTP_NV_COUNTERS_AREA_ADDR + \ + TFM_OTP_NV_COUNTERS_AREA_SIZE) + ++ ++#if (MCUBOOT_IMAGE_NUMBER == 1) ++/* ++ * NOTE: the definition below returns the same values for true/false on ++ * purpose, to avoid having to mark x as non-used by all callers when ++ * running in single image mode. ++ */ ++#define FLASH_AREA_IMAGE_PRIMARY(x) (((x) == 0) ? FLASH_AREA_0_ID : \ ++ FLASH_AREA_0_ID) ++#define FLASH_AREA_IMAGE_SECONDARY(x) (((x) == 0) ? FLASH_AREA_2_ID : \ ++ FLASH_AREA_2_ID) ++#elif (MCUBOOT_IMAGE_NUMBER == 2) ++/* MCUBoot currently supports only up to 2 updatable firmware images. ++ * If the number of the current image is greater than MCUBOOT_IMAGE_NUMBER - 1 ++ * then a dummy value will be assigned to the flash area macros. ++ */ ++#define FLASH_AREA_IMAGE_PRIMARY(x) (((x) == 0) ? FLASH_AREA_0_ID : \ ++ ((x) == 1) ? FLASH_AREA_1_ID : \ ++ 255 ) ++#define FLASH_AREA_IMAGE_SECONDARY(x) (((x) == 0) ? FLASH_AREA_2_ID : \ ++ ((x) == 1) ? FLASH_AREA_3_ID : \ ++ 255 ) ++#elif (MCUBOOT_IMAGE_NUMBER == 3) ++#define FLASH_AREA_IMAGE_PRIMARY(x) (((x) == 0) ? FLASH_AREA_0_ID : \ ++ ((x) == 1) ? FLASH_AREA_1_ID : \ ++ ((x) == 2) ? FLASH_AREA_1_0_ID : \ ++ 255 ) ++#define FLASH_AREA_IMAGE_SECONDARY(x) (((x) == 0) ? FLASH_AREA_2_ID : \ ++ ((x) == 1) ? FLASH_AREA_3_ID : \ ++ ((x) == 2) ? FLASH_AREA_3_0_ID : \ ++ 255 ) ++#else ++#error "Image slot and flash area mapping is not defined" ++#endif ++ ++#define FLASH_AREA_IMAGE_SCRATCH FLASH_AREA_SCRATCH_ID ++ + #endif /* __FLASH_LAYOUT_H__ */ +diff --git a/platform/ext/target/arm/mps3/corstone300/common/partition/region_defs.h b/platform/ext/target/arm/mps3/corstone300/common/partition/region_defs.h +index 643e5bd3d..f799a85ec 100644 +--- a/platform/ext/target/arm/mps3/corstone300/common/partition/region_defs.h ++++ b/platform/ext/target/arm/mps3/corstone300/common/partition/region_defs.h +@@ -79,6 +79,9 @@ + #define IMAGE_NS_CODE_SIZE \ + (FLASH_NS_PARTITION_SIZE - BL2_HEADER_SIZE - BL2_TRAILER_SIZE) + ++#define IMAGE_NS_ML_MODEL_CODE_SIZE \ ++ (FLASH_NS_ML_MODEL_PARTITION_SIZE - BL2_HEADER_SIZE - BL2_TRAILER_SIZE) ++ + /* Secure regions */ + #define S_IMAGE_PRIMARY_AREA_OFFSET \ + (S_IMAGE_PRIMARY_PARTITION_OFFSET + BL2_HEADER_SIZE) +@@ -120,7 +123,12 @@ + /* NS partition information is used for MPC and SAU configuration */ + #define NS_PARTITION_START \ + ((QSPI_SRAM_BASE_NS) + (NS_IMAGE_PRIMARY_PARTITION_OFFSET)) +-#define NS_PARTITION_SIZE (FLASH_NS_PARTITION_SIZE) ++ ++#if (MCUBOOT_IMAGE_NUMBER >= 3) ++ #define NS_PARTITION_SIZE (FLASH_NS_PARTITION_SIZE + FLASH_NS_ML_MODEL_PARTITION_SIZE) ++#else ++ #define NS_PARTITION_SIZE (FLASH_NS_PARTITION_SIZE) ++#endif + + /* Secondary partition for new images in case of firmware upgrade */ + #define SECONDARY_PARTITION_START \ +-- +2.34.1 + diff --git a/components/security/trusted_firmware-m/integration/patches/0002-corstone310-Add-ML-model-component.patch b/components/security/trusted_firmware-m/integration/patches/0002-corstone310-Add-ML-model-component.patch new file mode 100644 index 00000000..dc563ee9 --- /dev/null +++ b/components/security/trusted_firmware-m/integration/patches/0002-corstone310-Add-ML-model-component.patch @@ -0,0 +1,387 @@ +From b1c6fa4905ca0f861b45bac7c1b0abc966002693 Mon Sep 17 00:00:00 2001 +From: Ahmed Ismail +Date: Thu, 5 Dec 2024 10:58:07 +0000 +Subject: [PATCH 2/3] corstone310: Add ML model component + +As the TF-M is currently configured to enable a 2 image operation (for +the Secure and Non-Secure components), an update is required to enable +an ML-model-only OTA update, with the use of a new, third TF-M +component. + +Enable a 3-component TF-M setup. Apart from the standard Secure and +Non-Secure images, a third, Non-Secure ML model image is added to the +mix. To keep changes minimal, the NS partition is re-sized from 0x340000 +B to 0x240000 B, and the remaining 0x100000 B are used for the ML model. + +- Enable MCUBoot to support a 3 image setup. +- Add signing layout for the ML model image. +- Add provisioning data and SPE config for the ML model image. +- Add a custom, 3-image flash map, where the ML model image partition is +created at the cost of reduced NS partition size. +- Keep addresses of the Secure, Non-Secure and Scratch partitions +unchanged. +- Keep sizes of the Secure and Scratch partitions unchanged. + +Signed-off-by: Ahmed Ismail +--- + .../arm/mps3/corstone310/an555/config.cmake | 1 + + .../corstone310/common/bl2/flash_map_bl2.c | 144 ++++++++++++++++++ + .../arm/mps3/corstone310/common/common.cmake | 16 +- + .../arm/mps3/corstone310/common/config.cmake | 3 +- + .../common/partition/flash_layout.h | 83 +++++++++- + .../common/partition/region_defs.h | 10 +- + 6 files changed, 252 insertions(+), 5 deletions(-) + create mode 100644 platform/ext/target/arm/mps3/corstone310/common/bl2/flash_map_bl2.c + +diff --git a/platform/ext/target/arm/mps3/corstone310/an555/config.cmake b/platform/ext/target/arm/mps3/corstone310/an555/config.cmake +index 6f26782f1..e024c9a3a 100644 +--- a/platform/ext/target/arm/mps3/corstone310/an555/config.cmake ++++ b/platform/ext/target/arm/mps3/corstone310/an555/config.cmake +@@ -11,3 +11,4 @@ set(TEST_NS_FLIH_IRQ OFF CACHE BOOL "Whether to build NS regr + set(PROVISIONING_CODE_PADDED_SIZE "0x2400" CACHE STRING "") + set(PROVISIONING_VALUES_PADDED_SIZE "0x400" CACHE STRING "") + set(PROVISIONING_DATA_PADDED_SIZE "0x400" CACHE STRING "") ++set(DEFAULT_MCUBOOT_FLASH_MAP OFF CACHE BOOL "Whether to use the default flash map defined by TF-M project") +diff --git a/platform/ext/target/arm/mps3/corstone310/common/bl2/flash_map_bl2.c b/platform/ext/target/arm/mps3/corstone310/common/bl2/flash_map_bl2.c +new file mode 100644 +index 000000000..398222b26 +--- /dev/null ++++ b/platform/ext/target/arm/mps3/corstone310/common/bl2/flash_map_bl2.c +@@ -0,0 +1,144 @@ ++/* ++ * Copyright (c) 2021, 2024, Arm Limited. All rights reserved. ++ * ++ * SPDX-License-Identifier: BSD-3-Clause ++ * ++ */ ++ ++#include ++#include "flash_map/flash_map.h" ++#include "target.h" ++#include "Driver_Flash.h" ++ ++/* When undefined FLASH_DEV_NAME_0 or FLASH_DEVICE_ID_0 , default */ ++#if !defined(FLASH_DEV_NAME_0) || !defined(FLASH_DEVICE_ID_0) ++#define FLASH_DEV_NAME_0 FLASH_DEV_NAME ++#define FLASH_DEVICE_ID_0 FLASH_DEVICE_ID ++#endif ++ ++/* When undefined FLASH_DEV_NAME_1 or FLASH_DEVICE_ID_1 , default */ ++#if !defined(FLASH_DEV_NAME_1) || !defined(FLASH_DEVICE_ID_1) ++#define FLASH_DEV_NAME_1 FLASH_DEV_NAME ++#define FLASH_DEVICE_ID_1 FLASH_DEVICE_ID ++#endif ++ ++/* When undefined FLASH_DEV_NAME_2 or FLASH_DEVICE_ID_2 , default */ ++#if !defined(FLASH_DEV_NAME_2) || !defined(FLASH_DEVICE_ID_2) ++#define FLASH_DEV_NAME_2 FLASH_DEV_NAME ++#define FLASH_DEVICE_ID_2 FLASH_DEVICE_ID ++#endif ++ ++/* When undefined FLASH_DEV_NAME_3 or FLASH_DEVICE_ID_3 , default */ ++#if !defined(FLASH_DEV_NAME_3) || !defined(FLASH_DEVICE_ID_3) ++#define FLASH_DEV_NAME_3 FLASH_DEV_NAME ++#define FLASH_DEVICE_ID_3 FLASH_DEVICE_ID ++#endif ++ ++#if defined(MCUBOOT_SWAP_USING_SCRATCH) ++/* When undefined FLASH_DEV_NAME_SCRATCH or FLASH_DEVICE_ID_SCRATCH , default */ ++#if !defined(FLASH_DEV_NAME_SCRATCH) || !defined(FLASH_DEVICE_ID_SCRATCH) ++#define FLASH_DEV_NAME_SCRATCH FLASH_DEV_NAME ++#define FLASH_DEVICE_ID_SCRATCH FLASH_DEVICE_ID ++#endif ++#endif /* defined(MCUBOOT_SWAP_USING_SCRATCH) */ ++ ++#define ARRAY_SIZE(arr) (sizeof(arr)/sizeof((arr)[0])) ++ ++/* Flash device names must be specified by target */ ++extern ARM_DRIVER_FLASH FLASH_DEV_NAME_0; ++extern ARM_DRIVER_FLASH FLASH_DEV_NAME_1; ++extern ARM_DRIVER_FLASH FLASH_DEV_NAME_2; ++extern ARM_DRIVER_FLASH FLASH_DEV_NAME_3; ++extern ARM_DRIVER_FLASH FLASH_DEV_NAME_SCRATCH; ++ ++#if !defined(FLASH_DRIVER_LIST) ++/* Default Drivers list */ ++const ARM_DRIVER_FLASH *flash_driver[] = { ++ &FLASH_DEV_NAME, ++#if FLASH_DEV_NAME_0 != FLASH_DEV_NAME ++ &FLASH_DEV_NAME_0, ++#endif ++#if FLASH_DEV_NAME_1 != FLASH_DEV_NAME ++ &FLASH_DEV_NAME_1, ++#endif ++#if FLASH_DEV_NAME_2 != FLASH_DEV_NAME ++ &FLASH_DEV_NAME_2, ++#endif ++#if (MCUBOOT_IMAGE_NUMBER == 2) ++#if FLASH_DEV_NAME_1 != FLASH_DEV_NAME ++ &FLASH_DEV_NAME_1, ++#endif ++#if FLASH_DEV_NAME_3 != FLASH_DEV_NAME ++ &FLASH_DEV_NAME_3, ++#endif ++#endif /* (MCUBOOT_IMAGE_NUMBER == 2) */ ++#if defined(MCUBOOT_SWAP_USING_SCRATCH) && \ ++ defined(FLASH_DEV_NAME_SCRATCH) && FLASH_DEV_NAME_SCRATCH != FLASH_DEV_NAME ++ &FLASH_DEV_NAME_SCRATCH ++#endif ++}; ++#else ++/* Platform driver list */ ++const ARM_DRIVER_FLASH *flash_driver[] = FLASH_DRIVER_LIST; ++#endif /* !defined(FLASH_DRIVER_LIST) */ ++const int flash_driver_entry_num = ARRAY_SIZE(flash_driver); ++ ++const struct flash_area flash_map[] = { ++ { ++ .fa_id = FLASH_AREA_0_ID, ++ .fa_device_id = FLASH_DEVICE_ID_0, ++ .fa_driver = &FLASH_DEV_NAME_0, ++ .fa_off = FLASH_AREA_0_OFFSET, ++ .fa_size = FLASH_AREA_0_SIZE, ++ }, ++ { ++ .fa_id = FLASH_AREA_2_ID, ++ .fa_device_id = FLASH_DEVICE_ID_2, ++ .fa_driver = &FLASH_DEV_NAME_2, ++ .fa_off = FLASH_AREA_2_OFFSET, ++ .fa_size = FLASH_AREA_2_SIZE, ++ }, ++#if (MCUBOOT_IMAGE_NUMBER >= 2) ++ { ++ .fa_id = FLASH_AREA_1_ID, ++ .fa_device_id = FLASH_DEVICE_ID_1, ++ .fa_driver = &FLASH_DEV_NAME_1, ++ .fa_off = FLASH_AREA_1_OFFSET, ++ .fa_size = FLASH_AREA_1_SIZE, ++ }, ++ { ++ .fa_id = FLASH_AREA_3_ID, ++ .fa_device_id = FLASH_DEVICE_ID_3, ++ .fa_driver = &FLASH_DEV_NAME_3, ++ .fa_off = FLASH_AREA_3_OFFSET, ++ .fa_size = FLASH_AREA_3_SIZE, ++ }, ++#endif ++#if (MCUBOOT_IMAGE_NUMBER >= 3) ++ { ++ .fa_id = FLASH_AREA_1_0_ID, ++ .fa_device_id = FLASH_DEVICE_ID_1, ++ .fa_driver = &FLASH_DEV_NAME_1, ++ .fa_off = FLASH_AREA_1_0_OFFSET, ++ .fa_size = FLASH_AREA_1_0_SIZE, ++ }, ++ { ++ .fa_id = FLASH_AREA_3_0_ID, ++ .fa_device_id = FLASH_DEVICE_ID_3, ++ .fa_driver = &FLASH_DEV_NAME_3, ++ .fa_off = FLASH_AREA_3_0_OFFSET, ++ .fa_size = FLASH_AREA_3_0_SIZE, ++ }, ++#endif ++#if defined(MCUBOOT_SWAP_USING_SCRATCH) ++ { ++ .fa_id = FLASH_AREA_SCRATCH_ID, ++ .fa_device_id = FLASH_DEVICE_ID_SCRATCH, ++ .fa_driver = &FLASH_DEV_NAME_SCRATCH, ++ .fa_off = FLASH_AREA_SCRATCH_OFFSET, ++ .fa_size = FLASH_AREA_SCRATCH_SIZE, ++ }, ++#endif /* defined(MCUBOOT_SWAP_USING_SCRATCH) */ ++}; ++ ++const int flash_map_entry_num = ARRAY_SIZE(flash_map); +diff --git a/platform/ext/target/arm/mps3/corstone310/common/common.cmake b/platform/ext/target/arm/mps3/corstone310/common/common.cmake +index 1e6ac0c60..97fb014a6 100644 +--- a/platform/ext/target/arm/mps3/corstone310/common/common.cmake ++++ b/platform/ext/target/arm/mps3/corstone310/common/common.cmake +@@ -151,6 +151,13 @@ if(BL2) + ${CORSTONE310_COMMON_DIR}/bl2/boot_hal_bl2.c + ) + ++ if(MCUBOOT_IMAGE_NUMBER GREATER 2) ++ target_sources(bl2 ++ PRIVATE ++ ${CORSTONE310_COMMON_DIR}/bl2/flash_map_bl2.c ++ ) ++ endif() ++ + target_compile_options(bl2 + PUBLIC + ${BL2_COMPILER_CP_FLAG} +@@ -204,7 +211,12 @@ if(BL2) + $<$,$>:tfm_boot_status> + device_definition + ) +- ++ if(MCUBOOT_IMAGE_NUMBER GREATER 2) ++ target_sources(tfm_fwu_mcuboot_util ++ INTERFACE ++ ${CORSTONE310_COMMON_DIR}/bl2/flash_map_bl2.c ++ ) ++ endif() + endif() + + #========================= tfm_spm ============================================# +@@ -233,6 +245,7 @@ target_compile_definitions(platform_region_defs + S_DATA_OVERALL_SIZE=${S_DATA_OVERALL_SIZE} + FLASH_S_PARTITION_SIZE=${FLASH_S_PARTITION_SIZE} + FLASH_NS_PARTITION_SIZE=${FLASH_NS_PARTITION_SIZE} ++ FLASH_NS_ML_MODEL_PARTITION_SIZE=${FLASH_NS_ML_MODEL_PARTITION_SIZE} + PROVISIONING_CODE_PADDED_SIZE=${PROVISIONING_CODE_PADDED_SIZE} + PROVISIONING_VALUES_PADDED_SIZE=${PROVISIONING_VALUES_PADDED_SIZE} + PROVISIONING_DATA_PADDED_SIZE=${PROVISIONING_DATA_PADDED_SIZE} +@@ -249,6 +262,7 @@ target_compile_definitions(tfm_config + S_DATA_OVERALL_SIZE=${S_DATA_OVERALL_SIZE} + FLASH_S_PARTITION_SIZE=${FLASH_S_PARTITION_SIZE} + FLASH_NS_PARTITION_SIZE=${FLASH_NS_PARTITION_SIZE} ++ FLASH_NS_ML_MODEL_PARTITION_SIZE=${FLASH_NS_ML_MODEL_PARTITION_SIZE} + PROVISIONING_CODE_PADDED_SIZE=${PROVISIONING_CODE_PADDED_SIZE} + PROVISIONING_VALUES_PADDED_SIZE=${PROVISIONING_VALUES_PADDED_SIZE} + PROVISIONING_DATA_PADDED_SIZE=${PROVISIONING_DATA_PADDED_SIZE} +diff --git a/platform/ext/target/arm/mps3/corstone310/common/config.cmake b/platform/ext/target/arm/mps3/corstone310/common/config.cmake +index f772963b4..67d9597e6 100644 +--- a/platform/ext/target/arm/mps3/corstone310/common/config.cmake ++++ b/platform/ext/target/arm/mps3/corstone310/common/config.cmake +@@ -12,7 +12,8 @@ set(PROVISIONING_KEYS_CONFIG "" CACHE FILEPATH "The config file whi + + set(S_DATA_OVERALL_SIZE "0x20000" CACHE STRING "Secure data size") + set(FLASH_S_PARTITION_SIZE "0x80000" CACHE STRING "Secure code size") +-set(FLASH_NS_PARTITION_SIZE "0x300000" CACHE STRING "Non-secure code size") ++set(FLASH_NS_PARTITION_SIZE "0x240000" CACHE STRING "Non-secure code size") ++set(FLASH_NS_ML_MODEL_PARTITION_SIZE "0x100000" CACHE STRING "Non-secure ML model size") + + if(BL2) + set(BL2_TRAILER_SIZE 0x800 CACHE STRING "Trailer size") +diff --git a/platform/ext/target/arm/mps3/corstone310/common/partition/flash_layout.h b/platform/ext/target/arm/mps3/corstone310/common/partition/flash_layout.h +index 8a1d7df66..2ab198dee 100644 +--- a/platform/ext/target/arm/mps3/corstone310/common/partition/flash_layout.h ++++ b/platform/ext/target/arm/mps3/corstone310/common/partition/flash_layout.h +@@ -143,8 +143,53 @@ + /* Maximum number of image sectors supported by the bootloader. */ + #define MCUBOOT_MAX_IMG_SECTORS (FLASH_MAX_PARTITION_SIZE / \ + FLASH_AREA_IMAGE_SECTOR_SIZE) +-#else /* MCUBOOT_IMAGE_NUMBER > 2 */ +-#error "Only MCUBOOT_IMAGE_NUMBER 1 and 2 are supported!" ++#elif (MCUBOOT_IMAGE_NUMBER == 3) ++ ++/* Secure image primary slot */ ++#define FLASH_AREA_0_ID (1) ++#define FLASH_AREA_0_OFFSET (0) ++#define FLASH_AREA_0_SIZE (FLASH_S_PARTITION_SIZE) ++ ++/* Non-secure image primary slot */ ++#define FLASH_AREA_1_ID (FLASH_AREA_0_ID + 1) ++#define FLASH_AREA_1_OFFSET (FLASH_AREA_0_OFFSET + FLASH_AREA_0_SIZE) ++#define FLASH_AREA_1_SIZE (FLASH_NS_PARTITION_SIZE) ++ ++/* Non-secure ML model image primary slot */ /* Use a _0 suffix to keep other slot names unchanged. */ ++#define FLASH_AREA_1_0_ID (FLASH_AREA_1_ID + 1) ++#define FLASH_AREA_1_0_OFFSET (FLASH_AREA_1_OFFSET + FLASH_AREA_1_SIZE) ++#define FLASH_AREA_1_0_SIZE (FLASH_NS_ML_MODEL_PARTITION_SIZE) ++ ++/* Secure image secondary slot */ ++#define FLASH_AREA_2_ID (FLASH_AREA_1_0_ID + 1) ++#define FLASH_AREA_2_OFFSET (FLASH_AREA_1_0_OFFSET + FLASH_AREA_1_0_SIZE) ++#define FLASH_AREA_2_SIZE (FLASH_S_PARTITION_SIZE) ++ ++/* Non-secure image secondary slot */ ++#define FLASH_AREA_3_ID (FLASH_AREA_2_ID + 1) ++#define FLASH_AREA_3_OFFSET (FLASH_AREA_2_OFFSET + FLASH_AREA_2_SIZE) ++#define FLASH_AREA_3_SIZE (FLASH_NS_PARTITION_SIZE) ++ ++/* Non-secure ML model image secondary slot */ /* Use a _0 suffix to keep other slot names unchanged. */ ++#define FLASH_AREA_3_0_ID (FLASH_AREA_3_ID + 1) ++#define FLASH_AREA_3_0_OFFSET (FLASH_AREA_3_OFFSET + FLASH_AREA_3_SIZE) ++#define FLASH_AREA_3_0_SIZE (FLASH_NS_ML_MODEL_PARTITION_SIZE) ++ ++/* Scratch area */ ++#define FLASH_AREA_SCRATCH_ID (FLASH_AREA_3_0_ID + 1) ++#define FLASH_AREA_SCRATCH_OFFSET (FLASH_AREA_3_0_OFFSET + FLASH_AREA_3_0_SIZE) ++#define FLASH_AREA_SCRATCH_SIZE (0x80000) /* 512 kB */ ++ ++/* The maximum number of status entries supported by the bootloader. */ ++#define MCUBOOT_STATUS_MAX_ENTRIES (FLASH_MAX_PARTITION_SIZE / \ ++ FLASH_AREA_SCRATCH_SIZE) ++ ++/* Maximum number of image sectors supported by the bootloader. */ ++#define MCUBOOT_MAX_IMG_SECTORS (FLASH_MAX_PARTITION_SIZE / \ ++ FLASH_AREA_IMAGE_SECTOR_SIZE) ++ ++#else /* MCUBOOT_IMAGE_NUMBER > 3 */ ++#error "Only MCUBOOT_IMAGE_NUMBER 1, 2 and 3 are supported!" + #endif /* MCUBOOT_IMAGE_NUMBER */ + + /* Protected Storage (PS) Service definitions */ +@@ -253,5 +298,39 @@ + #define TFM_OTP_NV_COUNTERS_SECTOR_SIZE FLASH_OTP_NV_COUNTERS_SECTOR_SIZE + #define TFM_OTP_NV_COUNTERS_BACKUP_AREA_ADDR (TFM_OTP_NV_COUNTERS_AREA_ADDR + \ + TFM_OTP_NV_COUNTERS_AREA_SIZE) ++#if (MCUBOOT_IMAGE_NUMBER == 1) ++/* ++ * NOTE: the definition below returns the same values for true/false on ++ * purpose, to avoid having to mark x as non-used by all callers when ++ * running in single image mode. ++ */ ++#define FLASH_AREA_IMAGE_PRIMARY(x) (((x) == 0) ? FLASH_AREA_0_ID : \ ++ FLASH_AREA_0_ID) ++#define FLASH_AREA_IMAGE_SECONDARY(x) (((x) == 0) ? FLASH_AREA_2_ID : \ ++ FLASH_AREA_2_ID) ++#elif (MCUBOOT_IMAGE_NUMBER == 2) ++/* MCUBoot currently supports only up to 2 updatable firmware images. ++ * If the number of the current image is greater than MCUBOOT_IMAGE_NUMBER - 1 ++ * then a dummy value will be assigned to the flash area macros. ++ */ ++#define FLASH_AREA_IMAGE_PRIMARY(x) (((x) == 0) ? FLASH_AREA_0_ID : \ ++ ((x) == 1) ? FLASH_AREA_1_ID : \ ++ 255 ) ++#define FLASH_AREA_IMAGE_SECONDARY(x) (((x) == 0) ? FLASH_AREA_2_ID : \ ++ ((x) == 1) ? FLASH_AREA_3_ID : \ ++ 255 ) ++#elif (MCUBOOT_IMAGE_NUMBER == 3) ++#define FLASH_AREA_IMAGE_PRIMARY(x) (((x) == 0) ? FLASH_AREA_0_ID : \ ++ ((x) == 1) ? FLASH_AREA_1_ID : \ ++ ((x) == 2) ? FLASH_AREA_1_0_ID : \ ++ 255 ) ++#define FLASH_AREA_IMAGE_SECONDARY(x) (((x) == 0) ? FLASH_AREA_2_ID : \ ++ ((x) == 1) ? FLASH_AREA_3_ID : \ ++ ((x) == 2) ? FLASH_AREA_3_0_ID : \ ++ 255 ) ++#else ++#error "Image slot and flash area mapping is not defined" ++#endif + ++#define FLASH_AREA_IMAGE_SCRATCH FLASH_AREA_SCRATCH_ID + #endif /* __FLASH_LAYOUT_H__ */ +diff --git a/platform/ext/target/arm/mps3/corstone310/common/partition/region_defs.h b/platform/ext/target/arm/mps3/corstone310/common/partition/region_defs.h +index 689076ab8..4f3a15e08 100644 +--- a/platform/ext/target/arm/mps3/corstone310/common/partition/region_defs.h ++++ b/platform/ext/target/arm/mps3/corstone310/common/partition/region_defs.h +@@ -79,6 +79,9 @@ + #define IMAGE_NS_CODE_SIZE \ + (FLASH_NS_PARTITION_SIZE - BL2_HEADER_SIZE - BL2_TRAILER_SIZE) + ++#define IMAGE_NS_ML_MODEL_CODE_SIZE \ ++ (FLASH_NS_ML_MODEL_PARTITION_SIZE - BL2_HEADER_SIZE - BL2_TRAILER_SIZE) ++ + /* Secure regions */ + #define S_IMAGE_PRIMARY_AREA_OFFSET \ + (S_IMAGE_PRIMARY_PARTITION_OFFSET + BL2_HEADER_SIZE) +@@ -120,7 +123,12 @@ + /* NS partition information is used for MPC and SAU configuration */ + #define NS_PARTITION_START \ + ((QSPI_SRAM_BASE_NS) + (NS_IMAGE_PRIMARY_PARTITION_OFFSET)) +-#define NS_PARTITION_SIZE (FLASH_NS_PARTITION_SIZE) ++ ++#if (MCUBOOT_IMAGE_NUMBER >= 3) ++ #define NS_PARTITION_SIZE (FLASH_NS_PARTITION_SIZE + FLASH_NS_ML_MODEL_PARTITION_SIZE) ++#else ++ #define NS_PARTITION_SIZE (FLASH_NS_PARTITION_SIZE) ++#endif + + /* Secondary partition for new images in case of firmware upgrade */ + #define SECONDARY_PARTITION_START \ +-- +2.34.1 + diff --git a/components/security/trusted_firmware-m/integration/patches/0003-mps4-Add-ML-model-component.patch b/components/security/trusted_firmware-m/integration/patches/0003-mps4-Add-ML-model-component.patch new file mode 100644 index 00000000..a00b53ce --- /dev/null +++ b/components/security/trusted_firmware-m/integration/patches/0003-mps4-Add-ML-model-component.patch @@ -0,0 +1,399 @@ +From 49e7a03d06167073de1d36bc89f976304f94632f Mon Sep 17 00:00:00 2001 +From: Ahmed Ismail +Date: Thu, 5 Dec 2024 10:58:37 +0000 +Subject: [PATCH 3/3] mps4: Add ML model component + +As the TF-M is currently configured to enable a 2 image operation (for +the Secure and Non-Secure components), an update is required to enable +an ML-model-only OTA update, with the use of a new, third TF-M +component. + +Enable a 3-component TF-M setup. Apart from the standard Secure and +Non-Secure images, a third, Non-Secure ML model image is added to the +mix. To keep changes minimal, the NS partition is re-sized from 0x340000 +B to 0x240000 B, and the remaining 0x100000 B are used for the ML model. + +- Enable MCUBoot to support a 3 image setup. +- Add signing layout for the ML model image. +- Add provisioning data and SPE config for the ML model image. +- Add a custom, 3-image flash map, where the ML model image partition is +created at the cost of reduced NS partition size. +- Keep addresses of the Secure, Non-Secure and Scratch partitions +unchanged. +- Keep sizes of the Secure and Scratch partitions unchanged. + +Signed-off-by: Ahmed Ismail +--- + .../arm/mps4/common/bl2/flash_map_bl2.c | 144 ++++++++++++++++++ + .../ext/target/arm/mps4/common/common.cmake | 16 +- + .../ext/target/arm/mps4/common/config.cmake | 4 +- + .../arm/mps4/common/partition/flash_layout.h | 85 ++++++++++- + .../arm/mps4/common/partition/region_defs.h | 10 +- + .../provisioning/bundle_dm/CMakeLists.txt | 1 + + 6 files changed, 255 insertions(+), 5 deletions(-) + create mode 100644 platform/ext/target/arm/mps4/common/bl2/flash_map_bl2.c + +diff --git a/platform/ext/target/arm/mps4/common/bl2/flash_map_bl2.c b/platform/ext/target/arm/mps4/common/bl2/flash_map_bl2.c +new file mode 100644 +index 000000000..398222b26 +--- /dev/null ++++ b/platform/ext/target/arm/mps4/common/bl2/flash_map_bl2.c +@@ -0,0 +1,144 @@ ++/* ++ * Copyright (c) 2021, 2024, Arm Limited. All rights reserved. ++ * ++ * SPDX-License-Identifier: BSD-3-Clause ++ * ++ */ ++ ++#include ++#include "flash_map/flash_map.h" ++#include "target.h" ++#include "Driver_Flash.h" ++ ++/* When undefined FLASH_DEV_NAME_0 or FLASH_DEVICE_ID_0 , default */ ++#if !defined(FLASH_DEV_NAME_0) || !defined(FLASH_DEVICE_ID_0) ++#define FLASH_DEV_NAME_0 FLASH_DEV_NAME ++#define FLASH_DEVICE_ID_0 FLASH_DEVICE_ID ++#endif ++ ++/* When undefined FLASH_DEV_NAME_1 or FLASH_DEVICE_ID_1 , default */ ++#if !defined(FLASH_DEV_NAME_1) || !defined(FLASH_DEVICE_ID_1) ++#define FLASH_DEV_NAME_1 FLASH_DEV_NAME ++#define FLASH_DEVICE_ID_1 FLASH_DEVICE_ID ++#endif ++ ++/* When undefined FLASH_DEV_NAME_2 or FLASH_DEVICE_ID_2 , default */ ++#if !defined(FLASH_DEV_NAME_2) || !defined(FLASH_DEVICE_ID_2) ++#define FLASH_DEV_NAME_2 FLASH_DEV_NAME ++#define FLASH_DEVICE_ID_2 FLASH_DEVICE_ID ++#endif ++ ++/* When undefined FLASH_DEV_NAME_3 or FLASH_DEVICE_ID_3 , default */ ++#if !defined(FLASH_DEV_NAME_3) || !defined(FLASH_DEVICE_ID_3) ++#define FLASH_DEV_NAME_3 FLASH_DEV_NAME ++#define FLASH_DEVICE_ID_3 FLASH_DEVICE_ID ++#endif ++ ++#if defined(MCUBOOT_SWAP_USING_SCRATCH) ++/* When undefined FLASH_DEV_NAME_SCRATCH or FLASH_DEVICE_ID_SCRATCH , default */ ++#if !defined(FLASH_DEV_NAME_SCRATCH) || !defined(FLASH_DEVICE_ID_SCRATCH) ++#define FLASH_DEV_NAME_SCRATCH FLASH_DEV_NAME ++#define FLASH_DEVICE_ID_SCRATCH FLASH_DEVICE_ID ++#endif ++#endif /* defined(MCUBOOT_SWAP_USING_SCRATCH) */ ++ ++#define ARRAY_SIZE(arr) (sizeof(arr)/sizeof((arr)[0])) ++ ++/* Flash device names must be specified by target */ ++extern ARM_DRIVER_FLASH FLASH_DEV_NAME_0; ++extern ARM_DRIVER_FLASH FLASH_DEV_NAME_1; ++extern ARM_DRIVER_FLASH FLASH_DEV_NAME_2; ++extern ARM_DRIVER_FLASH FLASH_DEV_NAME_3; ++extern ARM_DRIVER_FLASH FLASH_DEV_NAME_SCRATCH; ++ ++#if !defined(FLASH_DRIVER_LIST) ++/* Default Drivers list */ ++const ARM_DRIVER_FLASH *flash_driver[] = { ++ &FLASH_DEV_NAME, ++#if FLASH_DEV_NAME_0 != FLASH_DEV_NAME ++ &FLASH_DEV_NAME_0, ++#endif ++#if FLASH_DEV_NAME_1 != FLASH_DEV_NAME ++ &FLASH_DEV_NAME_1, ++#endif ++#if FLASH_DEV_NAME_2 != FLASH_DEV_NAME ++ &FLASH_DEV_NAME_2, ++#endif ++#if (MCUBOOT_IMAGE_NUMBER == 2) ++#if FLASH_DEV_NAME_1 != FLASH_DEV_NAME ++ &FLASH_DEV_NAME_1, ++#endif ++#if FLASH_DEV_NAME_3 != FLASH_DEV_NAME ++ &FLASH_DEV_NAME_3, ++#endif ++#endif /* (MCUBOOT_IMAGE_NUMBER == 2) */ ++#if defined(MCUBOOT_SWAP_USING_SCRATCH) && \ ++ defined(FLASH_DEV_NAME_SCRATCH) && FLASH_DEV_NAME_SCRATCH != FLASH_DEV_NAME ++ &FLASH_DEV_NAME_SCRATCH ++#endif ++}; ++#else ++/* Platform driver list */ ++const ARM_DRIVER_FLASH *flash_driver[] = FLASH_DRIVER_LIST; ++#endif /* !defined(FLASH_DRIVER_LIST) */ ++const int flash_driver_entry_num = ARRAY_SIZE(flash_driver); ++ ++const struct flash_area flash_map[] = { ++ { ++ .fa_id = FLASH_AREA_0_ID, ++ .fa_device_id = FLASH_DEVICE_ID_0, ++ .fa_driver = &FLASH_DEV_NAME_0, ++ .fa_off = FLASH_AREA_0_OFFSET, ++ .fa_size = FLASH_AREA_0_SIZE, ++ }, ++ { ++ .fa_id = FLASH_AREA_2_ID, ++ .fa_device_id = FLASH_DEVICE_ID_2, ++ .fa_driver = &FLASH_DEV_NAME_2, ++ .fa_off = FLASH_AREA_2_OFFSET, ++ .fa_size = FLASH_AREA_2_SIZE, ++ }, ++#if (MCUBOOT_IMAGE_NUMBER >= 2) ++ { ++ .fa_id = FLASH_AREA_1_ID, ++ .fa_device_id = FLASH_DEVICE_ID_1, ++ .fa_driver = &FLASH_DEV_NAME_1, ++ .fa_off = FLASH_AREA_1_OFFSET, ++ .fa_size = FLASH_AREA_1_SIZE, ++ }, ++ { ++ .fa_id = FLASH_AREA_3_ID, ++ .fa_device_id = FLASH_DEVICE_ID_3, ++ .fa_driver = &FLASH_DEV_NAME_3, ++ .fa_off = FLASH_AREA_3_OFFSET, ++ .fa_size = FLASH_AREA_3_SIZE, ++ }, ++#endif ++#if (MCUBOOT_IMAGE_NUMBER >= 3) ++ { ++ .fa_id = FLASH_AREA_1_0_ID, ++ .fa_device_id = FLASH_DEVICE_ID_1, ++ .fa_driver = &FLASH_DEV_NAME_1, ++ .fa_off = FLASH_AREA_1_0_OFFSET, ++ .fa_size = FLASH_AREA_1_0_SIZE, ++ }, ++ { ++ .fa_id = FLASH_AREA_3_0_ID, ++ .fa_device_id = FLASH_DEVICE_ID_3, ++ .fa_driver = &FLASH_DEV_NAME_3, ++ .fa_off = FLASH_AREA_3_0_OFFSET, ++ .fa_size = FLASH_AREA_3_0_SIZE, ++ }, ++#endif ++#if defined(MCUBOOT_SWAP_USING_SCRATCH) ++ { ++ .fa_id = FLASH_AREA_SCRATCH_ID, ++ .fa_device_id = FLASH_DEVICE_ID_SCRATCH, ++ .fa_driver = &FLASH_DEV_NAME_SCRATCH, ++ .fa_off = FLASH_AREA_SCRATCH_OFFSET, ++ .fa_size = FLASH_AREA_SCRATCH_SIZE, ++ }, ++#endif /* defined(MCUBOOT_SWAP_USING_SCRATCH) */ ++}; ++ ++const int flash_map_entry_num = ARRAY_SIZE(flash_map); +diff --git a/platform/ext/target/arm/mps4/common/common.cmake b/platform/ext/target/arm/mps4/common/common.cmake +index a15fbbc1e..7c5fed8db 100644 +--- a/platform/ext/target/arm/mps4/common/common.cmake ++++ b/platform/ext/target/arm/mps4/common/common.cmake +@@ -166,6 +166,13 @@ if(BL2) + ${CMAKE_CURRENT_LIST_DIR}/bl2/boot_hal_bl2.c + ) + ++ if(MCUBOOT_IMAGE_NUMBER GREATER 2) ++ target_sources(bl2 ++ PRIVATE ++ ${CMAKE_CURRENT_LIST_DIR}/bl2/flash_map_bl2.c ++ ) ++ endif() ++ + target_sources(platform_bl2 + PRIVATE + ${CMAKE_CURRENT_LIST_DIR}/nv_counters.c +@@ -210,7 +217,12 @@ if(BL2) + $<$,$>:tfm_boot_status> + device_definition + ) +- ++ if(MCUBOOT_IMAGE_NUMBER GREATER 2) ++ target_sources(tfm_fwu_mcuboot_util ++ INTERFACE ++ ${CMAKE_CURRENT_LIST_DIR}/bl2/flash_map_bl2.c ++ ) ++ endif() + endif() + + #========================= tfm_spm ============================================# +@@ -238,6 +250,7 @@ target_compile_definitions(platform_region_defs + S_DATA_OVERALL_SIZE=${S_DATA_OVERALL_SIZE} + FLASH_S_PARTITION_SIZE=${FLASH_S_PARTITION_SIZE} + FLASH_NS_PARTITION_SIZE=${FLASH_NS_PARTITION_SIZE} ++ FLASH_NS_ML_MODEL_PARTITION_SIZE=${FLASH_NS_ML_MODEL_PARTITION_SIZE} + PROVISIONING_CODE_PADDED_SIZE=${PROVISIONING_CODE_PADDED_SIZE} + PROVISIONING_VALUES_PADDED_SIZE=${PROVISIONING_VALUES_PADDED_SIZE} + PROVISIONING_DATA_PADDED_SIZE=${PROVISIONING_DATA_PADDED_SIZE} +@@ -414,6 +427,7 @@ target_compile_definitions(tfm_config + S_DATA_OVERALL_SIZE=${S_DATA_OVERALL_SIZE} + FLASH_S_PARTITION_SIZE=${FLASH_S_PARTITION_SIZE} + FLASH_NS_PARTITION_SIZE=${FLASH_NS_PARTITION_SIZE} ++ FLASH_NS_ML_MODEL_PARTITION_SIZE=${FLASH_NS_ML_MODEL_PARTITION_SIZE} + PROVISIONING_CODE_PADDED_SIZE=${PROVISIONING_CODE_PADDED_SIZE} + PROVISIONING_VALUES_PADDED_SIZE=${PROVISIONING_VALUES_PADDED_SIZE} + PROVISIONING_DATA_PADDED_SIZE=${PROVISIONING_DATA_PADDED_SIZE} +diff --git a/platform/ext/target/arm/mps4/common/config.cmake b/platform/ext/target/arm/mps4/common/config.cmake +index 1c60bb9bd..e376a2cc6 100644 +--- a/platform/ext/target/arm/mps4/common/config.cmake ++++ b/platform/ext/target/arm/mps4/common/config.cmake +@@ -10,7 +10,8 @@ set(PROVISIONING_KEYS_CONFIG "" CACHE FILEPATH "The config file whi + + set(S_DATA_OVERALL_SIZE "0x20000" CACHE STRING "Secure data size") + set(FLASH_S_PARTITION_SIZE "0x80000" CACHE STRING "Secure code size") +-set(FLASH_NS_PARTITION_SIZE "0x300000" CACHE STRING "Non-secure code size") ++set(FLASH_NS_PARTITION_SIZE "0x240000" CACHE STRING "Non-secure code size") ++set(FLASH_NS_ML_MODEL_PARTITION_SIZE "0x100000" CACHE STRING "Non-secure ML model size") + + if(BL2) + set(BL2_TRAILER_SIZE 0x800 CACHE STRING "Trailer size") +@@ -33,6 +34,7 @@ set(PLATFORM_SVC_HANDLERS ON CACHE BOOL "Platform + set(PROVISIONING_CODE_PADDED_SIZE "0x2000" CACHE STRING "") + set(PROVISIONING_VALUES_PADDED_SIZE "0x3800" CACHE STRING "") + set(PROVISIONING_DATA_PADDED_SIZE "0x1000" CACHE STRING "") ++set(DEFAULT_MCUBOOT_FLASH_MAP OFF CACHE BOOL "Whether to use the default flash map defined by TF-M project") + set(CRYPTO_HW_ACCELERATOR OFF CACHE BOOL "Whether to enable the crypto hardware accelerator on supported platforms") + set(BL1 ON CACHE BOOL "Whether to build BL1") + set(PLATFORM_DEFAULT_BL1 ON CACHE STRING "Whether to use default BL1 or platform-specific one") +diff --git a/platform/ext/target/arm/mps4/common/partition/flash_layout.h b/platform/ext/target/arm/mps4/common/partition/flash_layout.h +index 61dbdd5fa..0b0749297 100644 +--- a/platform/ext/target/arm/mps4/common/partition/flash_layout.h ++++ b/platform/ext/target/arm/mps4/common/partition/flash_layout.h +@@ -160,8 +160,53 @@ + /* Maximum number of image sectors supported by the bootloader. */ + #define MCUBOOT_MAX_IMG_SECTORS (FLASH_MAX_PARTITION_SIZE / \ + FLASH_AREA_IMAGE_SECTOR_SIZE) +-#else /* MCUBOOT_IMAGE_NUMBER > 2 */ +-#error "Only MCUBOOT_IMAGE_NUMBER 1 and 2 are supported!" ++#elif (MCUBOOT_IMAGE_NUMBER == 3) ++ ++/* Secure image primary slot */ ++#define FLASH_AREA_0_ID (1) ++#define FLASH_AREA_0_OFFSET (0) ++#define FLASH_AREA_0_SIZE (FLASH_S_PARTITION_SIZE) ++ ++/* Non-secure image primary slot */ ++#define FLASH_AREA_1_ID (FLASH_AREA_0_ID + 1) ++#define FLASH_AREA_1_OFFSET (FLASH_AREA_0_OFFSET + FLASH_AREA_0_SIZE) ++#define FLASH_AREA_1_SIZE (FLASH_NS_PARTITION_SIZE) ++ ++/* Non-secure ML model image primary slot */ /* Use a _0 suffix to keep other slot names unchanged. */ ++#define FLASH_AREA_1_0_ID (FLASH_AREA_1_ID + 1) ++#define FLASH_AREA_1_0_OFFSET (FLASH_AREA_1_OFFSET + FLASH_AREA_1_SIZE) ++#define FLASH_AREA_1_0_SIZE (FLASH_NS_ML_MODEL_PARTITION_SIZE) ++ ++/* Secure image secondary slot */ ++#define FLASH_AREA_2_ID (FLASH_AREA_1_0_ID + 1) ++#define FLASH_AREA_2_OFFSET (FLASH_AREA_1_0_OFFSET + FLASH_AREA_1_0_SIZE) ++#define FLASH_AREA_2_SIZE (FLASH_S_PARTITION_SIZE) ++ ++/* Non-secure image secondary slot */ ++#define FLASH_AREA_3_ID (FLASH_AREA_2_ID + 1) ++#define FLASH_AREA_3_OFFSET (FLASH_AREA_2_OFFSET + FLASH_AREA_2_SIZE) ++#define FLASH_AREA_3_SIZE (FLASH_NS_PARTITION_SIZE) ++ ++/* Non-secure ML model image secondary slot */ /* Use a _0 suffix to keep other slot names unchanged. */ ++#define FLASH_AREA_3_0_ID (FLASH_AREA_3_ID + 1) ++#define FLASH_AREA_3_0_OFFSET (FLASH_AREA_3_OFFSET + FLASH_AREA_3_SIZE) ++#define FLASH_AREA_3_0_SIZE (FLASH_NS_ML_MODEL_PARTITION_SIZE) ++ ++/* Scratch area */ ++#define FLASH_AREA_SCRATCH_ID (FLASH_AREA_3_0_ID + 1) ++#define FLASH_AREA_SCRATCH_OFFSET (FLASH_AREA_3_0_OFFSET + FLASH_AREA_3_0_SIZE) ++#define FLASH_AREA_SCRATCH_SIZE (0x80000) /* 512 kB */ ++ ++/* The maximum number of status entries supported by the bootloader. */ ++#define MCUBOOT_STATUS_MAX_ENTRIES (FLASH_MAX_PARTITION_SIZE / \ ++ FLASH_AREA_SCRATCH_SIZE) ++ ++/* Maximum number of image sectors supported by the bootloader. */ ++#define MCUBOOT_MAX_IMG_SECTORS (FLASH_MAX_PARTITION_SIZE / \ ++ FLASH_AREA_IMAGE_SECTOR_SIZE) ++ ++#else /* MCUBOOT_IMAGE_NUMBER > 3 */ ++#error "Only MCUBOOT_IMAGE_NUMBER 1, 2 and 3 are supported!" + #endif /* MCUBOOT_IMAGE_NUMBER */ + + /* Protected Storage (PS) Service definitions */ +@@ -276,4 +321,40 @@ + #define TFM_OTP_NV_COUNTERS_BACKUP_AREA_ADDR (TFM_OTP_NV_COUNTERS_AREA_ADDR + \ + TFM_OTP_NV_COUNTERS_AREA_SIZE) + ++#if (MCUBOOT_IMAGE_NUMBER == 1) ++/* ++ * NOTE: the definition below returns the same values for true/false on ++ * purpose, to avoid having to mark x as non-used by all callers when ++ * running in single image mode. ++ */ ++#define FLASH_AREA_IMAGE_PRIMARY(x) (((x) == 0) ? FLASH_AREA_0_ID : \ ++ FLASH_AREA_0_ID) ++#define FLASH_AREA_IMAGE_SECONDARY(x) (((x) == 0) ? FLASH_AREA_2_ID : \ ++ FLASH_AREA_2_ID) ++#elif (MCUBOOT_IMAGE_NUMBER == 2) ++/* MCUBoot currently supports only up to 2 updatable firmware images. ++ * If the number of the current image is greater than MCUBOOT_IMAGE_NUMBER - 1 ++ * then a dummy value will be assigned to the flash area macros. ++ */ ++#define FLASH_AREA_IMAGE_PRIMARY(x) (((x) == 0) ? FLASH_AREA_0_ID : \ ++ ((x) == 1) ? FLASH_AREA_1_ID : \ ++ 255 ) ++#define FLASH_AREA_IMAGE_SECONDARY(x) (((x) == 0) ? FLASH_AREA_2_ID : \ ++ ((x) == 1) ? FLASH_AREA_3_ID : \ ++ 255 ) ++#elif (MCUBOOT_IMAGE_NUMBER == 3) ++#define FLASH_AREA_IMAGE_PRIMARY(x) (((x) == 0) ? FLASH_AREA_0_ID : \ ++ ((x) == 1) ? FLASH_AREA_1_ID : \ ++ ((x) == 2) ? FLASH_AREA_1_0_ID : \ ++ 255 ) ++#define FLASH_AREA_IMAGE_SECONDARY(x) (((x) == 0) ? FLASH_AREA_2_ID : \ ++ ((x) == 1) ? FLASH_AREA_3_ID : \ ++ ((x) == 2) ? FLASH_AREA_3_0_ID : \ ++ 255 ) ++#else ++#error "Image slot and flash area mapping is not defined" ++#endif ++ ++#define FLASH_AREA_IMAGE_SCRATCH FLASH_AREA_SCRATCH_ID ++ + #endif /* __FLASH_LAYOUT_H__ */ +diff --git a/platform/ext/target/arm/mps4/common/partition/region_defs.h b/platform/ext/target/arm/mps4/common/partition/region_defs.h +index 7ccfe6886..f6012f026 100644 +--- a/platform/ext/target/arm/mps4/common/partition/region_defs.h ++++ b/platform/ext/target/arm/mps4/common/partition/region_defs.h +@@ -88,6 +88,9 @@ + #define IMAGE_NS_CODE_SIZE \ + (FLASH_NS_PARTITION_SIZE - BL2_HEADER_SIZE - BL2_TRAILER_SIZE) + ++#define IMAGE_NS_ML_MODEL_CODE_SIZE \ ++ (FLASH_NS_ML_MODEL_PARTITION_SIZE - BL2_HEADER_SIZE - BL2_TRAILER_SIZE) ++ + /* Secure regions */ + #define S_IMAGE_PRIMARY_AREA_OFFSET \ + (S_IMAGE_PRIMARY_PARTITION_OFFSET + BL2_HEADER_SIZE) +@@ -124,7 +127,12 @@ + /* NS partition information is used for MPC and SAU configuration */ + #define NS_PARTITION_START \ + ((QSPI_SRAM_BASE_NS) + (NS_IMAGE_PRIMARY_PARTITION_OFFSET)) +-#define NS_PARTITION_SIZE (FLASH_NS_PARTITION_SIZE) ++ ++#if (MCUBOOT_IMAGE_NUMBER >= 3) ++ #define NS_PARTITION_SIZE (FLASH_NS_PARTITION_SIZE + FLASH_NS_ML_MODEL_PARTITION_SIZE) ++#else ++ #define NS_PARTITION_SIZE (FLASH_NS_PARTITION_SIZE) ++#endif + + /* Secondary partition for new images in case of firmware upgrade */ + #define SECONDARY_PARTITION_START \ +diff --git a/platform/ext/target/arm/mps4/common/provisioning/bundle_dm/CMakeLists.txt b/platform/ext/target/arm/mps4/common/provisioning/bundle_dm/CMakeLists.txt +index 9102d4564..c27b7c64f 100644 +--- a/platform/ext/target/arm/mps4/common/provisioning/bundle_dm/CMakeLists.txt ++++ b/platform/ext/target/arm/mps4/common/provisioning/bundle_dm/CMakeLists.txt +@@ -95,6 +95,7 @@ add_custom_command(OUTPUT dm_provisioning_data.c + --bl2_mcuboot_hw_key=${MCUBOOT_HW_KEY} + --bl2_rot_priv_key_0=${MCUBOOT_KEY_S} + --bl2_rot_priv_key_1=${MCUBOOT_KEY_NS} ++ --bl2_rot_priv_key_2=${MCUBOOT_KEY_NS} + --implementation_id=${IMPLEMENTATION_ID} + --verification_service_url=${VERIFICATION_SERVICE_URL} + --attestation_profile_definition=${ATTESTATION_PROFILE_DEFINITION} +-- +2.34.1 + diff --git a/docs/applications/ml_model_update/ml-model-update.md b/docs/applications/ml_model_update/ml-model-update.md new file mode 100644 index 00000000..76957501 --- /dev/null +++ b/docs/applications/ml_model_update/ml-model-update.md @@ -0,0 +1,203 @@ +## Introduction + +This document shows how to configure the project to extend +the Over the Air (OTA) firmware update feature to allow an ML-model-only +update. + +## Supported toolchain and example + +1. Toolchain support is limited to `GNU`. +1. Example application support is limited to `Keyword-Detection`. + +## Details + +The PSA Firmware Update API already uses the concept of a firmware component, +and the reference implementation integrated into the FRI, the Trusted +Firmware-M, operates on either two-component configuration (Secure and +Non-Secure images), or a single-component config (where the Secure and +Non-Secure images are merged). To enable the ML model OTA update, it was +necessary to update the default configuration to support a 3-component setup, +and to lift any limitations specific to a 2-component implementation. + +### Summary of changes + +#### ML Model extraction + +The ML model was moved from the DDR memory into a separate binary loaded into +flash. This enabled the MCUBoot bootloader to handle the model in the same way +as the other firmware components that are stored in their dedicated flash +partitions. Now, MCUBoot can successfully validate or update the ML model image. + +#### Partition resizing + +To keep the changes minimal, the ML model partitions were created at the cost of +the Non-Secure partitions. These were re-sized from `0x340000 B` to +`0x240000 B`, and the remaining `0x100000 B` were used for the ML model. As a +result, addresses of the Secure, Non-Secure and Scratch partitions are +unchanged. Also the sizes of the Secure and Scratch partitions remain unchanged. + +#### Runtime copy + +Since the Ethos NPU doesn't have access flash, the model is copied to DDR +at runtime (during the ML task init). This is why the model is still kept in the +DDR memory region in the linker script. + +#### OTA PAL version handling & file path + +The OTA PAL (precisely, the `OtaPalInterface_t` interface) had to be extended +with `getPlatformImageVersion` to enable independent version handling for each +component in a multi-component setup. + +#### Image processing + +Also the build environment required a number of updates to correctly process the +additional ML model image. Provisioning data and signing layout were configured +for the ML model image based on the Non-Secure image config. Currently, the ML +model image is signed with the same key as the Non-Secure image (i.e. `image_ns_signing_private_key.pem`), +but this can be easily changed by adding a new input parameter to the +[SignTfmImage CMake module](../../../components/security/trusted_firmware-m/integration/cmake/SignTfmImage.cmake) +to accept the designated signing key for each image. + +## Build instructions + +Currently, the ML model update is supported for the Keyword-Detection example +application built with the `GNU` toolchain for all FRI's supported platforms. +Please follow [the application-specific build instructions](../keyword_detection.md). + +## Run instructions + +Please follow [the application-specific run instructions](../keyword_detection.md). + +If you prefer to run the FVP manually, and explicitly set all the arguments +(e.g. when debugging), run the following command: + +```bash +FVP_Corstone_SSE-300_Ethos-U55 \ +-C mps3_board.visualisation.disable-visualisation=1 \ +-C core_clk.mul=200000000 \ +-C mps3_board.smsc_91c111.enabled=1 \ +-C mps3_board.hostbridge.userNetworking=1 \ +-C mps3_board.telnetterminal0.start_telnet=0 \ +-C mps3_board.uart0.out_file=- \ +-C mps3_board.uart0.unbuffered_output=1 \ +-C mps3_board.DISABLE_GATING=1 \ +-a /workspaces/iot-reference-arm-corstone3xx/build/iot_reference_arm_corstone3xx/components/security/trusted_firmware-m/integration/trusted_firmware-m-build-prefix/src/trusted_firmware-m-build-build/bin/bl2.axf \ +--data build/iot_reference_arm_corstone3xx/components/security/trusted_firmware-m/integration/trusted_firmware-m-build-prefix/src/trusted_firmware-m-build-build/api_ns/bin/encrypted_provisioning_bundle.bin@0x10022000 \ +--data build/keyword-detection_signed.bin@0x28040000 \ +--data build/iot_reference_arm_corstone3xx/components/security/trusted_firmware-m/integration/trusted_firmware-m-build-prefix/src/trusted_firmware-m-build-build/api_ns/bin/tfm_s_signed.bin@0x38000000 \ +--data build/helpers/provisioning/provisioning_data.bin@0x211ff000 \ +--data build/application_sectors/ddr.bin@0x60100000 \ +--data build/keyword-detection-model_signed.bin@0x28280000 +``` + +### ML Model update with AWS + +As for the usual Non-Secure OTA update demo, the updated ML model firmware image +is created during the application build process. The updated image will only +differ in version number. That is enough to demonstrate the OTA process using a +newly created image. + +Deploy an AWS update job as described in the [Firmware update +with AWS](../aws_iot/aws_iot_cloud_connection.md) section. The +flow for the ML model is very similar to the one for the Non-Secure image; the +only differences are: + +- use `ml_model image` for **Path name of file on device**, +- upload the signed update binary, `build/keyword-detection-model-update_signed.bin` +- use the signature string from `build/model-update-signature.txt`. + +Now, start the Keyword-Detection example, and observe the ML model update. + +#### Making the ML model update demo more appealing + +Although it is enough to observe the ML model component version bump, a more +demonstrative output can be obtained with minimal effort. Follow the (optional) +steps below to run the Keyword-Detection example with a modified faulty model, unable +to detect any keyword, deploy the OTA update of the ML model, after which correct +ML inference results can be observed after the update is complete. + +1. Save the update image with a correctly working ML model. + + By default, the keyword-detection example is built with a fully-functional + ML model, fetched from the [ML-zoo][kws-model]. If you have already built + the application, the signed model update is available in the build + directory. Back it up together with its signature string. + + ```bash + cp build/keyword-detection-model-update_signed.bin build/model-update-signature.txt applications/keyword_detection/ml-model-update-demo + ``` + +1. Alter the ML model artifacts in the build dir. + + A modified model is available in + `../../../applications/keyword_detection/ml-model-update-demo/faulty_kws_micronet_m.tflite`. Compile it with + Vela and replace the original tflite file. + + ```bash + source build/mlek_resources_downloaded/env/bin/activate && vela applications/keyword_detection/ml-model-update-demo/faulty_kws_micronet_m.tflite --accelerator-config=ethos-u55-128 --optimise Performance --config components/ai/ml_embedded_evaluation_kit/library/scripts/vela/default_vela.ini --memory-mode=Shared_Sram --system-config=Ethos_U55_High_End_Embedded --output-dir=applications/keyword_detection/ml-model-update-demo --arena-cache-size=2097152 + cp applications/keyword_detection/ml-model-update-demo/faulty_kws_micronet_m_vela.tflite build/mlek_resources_downloaded/kws/kws_micronet_m_vela_H128.tflite + ``` + +1. Build the application with the modified model. + + Simply run the build command mentioned in the [Build + instructions](#build-instructions) section. + +1. Run the Keyword-Detection application and confirm that no keywords are +detected. Then stop the application. + +1. Deploy an AWS OTA job with the functional ML model from the +`../../../applications/keyword_detection/ml-model-update-demo` dir. + +1. Start the Keyword-Detection example again, let it update the ML model, and +detect keywords correctly again. + + +Before the ML Model update: + +``` +(...) +58 10031 [ML_TASK] [INFO] Running inference on an audio clip in local memory +59 10058 [OTA Agent Task] [INFO] Current State=[WaitingForJob], Event=[ReceivedJobDocument], New state=[CreatingFile] +60 10103 [ML_TASK] [INFO] ML UNKNOWN +61 10109 [ML_MQTT] [INFO] Attempting to publish (_unknown_) to the MQTT topic MyThing_eu_central_1/ml/inference. +62 10128 [ML_TASK] [INFO] For timestamp: 0.000000 (inference #: 0); label: ; threshold: 0.000000 +63 10168 [ML_TASK] [INFO] For timestamp: 0.500000 (inference #: 1); label: ; threshold: 0.000000 +64 10208 [ML_TASK] [INFO] For timestamp: 1.000000 (inference #: 2); label: ; threshold: 0.000000 +65 10248 [ML_TASK] [INFO] For timestamp: 1.500000 (inference #: 3); label: ; threshold: 0.000000 +66 10288 [ML_TASK] [INFO] For timestamp: 2.000000 (inference #: 4); label: ; threshold: 0.000000 +67 10328 [ML_TASK] [INFO] For timestamp: 2.500000 (inference #: 5); label: ; threshold: 0.000000 +68 10368 [ML_TASK] [INFO] For timestamp: 3.000000 (inference #: 6); label: ; threshold: 0.000000 +69 10408 [ML_TASK] [INFO] For timestamp: 3.500000 (inference #: 7); label: ; threshold: 0.000000 +``` + +After the ML Model update: + +``` +(...) +57 10000 [OTA Agent Task] [INFO] In self test mode. +58 10009 [OTA Agent Task] [INFO] New image has a higher version number than the current image: New image version=0.0.42, Previous image version=0.0.11 +59 10034 [OTA Agent Task] [INFO] Image version is valid: Begin testing file: File ID=0 +(...) +75 12259 [OTA Agent Task] [INFO] New image validation succeeded in self test mode. +(...) +95 14005 [ML_TASK] [INFO] Running inference on an audio clip in local memory +96 14032 [OTA Agent Task] [INFO] Current State=[WaitingForJob], Event=[ReceivedJobDocument], New state=[CreatingFile] +97 14078 [ML_TASK] [INFO] ML_HEARD_ON +98 14084 [ML_MQTT] [INFO] Attempting to publish (on) to the MQTT topic MyThing_eu_central_1/ml/inference. +99 14102 [ML_TASK] [INFO] For timestamp: 0.000000 (inference #: 0); label: on, score: 0.996127; threshold: 0.700000 +100 14144 [ML_TASK] [INFO] For timestamp: 0.500000 (inference #: 1); label: on, score: 0.962542; threshold: 0.700000 +101 14186 [ML_TASK] [INFO] ML UNKNOWN +102 14192 [ML_TASK] [INFO] For timestamp: 1.000000 (inference #: 2); label: ; threshold: 0.000000 +103 14232 [ML_TASK] [INFO] ML_HEARD_OFF +104 14239 [ML_TASK] [INFO] For timestamp: 1.500000 (inference #: 3); label: off, score: 0.999030; threshold: 0.700000 +105 14281 [ML_TASK] [INFO] ML UNKNOWN +106 14287 [ML_TASK] [INFO] For timestamp: 2.000000 (inference #: 4); label: ; threshold: 0.000000 +107 14328 [ML_TASK] [INFO] For timestamp: 2.500000 (inference #: 5); label: ; threshold: 0.000000 +108 14368 [ML_TASK] [INFO] ML_HEARD_GO +109 14375 [ML_TASK] [INFO] For timestamp: 3.000000 (inference #: 6); label: go, score: 0.998854; threshold: 0.700000 +110 14417 [ML_TASK] [INFO] ML UNKNOWN +111 14423 [ML_TASK] [INFO] For timestamp: 3.500000 (inference #: 7); label: ; threshold: 0.000000 +``` + +[kws-model]: https://github.com/ARM-software/ML-zoo/tree/9f506fe52b39df545f0e6c5ff9223f671bc5ae00/models/keyword_spotting/micronet_medium/tflite_int8 diff --git a/docs/components/security/trusted_firmware-m/trusted_firmware-m.md b/docs/components/security/trusted_firmware-m/trusted_firmware-m.md index 99e5ce38..0d7149f6 100644 --- a/docs/components/security/trusted_firmware-m/trusted_firmware-m.md +++ b/docs/components/security/trusted_firmware-m/trusted_firmware-m.md @@ -56,16 +56,32 @@ You need to link your application against the `tfm-ns-interface` library so that Your non-secure application image must be signed using the signing script from Trusted Firmware-M. In the signed image, the executable binary is prepended with a header area containing information such as the image size, version, checksum, signature, etc. The bootloader uses this information to validate the image during the boot process. -To sign your application image, you can include the CMake module [`SignTfmImage`](../../../../components/security/trusted_firmware-m/integration/cmake/SignTfmImage.cmake) and call the helper function `iot_reference_arm_corstone3xx_tf_m_sign_image()` in your `CMakeLists.txt`: +To sign your application image, you need to do the following: + +1. Include the CMake modules [`SignTfmImage`](../../../../components/security/trusted_firmware-m/integration/cmake/SignTfmImage.cmake) and [`ConvertElfToBin`](../../../../tools/cmake/ConvertElfToBin.cmake) in your `CMakeLists.txt`. +2. Extract the sections that won't be signed as part of the image (ex. `ddr.bin`) using the helper function `extract_sections_from_axf()`. +3. Use the output binary file (i.e. `OUTPUT_BIN_NAME`) to sign the image using the helper function `iot_reference_arm_corstone3xx_tf_m_sign_image()`. ```cmake +list(APPEND CMAKE_MODULE_PATH ${IOT_REFERENCE_ARM_CORSTONE3XX_SOURCE_DIR}/tools/cmake) list(APPEND CMAKE_MODULE_PATH ${IOT_REFERENCE_ARM_CORSTONE3XX_SOURCE_DIR}/components/security/trusted_firmware-m/integration/cmake) +include(ConvertElfToBin) include(SignTfmImage) +include(ExternalProject) +ExternalProject_Get_Property(trusted_firmware-m-build BINARY_DIR) + +extract_sections_from_axf( + keyword-detection + SECTIONS_NAMES "ddr.bin" + OUTPUT_BIN_NAME "ns_image" +) iot_reference_arm_corstone3xx_tf_m_sign_image( my_application + "ns_image" my_application_signed ${MCUBOOT_IMAGE_VERSION_NS} + "${BINARY_DIR}/api_ns/image_signing/layout_files/signing_layout_ns.o" TRUE ) ``` @@ -74,7 +90,11 @@ This will generate a signed image, `my_application_signed.bin`, in your build di > Replace `my_application` with the actual name of your application executable. > +> Replace `ns_image` with the name used as `OUTPUT_BIN_NAME` in `extract_sections_from_axf` function. +> > Replace `MCUBOOT_IMAGE_VERSION_NS` with a version of your choice. +> +> Replace `signing_layout_ns.o` with the signature layout file to be used to sign the image. You can merge the bootloader, the secure image, the non-secure application,image, secure provisioning bundle binary, non-secure provisioning bundle binary, and DDR binary into a single `.elf` image to ease loading of the code onto the target. To do this: diff --git a/release_changes/202407151057.change b/release_changes/202407151057.change new file mode 100644 index 00000000..f7c171c9 --- /dev/null +++ b/release_changes/202407151057.change @@ -0,0 +1 @@ +ml-model: Add ML-Model component update feature to keyword-detection application. diff --git a/tools/ci/license/license.schema b/tools/ci/license/license.schema index f79a1324..f716e2c7 100644 --- a/tools/ci/license/license.schema +++ b/tools/ci/license/license.schema @@ -92,7 +92,7 @@ "properties": { "path": { "type": "string", - "pattern": "(gitmodules|CODEOWNERS|doxyfile_options|gitlint|license\\.schema|^(?!CMakeLists).+\\.txt|.gitkeep|.astylerc)$" + "pattern": "(gitmodules|CODEOWNERS|doxyfile_options|gitlint|license\\.schema|^(?!CMakeLists).+\\.txt|.gitkeep|.astylerc|.tflite)$" }, "type": { "type": "string", diff --git a/tools/cmake/ConvertElfToBin.cmake b/tools/cmake/ConvertElfToBin.cmake index a5a44812..2aafe6b6 100644 --- a/tools/cmake/ConvertElfToBin.cmake +++ b/tools/cmake/ConvertElfToBin.cmake @@ -1,4 +1,4 @@ -# Copyright 2021-2024 Arm Limited and/or its affiliates +# Copyright 2021-2025 Arm Limited and/or its affiliates # # SPDX-License-Identifier: MIT @@ -52,6 +52,7 @@ function(extract_sections_from_axf target) find_program(objcopy NAMES arm-none-eabi-objcopy objcopy REQUIRED) list(LENGTH PARSED_SECTIONS_NAMES N_SECTIONS) math(EXPR MAX_IDX "${N_SECTIONS} - 1") + set(RM_SECTION_ARG_LIST "") foreach(IDX RANGE ${MAX_IDX}) list(GET PARSED_SECTIONS_NAMES ${IDX} SECTION_NAME) @@ -67,14 +68,23 @@ function(extract_sections_from_axf target) --only-section ${SECTION_NAME} $ ${SECTORS_BIN_DIR}/${SECTION_NAME} - COMMAND - ${objcopy} -O binary - --remove-section ${SECTION_NAME} - $ - ${SECTORS_BIN_DIR}/${PARSED_OUTPUT_BIN_NAME}.bin ) + list(APPEND RM_SECTION_ARG_LIST "--remove-section" "${SECTION_NAME}") endforeach() + add_custom_command( + TARGET + ${target} + POST_BUILD + DEPENDS + $ + COMMAND + ${objcopy} -O binary + ${RM_SECTION_ARG_LIST} + $ + ${SECTORS_BIN_DIR}/${PARSED_OUTPUT_BIN_NAME}.bin + ) + elseif(CMAKE_C_COMPILER_ID STREQUAL "ARMClang") find_program(fromelf NAMES fromelf REQUIRED) add_custom_command( diff --git a/tools/scripts/run.sh b/tools/scripts/run.sh index b5562f22..0a9a9f43 100755 --- a/tools/scripts/run.sh +++ b/tools/scripts/run.sh @@ -1,6 +1,6 @@ #!/bin/bash -# Copyright 2023-2024 Arm Limited and/or its affiliates +# Copyright 2023-2025 Arm Limited and/or its affiliates # # SPDX-License-Identifier: MIT @@ -199,7 +199,6 @@ case "$TARGET" in -C mps3_board.telnetterminal0.start_telnet=0 \ -C mps3_board.uart0.out_file="-" \ -C mps3_board.uart0.unbuffered_output=1 \ - -C ethosu.extra_args="--fast" \ --stat \ -C mps3_board.DISABLE_GATING=1" ;; @@ -212,7 +211,6 @@ case "$TARGET" in -C mps4_board.telnetterminal0.start_telnet=0 \ -C mps4_board.uart0.out_file="-" \ -C mps4_board.uart0.unbuffered_output=1 \ - -C mps4_board.subsystem.ethosu.extra_args="--fast" \ -C mps4_board.isp_c55_capture_ds.do_capture=0 \ -C mps4_board.isp_c55_capture_fr.do_capture=0 \ -C mps4_board.isp_c55_camera.image_file=${FRAMES} \ diff --git a/tools/tests/aws_test_util.py b/tools/tests/aws_test_util.py index 8fa247e3..7f10092e 100755 --- a/tools/tests/aws_test_util.py +++ b/tools/tests/aws_test_util.py @@ -1,4 +1,4 @@ -# Copyright 2023-2024, Arm Limited and/or its affiliates +# Copyright 2023-2025, Arm Limited and/or its affiliates # # SPDX-License-Identifier: MIT @@ -50,13 +50,21 @@ def __init__( self.OTA_S3_BUCKET = "iotmsw-ci-test-bucket-" + self.TEST_ID self.OTA_POLICY_NAME = "iotmsw-ci-test-policy-" + self.TEST_ID self.OTA_BINARY = signed_update_bin_name + self.FILE_NAME = "" + self.UPDATE_SIGNATURE = "" + if "model" in self.OTA_BINARY: + self.FILE_NAME = "ml_model image" + self.UPDATE_SIGNATURE = "model-update-signature.txt" + else: + self.FILE_NAME = "non_secure image" + self.UPDATE_SIGNATURE = "update-signature.txt" self.OTA_BINARY_PATH = Path(self.BUILD_ARTEFACTS_PATH) / self.OTA_BINARY self.OTA_ROLE_ARN = f"arn:aws:iam::{self.AWS_ACCOUNT}:role/{OTA_ROLE_NAME}" self.OTA_UPDATE_PROTOCOLS = ["MQTT"] self.OTA_UPDATE_TARGET_SELECTION = "SNAPSHOT" self.OTA_UPDATE_FILES = [ { - "fileName": "non_secure image", + "fileName": self.FILE_NAME, "fileLocation": { "s3Location": {"bucket": self.OTA_S3_BUCKET, "key": self.OTA_BINARY} }, @@ -67,7 +75,7 @@ def __init__( read_whole_file( ( Path(self.BUILD_ARTEFACTS_PATH) - / "update-signature.txt" + / self.UPDATE_SIGNATURE ) ).strip(), "utf-8", diff --git a/tools/tests/conftest.py b/tools/tests/conftest.py index 1c646c16..ffcf113a 100644 --- a/tools/tests/conftest.py +++ b/tools/tests/conftest.py @@ -1,4 +1,4 @@ -# Copyright (c) 2023-2024, Arm Limited. All rights reserved. +# Copyright (c) 2023-2025, Arm Limited. All rights reserved. # SPDX-License-Identifier: MIT import pytest @@ -163,8 +163,6 @@ def fvp_process( "mps4_board.smsc_91c111.enabled=1", "-C", "mps4_board.hostbridge.userNetworking=1", - "-C", - "mps4_board.subsystem.ethosu.extra_args=--fast", ] vsi_options = [ @@ -205,8 +203,6 @@ def fvp_process( "mps3_board.hostbridge.userNetworking=1", "-C", "mps3_board.DISABLE_GATING=1", - "-C", - "ethosu.extra_args=--fast", ] vsi_options = [ diff --git a/tools/tests/test_integration.py b/tools/tests/test_integration.py index 5d9b0098..2e7cf84c 100755 --- a/tools/tests/test_integration.py +++ b/tools/tests/test_integration.py @@ -1,10 +1,8 @@ -# Copyright (c) 2023-2024 Arm Limited. All rights reserved. +# Copyright (c) 2023-2025 Arm Limited. All rights reserved. # SPDX-License-Identifier: MIT import subprocess from timeit import default_timer as timer -from pytest import fixture -from aws_test_util import Flags, create_aws_resources, cleanup_aws_resources import re # If you have failing test cases to ignore, @@ -17,33 +15,7 @@ test_cases_to_ignore = {} -@fixture(scope="function") -def setup_resources( - build_artefacts_path: str, - credentials_path: str, - signed_update_bin_name: str, - signing_algo: str, -): - """ - Setup resources needed to run the test. - - build_artefacts_path: Path to all the artefacts needed to create AWS resources. - credentials_path: Path to AWS credentials. - signed_update_bin_name: Name of the binary to be used for the OTA update. - """ - flags = Flags( - build_artefacts_path, credentials_path, signed_update_bin_name, signing_algo - ) - flags = create_aws_resources(flags) - try: - # Caller won't actually do anything with this, but we have to yield something. - yield flags - finally: - cleanup_aws_resources(flags) - - def test_integration( - setup_resources, fvp_process: subprocess.Popen, timeout_seconds: int, ):