From 85d3970237f8b9f7627ca1ecde36b411bee9f470 Mon Sep 17 00:00:00 2001 From: Alex Tsitsiura <s07641069@gmail.com> Date: Mon, 23 Dec 2024 12:52:43 +0000 Subject: [PATCH 1/3] [Telink] Add OTA resume support --- src/platform/telink/OTAImageProcessorImpl.cpp | 81 ++++++++++++++++--- src/platform/telink/OTAImageProcessorImpl.h | 7 ++ 2 files changed, 76 insertions(+), 12 deletions(-) diff --git a/src/platform/telink/OTAImageProcessorImpl.cpp b/src/platform/telink/OTAImageProcessorImpl.cpp index a47a59fadfdb38..e335ac531c33cd 100644 --- a/src/platform/telink/OTAImageProcessorImpl.cpp +++ b/src/platform/telink/OTAImageProcessorImpl.cpp @@ -20,6 +20,7 @@ #include <app/clusters/ota-requestor/OTADownloader.h> #include <app/clusters/ota-requestor/OTARequestorInterface.h> #include <platform/CHIPDeviceLayer.h> +#include <platform/KeyValueStoreManager.h> #include <zephyr/dfu/mcuboot.h> #include <zephyr/storage/flash_map.h> @@ -28,6 +29,8 @@ static struct stream_flash_ctx stream; +using namespace ::chip::DeviceLayer::PersistedStorage; + namespace chip { namespace { @@ -53,14 +56,10 @@ CHIP_ERROR OTAImageProcessorImpl::PrepareDownload() return DeviceLayer::SystemLayer().ScheduleLambda([this] { mDownloader->OnPreparedForDownload(PrepareDownloadImpl()); }); } - -CHIP_ERROR OTAImageProcessorImpl::PrepareDownloadImpl() -{ - mHeaderParser.Init(); - mParams = {}; - const struct device * flash_dev; +CHIP_ERROR OTAImageProcessorImpl::InitFlashStream(size_t offset) +{ flash_dev = DEVICE_DT_GET(DT_CHOSEN(zephyr_flash_controller)); if (flash_dev == NULL) { @@ -68,18 +67,28 @@ CHIP_ERROR OTAImageProcessorImpl::PrepareDownloadImpl() return System::MapErrorZephyr(-EFAULT); } - int err = stream_flash_init(&stream, flash_dev, mBuffer, sizeof(mBuffer), FIXED_PARTITION_OFFSET(slot1_partition), - FIXED_PARTITION_SIZE(slot1_partition), NULL); + int err = stream_flash_init(&stream, flash_dev, mBuffer, sizeof(mBuffer), FIXED_PARTITION_OFFSET(slot1_partition) + offset, + FIXED_PARTITION_SIZE(slot1_partition) - offset, NULL); if (err) { ChipLogError(SoftwareUpdate, "stream_flash_init failed (err %d)", err); } - PostOTAStateChangeEvent(DeviceLayer::kOtaDownloadInProgress); return System::MapErrorZephyr(err); } +CHIP_ERROR OTAImageProcessorImpl::PrepareDownloadImpl() +{ + mHeaderParser.Init(); + mParams = {}; + + CHIP_ERROR error = InitFlashStream(0); + + PostOTAStateChangeEvent(DeviceLayer::kOtaDownloadInProgress); + return error; +} + CHIP_ERROR OTAImageProcessorImpl::Finalize() { int err = stream_flash_buffered_write(&stream, NULL, 0, true); @@ -136,8 +145,16 @@ CHIP_ERROR OTAImageProcessorImpl::ProcessBlock(ByteSpan & aBlock) if (error == CHIP_NO_ERROR) { - error = System::MapErrorZephyr(stream_flash_buffered_write(&stream, aBlock.data(), aBlock.size(), false)); - mParams.downloadedBytes += aBlock.size(); + if (downloadedBytesRestored) + { + mParams.downloadedBytes = downloadedBytesRestored; + } + else + { + error = System::MapErrorZephyr(stream_flash_buffered_write(&stream, aBlock.data(), aBlock.size(), false)); + mParams.downloadedBytes += aBlock.size(); + } + ReturnErrorOnFailure(KeyValueStoreMgr().Put(kDownloadedBytes, &mParams.downloadedBytes, sizeof(mParams.downloadedBytes))); } // Report the result back to the downloader asynchronously. @@ -146,7 +163,15 @@ CHIP_ERROR OTAImageProcessorImpl::ProcessBlock(ByteSpan & aBlock) { ChipLogDetail(SoftwareUpdate, "Downloaded %u/%u bytes", static_cast<unsigned>(mParams.downloadedBytes), static_cast<unsigned>(mParams.totalFileBytes)); - mDownloader->FetchNextData(); + if (downloadedBytesRestored) + { + mDownloader->SkipData(downloadedBytesRestored - aBlock.size()); + downloadedBytesRestored = 0; + } + else + { + mDownloader->FetchNextData(); + } } else { @@ -174,6 +199,34 @@ CHIP_ERROR OTAImageProcessorImpl::ConfirmCurrentImage() return System::MapErrorZephyr(boot_write_img_confirmed()); } +CHIP_ERROR OTAImageProcessorImpl::RestoreBytes(ByteSpan & aBlock) +{ + uint8_t *ImageDigestBuffer = new uint8_t[aBlock.size()]; + MutableByteSpan mImageDigest(ImageDigestBuffer, aBlock.size()); + + if (KeyValueStoreMgr().Get(kImageDigest, mImageDigest.data(), mImageDigest.size()) == CHIP_NO_ERROR && + KeyValueStoreMgr().Get(kDownloadedBytes, &downloadedBytesRestored, sizeof(downloadedBytesRestored)) == CHIP_NO_ERROR && + mImageDigest.data_equal(aBlock) && downloadedBytesRestored < mParams.totalFileBytes) + { + // Align to the nearest lower multiple of sector size (4 KB) for Flash erase/write + downloadedBytesRestored = ROUND_DOWN(downloadedBytesRestored, 0x1000); + ChipLogDetail(SoftwareUpdate, "Restored %u/%u bytes", static_cast<unsigned>(downloadedBytesRestored), + static_cast<unsigned>(mParams.totalFileBytes)) + + // Reinit Flash Stream with offset + ReturnErrorOnFailure(System::MapErrorZephyr(stream_flash_buffered_write(&stream, NULL, 0, true))); + ReturnErrorOnFailure(InitFlashStream(downloadedBytesRestored)); + } + else + { + downloadedBytesRestored = 0; + ReturnErrorOnFailure(KeyValueStoreMgr().Put(kImageDigest, aBlock.data(), aBlock.size())); + } + delete[] ImageDigestBuffer; + + return CHIP_NO_ERROR; +} + CHIP_ERROR OTAImageProcessorImpl::ProcessHeader(ByteSpan & aBlock) { if (mHeaderParser.IsInitialized()) @@ -186,6 +239,10 @@ CHIP_ERROR OTAImageProcessorImpl::ProcessHeader(ByteSpan & aBlock) ReturnErrorOnFailure(error); mParams.totalFileBytes = header.mPayloadSize; + + // Restore interrupted OTA process + RestoreBytes(header.mImageDigest); + mHeaderParser.Clear(); } diff --git a/src/platform/telink/OTAImageProcessorImpl.h b/src/platform/telink/OTAImageProcessorImpl.h index e49da76b835739..96870a016369e5 100755 --- a/src/platform/telink/OTAImageProcessorImpl.h +++ b/src/platform/telink/OTAImageProcessorImpl.h @@ -44,10 +44,17 @@ class OTAImageProcessorImpl : public OTAImageProcessorInterface private: CHIP_ERROR PrepareDownloadImpl(); CHIP_ERROR ProcessHeader(ByteSpan & aBlock); + CHIP_ERROR InitFlashStream(size_t offset); + CHIP_ERROR RestoreBytes(ByteSpan & aBlock); OTADownloader * mDownloader = nullptr; OTAImageHeaderParser mHeaderParser; uint8_t mBuffer[kBufferSize]; + + // Define non-volatile storage keys for DownloadedBytes and ImageDigest. + static constexpr char kDownloadedBytes[] = "DownloadedBytes"; + static constexpr char kImageDigest[] = "ImageDigest"; + uint64_t downloadedBytesRestored = 0; }; } // namespace DeviceLayer From e0375206183bfcfc662d3863b3b1954fe15e139f Mon Sep 17 00:00:00 2001 From: "Restyled.io" <commits@restyled.io> Date: Wed, 12 Mar 2025 11:17:39 +0000 Subject: [PATCH 2/3] Restyled by whitespace --- src/platform/telink/OTAImageProcessorImpl.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/platform/telink/OTAImageProcessorImpl.cpp b/src/platform/telink/OTAImageProcessorImpl.cpp index e335ac531c33cd..c8911b3ba28675 100644 --- a/src/platform/telink/OTAImageProcessorImpl.cpp +++ b/src/platform/telink/OTAImageProcessorImpl.cpp @@ -204,7 +204,7 @@ CHIP_ERROR OTAImageProcessorImpl::RestoreBytes(ByteSpan & aBlock) uint8_t *ImageDigestBuffer = new uint8_t[aBlock.size()]; MutableByteSpan mImageDigest(ImageDigestBuffer, aBlock.size()); - if (KeyValueStoreMgr().Get(kImageDigest, mImageDigest.data(), mImageDigest.size()) == CHIP_NO_ERROR && + if (KeyValueStoreMgr().Get(kImageDigest, mImageDigest.data(), mImageDigest.size()) == CHIP_NO_ERROR && KeyValueStoreMgr().Get(kDownloadedBytes, &downloadedBytesRestored, sizeof(downloadedBytesRestored)) == CHIP_NO_ERROR && mImageDigest.data_equal(aBlock) && downloadedBytesRestored < mParams.totalFileBytes) { From 109469d2b060e07f3f9c65d986413061112425b0 Mon Sep 17 00:00:00 2001 From: "Restyled.io" <commits@restyled.io> Date: Wed, 12 Mar 2025 11:17:43 +0000 Subject: [PATCH 3/3] Restyled by clang-format --- src/platform/telink/OTAImageProcessorImpl.cpp | 8 ++++---- src/platform/telink/OTAImageProcessorImpl.h | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) mode change 100755 => 100644 src/platform/telink/OTAImageProcessorImpl.h diff --git a/src/platform/telink/OTAImageProcessorImpl.cpp b/src/platform/telink/OTAImageProcessorImpl.cpp index c8911b3ba28675..d3bcff3129b58b 100644 --- a/src/platform/telink/OTAImageProcessorImpl.cpp +++ b/src/platform/telink/OTAImageProcessorImpl.cpp @@ -56,7 +56,7 @@ CHIP_ERROR OTAImageProcessorImpl::PrepareDownload() return DeviceLayer::SystemLayer().ScheduleLambda([this] { mDownloader->OnPreparedForDownload(PrepareDownloadImpl()); }); } - const struct device * flash_dev; +const struct device * flash_dev; CHIP_ERROR OTAImageProcessorImpl::InitFlashStream(size_t offset) { @@ -201,7 +201,7 @@ CHIP_ERROR OTAImageProcessorImpl::ConfirmCurrentImage() CHIP_ERROR OTAImageProcessorImpl::RestoreBytes(ByteSpan & aBlock) { - uint8_t *ImageDigestBuffer = new uint8_t[aBlock.size()]; + uint8_t * ImageDigestBuffer = new uint8_t[aBlock.size()]; MutableByteSpan mImageDigest(ImageDigestBuffer, aBlock.size()); if (KeyValueStoreMgr().Get(kImageDigest, mImageDigest.data(), mImageDigest.size()) == CHIP_NO_ERROR && @@ -213,8 +213,8 @@ CHIP_ERROR OTAImageProcessorImpl::RestoreBytes(ByteSpan & aBlock) ChipLogDetail(SoftwareUpdate, "Restored %u/%u bytes", static_cast<unsigned>(downloadedBytesRestored), static_cast<unsigned>(mParams.totalFileBytes)) - // Reinit Flash Stream with offset - ReturnErrorOnFailure(System::MapErrorZephyr(stream_flash_buffered_write(&stream, NULL, 0, true))); + // Reinit Flash Stream with offset + ReturnErrorOnFailure(System::MapErrorZephyr(stream_flash_buffered_write(&stream, NULL, 0, true))); ReturnErrorOnFailure(InitFlashStream(downloadedBytesRestored)); } else diff --git a/src/platform/telink/OTAImageProcessorImpl.h b/src/platform/telink/OTAImageProcessorImpl.h old mode 100755 new mode 100644 index 96870a016369e5..19ebb291fa98ea --- a/src/platform/telink/OTAImageProcessorImpl.h +++ b/src/platform/telink/OTAImageProcessorImpl.h @@ -54,7 +54,7 @@ class OTAImageProcessorImpl : public OTAImageProcessorInterface // Define non-volatile storage keys for DownloadedBytes and ImageDigest. static constexpr char kDownloadedBytes[] = "DownloadedBytes"; static constexpr char kImageDigest[] = "ImageDigest"; - uint64_t downloadedBytesRestored = 0; + uint64_t downloadedBytesRestored = 0; }; } // namespace DeviceLayer