From 510069dde87136544b70c66097c3e7c4889194eb Mon Sep 17 00:00:00 2001 From: Sergei Lissianoi <54454955+selissia@users.noreply.github.com> Date: Mon, 14 Mar 2022 17:12:04 -0400 Subject: [PATCH] [OTA] EFR32: Parse Matter OTA header, update documentation (#16120) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Add header parsing logic to OTAImageProcessorImpl * Use a local variable for the buffer when parsing the header * Test added march 8 (#15957) * Added new manual scripts * Added Auto generated File * [OTA] Fix OTARequestorDriverImpl inclusion (#15981) * Regen to fix CI failures (#15990) * [ota] Store Default OTA Providers in flash (#15970) * [ota] Store Default OTA Providers in flash Store Default OTA Providers in flash each time the attribute is modified and load it back on the application startup. * Restyled by clang-format * Fix build and reduce flash usage Co-authored-by: Restyled.io * Set periodic query timeout * Make OTAImageProcessorImpl::Apply() schedule work instead of running directly * Update error logs * Remove files that got out of synch with the upstream repo * Return after bootloader errors * Update OTA documentation for EFR32 * Fix spelling * Add OTA_PERIODIC_TIMEOUT to the lock-app build * Fix typo * Add OTA_periodic_query_timeout to EFR32 light-switch and window-app * Restyled by clang-format * Restyled by gn * Restyled by prettier-markdown * Fix typos * Update dictionary Co-authored-by: kowsisoundhar12 <57476670+kowsisoundhar12@users.noreply.github.com> Co-authored-by: Carol Yang Co-authored-by: Boris Zbarsky Co-authored-by: Damian Królik <66667989+Damian-Nordic@users.noreply.github.com> Co-authored-by: Restyled.io --- .github/.wordlist.txt | 18 +++ docs/guides/silabs_efr32_software_update.md | 88 +++++++++++++ examples/light-switch-app/efr32/BUILD.gn | 4 + examples/light-switch-app/efr32/README.md | 8 ++ examples/lighting-app/efr32/BUILD.gn | 4 +- examples/lighting-app/efr32/README.md | 8 ++ examples/lock-app/efr32/BUILD.gn | 6 +- examples/lock-app/efr32/README.md | 8 ++ examples/ota-requestor-app/efr32/README.md | 125 +------------------ examples/platform/efr32/OTAConfig.cpp | 2 + examples/window-app/efr32/BUILD.gn | 6 +- examples/window-app/efr32/README.md | 8 ++ src/platform/EFR32/OTAImageProcessorImpl.cpp | 104 ++++++++------- src/platform/EFR32/OTAImageProcessorImpl.h | 4 + 14 files changed, 226 insertions(+), 167 deletions(-) create mode 100644 docs/guides/silabs_efr32_software_update.md diff --git a/.github/.wordlist.txt b/.github/.wordlist.txt index 033480471f4730..ef7265d8085079 100644 --- a/.github/.wordlist.txt +++ b/.github/.wordlist.txt @@ -805,6 +805,7 @@ MX mydir MyPASSWORD MySSID +NAMESERVER nameserver namespacing nano @@ -1294,6 +1295,7 @@ virtualenv visualstudio vlatest VLEDs +vn vnc vous VPN @@ -1382,3 +1384,19 @@ zephyrproject Zigbee zigbeealliance zigbeethread +libshell +TestGroupDemoConfig +ACLs +AddNOC +CHIPConfig +CHIPProjectAppConfig +CaseAdminNode +DataVersion +ProxyView +ReadAttribute +WriteAttribute +kAdminister +kManage +kOperate +kView +xFFFFFFFD diff --git a/docs/guides/silabs_efr32_software_update.md b/docs/guides/silabs_efr32_software_update.md new file mode 100644 index 00000000000000..29660f133f6708 --- /dev/null +++ b/docs/guides/silabs_efr32_software_update.md @@ -0,0 +1,88 @@ +# Matter Software Update with EFR32 example applications + +The Over The Air (OTA) Software Update functionality can be added to any of the +EFR32 example applications by passing the `chip_enable_ota_requestor=true` +option to the build script. This option is supposed to be enabled by default for +all of the EFR32 example applications. + +## Running the OTA Download scenario + +- For Matter with OpenThread: Bring up the OpenThread Border Router as + discussed in examples/lighting-app/efr32/README.md and get its operational + dataset. + +- On a Linux or Darwin platform build the chip-tool and the ota-provider-app + as follows: + + scripts/examples/gn_build_example.sh examples/chip-tool out/ + scripts/examples/gn_build_example.sh examples/ota-provider-app/linux out/debug chip_config_network_layer_ble=false + +- Build or download the Gecko Bootloader binary. Bootloader should be built + with the Gecko SDK version 3.2.1 or earlier, type "external SPI" configured + with a single slot of at least 1000 KB. Pre-built binaries should be + available in + + third_party/efr32_sdk/repo/platform/bootloader/sample-apps/bootloader-storage-spiflash-single + +- Using the commander tool upload the bootloader to the device running the + application. + +- Create a bootable image file (using the Lighting application image as an + example): + + commander gbl create chip-efr32-lighting-example.gbl --app chip-efr32-lighting-example.s37 + +- Create the Matter OTA file from the bootable image file: + + ./src/app/ota_image_tool.py create -v 0xFFF1 -p 0x8005 -vn 1 -vs "1.0" -da sha256 chip-efr32-lighting-example.gbl chip-efr32-lighting-example.ota + +- In a terminal start the Provider app passing to it the path to the Matter + OTA file created in the previous step: + + rm -r /tmp/chip_* + ./out/debug/chip-ota-provider-app -f chip-efr32-lighting-example.ota + +- In a separate terminal run the chip-tool commands to provision the Provider: + + ./out/chip-tool pairing onnetwork 1 20202021 + ./out/chip-tool accesscontrol write acl '[{"fabricIndex": 1, "privilege": 5, "authMode": 2, "subjects": [112233], "targets": null}, {"fabricIndex": 1, "privilege": 3, "authMode": 2, "subjects": null, "targets": null}]' 1 0 + +- If the application device had been previously commissioned hold Button 0 for + six seconds to factory-reset the device. + +- In the chip-tool terminal enter: + + ./out/chip-tool pairing ble-thread 2 hex: 20202021 3840 + +where operationalDataset is obtained from the OpenThread Border Router. + +- Once the commissioning process completes enter: + + ./out/chip-tool otasoftwareupdaterequestor announce-ota-provider 1 0 0 0 2 0 + +- The application device will connect to the Provider and start the image + download. Once the image is downloaded the device will reboot into the + downloaded image. + +## Managing the Software Version, Vendor and Product ID + +Starting the ota-provider-app with the --otaImageList command line option allows +the user to supply a JSON file specifying the Software Version, Vendor and +Product ID that identify the image served by the Provider, see +[ota-provider-app](../../examples/ota-provider-app/linux/README.md) + +Example provider configuration file: + +``` +{ "foo": 1, // ignored by parser + "deviceSoftwareVersionModel": + [ + { "vendorId": 65521, "productId": 32773, "softwareVersion": 1, "softwareVersionString": "1.0.0", "cDVersionNumber": 18, "softwareVersionValid": true, "minApplicableSoftwareVersion": 0, "maxApplicableSoftwareVersion": 100, "otaURL": "chip-efr32-lighting-example.ota" } + ] +} +``` + +In order for the Provider to successfully serve the image to a device during the +OTA Software Update process the softwareVersion parameter in the Provider config +file must be greater than the CHIP_DEVICE_CONFIG_DEVICE_SOFTWARE_VERSION +parameter set in the application's CHIPProjectConfig.h file. diff --git a/examples/light-switch-app/efr32/BUILD.gn b/examples/light-switch-app/efr32/BUILD.gn index 1aaa38b1afbb95..495edd87749b0f 100644 --- a/examples/light-switch-app/efr32/BUILD.gn +++ b/examples/light-switch-app/efr32/BUILD.gn @@ -48,6 +48,9 @@ declare_args() { # Enable Sleepy end device enable_sleepy_device = false + # OTA timeout in seconds + OTA_periodic_query_timeout = 86400 + # Wifi related stuff - they are overridden by gn -args="use_wf200=true" use_wf200 = false use_rs911x = false @@ -100,6 +103,7 @@ efr32_sdk("sdk") { "BOARD_ID=${efr32_board}", "CHIP_DEVICE_CONFIG_USE_TEST_SETUP_PIN_CODE=${setupPinCode}", "CHIP_DEVICE_CONFIG_USE_TEST_SETUP_DISCRIMINATOR=${setupDiscriminator}", + "OTA_PERIODIC_TIMEOUT=${OTA_periodic_query_timeout}", ] if (chip_enable_pw_rpc) { diff --git a/examples/light-switch-app/efr32/README.md b/examples/light-switch-app/efr32/README.md index b24401112e60c0..d73a2ab2fc9b63 100644 --- a/examples/light-switch-app/efr32/README.md +++ b/examples/light-switch-app/efr32/README.md @@ -13,6 +13,8 @@ An example showing the use of CHIP on the Silicon Labs EFR32 MG12. - [Running the Complete Example](#running-the-complete-example) - [Notes](#notes) - [Running RPC console](#running-rpc-console) + - [Memory settings](#memory-settings) + - [OTA Software Update](#ota-software-update)
@@ -362,3 +364,9 @@ console the RAM usage of each individual task and the number of Memory allocation and Free. While this is not extensive monitoring you're welcome to modify `examples/platform/efr32/MemMonitoring.cpp` to add your own memory tracking code inside the `trackAlloc` and `trackFree` function + +## OTA Software Update + +For the description of Software Update process with EFR32 example applications +see +[EFR32 OTA Software Update](../../../docs/guides/silabs_efr32_software_update.md) diff --git a/examples/lighting-app/efr32/BUILD.gn b/examples/lighting-app/efr32/BUILD.gn index b0a5e2c356d8e5..7f8f3bd1295f7d 100644 --- a/examples/lighting-app/efr32/BUILD.gn +++ b/examples/lighting-app/efr32/BUILD.gn @@ -49,9 +49,9 @@ declare_args() { enable_sleepy_device = false # OTA timeout in seconds - OTA_periodic_query_timeout = 10 + OTA_periodic_query_timeout = 86400 - # Wifi related stuff - they are overriden by gn -args="use_wf200=true" + # Wifi related stuff - they are overridden by gn -args="use_wf200=true" use_wf200 = false use_rs911x = false use_rs911x_sockets = false diff --git a/examples/lighting-app/efr32/README.md b/examples/lighting-app/efr32/README.md index 27ace2b6dba9cd..cebe0ee127a402 100644 --- a/examples/lighting-app/efr32/README.md +++ b/examples/lighting-app/efr32/README.md @@ -13,6 +13,8 @@ An example showing the use of CHIP on the Silicon Labs EFR32 MG12. - [Running the Complete Example](#running-the-complete-example) - [Notes](#notes) - [Running RPC console](#running-rpc-console) + - [Memory settings](#memory-settings) + - [OTA Software Update](#ota-software-update)
@@ -315,3 +317,9 @@ console the RAM usage of each individual task and the number of Memory allocation and Free. While this is not extensive monitoring you're welcome to modify `examples/platform/efr32/MemMonitoring.cpp` to add your own memory tracking code inside the `trackAlloc` and `trackFree` function + +## OTA Software Update + +For the description of Software Update process with EFR32 example applications +see +[EFR32 OTA Software Update](../../../docs/guides/silabs_efr32_software_update.md) diff --git a/examples/lock-app/efr32/BUILD.gn b/examples/lock-app/efr32/BUILD.gn index fd1e6ba0963738..b6db7044c681df 100644 --- a/examples/lock-app/efr32/BUILD.gn +++ b/examples/lock-app/efr32/BUILD.gn @@ -47,7 +47,10 @@ declare_args() { # Enable Sleepy end device enable_sleepy_device = false - # Wifi related stuff - they are overriden by gn -args="use_wf200=true" + # OTA timeout in seconds + OTA_periodic_query_timeout = 86400 + + # Wifi related stuff - they are overridden by gn -args="use_wf200=true" use_wf200 = false use_rs911x = false use_rs911x_sockets = false @@ -98,6 +101,7 @@ efr32_sdk("sdk") { defines = [ "BOARD_ID=${efr32_board}", "CHIP_DEVICE_CONFIG_USE_TEST_SETUP_PIN_CODE=${setupPinCode}", + "OTA_PERIODIC_TIMEOUT=${OTA_periodic_query_timeout}", ] if (chip_enable_pw_rpc) { diff --git a/examples/lock-app/efr32/README.md b/examples/lock-app/efr32/README.md index f176e9825e1483..4c82af13cfb24b 100644 --- a/examples/lock-app/efr32/README.md +++ b/examples/lock-app/efr32/README.md @@ -12,6 +12,8 @@ An example showing the use of CHIP on the Silicon Labs EFR32 MG12. - [Viewing Logging Output](#viewing-logging-output) - [Running the Complete Example](#running-the-complete-example) - [Notes](#notes) + - [Memory settings](#memory-settings) + - [OTA Software Update](#ota-software-update)
@@ -289,3 +291,9 @@ console the RAM usage of each individual task and the number of Memory allocation and Free. While this is not extensive monitoring you're welcome to modify `examples/platform/efr32/MemMonitoring.cpp` to add your own memory tracking code inside the `trackAlloc` and `trackFree` function + +## OTA Software Update + +For the description of Software Update process with EFR32 example applications +see +[EFR32 OTA Software Update](../../../docs/guides/silabs_efr32_software_update.md) diff --git a/examples/ota-requestor-app/efr32/README.md b/examples/ota-requestor-app/efr32/README.md index a16a357319fb80..db7d65e5c66b87 100644 --- a/examples/ota-requestor-app/efr32/README.md +++ b/examples/ota-requestor-app/efr32/README.md @@ -1,121 +1,6 @@ -# CHIP EFR32 OTA Requestor Example +For the description of Software Update process with EFR32 example applications +see +[EFR32 OTA Software Update](../../../docs/guides/silabs_efr32_software_update.md) -An example showing the use of the Matter OTA Requestor functionality on the -Silicon Labs EFR32 MG12. - - - -## Introduction - -The EFR32 OTA Requestor example provides a baseline demonstration the Matter OTA -Requestor functionality built with the Silicon Labs gecko SDK. It can be -controlled by a Chip controller over OpenThread network. - - - -## Building - -For initial setup steps please see the CHIP EFR32 Lighting Example README at -examples/lighting-app/efr32/README.md - -- Supported hardware: - - MG12 boards: - - - BRD4161A / SLWSTK6000B / Wireless Starter Kit / 2.4GHz@19dBm - - BRD4164A / SLWSTK6000B / Wireless Starter Kit / 2.4GHz@19dBm - - BRD4166A / SLTB004A / Thunderboard Sense 2 / 2.4GHz@10dBm - - BRD4170A / SLWSTK6000B / Multiband Wireless Starter Kit / 2.4GHz@19dBm, - 915MHz@19dBm - - BRD4304A / SLWSTK6000B / MGM12P Module / 2.4GHz@19dBm - - MG21 boards: Currently not supported due to RAM limitation. - - - BRD4180A / SLWSTK6006A / Wireless Starter Kit / 2.4GHz@20dBm - - MG24 boards : - - - BRD4186A / SLWSTK6006A / Wireless Starter Kit / 2.4GHz@10dBm - - BRD4187A / SLWSTK6006A / Wireless Starter Kit / 2.4GHz@20dBm - -* Build the example application: - - cd ~/connectedhomeip - ./scripts/examples/gn_efr32_example.sh  ./examples/ota-requestor-app/efr32/ ./out/ota-requestor-app BRD4161A - -- To delete generated executable, libraries and object files use: - - $ cd ~/connectedhomeip - $ rm -rf ./out/ - - - -## Flashing the Application - -- On the command line: - - $ cd ~/connectedhomeip/out/ota-requestor-app/BRD4161A - $ python3 chip-efr32-ota-requestor-example.flash.py - -- Or with the Ozone debugger, just load the .out file. - - - -## Viewing Logging Output - -See `examples/lighting-app/efr32/README.md` - - - -## Running the OTA Download scenario - -- Bring up the OpenThread Border Router as discussed in - examples/lighting-app/efr32/README.md and get its operational dataset. - -- On a Linux or Darwin platform build the chip-tool and the ota-provider-app - as follows: - - scripts/examples/gn_build_example.sh examples/chip-tool out/ - scripts/examples/gn_build_example.sh examples/ota-provider-app/linux out/debug chip_config_network_layer_ble=false - -- Build or download the Gecko Bootloader binary. Bootloader should be built - with the Gecko SDK version 3.2.1 or earlier, type "external SPI" configured - with a single slot of at least 1000 KB. Pre-built binaries should be - available in - - third_party/efr32_sdk/repo/platform/bootloader/sample-apps/bootloader-storage-spiflash-single - -- Using the commander tool upload the bootloader to the device running the - requestor application. - -- Create a bootable image file: - - commander gbl create chip-efr32-ota-requestor-example.gbl --app chip-efr32-ota-requestor-example.s37 - -- In a terminal start the provider app passing to it the path to the bootable - image file created in the previous step: - - rm -r /tmp/chip_* - ./out/debug/chip-ota-provider-app -f chip-efr32-ota-requestor-example.gbl - -- In a separate terminal run the chip-tool commands to provision the Provider: - - ./out/chip-tool pairing onnetwork 1 20202021 - ./out/chip-tool accesscontrol write acl '[{"fabricIndex": 1, "privilege": 5, "authMode": 2, "subjects": [112233], "targets": null}, {"fabricIndex": 1, "privilege": 3, "authMode": 2, "subjects": null, "targets": null}]' 1 0 - -- If the Requestor had been previously commissioned hold Button 0 for six - seconds to factory-reset the device. - -- In the chip-tool terminal enter: - - ./out/chip-tool pairing ble-thread 2 hex: 20202021 3840 - -where operationalDataset is obtained from the OpenThread Border Router. - -- Once the commissioning process completes enter: - - ./out/chip-tool otasoftwareupdaterequestor announce-ota-provider 1 0 0 0 2 0 - -- The Requestor will connect to the Provider and start the image download. - Once the image is downloaded the Requestor will reboot into the downloaded - image. +The EFR32 ota-requestor-app example app has been deprecated. The OTA Software +Update functionality can be used in any EFR32 example application. diff --git a/examples/platform/efr32/OTAConfig.cpp b/examples/platform/efr32/OTAConfig.cpp index 4b9201230c84da..c46fab91deb76b 100644 --- a/examples/platform/efr32/OTAConfig.cpp +++ b/examples/platform/efr32/OTAConfig.cpp @@ -75,6 +75,8 @@ void OTAConfig::Init() gRequestorStorage.Init(chip::Server::GetInstance().GetPersistentStorage()); gRequestorCore.Init(chip::Server::GetInstance(), gRequestorStorage, gRequestorUser, gDownloader); + // Periodic query timeout must be set prior to requestor being initialized + gRequestorUser.SetPeriodicQueryTimeout(OTA_PERIODIC_TIMEOUT); gRequestorUser.Init(&gRequestorCore, &gImageProcessor); gImageProcessor.SetOTAImageFile(chip::CharSpan("test.txt")); diff --git a/examples/window-app/efr32/BUILD.gn b/examples/window-app/efr32/BUILD.gn index 4fa393eeaf73fd..4cb40bbc93f1f5 100644 --- a/examples/window-app/efr32/BUILD.gn +++ b/examples/window-app/efr32/BUILD.gn @@ -41,7 +41,10 @@ declare_args() { # Enable Sleepy end device enable_sleepy_device = false - # Wifi related stuff - they are overriden by gn -args="use_wf200=true" + # OTA timeout in seconds + OTA_periodic_query_timeout = 86400 + + # Wifi related stuff - they are overridden by gn -args="use_wf200=true" use_wf200 = false use_rs911x = false use_rs911x_sockets = false @@ -92,6 +95,7 @@ efr32_sdk("sdk") { defines = [ "BOARD_ID=${efr32_board}", "CHIP_DEVICE_CONFIG_USE_TEST_SETUP_PIN_CODE=${setupPinCode}", + "OTA_PERIODIC_TIMEOUT=${OTA_periodic_query_timeout}", ] if (use_rs911x) { defines += rs911x_defs diff --git a/examples/window-app/efr32/README.md b/examples/window-app/efr32/README.md index ece65fe2b95e45..c444d8bae3df0a 100644 --- a/examples/window-app/efr32/README.md +++ b/examples/window-app/efr32/README.md @@ -5,6 +5,7 @@ An example showing the use of CHIP on the Silicon Labs EFR32 MG12.
- [CHIP EFR32 Window Covering Example](#chip-efr32-window-covering-example) + - [Introduction](#introduction) - [Building](#building) - [Note](#note) @@ -13,6 +14,7 @@ An example showing the use of CHIP on the Silicon Labs EFR32 MG12. - [Running the Complete Example](#running-the-complete-example) - [Notes](#notes) - [Running Pigweed RPC console](#running-pigweed-rpc-console) + - [OTA Software Update](#ota-software-update)
@@ -324,3 +326,9 @@ combination with JLinkRTTClient as follows: $ sudo ip route add /64 via 2002::2 + +## OTA Software Update + +For the description of Software Update process with EFR32 example applications +see +[EFR32 OTA Software Update](../../../docs/guides/silabs_efr32_software_update.md) diff --git a/src/platform/EFR32/OTAImageProcessorImpl.cpp b/src/platform/EFR32/OTAImageProcessorImpl.cpp index be2284d61afc27..def99c8afab031 100644 --- a/src/platform/EFR32/OTAImageProcessorImpl.cpp +++ b/src/platform/EFR32/OTAImageProcessorImpl.cpp @@ -34,12 +34,6 @@ uint32_t OTAImageProcessorImpl::mWriteOffset; CHIP_ERROR OTAImageProcessorImpl::PrepareDownload() { - if (mImageFile.empty()) - { - ChipLogError(SoftwareUpdate, "Invalid output image file supplied"); - return CHIP_ERROR_INTERNAL; - } - DeviceLayer::PlatformMgr().ScheduleWork(HandlePrepareDownload, reinterpret_cast(this)); return CHIP_NO_ERROR; } @@ -49,43 +43,14 @@ CHIP_ERROR OTAImageProcessorImpl::Finalize() DeviceLayer::PlatformMgr().ScheduleWork(HandleFinalize, reinterpret_cast(this)); return CHIP_NO_ERROR; } - CHIP_ERROR OTAImageProcessorImpl::Apply() { - uint32_t err = SL_BOOTLOADER_OK; - - ChipLogError(SoftwareUpdate, "OTAImageProcessorImpl::Apply()"); - - // Assuming that bootloader_verifyImage() call is not too expensive and - // doesn't need to be offloaded to a different task. Revisit if necessary. - err = bootloader_verifyImage(mSlotId, NULL); - if (err != SL_BOOTLOADER_OK) - { - ChipLogError(SoftwareUpdate, "bootloader_verifyImage error %ld", err); - return CHIP_ERROR_INTERNAL; - } - - err = bootloader_setImageToBootload(mSlotId); - if (err != SL_BOOTLOADER_OK) - { - ChipLogError(SoftwareUpdate, "setImageToBootload error %ld", err); - return CHIP_ERROR_INTERNAL; - } - - // This reboots the device - bootloader_rebootAndInstall(); - + DeviceLayer::PlatformMgr().ScheduleWork(HandleApply, reinterpret_cast(this)); return CHIP_NO_ERROR; } CHIP_ERROR OTAImageProcessorImpl::Abort() { - if (mImageFile.empty()) - { - ChipLogError(SoftwareUpdate, "Invalid output image file supplied"); - return CHIP_ERROR_INTERNAL; - } - DeviceLayer::PlatformMgr().ScheduleWork(HandleAbort, reinterpret_cast(this)); return CHIP_NO_ERROR; } @@ -128,6 +93,8 @@ void OTAImageProcessorImpl::HandlePrepareDownload(intptr_t context) mSlotId = 0; // Single slot until we support multiple images mWriteOffset = 0; + imageProcessor->mHeaderParser.Init(); + // Not calling bootloader_eraseStorageSlot(mSlotId) here because we erase during each write imageProcessor->mDownloader->OnPreparedForDownload(err == SL_BOOTLOADER_OK ? CHIP_NO_ERROR : CHIP_ERROR_INTERNAL); @@ -143,7 +110,31 @@ void OTAImageProcessorImpl::HandleFinalize(intptr_t context) imageProcessor->ReleaseBlock(); - ChipLogProgress(SoftwareUpdate, "OTA image downloaded to %s", imageProcessor->mImageFile.data()); + ChipLogProgress(SoftwareUpdate, "OTA image downloaded successfully"); +} + +void OTAImageProcessorImpl::HandleApply(intptr_t context) +{ + uint32_t err = SL_BOOTLOADER_OK; + + ChipLogProgress(SoftwareUpdate, "OTAImageProcessorImpl::HandleApply()"); + + err = bootloader_verifyImage(mSlotId, NULL); + if (err != SL_BOOTLOADER_OK) + { + ChipLogError(SoftwareUpdate, "ERROR: bootloader_verifyImage() error %ld", err); + return; + } + + err = bootloader_setImageToBootload(mSlotId); + if (err != SL_BOOTLOADER_OK) + { + ChipLogError(SoftwareUpdate, "ERROR: bootloader_setImageToBootload() error %ld", err); + return; + } + + // This reboots the device + bootloader_rebootAndInstall(); } void OTAImageProcessorImpl::HandleAbort(intptr_t context) @@ -173,24 +164,51 @@ void OTAImageProcessorImpl::HandleProcessBlock(intptr_t context) return; } - // TODO: Process block header if any + ByteSpan block = imageProcessor->mBlock; + CHIP_ERROR chip_error = imageProcessor->ProcessHeader(block); - err = bootloader_eraseWriteStorage(mSlotId, mWriteOffset, reinterpret_cast(imageProcessor->mBlock.data()), - imageProcessor->mBlock.size()); + if (chip_error != CHIP_NO_ERROR) + { + ChipLogError(SoftwareUpdate, "Matter image header parser error %s", chip::ErrorStr(chip_error)); + imageProcessor->mDownloader->EndDownload(CHIP_ERROR_INVALID_FILE_IDENTIFIER); + return; + } + + err = bootloader_eraseWriteStorage(mSlotId, mWriteOffset, (uint8_t *) (block.data()), block.size()); if (err) { - ChipLogError(SoftwareUpdate, "bootloader_eraseWriteStorage err %ld", err); + ChipLogError(SoftwareUpdate, "ERROR (possible wrong bootloader version): bootloader_eraseWriteStorage() error %ld", err); imageProcessor->mDownloader->EndDownload(CHIP_ERROR_WRITE_FAILED); return; } - mWriteOffset += imageProcessor->mBlock.size(); // Keep our own track of how far we've written - imageProcessor->mParams.downloadedBytes += imageProcessor->mBlock.size(); + mWriteOffset += block.size(); // Keep our own track of how far we've written + imageProcessor->mParams.downloadedBytes += block.size(); imageProcessor->mDownloader->FetchNextData(); } +CHIP_ERROR OTAImageProcessorImpl::ProcessHeader(ByteSpan & block) +{ + if (mHeaderParser.IsInitialized()) + { + OTAImageHeader header; + CHIP_ERROR error = mHeaderParser.AccumulateAndDecode(block, header); + + // Needs more data to decode the header + ReturnErrorCodeIf(error == CHIP_ERROR_BUFFER_TOO_SMALL, CHIP_NO_ERROR); + ReturnErrorOnFailure(error); + + // SL TODO -- store version somewhere + ChipLogProgress(SoftwareUpdate, "Image Header software version: %ld payload size: %lu", header.mSoftwareVersion, + (long unsigned int) header.mPayloadSize); + mParams.totalFileBytes = header.mPayloadSize; + mHeaderParser.Clear(); + } + return CHIP_NO_ERROR; +} + // Store block data for HandleProcessBlock to access CHIP_ERROR OTAImageProcessorImpl::SetBlock(ByteSpan & block) { diff --git a/src/platform/EFR32/OTAImageProcessorImpl.h b/src/platform/EFR32/OTAImageProcessorImpl.h index 356cfb22af6070..7bb97dd2c96eae 100644 --- a/src/platform/EFR32/OTAImageProcessorImpl.h +++ b/src/platform/EFR32/OTAImageProcessorImpl.h @@ -19,6 +19,7 @@ #pragma once #include +#include #include #include @@ -45,8 +46,10 @@ class OTAImageProcessorImpl : public OTAImageProcessorInterface //////////// Actual handlers for the OTAImageProcessorInterface /////////////// static void HandlePrepareDownload(intptr_t context); static void HandleFinalize(intptr_t context); + static void HandleApply(intptr_t context); static void HandleAbort(intptr_t context); static void HandleProcessBlock(intptr_t context); + CHIP_ERROR ProcessHeader(ByteSpan & block); /** * Called to allocate memory for mBlock if necessary and set it to block @@ -62,6 +65,7 @@ class OTAImageProcessorImpl : public OTAImageProcessorInterface static uint8_t mSlotId; // Bootloader storage slot MutableByteSpan mBlock; OTADownloader * mDownloader; + OTAImageHeaderParser mHeaderParser; CharSpan mImageFile; };