From 27769774ce5ad9b4a1780164813f1282644b4db8 Mon Sep 17 00:00:00 2001 From: Shubham Patil Date: Wed, 9 Feb 2022 23:07:56 +0530 Subject: [PATCH] [ESP32] Parse OTA image header (#14957) * [ESP32] Parse OTA image header Added documentation for building OTA image Added more help for CHIP_OTA_IMAGE_BUILD config option Fixed the usage of CHIP_OTA_IMAGE_BUILD option * End download if OTA image header parsing fails --- config/esp32/components/chip/Kconfig | 7 ++-- config/esp32/components/chip/ota-image.cmake | 3 +- examples/ota-requestor-app/esp32/README.md | 15 ++++++++ src/platform/ESP32/OTAImageProcessorImpl.cpp | 36 ++++++++++++++++++-- src/platform/ESP32/OTAImageProcessorImpl.h | 3 ++ 5 files changed, 58 insertions(+), 6 deletions(-) diff --git a/config/esp32/components/chip/Kconfig b/config/esp32/components/chip/Kconfig index be7a942a113339..4f7c1229c7406f 100644 --- a/config/esp32/components/chip/Kconfig +++ b/config/esp32/components/chip/Kconfig @@ -789,8 +789,11 @@ menu "CHIP Device Layer" string "OTA image creator extra arguments" depends on CHIP_OTA_IMAGE_BUILD help - This option allows one to pass optional arguments to the ota_image_tool.py script, - used for building OTA image with Matter OTA header. + ota_image_tool.py is used to create the OTA image. + Mandatory arguments(Version, VersionString, VID, PID) are picked up from the config options. + This option allows us to pass optional arguments(MinApplicableSoftwareVersion, MaxApplicableSoftwareVersion, + and ReleaseNotesURL) to the ota_image_tool.py script. + eg: "-mi 2 -ma 4 -rn https://github.com/espressif/esp-idf/releases/tag/v4.4" endmenu diff --git a/config/esp32/components/chip/ota-image.cmake b/config/esp32/components/chip/ota-image.cmake index 59646edcab08a6..887333962d0aef 100644 --- a/config/esp32/components/chip/ota-image.cmake +++ b/config/esp32/components/chip/ota-image.cmake @@ -43,7 +43,7 @@ function(chip_ota_image TARGET_NAME) "sha256" ) - separate_arguments(OTA_EXTRA_ARGS NATIVE_COMMAND "${CHIP_OTA_IMAGE_EXTRA_ARGS}") + separate_arguments(OTA_EXTRA_ARGS NATIVE_COMMAND "${CONFIG_CHIP_OTA_IMAGE_EXTRA_ARGS}") list(APPEND OTA_ARGS ${OTA_EXTRA_ARGS}) list(APPEND OTA_ARGS ${ARG_INPUT_FILES}) @@ -60,6 +60,5 @@ function(chip_ota_image TARGET_NAME) add_custom_target(${TARGET_NAME} ALL COMMAND ${Python3_EXECUTABLE} ${CHIP_ROOT}/src/app/ota_image_tool.py create @${BUILD_DIR}/args-ota-image.tmp - COMMAND ${CMAKE_COMMAND} -E remove ${BUILD_DIR}/args-ota-image.tmp ) endfunction() diff --git a/examples/ota-requestor-app/esp32/README.md b/examples/ota-requestor-app/esp32/README.md index 9c835aa11009f6..513c070578a088 100644 --- a/examples/ota-requestor-app/esp32/README.md +++ b/examples/ota-requestor-app/esp32/README.md @@ -63,3 +63,18 @@ application of OTA image. ``` ./out/debug/chip-tool pairing onnetwork 12345 20202021 ``` + +## Generate OTA image + +User can generate the Matter OTA image by simply enabling +`CONFIG_CHIP_OTA_IMAGE_BUILD` config option. OTA image is generated in `build` +directory with name `-ota.bin`. This image then can be used with +OTA Provider Application. + +Please make sure that version number is set to correct value. Use +`CONFIG_DEVICE_SOFTWARE_VERSION` and `CONFIG_DEVICE_SOFTWARE_VERSION_NUMBER` +config options for setting software version. + +Matter OTA image can also be generated using +[ota_image_tool.py](https://github.com/project-chip/connectedhomeip/blob/master/src/app/ota_image_tool.py) +script. diff --git a/src/platform/ESP32/OTAImageProcessorImpl.cpp b/src/platform/ESP32/OTAImageProcessorImpl.cpp index c539b89c073932..41d18eb4038ab5 100644 --- a/src/platform/ESP32/OTAImageProcessorImpl.cpp +++ b/src/platform/ESP32/OTAImageProcessorImpl.cpp @@ -100,6 +100,7 @@ void OTAImageProcessorImpl::HandlePrepareDownload(intptr_t context) imageProcessor->mDownloader->OnPreparedForDownload(ESP32Utils::MapError(err)); return; } + imageProcessor->mHeaderParser.Init(); imageProcessor->mDownloader->OnPreparedForDownload(CHIP_NO_ERROR); } @@ -156,13 +157,25 @@ void OTAImageProcessorImpl::HandleProcessBlock(intptr_t context) ChipLogError(SoftwareUpdate, "mDownloader is null"); return; } - esp_err_t err = esp_ota_write(imageProcessor->mOTAUpdateHandle, imageProcessor->mBlock.data(), imageProcessor->mBlock.size()); + + ByteSpan block = ByteSpan(imageProcessor->mBlock.data(), imageProcessor->mBlock.size()); + + CHIP_ERROR error = imageProcessor->ProcessBlock(block); + if (error != CHIP_NO_ERROR) + { + ESP_LOGE(TAG, "Failed to process OTA image header"); + imageProcessor->mDownloader->EndDownload(error); + return; + } + + esp_err_t err = esp_ota_write(imageProcessor->mOTAUpdateHandle, block.data(), block.size()); if (err != ESP_OK) { ESP_LOGE(TAG, "esp_ota_write failed (%s)", esp_err_to_name(err)); imageProcessor->mDownloader->EndDownload(CHIP_ERROR_WRITE_FAILED); + return; } - imageProcessor->mParams.downloadedBytes += imageProcessor->mBlock.size(); + imageProcessor->mParams.downloadedBytes += block.size(); imageProcessor->mDownloader->FetchNextData(); } @@ -219,4 +232,23 @@ CHIP_ERROR OTAImageProcessorImpl::ReleaseBlock() mBlock = MutableByteSpan(); return CHIP_NO_ERROR; } + +CHIP_ERROR OTAImageProcessorImpl::ProcessHeader(ByteSpan & block) +{ + if (mHeaderParser.IsInitialized()) + { + OTAImageHeader header; + CHIP_ERROR error = mHeaderParser.AccumulateAndDecode(block, header); + + // Need more data to decode the header + ReturnErrorCodeIf(error == CHIP_ERROR_BUFFER_TOO_SMALL, CHIP_NO_ERROR); + ReturnErrorOnFailure(error); + + mParams.totalFileBytes = header.mPayloadSize; + mHeaderParser.Clear(); + } + + return CHIP_NO_ERROR; +} + } // namespace chip diff --git a/src/platform/ESP32/OTAImageProcessorImpl.h b/src/platform/ESP32/OTAImageProcessorImpl.h index f8530606229645..b48fb35554874f 100644 --- a/src/platform/ESP32/OTAImageProcessorImpl.h +++ b/src/platform/ESP32/OTAImageProcessorImpl.h @@ -19,6 +19,7 @@ #include "esp_ota_ops.h" #include +#include #include #include @@ -44,11 +45,13 @@ class OTAImageProcessorImpl : public OTAImageProcessorInterface CHIP_ERROR SetBlock(ByteSpan & block); CHIP_ERROR ReleaseBlock(); + CHIP_ERROR ProcessHeader(ByteSpan & block); OTADownloader * mDownloader = nullptr; MutableByteSpan mBlock; const esp_partition_t * mOTAUpdatePartition = nullptr; esp_ota_handle_t mOTAUpdateHandle; + OTAImageHeaderParser mHeaderParser; }; } // namespace chip