diff --git a/.github/workflows/examples-nrfconnect.yaml b/.github/workflows/examples-nrfconnect.yaml index 3bab89a42947c4..7f7e949f23b8ea 100644 --- a/.github/workflows/examples-nrfconnect.yaml +++ b/.github/workflows/examples-nrfconnect.yaml @@ -34,7 +34,7 @@ jobs: if: github.actor != 'restyled-io[bot]' container: - image: connectedhomeip/chip-build-nrf-platform:0.5.58 + image: connectedhomeip/chip-build-nrf-platform:0.5.64 volumes: - "/tmp/bloat_reports:/tmp/bloat_reports" diff --git a/config/nrfconnect/.nrfconnect-recommended-revision b/config/nrfconnect/.nrfconnect-recommended-revision index ba1e8bf0bd53b5..64f70a191193e6 100644 --- a/config/nrfconnect/.nrfconnect-recommended-revision +++ b/config/nrfconnect/.nrfconnect-recommended-revision @@ -1 +1 @@ -v1.9.1 +5ea8f7fa91d7315fcc6cd9eb3aa74f9640d0abac diff --git a/integrations/cloudbuild/build-all.yaml b/integrations/cloudbuild/build-all.yaml index f37063f4877199..0bdffaf02e1ae9 100644 --- a/integrations/cloudbuild/build-all.yaml +++ b/integrations/cloudbuild/build-all.yaml @@ -1,5 +1,5 @@ steps: - - name: "connectedhomeip/chip-build-vscode:0.5.58" + - name: "connectedhomeip/chip-build-vscode:0.5.64" env: - PW_ENVIRONMENT_ROOT=/pwenv args: @@ -12,7 +12,7 @@ steps: path: /pwenv timeout: 900s - - name: "connectedhomeip/chip-build-vscode:0.5.58" + - name: "connectedhomeip/chip-build-vscode:0.5.64" env: - PW_ENVIRONMENT_ROOT=/pwenv args: diff --git a/integrations/cloudbuild/smoke-test.yaml b/integrations/cloudbuild/smoke-test.yaml index e50bc2895f4e94..7f233321bb5c73 100644 --- a/integrations/cloudbuild/smoke-test.yaml +++ b/integrations/cloudbuild/smoke-test.yaml @@ -1,5 +1,5 @@ steps: - - name: "connectedhomeip/chip-build-vscode:0.5.58" + - name: "connectedhomeip/chip-build-vscode:0.5.64" env: - PW_ENVIRONMENT_ROOT=/pwenv args: @@ -12,7 +12,7 @@ steps: path: /pwenv timeout: 900s - - name: "connectedhomeip/chip-build-vscode:0.5.58" + - name: "connectedhomeip/chip-build-vscode:0.5.64" id: ESP32 env: - PW_ENVIRONMENT_ROOT=/pwenv @@ -28,7 +28,7 @@ steps: - name: pwenv path: /pwenv - - name: "connectedhomeip/chip-build-vscode:0.5.58" + - name: "connectedhomeip/chip-build-vscode:0.5.64" id: NRFConnect env: - PW_ENVIRONMENT_ROOT=/pwenv @@ -45,7 +45,7 @@ steps: - name: pwenv path: /pwenv - - name: "connectedhomeip/chip-build-vscode:0.5.58" + - name: "connectedhomeip/chip-build-vscode:0.5.64" id: EFR32 env: - PW_ENVIRONMENT_ROOT=/pwenv @@ -62,7 +62,7 @@ steps: - name: pwenv path: /pwenv - - name: "connectedhomeip/chip-build-vscode:0.5.58" + - name: "connectedhomeip/chip-build-vscode:0.5.64" id: Linux env: - PW_ENVIRONMENT_ROOT=/pwenv @@ -79,7 +79,7 @@ steps: - name: pwenv path: /pwenv - - name: "connectedhomeip/chip-build-vscode:0.5.58" + - name: "connectedhomeip/chip-build-vscode:0.5.64" id: Android env: - PW_ENVIRONMENT_ROOT=/pwenv diff --git a/src/platform/nrfconnect/OTAImageProcessorImpl.cpp b/src/platform/nrfconnect/OTAImageProcessorImpl.cpp index f7e3e6c8f4190a..fc4d49a9495172 100644 --- a/src/platform/nrfconnect/OTAImageProcessorImpl.cpp +++ b/src/platform/nrfconnect/OTAImageProcessorImpl.cpp @@ -25,6 +25,7 @@ #include #include #include +#include #include #include @@ -45,7 +46,7 @@ CHIP_ERROR OTAImageProcessorImpl::PrepareDownloadImpl() ReturnErrorOnFailure(System::MapErrorZephyr(dfu_target_mcuboot_set_buf(mBuffer, sizeof(mBuffer)))); ReturnErrorOnFailure(System::MapErrorZephyr(dfu_target_reset())); - return System::MapErrorZephyr(dfu_target_init(DFU_TARGET_IMAGE_TYPE_MCUBOOT, /* size */ 0, nullptr)); + return CHIP_NO_ERROR; } CHIP_ERROR OTAImageProcessorImpl::Finalize() @@ -60,19 +61,31 @@ CHIP_ERROR OTAImageProcessorImpl::Abort() CHIP_ERROR OTAImageProcessorImpl::Apply() { - ReturnErrorOnFailure(System::MapErrorZephyr(dfu_target_done(true))); + int err = dfu_target_done(true); + if (err == 0) + { + // schedule update of all possible targets by caling this function with argument -1 + err = dfu_target_schedule_update(-1); + } #ifdef CONFIG_CHIP_OTA_REQUESTOR_REBOOT_ON_APPLY - return SystemLayer().StartTimer( - System::Clock::Milliseconds32(CHIP_DEVICE_CONFIG_OTA_REQUESTOR_REBOOT_DELAY_MS), - [](System::Layer *, void * /* context */) { - PlatformMgr().HandleServerShuttingDown(); - k_msleep(CHIP_DEVICE_CONFIG_SERVER_SHUTDOWN_ACTIONS_SLEEP_MS); - sys_reboot(SYS_REBOOT_WARM); - }, - nullptr /* context */); + if (err == 0) + { + return SystemLayer().StartTimer( + System::Clock::Milliseconds32(CHIP_DEVICE_CONFIG_OTA_REQUESTOR_REBOOT_DELAY_MS), + [](System::Layer *, void * /* context */) { + PlatformMgr().HandleServerShuttingDown(); + k_msleep(CHIP_DEVICE_CONFIG_SERVER_SHUTDOWN_ACTIONS_SLEEP_MS); + sys_reboot(SYS_REBOOT_WARM); + }, + nullptr /* context */); + } + else + { + return System::MapErrorZephyr(err); + } #else - return CHIP_NO_ERROR; + return System::MapErrorZephyr(err); #endif } @@ -81,11 +94,45 @@ CHIP_ERROR OTAImageProcessorImpl::ProcessBlock(ByteSpan & block) VerifyOrReturnError(mDownloader != nullptr, CHIP_ERROR_INCORRECT_STATE); CHIP_ERROR error = ProcessHeader(block); - if (error == CHIP_NO_ERROR) { - // DFU target library buffers data internally, so do not clone the block data. - error = System::MapErrorZephyr(dfu_target_write(block.data(), block.size())); + mCurrentImage.mCurrentOffset += block.size(); + if (mCurrentImage.mCurrentOffset >= mCurrentImage.mFileInfo->mFileSize) + { + // calculate how many data should be moved to the next image + uint64_t remainingDataSize = mCurrentImage.mCurrentOffset - static_cast(mCurrentImage.mFileInfo->mFileSize); + // write last data of previous image + error = System::MapErrorZephyr(dfu_target_write(block.data(), block.size() - remainingDataSize)); + // switch to net image + mCurrentImage.mIndex++; + mCurrentImage.mFileInfo = &mContentHeader.mFiles[mCurrentImage.mIndex]; + + if (OTAImageContentHeader::FileId::kNetMcuboot == mCurrentImage.mFileInfo->mFileId && + mCurrentImage.mFileInfo->mFileSize > 0 && CHIP_NO_ERROR == error) + { + // finish previous image and reset target + dfu_target_done(true); + dfu_target_reset(); + // initialize next dfu target to store net-core image. + dfu_target_init(DFU_TARGET_IMAGE_TYPE_MCUBOOT, mCurrentImage.mIndex, /* size */ 0, nullptr); + // write remaining data to new image + error = + System::MapErrorZephyr(dfu_target_write(block.data() + (block.size() - remainingDataSize), remainingDataSize)); + mCurrentImage.mCurrentOffset = remainingDataSize; + } + else + { + // Finish process with error to ensure that only two images are available. + error = CHIP_ERROR_INVALID_DATA_LIST; + } + } + else + { + // DFU target library buffers data internally, so do not clone the block data. + error = System::MapErrorZephyr(dfu_target_write(block.data(), block.size())); + } + ChipLogDetail(SoftwareUpdate, "Processed %llu/%u Bytes of image no. %u", mCurrentImage.mCurrentOffset, + mCurrentImage.mFileInfo->mFileSize, mCurrentImage.mIndex); } // Report the result back to the downloader asynchronously. @@ -129,13 +176,22 @@ CHIP_ERROR OTAImageProcessorImpl::ProcessHeader(ByteSpan & block) if (mContentHeaderParser.IsInitialized() && !block.empty()) { - OTAImageContentHeader header = {}; - CHIP_ERROR error = mContentHeaderParser.AccumulateAndDecode(block, header); + CHIP_ERROR error = mContentHeaderParser.AccumulateAndDecode(block, mContentHeader); // Needs more data to decode the header ReturnErrorCodeIf(error == CHIP_ERROR_BUFFER_TOO_SMALL, CHIP_NO_ERROR); ReturnErrorOnFailure(error); + if (OTAImageContentHeader::FileId::kAppMcuboot == mContentHeader.mFiles[0].mFileId) + { + mCurrentImage.mIndex = 0; + mCurrentImage.mFileInfo = &mContentHeader.mFiles[mCurrentImage.mIndex]; + // Initialize dfu target to receive first image + error = + System::MapErrorZephyr(dfu_target_init(DFU_TARGET_IMAGE_TYPE_MCUBOOT, mCurrentImage.mIndex, /* size */ 0, nullptr)); + ReturnErrorOnFailure(error); + } + mContentHeaderParser.Clear(); } diff --git a/src/platform/nrfconnect/OTAImageProcessorImpl.h b/src/platform/nrfconnect/OTAImageProcessorImpl.h index acdd0c89e0d710..2e0507a5347422 100644 --- a/src/platform/nrfconnect/OTAImageProcessorImpl.h +++ b/src/platform/nrfconnect/OTAImageProcessorImpl.h @@ -34,6 +34,13 @@ class OTAImageProcessorImpl : public OTAImageProcessorInterface void SetOTADownloader(OTADownloader * downloader) { mDownloader = downloader; }; + struct OTAImage + { + OTAImageContentHeader::FileInfo * mFileInfo; + uint8_t mIndex; + uint64_t mCurrentOffset; + }; + CHIP_ERROR PrepareDownload() override; CHIP_ERROR Finalize() override; CHIP_ERROR Abort() override; @@ -50,6 +57,8 @@ class OTAImageProcessorImpl : public OTAImageProcessorInterface OTAImageHeaderParser mHeaderParser; OTAImageContentHeaderParser mContentHeaderParser; uint8_t mBuffer[kBufferSize]; + OTAImageContentHeader mContentHeader; + OTAImage mCurrentImage; }; class ExtFlashHandler