16
16
* limitations under the License.
17
17
*/
18
18
19
+ #include " OTAImageProcessorImpl.h"
19
20
#include < app/clusters/ota-requestor/OTADownloader.h>
20
21
21
- #include " OTAImageProcessorImpl.h"
22
+ extern " C" {
23
+ #include " platform/bootloader/api/btl_interface.h"
24
+ }
25
+
26
+ // / No error, operation OK
27
+ #define SL_BOOTLOADER_OK 0L
22
28
23
29
namespace chip {
24
30
31
+ // Define static memebers
32
+ uint8_t OTAImageProcessorImpl::mSlotId ;
33
+ uint16_t OTAImageProcessorImpl::mWriteOffset ;
34
+
25
35
CHIP_ERROR OTAImageProcessorImpl::PrepareDownload ()
26
36
{
27
37
if (mParams .imageFile .empty ())
@@ -42,6 +52,29 @@ CHIP_ERROR OTAImageProcessorImpl::Finalize()
42
52
43
53
CHIP_ERROR OTAImageProcessorImpl::Apply ()
44
54
{
55
+ uint32_t err = SL_BOOTLOADER_OK;
56
+
57
+ ChipLogError (SoftwareUpdate, " OTAImageProcessorImpl::Apply()" );
58
+
59
+ // Assuming that bootloader_verifyImage() call is not too expensive and
60
+ // doesn't need to be offloaded to a different task. Revisit if necessary.
61
+ err = bootloader_verifyImage (mSlotId , NULL );
62
+ if (err != SL_BOOTLOADER_OK)
63
+ {
64
+ ChipLogError (SoftwareUpdate, " bootloader_verifyImage error %ld" , err);
65
+ return CHIP_ERROR_INTERNAL;
66
+ }
67
+
68
+ err = bootloader_setImageToBootload (mSlotId );
69
+ if (err != SL_BOOTLOADER_OK)
70
+ {
71
+ ChipLogError (SoftwareUpdate, " setImageToBootload error %ld" , err);
72
+ return CHIP_ERROR_INTERNAL;
73
+ }
74
+
75
+ // This reboots the device
76
+ bootloader_rebootAndInstall ();
77
+
45
78
return CHIP_NO_ERROR;
46
79
}
47
80
@@ -59,11 +92,6 @@ CHIP_ERROR OTAImageProcessorImpl::Abort()
59
92
60
93
CHIP_ERROR OTAImageProcessorImpl::ProcessBlock (ByteSpan & block)
61
94
{
62
- if (!mOfs .is_open () || !mOfs .good ())
63
- {
64
- return CHIP_ERROR_INTERNAL;
65
- }
66
-
67
95
if ((block.data () == nullptr ) || block.empty ())
68
96
{
69
97
return CHIP_ERROR_INVALID_ARGUMENT;
@@ -82,7 +110,9 @@ CHIP_ERROR OTAImageProcessorImpl::ProcessBlock(ByteSpan & block)
82
110
83
111
void OTAImageProcessorImpl::HandlePrepareDownload (intptr_t context)
84
112
{
113
+ int32_t err = SL_BOOTLOADER_OK;
85
114
auto * imageProcessor = reinterpret_cast <OTAImageProcessorImpl *>(context);
115
+
86
116
if (imageProcessor == nullptr )
87
117
{
88
118
ChipLogError (SoftwareUpdate, " ImageProcessor context is null" );
@@ -94,17 +124,13 @@ void OTAImageProcessorImpl::HandlePrepareDownload(intptr_t context)
94
124
return ;
95
125
}
96
126
97
- imageProcessor->mOfs .open (imageProcessor->mParams .imageFile .data (),
98
- std::ofstream::out | std::ofstream::ate | std::ofstream::app);
99
- if (!imageProcessor->mOfs .good ())
100
- {
101
- imageProcessor->mDownloader ->OnPreparedForDownload (CHIP_ERROR_OPEN_FAILED);
102
- return ;
103
- }
127
+ bootloader_init ();
128
+ mSlotId = 0 ; // Single slot until we support multiple images
129
+ mWriteOffset = 0 ;
104
130
105
- // TODO: if file already exists and is not empty, erase previous contents
131
+ // Not calling bootloader_eraseStorageSlot(mSlotId) here because we erase during each write
106
132
107
- imageProcessor->mDownloader ->OnPreparedForDownload (CHIP_NO_ERROR);
133
+ imageProcessor->mDownloader ->OnPreparedForDownload (err == SL_BOOTLOADER_OK ? CHIP_NO_ERROR : CHIP_ERROR_INTERNAL );
108
134
}
109
135
110
136
void OTAImageProcessorImpl::HandleFinalize (intptr_t context)
@@ -115,7 +141,6 @@ void OTAImageProcessorImpl::HandleFinalize(intptr_t context)
115
141
return ;
116
142
}
117
143
118
- imageProcessor->mOfs .close ();
119
144
imageProcessor->ReleaseBlock ();
120
145
121
146
ChipLogProgress (SoftwareUpdate, " OTA image downloaded to %s" , imageProcessor->mParams .imageFile .data ());
@@ -129,13 +154,13 @@ void OTAImageProcessorImpl::HandleAbort(intptr_t context)
129
154
return ;
130
155
}
131
156
132
- imageProcessor->mOfs .close ();
133
- remove (imageProcessor->mParams .imageFile .data ());
157
+ // Not clearing the image storage area as it is done during each write
134
158
imageProcessor->ReleaseBlock ();
135
159
}
136
160
137
161
void OTAImageProcessorImpl::HandleProcessBlock (intptr_t context)
138
162
{
163
+ uint32_t err = SL_BOOTLOADER_OK;
139
164
auto * imageProcessor = reinterpret_cast <OTAImageProcessorImpl *>(context);
140
165
if (imageProcessor == nullptr )
141
166
{
@@ -150,27 +175,35 @@ void OTAImageProcessorImpl::HandleProcessBlock(intptr_t context)
150
175
151
176
// TODO: Process block header if any
152
177
153
- if (!imageProcessor->mOfs .write (reinterpret_cast <const char *>(imageProcessor->mBlock .data ()),
154
- static_cast <std::streamsize>(imageProcessor->mBlock .size ())))
178
+ err = bootloader_eraseWriteStorage (mSlotId , mWriteOffset , reinterpret_cast <uint8_t *>(imageProcessor->mBlock .data ()),
179
+ imageProcessor->mBlock .size ());
180
+
181
+ if (err)
155
182
{
183
+ ChipLogError (SoftwareUpdate, " bootloader_eraseWriteStorage err %ld" , err);
184
+
156
185
imageProcessor->mDownloader ->EndDownload (CHIP_ERROR_WRITE_FAILED);
157
186
return ;
158
187
}
159
188
189
+ mWriteOffset += imageProcessor->mBlock .size (); // Keep our own track of how far we've written
160
190
imageProcessor->mParams .downloadedBytes += imageProcessor->mBlock .size ();
161
191
imageProcessor->mDownloader ->FetchNextData ();
162
192
}
163
193
194
+ // Store block data for HandleProcessBlock to access
164
195
CHIP_ERROR OTAImageProcessorImpl::SetBlock (ByteSpan & block)
165
196
{
166
197
if ((block.data () == nullptr ) || block.empty ())
167
198
{
168
199
return CHIP_NO_ERROR;
169
200
}
170
201
171
- // Allocate memory for block data if it has not been done yet
172
- if (mBlock .empty ())
202
+ // Allocate memory for block data if we don't have enough already
203
+ if (mBlock .size () < block. size ())
173
204
{
205
+ ReleaseBlock ();
206
+
174
207
mBlock = MutableByteSpan (static_cast <uint8_t *>(chip::Platform::MemoryAlloc (block.size ())), block.size ());
175
208
if (mBlock .data () == nullptr )
176
209
{
0 commit comments