2121
2222#include < app/clusters/ota-requestor/OTADownloader.h>
2323#include < app/clusters/ota-requestor/OTARequestorInterface.h>
24+ #include < cstring>
2425#include < lib/support/CodeUtils.h>
2526#include < platform/CHIPDeviceLayer.h>
2627#include < system/SystemError.h>
@@ -126,20 +127,29 @@ CHIP_ERROR OTAImageProcessorImpl::PrepareDownloadImpl()
126127
127128CHIP_ERROR OTAImageProcessorImpl::Finalize ()
128129{
129- PostOTAStateChangeEvent (DeviceLayer::kOtaDownloadComplete );
130- DFUSync::GetInstance ().Free (mDfuSyncMutexId );
131- return System::MapErrorZephyr (dfu_multi_image_done (true ));
130+ return DeviceLayer::SystemLayer ().ScheduleLambda ([this ] {
131+ PostOTAStateChangeEvent (DeviceLayer::kOtaDownloadComplete );
132+ DFUSync::GetInstance ().Free (mDfuSyncMutexId );
133+ CHIP_ERROR error = System::MapErrorZephyr (dfu_multi_image_done (true ));
134+ if (error != CHIP_NO_ERROR)
135+ {
136+ ChipLogError (SoftwareUpdate, " OTA failed to finalize: %" CHIP_ERROR_FORMAT, error.Format ());
137+ }
138+ });
132139}
133140
134141CHIP_ERROR OTAImageProcessorImpl::Abort ()
135142{
136- CHIP_ERROR error = System::MapErrorZephyr (dfu_multi_image_done (false ));
137-
138- DFUSync::GetInstance ().Free (mDfuSyncMutexId );
139- TriggerFlashAction (ExternalFlashManager::Action::SLEEP);
140- PostOTAStateChangeEvent (DeviceLayer::kOtaDownloadAborted );
141-
142- return error;
143+ return DeviceLayer::SystemLayer ().ScheduleLambda ([this ] {
144+ CHIP_ERROR error = System::MapErrorZephyr (dfu_multi_image_done (false ));
145+ DFUSync::GetInstance ().Free (mDfuSyncMutexId );
146+ TriggerFlashAction (ExternalFlashManager::Action::SLEEP);
147+ PostOTAStateChangeEvent (DeviceLayer::kOtaDownloadAborted );
148+ if (error != CHIP_NO_ERROR)
149+ {
150+ ChipLogError (SoftwareUpdate, " Failed to abort OTA: %" CHIP_ERROR_FORMAT, error.Format ());
151+ }
152+ });
143153}
144154
145155CHIP_ERROR OTAImageProcessorImpl::Apply ()
@@ -162,48 +172,66 @@ CHIP_ERROR OTAImageProcessorImpl::Apply()
162172 },
163173 nullptr /* context */ );
164174 }
165- else
166- {
167- PostOTAStateChangeEvent (DeviceLayer::kOtaApplyFailed );
168- return System::MapErrorZephyr (err);
169- }
175+ PostOTAStateChangeEvent (DeviceLayer::kOtaApplyFailed );
176+ return System::MapErrorZephyr (err);
170177#else
171178 return System::MapErrorZephyr (err);
172179#endif
173180}
174181
182+ CHIP_ERROR OTAImageProcessorImpl::WriteToFlash (size_t offset, const uint8_t * chunk, size_t chunk_size)
183+ {
184+ int err = dfu_multi_image_write (offset, chunk, chunk_size);
185+ if (err != 0 )
186+ {
187+ ChipLogError (SoftwareUpdate, " OTA block write failed %d" , err);
188+ return CHIP_ERROR_WRITE_FAILED;
189+ }
190+ mParams .downloadedBytes += chunk_size;
191+ ChipLogDetail (SoftwareUpdate, " Downloaded %u/%u bytes" , static_cast <unsigned >(mParams .downloadedBytes ),
192+ static_cast <unsigned >(mParams .totalFileBytes ));
193+ return CHIP_NO_ERROR;
194+ }
195+
175196CHIP_ERROR OTAImageProcessorImpl::ProcessBlock (ByteSpan & aBlock)
176197{
177198 VerifyOrReturnError (mDownloader != nullptr , CHIP_ERROR_INCORRECT_STATE);
178199
179200 CHIP_ERROR error = ProcessHeader (aBlock);
180201
181- if (error == CHIP_NO_ERROR)
202+ const size_t blockOffset = static_cast <size_t >(mParams .downloadedBytes );
203+ const size_t blockSize = aBlock.size ();
204+
205+ if (error == CHIP_NO_ERROR && blockSize > kBufferSize )
182206 {
183- // DFU target library buffers data internally, so do not clone the block data.
184- if (mParams .downloadedBytes > std::numeric_limits<size_t >::max ())
185- {
186- error = CHIP_ERROR_BUFFER_TOO_SMALL;
187- }
188- else
189- {
190- error = System::MapErrorZephyr (
191- dfu_multi_image_write (static_cast <size_t >(mParams .downloadedBytes ), aBlock.data (), aBlock.size ()));
192- mParams .downloadedBytes += aBlock.size ();
193- }
207+ error = CHIP_ERROR_BUFFER_TOO_SMALL;
208+ }
209+
210+ if (error != CHIP_NO_ERROR)
211+ {
212+ return DeviceLayer::SystemLayer ().ScheduleLambda ([this , error] {
213+ mDownloader ->EndDownload (error);
214+ PostOTAStateChangeEvent (DeviceLayer::kOtaDownloadFailed );
215+ });
194216 }
195217
196- // Report the result back to the downloader asynchronously.
197- return DeviceLayer::SystemLayer ().ScheduleLambda ([this , error, aBlock] {
198- if (error == CHIP_NO_ERROR)
218+ memcpy (mStagingBuffer , aBlock.data (), blockSize);
219+
220+ return DeviceLayer::SystemLayer ().ScheduleLambda ([this , blockOffset, blockSize] {
221+ CHIP_ERROR err = CHIP_NO_ERROR;
222+ const bool isLastBlock = blockOffset + blockSize >= mParams .totalFileBytes ;
223+ if (!isLastBlock)
199224 {
200- ChipLogDetail (SoftwareUpdate, " Downloaded %u/%u bytes" , static_cast <unsigned >(mParams .downloadedBytes ),
201- static_cast <unsigned >(mParams .totalFileBytes ));
202- mDownloader ->FetchNextData ();
225+ err = mDownloader ->FetchNextData ();
203226 }
204- else
227+ if (err == CHIP_NO_ERROR)
205228 {
206- mDownloader ->EndDownload (error);
229+ err = WriteToFlash (blockOffset, mStagingBuffer , blockSize);
230+ }
231+ if (err != CHIP_NO_ERROR)
232+ {
233+ ChipLogError (SoftwareUpdate, " OTA block processing failed: %" CHIP_ERROR_FORMAT, err.Format ());
234+ mDownloader ->EndDownload (err);
207235 PostOTAStateChangeEvent (DeviceLayer::kOtaDownloadFailed );
208236 }
209237 });
0 commit comments