20
20
#include < app/clusters/ota-requestor/OTADownloader.h>
21
21
#include < app/clusters/ota-requestor/OTARequestorInterface.h>
22
22
#include < platform/CHIPDeviceLayer.h>
23
+ #include < platform/KeyValueStoreManager.h>
23
24
24
25
#include < zephyr/dfu/mcuboot.h>
25
26
#include < zephyr/storage/flash_map.h>
28
29
29
30
static struct stream_flash_ctx stream;
30
31
32
+ using namespace ::chip::DeviceLayer::PersistedStorage;
33
+
31
34
namespace chip {
32
35
namespace {
33
36
@@ -53,33 +56,39 @@ CHIP_ERROR OTAImageProcessorImpl::PrepareDownload()
53
56
54
57
return DeviceLayer::SystemLayer ().ScheduleLambda ([this ] { mDownloader ->OnPreparedForDownload (PrepareDownloadImpl ()); });
55
58
}
59
+ const struct device * flash_dev;
56
60
57
- CHIP_ERROR OTAImageProcessorImpl::PrepareDownloadImpl ( )
61
+ CHIP_ERROR OTAImageProcessorImpl::InitFlashStream ( size_t offset )
58
62
{
59
- mHeaderParser .Init ();
60
- mParams = {};
61
-
62
- const struct device * flash_dev;
63
-
64
63
flash_dev = DEVICE_DT_GET (DT_CHOSEN (zephyr_flash_controller));
65
64
if (flash_dev == NULL )
66
65
{
67
66
ChipLogError (SoftwareUpdate, " Failed to get flash device" );
68
67
return System::MapErrorZephyr (-EFAULT);
69
68
}
70
69
71
- int err = stream_flash_init (&stream, flash_dev, mBuffer , sizeof (mBuffer ), FIXED_PARTITION_OFFSET (slot1_partition),
72
- FIXED_PARTITION_SIZE (slot1_partition), NULL );
70
+ int err = stream_flash_init (&stream, flash_dev, mBuffer , sizeof (mBuffer ), FIXED_PARTITION_OFFSET (slot1_partition) + offset ,
71
+ FIXED_PARTITION_SIZE (slot1_partition) - offset , NULL );
73
72
74
73
if (err)
75
74
{
76
75
ChipLogError (SoftwareUpdate, " stream_flash_init failed (err %d)" , err);
77
76
}
78
77
79
- PostOTAStateChangeEvent (DeviceLayer::kOtaDownloadInProgress );
80
78
return System::MapErrorZephyr (err);
81
79
}
82
80
81
+ CHIP_ERROR OTAImageProcessorImpl::PrepareDownloadImpl ()
82
+ {
83
+ mHeaderParser .Init ();
84
+ mParams = {};
85
+
86
+ CHIP_ERROR error = InitFlashStream (0 );
87
+
88
+ PostOTAStateChangeEvent (DeviceLayer::kOtaDownloadInProgress );
89
+ return error;
90
+ }
91
+
83
92
CHIP_ERROR OTAImageProcessorImpl::Finalize ()
84
93
{
85
94
int err = stream_flash_buffered_write (&stream, NULL , 0 , true );
@@ -136,8 +145,16 @@ CHIP_ERROR OTAImageProcessorImpl::ProcessBlock(ByteSpan & aBlock)
136
145
137
146
if (error == CHIP_NO_ERROR)
138
147
{
139
- error = System::MapErrorZephyr (stream_flash_buffered_write (&stream, aBlock.data (), aBlock.size (), false ));
140
- mParams .downloadedBytes += aBlock.size ();
148
+ if (downloadedBytesRestored)
149
+ {
150
+ mParams .downloadedBytes = downloadedBytesRestored;
151
+ }
152
+ else
153
+ {
154
+ error = System::MapErrorZephyr (stream_flash_buffered_write (&stream, aBlock.data (), aBlock.size (), false ));
155
+ mParams .downloadedBytes += aBlock.size ();
156
+ }
157
+ ReturnErrorOnFailure (KeyValueStoreMgr ().Put (kDownloadedBytes , &mParams .downloadedBytes , sizeof (mParams .downloadedBytes )));
141
158
}
142
159
143
160
// Report the result back to the downloader asynchronously.
@@ -146,7 +163,15 @@ CHIP_ERROR OTAImageProcessorImpl::ProcessBlock(ByteSpan & aBlock)
146
163
{
147
164
ChipLogDetail (SoftwareUpdate, " Downloaded %u/%u bytes" , static_cast <unsigned >(mParams .downloadedBytes ),
148
165
static_cast <unsigned >(mParams .totalFileBytes ));
149
- mDownloader ->FetchNextData ();
166
+ if (downloadedBytesRestored)
167
+ {
168
+ mDownloader ->SkipData (downloadedBytesRestored - aBlock.size ());
169
+ downloadedBytesRestored = 0 ;
170
+ }
171
+ else
172
+ {
173
+ mDownloader ->FetchNextData ();
174
+ }
150
175
}
151
176
else
152
177
{
@@ -174,6 +199,34 @@ CHIP_ERROR OTAImageProcessorImpl::ConfirmCurrentImage()
174
199
return System::MapErrorZephyr (boot_write_img_confirmed ());
175
200
}
176
201
202
+ CHIP_ERROR OTAImageProcessorImpl::RestoreBytes (ByteSpan & aBlock)
203
+ {
204
+ uint8_t * ImageDigestBuffer = new uint8_t [aBlock.size ()];
205
+ MutableByteSpan mImageDigest (ImageDigestBuffer, aBlock.size ());
206
+
207
+ if (KeyValueStoreMgr ().Get (kImageDigest , mImageDigest .data (), mImageDigest .size ()) == CHIP_NO_ERROR &&
208
+ KeyValueStoreMgr ().Get (kDownloadedBytes , &downloadedBytesRestored, sizeof (downloadedBytesRestored)) == CHIP_NO_ERROR &&
209
+ mImageDigest .data_equal (aBlock) && downloadedBytesRestored < mParams .totalFileBytes )
210
+ {
211
+ // Align to the nearest lower multiple of sector size (4 KB) for Flash erase/write
212
+ downloadedBytesRestored = ROUND_DOWN (downloadedBytesRestored, 0x1000 );
213
+ ChipLogDetail (SoftwareUpdate, " Restored %u/%u bytes" , static_cast <unsigned >(downloadedBytesRestored),
214
+ static_cast <unsigned >(mParams .totalFileBytes ))
215
+
216
+ // Reinit Flash Stream with offset
217
+ ReturnErrorOnFailure (System::MapErrorZephyr (stream_flash_buffered_write (&stream, NULL , 0 , true )));
218
+ ReturnErrorOnFailure (InitFlashStream (downloadedBytesRestored));
219
+ }
220
+ else
221
+ {
222
+ downloadedBytesRestored = 0 ;
223
+ ReturnErrorOnFailure (KeyValueStoreMgr ().Put (kImageDigest , aBlock.data (), aBlock.size ()));
224
+ }
225
+ delete[] ImageDigestBuffer;
226
+
227
+ return CHIP_NO_ERROR;
228
+ }
229
+
177
230
CHIP_ERROR OTAImageProcessorImpl::ProcessHeader (ByteSpan & aBlock)
178
231
{
179
232
if (mHeaderParser .IsInitialized ())
@@ -186,6 +239,10 @@ CHIP_ERROR OTAImageProcessorImpl::ProcessHeader(ByteSpan & aBlock)
186
239
ReturnErrorOnFailure (error);
187
240
188
241
mParams .totalFileBytes = header.mPayloadSize ;
242
+
243
+ // Restore interrupted OTA process
244
+ RestoreBytes (header.mImageDigest );
245
+
189
246
mHeaderParser .Clear ();
190
247
}
191
248
0 commit comments