Skip to content

Commit 8658676

Browse files
author
Jamie C. Driver
committed
ota: move valid/confirmed flag and fw-written value into ota ctx struct
Remove wrapping context structs and pass main ota ctx into all relevant ota functions and callbacks, so that all interesting ota progress data is consolidated into the one structure.
1 parent f8f12f9 commit 8658676

File tree

3 files changed

+72
-82
lines changed

3 files changed

+72
-82
lines changed

main/process/ota.c

Lines changed: 28 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -21,54 +21,52 @@
2121

2222
#include "process_utils.h"
2323

24-
typedef struct {
25-
bool* prevalidated;
26-
jade_ota_ctx_t* joctx;
27-
} ota_deflate_ctx_t;
28-
2924
/* this is called by the deflate library when it has uncompressed data to write */
3025
static int uncompressed_stream_writer(void* ctx, uint8_t* uncompressed, size_t length)
3126
{
3227
JADE_ASSERT(ctx);
3328
JADE_ASSERT(uncompressed);
3429
JADE_ASSERT(length);
3530

36-
ota_deflate_ctx_t* octx = (ota_deflate_ctx_t*)ctx;
37-
JADE_ASSERT(octx->joctx);
31+
jade_ota_ctx_t* joctx = (jade_ota_ctx_t*)ctx;
3832

39-
if (!*octx->prevalidated && length >= CUSTOM_HEADER_MIN_WRITE) {
40-
const enum ota_status res = ota_user_validation(octx->joctx, uncompressed);
33+
if (!*joctx->validated_confirmed && length >= CUSTOM_HEADER_MIN_WRITE) {
34+
const enum ota_status res = ota_user_validation(joctx, uncompressed);
4135
if (res != SUCCESS) {
4236
JADE_LOGE("ota_user_validation() error, %u", res);
43-
*octx->joctx->ota_return_status = res;
37+
*joctx->ota_return_status = res;
4438
return res;
4539
}
46-
*octx->prevalidated = true;
40+
*joctx->validated_confirmed = true;
4741
}
4842

49-
const esp_err_t res = esp_ota_write(*octx->joctx->ota_handle, (const void*)uncompressed, length);
43+
const esp_err_t res = esp_ota_write(*joctx->ota_handle, (const void*)uncompressed, length);
5044
if (res != ESP_OK) {
5145
JADE_LOGE("ota_write() error: %u", res);
52-
*octx->joctx->ota_return_status = ERROR_WRITE;
46+
*joctx->ota_return_status = ERROR_WRITE;
5347
return DEFLATE_ERROR;
5448
}
5549

56-
if (octx->joctx->hash_type == HASHTYPE_FULLFWDATA) {
50+
if (joctx->hash_type == HASHTYPE_FULLFWDATA) {
5751
// Add written to hash calculation
58-
JADE_ZERO_VERIFY(mbedtls_sha256_update(octx->joctx->sha_ctx, uncompressed, length));
52+
JADE_ZERO_VERIFY(mbedtls_sha256_update(joctx->sha_ctx, uncompressed, length));
5953
}
6054

61-
*octx->joctx->remaining_uncompressed -= length;
62-
const size_t written = octx->joctx->uncompressedsize - *octx->joctx->remaining_uncompressed;
55+
*joctx->remaining_uncompressed -= length;
56+
joctx->fwwritten += length;
57+
58+
// For a full ota, the amount of fw data uncompressed should always be equal to the
59+
// amount of new firmware we have written, as it should be the same thing.
60+
JADE_ASSERT(joctx->uncompressedsize - *joctx->remaining_uncompressed == joctx->fwwritten);
6361

64-
if (written > CUSTOM_HEADER_MIN_WRITE && !*octx->prevalidated) {
62+
if (joctx->fwwritten > CUSTOM_HEADER_MIN_WRITE && !*joctx->validated_confirmed) {
6563
return DEFLATE_ERROR;
6664
}
6765

6866
/* Update the progress bar once the user has confirmed and upload is in progress */
69-
if (*octx->prevalidated) {
70-
JADE_ASSERT(octx->joctx->progress_bar.progress_bar);
71-
update_progress_bar(&octx->joctx->progress_bar, octx->joctx->uncompressedsize, written);
67+
if (*joctx->validated_confirmed) {
68+
JADE_ASSERT(joctx->progress_bar.progress_bar);
69+
update_progress_bar(&joctx->progress_bar, joctx->uncompressedsize, joctx->fwwritten);
7270
}
7371

7472
return DEFLATE_OK;
@@ -81,7 +79,7 @@ void ota_process(void* process_ptr)
8179
jade_process_t* process = process_ptr;
8280
bool uploading = false;
8381
enum ota_status ota_return_status = ERROR_OTA_SETUP;
84-
bool prevalidated = false;
82+
bool validated_confirmed = false;
8583
bool ota_end_called = false;
8684

8785
char id[MAXLEN_ID + 1];
@@ -134,10 +132,6 @@ void ota_process(void* process_ptr)
134132
struct deflate_ctx* dctx = JADE_MALLOC_PREFER_SPIRAM(sizeof(struct deflate_ctx));
135133
jade_process_free_on_exit(process, dctx);
136134

137-
ota_deflate_ctx_t octx = {
138-
.prevalidated = &prevalidated,
139-
};
140-
141135
size_t remaining_uncompressed = firmwaresize;
142136

143137
jade_ota_ctx_t joctx = {
@@ -146,6 +140,7 @@ void ota_process(void* process_ptr)
146140
.hash_type = hash_type,
147141
.dctx = dctx,
148142
.id = id,
143+
.validated_confirmed = &validated_confirmed,
149144
.uncompressedsize = firmwaresize,
150145
.remaining_uncompressed = &remaining_uncompressed,
151146
.ota_return_status = &ota_return_status,
@@ -158,14 +153,12 @@ void ota_process(void* process_ptr)
158153
.expected_hash = expected_hash,
159154
};
160155

161-
octx.joctx = &joctx;
162-
163156
if (!ota_init(&joctx)) {
164157
jade_process_reject_message(process, CBOR_RPC_INTERNAL_ERROR, "Failed to initialize OTA", NULL);
165158
goto cleanup;
166159
}
167160

168-
const int dret = deflate_init_write_compressed(dctx, compressedsize, uncompressed_stream_writer, &octx);
161+
const int dret = deflate_init_write_compressed(dctx, compressedsize, uncompressed_stream_writer, &joctx);
169162
JADE_ASSERT(!dret);
170163

171164
// Send the ok response, which implies now we will get ota_data messages
@@ -182,7 +175,7 @@ void ota_process(void* process_ptr)
182175
goto cleanup;
183176
}
184177
}
185-
JADE_ASSERT(prevalidated);
178+
JADE_ASSERT(validated_confirmed);
186179

187180
// Uploading complete
188181
uploading = false;
@@ -192,6 +185,10 @@ void ota_process(void* process_ptr)
192185
JADE_LOGE("Expected uncompressed size: %u, got %u", firmwaresize, firmwaresize - remaining_uncompressed);
193186
ota_return_status = ERROR_DECOMPRESS;
194187
}
188+
if (joctx.fwwritten != firmwaresize) {
189+
JADE_LOGE("Expected amountof firmware written: %u, expected %u", joctx.fwwritten, firmwaresize);
190+
ota_return_status = ERROR_DECOMPRESS;
191+
}
195192

196193
// Expect a complete/request for status
197194
jade_process_load_in_message(process, true);
@@ -234,7 +231,7 @@ void ota_process(void* process_ptr)
234231
esp_restart();
235232
} else {
236233
JADE_LOGE("OTA error %u: %s", ota_return_status, MESSAGES[ota_return_status]);
237-
if (prevalidated && !ota_end_called) {
234+
if (validated_confirmed && !ota_end_called) {
238235
// ota_begin has been called, cleanup
239236
const esp_err_t err = esp_ota_abort(ota_handle);
240237
JADE_ASSERT(err == ESP_OK);

main/process/ota_delta.c

Lines changed: 42 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -22,14 +22,6 @@
2222
#include <bspatch.h>
2323
#include <deflate.h>
2424

25-
typedef struct {
26-
jade_ota_ctx_t* joctx;
27-
char* id;
28-
struct deflate_ctx* const dctx;
29-
size_t written;
30-
bool header_validated;
31-
} bsdiff_ctx_t;
32-
3325
// Error reply in ota_delta is complicated by the fact that we reply 'ok' when we push the received patch data
3426
// into the decompressor, but we carry on copying the base firmware and inflating/applying patch data.
3527
// If an error occurs at this stage - we have no message id to reply to so must cache the error until we do receive
@@ -59,36 +51,36 @@ typedef struct {
5951
// NOTE: uses macros above so may return error immediately, or may just cache it for later return
6052
static int patch_stream_reader(const struct bspatch_stream* stream, void* buffer, int length)
6153
{
62-
bsdiff_ctx_t* bctx = (bsdiff_ctx_t*)stream->opaque;
63-
JADE_ASSERT(bctx);
54+
jade_ota_ctx_t* joctx = (jade_ota_ctx_t*)stream->opaque;
55+
JADE_ASSERT(joctx);
6456

6557
if (length <= 0) {
66-
HANDLE_NEW_ERROR(bctx->joctx, ERROR_PATCH);
58+
HANDLE_NEW_ERROR(joctx, ERROR_PATCH);
6759
}
6860

6961
// Return any non-zero error code from the read routine
70-
const int ret = read_uncompressed(bctx->dctx, buffer, length);
62+
const int ret = read_uncompressed(joctx->dctx, buffer, length);
7163
if (ret) {
72-
HANDLE_NEW_ERROR(bctx->joctx, ret);
64+
HANDLE_NEW_ERROR(joctx, ret);
7365
}
7466

75-
*bctx->joctx->remaining_uncompressed -= length;
67+
*joctx->remaining_uncompressed -= length;
7668

7769
return SUCCESS;
7870
}
7971

8072
// NOTE: uses macros above so may return error immediately, or may just cache it for later return
8173
static int base_firmware_stream_reader(const struct bspatch_stream_i* stream, void* buffer, int pos, int length)
8274
{
83-
bsdiff_ctx_t* bctx = (bsdiff_ctx_t*)stream->opaque;
84-
JADE_ASSERT(bctx);
75+
jade_ota_ctx_t* joctx = (jade_ota_ctx_t*)stream->opaque;
76+
JADE_ASSERT(joctx);
8577

8678
// If currently in error, return immediately without reading anything
87-
HANDLE_ANY_CACHED_ERROR(bctx->joctx);
79+
HANDLE_ANY_CACHED_ERROR(joctx);
8880

89-
if (length <= 0 || pos + length >= bctx->joctx->running_partition->size
90-
|| esp_partition_read(bctx->joctx->running_partition, pos, buffer, length) != ESP_OK) {
91-
HANDLE_NEW_ERROR(bctx->joctx, ERROR_PATCH);
81+
if (length <= 0 || pos + length >= joctx->running_partition->size
82+
|| esp_partition_read(joctx->running_partition, pos, buffer, length) != ESP_OK) {
83+
HANDLE_NEW_ERROR(joctx, ERROR_PATCH);
9284
}
9385

9486
return SUCCESS;
@@ -97,37 +89,41 @@ static int base_firmware_stream_reader(const struct bspatch_stream_i* stream, vo
9789
// NOTE: uses macros above so may return error immediately, or may just cache it for later return
9890
static int ota_stream_writer(const struct bspatch_stream_n* stream, const void* buffer, int length)
9991
{
100-
bsdiff_ctx_t* bctx = (bsdiff_ctx_t*)stream->opaque;
101-
JADE_ASSERT(bctx);
92+
jade_ota_ctx_t* joctx = (jade_ota_ctx_t*)stream->opaque;
93+
JADE_ASSERT(joctx);
10294

10395
// If currently in error, return immediately without writing anything
104-
HANDLE_ANY_CACHED_ERROR(bctx->joctx);
96+
HANDLE_ANY_CACHED_ERROR(joctx);
10597

106-
if (length <= 0 || esp_ota_write(*bctx->joctx->ota_handle, buffer, length) != ESP_OK) {
107-
HANDLE_NEW_ERROR(bctx->joctx, ERROR_PATCH);
98+
if (length <= 0 || esp_ota_write(*joctx->ota_handle, buffer, length) != ESP_OK) {
99+
HANDLE_NEW_ERROR(joctx, ERROR_PATCH);
108100
}
109101

110-
if (!bctx->header_validated && length >= CUSTOM_HEADER_MIN_WRITE) {
111-
const enum ota_status validation = ota_user_validation(bctx->joctx, (uint8_t*)buffer);
102+
if (!*joctx->validated_confirmed && length >= CUSTOM_HEADER_MIN_WRITE) {
103+
const enum ota_status validation = ota_user_validation(joctx, (uint8_t*)buffer);
112104
if (validation != SUCCESS) {
113-
HANDLE_NEW_ERROR(bctx->joctx, validation);
105+
HANDLE_NEW_ERROR(joctx, validation);
114106
}
115-
bctx->header_validated = true;
107+
*joctx->validated_confirmed = true;
116108
}
117109

118-
if (bctx->joctx->hash_type == HASHTYPE_FULLFWDATA) {
110+
if (joctx->hash_type == HASHTYPE_FULLFWDATA) {
119111
// Add written to hash calculation
120-
JADE_ZERO_VERIFY(mbedtls_sha256_update(bctx->joctx->sha_ctx, buffer, length));
112+
JADE_ZERO_VERIFY(mbedtls_sha256_update(joctx->sha_ctx, buffer, length));
121113
}
122114

123-
bctx->written += length;
115+
joctx->fwwritten += length;
116+
117+
// For a patch, the amount of patch data uncompressed should always be more than the
118+
// amount of new firmware we have written, because of additional patch meta-data.
119+
JADE_ASSERT(joctx->uncompressedsize - *joctx->remaining_uncompressed > joctx->fwwritten);
124120

125-
if (bctx->written > CUSTOM_HEADER_MIN_WRITE && !bctx->header_validated) {
126-
HANDLE_NEW_ERROR(bctx->joctx, ERROR_PATCH);
121+
if (joctx->fwwritten > CUSTOM_HEADER_MIN_WRITE && !*joctx->validated_confirmed) {
122+
HANDLE_NEW_ERROR(joctx, ERROR_PATCH);
127123
}
128124

129-
if (bctx->header_validated) {
130-
update_progress_bar(&bctx->joctx->progress_bar, bctx->joctx->firmwaresize, bctx->written);
125+
if (*joctx->validated_confirmed) {
126+
update_progress_bar(&joctx->progress_bar, joctx->firmwaresize, joctx->fwwritten);
131127
}
132128

133129
return SUCCESS;
@@ -137,13 +133,12 @@ static int compressed_stream_reader(void* ctx)
137133
{
138134
JADE_ASSERT(ctx);
139135

140-
bsdiff_ctx_t* bctx = (bsdiff_ctx_t*)ctx;
141-
JADE_ASSERT(bctx->joctx);
136+
jade_ota_ctx_t* joctx = (jade_ota_ctx_t*)ctx;
142137

143138
// NOTE: the ota_return_status can be set via ptr in joctx
144139
// Return any error here as it can be returned to the caller in the message reply
145-
jade_process_get_in_message(bctx->joctx, &handle_in_bin_data, true);
146-
return *bctx->joctx->ota_return_status;
140+
jade_process_get_in_message(joctx, &handle_in_bin_data, true);
141+
return *joctx->ota_return_status;
147142
}
148143

149144
void ota_delta_process(void* process_ptr)
@@ -208,10 +203,7 @@ void ota_delta_process(void* process_ptr)
208203
struct deflate_ctx* dctx = JADE_MALLOC_PREFER_SPIRAM(sizeof(struct deflate_ctx));
209204
jade_process_free_on_exit(process, dctx);
210205

211-
bsdiff_ctx_t bctx = {
212-
.dctx = dctx,
213-
};
214-
206+
bool validated_confirmed = false;
215207
size_t remaining_uncompressed = uncompressedpatchsize;
216208

217209
jade_ota_ctx_t joctx = {
@@ -221,6 +213,7 @@ void ota_delta_process(void* process_ptr)
221213
.ota_handle = &ota_handle,
222214
.dctx = dctx,
223215
.id = id,
216+
.validated_confirmed = &validated_confirmed,
224217
.uncompressedsize = uncompressedpatchsize,
225218
.remaining_uncompressed = &remaining_uncompressed,
226219
.ota_return_status = &ota_return_status,
@@ -232,9 +225,7 @@ void ota_delta_process(void* process_ptr)
232225
.expected_hash = expected_hash,
233226
};
234227

235-
bctx.joctx = &joctx;
236-
237-
int ret = deflate_init_read_uncompressed(dctx, compressedsize, compressed_stream_reader, &bctx);
228+
int ret = deflate_init_read_uncompressed(dctx, compressedsize, compressed_stream_reader, &joctx);
238229
JADE_ASSERT(!ret);
239230

240231
if (!ota_init(&joctx)) {
@@ -251,15 +242,15 @@ void ota_delta_process(void* process_ptr)
251242
struct bspatch_stream_n destination_firmware_stream_writer;
252243
// new partition
253244
destination_firmware_stream_writer.write = &ota_stream_writer;
254-
destination_firmware_stream_writer.opaque = &bctx;
245+
destination_firmware_stream_writer.opaque = &joctx;
255246
// patch
256247
struct bspatch_stream stream;
257248
stream.read = &patch_stream_reader;
258-
stream.opaque = &bctx;
249+
stream.opaque = &joctx;
259250
// old partition / base
260251
struct bspatch_stream_i basestream;
261252
basestream.read = &base_firmware_stream_reader;
262-
basestream.opaque = &bctx;
253+
basestream.opaque = &joctx;
263254

264255
ota_return_status = SUCCESS;
265256
ret = bspatch(
@@ -275,7 +266,7 @@ void ota_delta_process(void* process_ptr)
275266
// Uploading complete
276267
uploading = false;
277268

278-
if (bctx.written != firmwaresize) {
269+
if (joctx.fwwritten != firmwaresize) {
279270
ota_return_status = ERROR_PATCH;
280271
}
281272

main/process/ota_util.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,11 +47,13 @@ typedef struct {
4747
enum ota_status* ota_return_status;
4848
struct deflate_ctx* dctx;
4949
const jade_msg_source_t* expected_source;
50+
bool* validated_confirmed;
5051
size_t* const remaining_uncompressed;
5152
size_t remaining_compressed;
5253
size_t uncompressedsize;
5354
size_t compressedsize;
5455
size_t firmwaresize;
56+
size_t fwwritten;
5557
} jade_ota_ctx_t;
5658

5759
enum ota_status {

0 commit comments

Comments
 (0)