Skip to content

Commit 2389420

Browse files
selissiakghostandy31415restyled-commits
authored andcommitted
[EFR32 OTA] Invoke Silabs API for writing, verifying and applying the image (#13499)
* Code for testing bootloader integration * Add bootloader API calls * Add the rest of booloader calls to EFR32 OTA Requestor * Call the OTARequestor Init() method * Use correct booloader API * Close exchange when session is released (#13448) * Close exchange when session is released * Add clearRetransTable parameter to DoClose call Co-authored-by: Andrei Litvin <[email protected]> * Clean up comments and debug code * Restyled by whitespace * Restyled by clang-format Co-authored-by: Zang MingJie <[email protected]> Co-authored-by: Andrei Litvin <[email protected]> Co-authored-by: Restyled.io <[email protected]>
1 parent 924cf9c commit 2389420

File tree

3 files changed

+101
-23
lines changed

3 files changed

+101
-23
lines changed

examples/ota-requestor-app/efr32/src/main.cpp

+44
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,48 @@ BDXDownloader gDownloader;
8888
OTAImageProcessorImpl gImageProcessor;
8989

9090
volatile int apperror_cnt;
91+
92+
#include "platform/bootloader/api/application_properties.h"
93+
94+
// Header used for building the image GBL file
95+
#define APP_PROPERTIES_VERSION 1
96+
#define APP_PROPERTIES_ID \
97+
{ \
98+
0 \
99+
}
100+
101+
__attribute__((used)) ApplicationProperties_t sl_app_properties = {
102+
/// @brief Magic value indicating that this is an ApplicationProperties_t
103+
/// Must equal @ref APPLICATION_PROPERTIES_MAGIC
104+
.magic = APPLICATION_PROPERTIES_MAGIC,
105+
106+
/// Version number of this struct
107+
.structVersion = APPLICATION_PROPERTIES_VERSION,
108+
109+
/// Type of signature this application is signed with
110+
.signatureType = APPLICATION_SIGNATURE_NONE,
111+
112+
/// Location of the signature. Typically a pointer to the end of application
113+
.signatureLocation = 0,
114+
115+
/// Information about the application
116+
.app = {
117+
118+
/// Bitfield representing type of application
119+
/// e.g. @ref APPLICATION_TYPE_BLUETOOTH_APP
120+
.type = APPLICATION_TYPE_ZIGBEE,
121+
122+
/// Version number for this application
123+
.version = APP_PROPERTIES_VERSION,
124+
125+
/// Capabilities of this application
126+
.capabilities = 0,
127+
128+
/// Unique ID (e.g. UUID/GUID) for the product this application is built for
129+
.productId = APP_PROPERTIES_ID,
130+
},
131+
};
132+
91133
// ================================================================================
92134
// App Error
93135
//=================================================================================
@@ -174,6 +216,8 @@ int main(void)
174216

175217
gRequestorCore.Init(&(chip::Server::GetInstance()), &gRequestorUser, &gDownloader);
176218

219+
gRequestorUser.Init(&gRequestorCore, &gImageProcessor);
220+
177221
OTAImageProcessorParams ipParams;
178222
ipParams.imageFile = CharSpan("test.txt");
179223
gImageProcessor.SetOTAImageProcessorParams(ipParams);

src/platform/EFR32/OTAImageProcessorImpl.cpp

+55-22
Original file line numberDiff line numberDiff line change
@@ -16,12 +16,22 @@
1616
* limitations under the License.
1717
*/
1818

19+
#include "OTAImageProcessorImpl.h"
1920
#include <app/clusters/ota-requestor/OTADownloader.h>
2021

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
2228

2329
namespace chip {
2430

31+
// Define static memebers
32+
uint8_t OTAImageProcessorImpl::mSlotId;
33+
uint16_t OTAImageProcessorImpl::mWriteOffset;
34+
2535
CHIP_ERROR OTAImageProcessorImpl::PrepareDownload()
2636
{
2737
if (mParams.imageFile.empty())
@@ -42,6 +52,29 @@ CHIP_ERROR OTAImageProcessorImpl::Finalize()
4252

4353
CHIP_ERROR OTAImageProcessorImpl::Apply()
4454
{
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+
4578
return CHIP_NO_ERROR;
4679
}
4780

@@ -59,11 +92,6 @@ CHIP_ERROR OTAImageProcessorImpl::Abort()
5992

6093
CHIP_ERROR OTAImageProcessorImpl::ProcessBlock(ByteSpan & block)
6194
{
62-
if (!mOfs.is_open() || !mOfs.good())
63-
{
64-
return CHIP_ERROR_INTERNAL;
65-
}
66-
6795
if ((block.data() == nullptr) || block.empty())
6896
{
6997
return CHIP_ERROR_INVALID_ARGUMENT;
@@ -82,7 +110,9 @@ CHIP_ERROR OTAImageProcessorImpl::ProcessBlock(ByteSpan & block)
82110

83111
void OTAImageProcessorImpl::HandlePrepareDownload(intptr_t context)
84112
{
113+
int32_t err = SL_BOOTLOADER_OK;
85114
auto * imageProcessor = reinterpret_cast<OTAImageProcessorImpl *>(context);
115+
86116
if (imageProcessor == nullptr)
87117
{
88118
ChipLogError(SoftwareUpdate, "ImageProcessor context is null");
@@ -94,17 +124,13 @@ void OTAImageProcessorImpl::HandlePrepareDownload(intptr_t context)
94124
return;
95125
}
96126

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;
104130

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
106132

107-
imageProcessor->mDownloader->OnPreparedForDownload(CHIP_NO_ERROR);
133+
imageProcessor->mDownloader->OnPreparedForDownload(err == SL_BOOTLOADER_OK ? CHIP_NO_ERROR : CHIP_ERROR_INTERNAL);
108134
}
109135

110136
void OTAImageProcessorImpl::HandleFinalize(intptr_t context)
@@ -115,7 +141,6 @@ void OTAImageProcessorImpl::HandleFinalize(intptr_t context)
115141
return;
116142
}
117143

118-
imageProcessor->mOfs.close();
119144
imageProcessor->ReleaseBlock();
120145

121146
ChipLogProgress(SoftwareUpdate, "OTA image downloaded to %s", imageProcessor->mParams.imageFile.data());
@@ -129,13 +154,13 @@ void OTAImageProcessorImpl::HandleAbort(intptr_t context)
129154
return;
130155
}
131156

132-
imageProcessor->mOfs.close();
133-
remove(imageProcessor->mParams.imageFile.data());
157+
// Not clearing the image storage area as it is done during each write
134158
imageProcessor->ReleaseBlock();
135159
}
136160

137161
void OTAImageProcessorImpl::HandleProcessBlock(intptr_t context)
138162
{
163+
uint32_t err = SL_BOOTLOADER_OK;
139164
auto * imageProcessor = reinterpret_cast<OTAImageProcessorImpl *>(context);
140165
if (imageProcessor == nullptr)
141166
{
@@ -150,27 +175,35 @@ void OTAImageProcessorImpl::HandleProcessBlock(intptr_t context)
150175

151176
// TODO: Process block header if any
152177

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)
155182
{
183+
ChipLogError(SoftwareUpdate, "bootloader_eraseWriteStorage err %ld", err);
184+
156185
imageProcessor->mDownloader->EndDownload(CHIP_ERROR_WRITE_FAILED);
157186
return;
158187
}
159188

189+
mWriteOffset += imageProcessor->mBlock.size(); // Keep our own track of how far we've written
160190
imageProcessor->mParams.downloadedBytes += imageProcessor->mBlock.size();
161191
imageProcessor->mDownloader->FetchNextData();
162192
}
163193

194+
// Store block data for HandleProcessBlock to access
164195
CHIP_ERROR OTAImageProcessorImpl::SetBlock(ByteSpan & block)
165196
{
166197
if ((block.data() == nullptr) || block.empty())
167198
{
168199
return CHIP_NO_ERROR;
169200
}
170201

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())
173204
{
205+
ReleaseBlock();
206+
174207
mBlock = MutableByteSpan(static_cast<uint8_t *>(chip::Platform::MemoryAlloc(block.size())), block.size());
175208
if (mBlock.data() == nullptr)
176209
{

src/platform/EFR32/OTAImageProcessorImpl.h

+2-1
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,8 @@ class OTAImageProcessorImpl : public OTAImageProcessorInterface
5555
*/
5656
CHIP_ERROR ReleaseBlock();
5757

58-
std::ofstream mOfs;
58+
static uint16_t mWriteOffset; // End of last written block
59+
static uint8_t mSlotId; // Bootloader storage slot
5960
MutableByteSpan mBlock;
6061
OTADownloader * mDownloader;
6162
};

0 commit comments

Comments
 (0)