1 /*
2 * Copyright (c) 2020 HiSilicon (Shanghai) Technologies CO., LIMITED.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 * @brief FOTA patch application program
15 */
16
17 #include <stdint.h>
18 #include <stddef.h>
19 #include <stdbool.h>
20 #include <stdio.h>
21 #include <string.h>
22 #include "securec.h"
23 #include "common_def.h"
24 #include "upg_patch_info.h"
25 #include "upg_alloc.h"
26 #include "upg_debug.h"
27 #include "upg_porting.h"
28 #include "errcode.h"
29 #include "LzmaDec.h"
30 #include "upg_common_porting.h"
31 #include "upg_common.h"
32 #include "upg_config.h"
33
34 #include "upg_patch.h"
35
36 #define Z_OK SZ_OK
37 #define ZIP_STREAM_END 99
38 #define WORD_WIDTH 4
39
40 /* Code style related constants */
41 #define PATCH_KNVD_STR "KNVD"
42 #define PATCH_KNVD_STR_LEN 4
43 #define PAGE_STATUS_BIT_SEARCH_START 1
44 #define PAGE_STATUS_BIT_SEARCH_END 5
45 #define PAGE_STATUS_BIT_SEARCH_INC 2
46
fota_patch_free(void * mem)47 STATIC void fota_patch_free(void *mem)
48 {
49 if (mem == NULL) {
50 return;
51 }
52
53 /* first words of the allocated memory is an int32_t indicating how much memory is allocated... */
54 int32_t *q = ((int32_t *)mem) - 1;
55 upg_free(q);
56 }
57
fota_patch_alloc(size_t size)58 STATIC void* fota_patch_alloc(size_t size)
59 {
60 volatile int32_t *p = NULL;
61 uint32_t len = size + (uint32_t)sizeof(int32_t);
62 p = (int32_t*)upg_malloc(len);
63 if (p == NULL) {
64 upg_log_err("[UPG] upg_malloc failure for requested size = 0x%x\r\n", (uint32_t)size);
65 return NULL;
66 }
67 /* This will panic if it fails so no need to check the return value. */
68 (void)memset_s((int32_t *)p, len, 0, len);
69
70 *p = (int32_t)size;
71
72 return (void*)(p + 1);
73 }
74
lzma_malloc(ISzAllocPtr p,size_t size)75 STATIC void* lzma_malloc(ISzAllocPtr p, size_t size)
76 {
77 unused(p);
78 return fota_patch_alloc(size);
79 }
80
lzma_free(ISzAllocPtr p,void * address)81 STATIC void lzma_free(ISzAllocPtr p, void *address)
82 {
83 unused(p);
84 fota_patch_free(address);
85 }
86
fota_pkg_flash_read_image(patch * desc,uint32_t length,int32_t location,uint8_t * dest)87 STATIC errcode_t fota_pkg_flash_read_image(patch *desc, uint32_t length, int32_t location, uint8_t *dest)
88 {
89 if (desc->use_plain_text_cache) {
90 /* Read from the plain text cache. */
91 uint8_t *src = NULL;
92
93 if (desc->image_cache == NULL) {
94 return ERRCODE_FAIL;
95 }
96 src = desc->image_cache + location;
97 /* This will panic if it fails so no need to check the return value. */
98 (void)memcpy_s(dest, length, src, length);
99 } else {
100 errcode_t ret = ERRCODE_SUCC;
101 ret = upg_read_old_image_data((uint32_t)location, dest, &length, desc->image_id);
102 if (ret != ERRCODE_SUCC) {
103 upg_log_err("[UPG] fota_pkg_flash_read_image read flash error. ret = 0x%x\r\n", ret);
104 return ret;
105 }
106 }
107 return ERRCODE_SUCC;
108 }
109
fota_pkg_flash_prep_page_contents_for_write(patch * desc,uint32_t image_page_no,uint8_t * page_contents)110 STATIC errcode_t fota_pkg_flash_prep_page_contents_for_write(patch *desc, uint32_t image_page_no,
111 uint8_t *page_contents)
112 {
113 errcode_t ret = ERRCODE_SUCC;
114 uint8_t *dest = NULL;
115
116 if (desc->use_plain_text_cache) {
117 /* Update the plaintext cache. */
118 if (desc->image_cache == NULL) {
119 return ERRCODE_FAIL;
120 }
121 dest = desc->image_cache + image_page_no * UPG_FLASH_PAGE_SIZE;
122 /* This will panic if it fails so no need to check the return value. */
123 (void)memcpy_s(dest, UPG_FLASH_PAGE_SIZE, page_contents, UPG_FLASH_PAGE_SIZE);
124 }
125
126 return ret;
127 }
128
fota_pkg_plaintext_flash_cache_init(patch * desc)129 STATIC errcode_t fota_pkg_plaintext_flash_cache_init(patch *desc)
130 {
131 errcode_t ret = ERRCODE_SUCC;
132
133 if (!desc->use_plain_text_cache) {
134 return ret;
135 }
136
137 /* 以下为加解密时使用 */
138 uint32_t image_len = desc->image_flash_length;
139 upg_log_info("[UPG] cache_init: flash_offset = 0x%x, len = 0x%x\r\n", desc->image_flash_offset, image_len);
140
141 desc->image_cache = (uint8_t*)upg_malloc(image_len);
142 upg_log_info("[UPG] cache_init: desc->image_cache = 0x%x\r\n", (uint32_t)(uintptr_t)desc->image_cache);
143 if (desc->image_cache == NULL) {
144 upg_log_err("[UPG] cache_init: malloc failure\r\n");
145 return ERRCODE_MALLOC;
146 }
147
148 /* Cache the Plain Text region. */
149 uint8_t *dst_addr = desc->image_cache;
150 uint32_t src_offset = desc->image_flash_offset;
151 ret = upg_read_old_image_data(src_offset, dst_addr, &image_len, desc->image_id);
152
153 return ret;
154 }
155
read_diff_data_from_ram(const uint8_t * addr,uint8_t * data,uint32_t length)156 STATIC bool read_diff_data_from_ram(const uint8_t *addr, uint8_t *data, uint32_t length)
157 {
158 size_t copy_size = length;
159 /* This will panic if it fails so no need to check the return value. */
160 (void)memcpy_s(data, length, addr, copy_size);
161 return true;
162 }
163
read_diff_data_to_ram(uint32_t offsets,uint8_t * data,uint32_t length,patch_state_t * state)164 STATIC bool read_diff_data_to_ram(uint32_t offsets, uint8_t *data, uint32_t length, patch_state_t *state)
165 {
166 uint32_t read_len = length;
167 bool success = true;
168
169 memset_s(data, DECOMPRESSION_SIZE, 0, DECOMPRESSION_SIZE);
170 if (state->desc->patch_contents_ram_copy != 0) {
171 success = read_diff_data_from_ram((uint8_t *)(uintptr_t)(state->desc->patch_contents_ram_copy + offsets),
172 data, read_len);
173 } else {
174 if (upg_read_fota_pkg_data((uint32_t)state->desc->patch_contents_flash_offset + offsets,
175 (uint8_t *)data, &read_len) != ERRCODE_SUCC) {
176 success = false;
177 }
178 }
179 if (!success) {
180 upg_log_err("[UPG] read diff to ram error");
181 return false;
182 }
183
184 return true;
185 }
186
zip_init_helper(zip_context_t * z,patch_state_t * state)187 STATIC errcode_t zip_init_helper(zip_context_t *z, patch_state_t *state)
188 {
189 SRes sres;
190 bool success;
191 uint32_t i;
192 uint8_t cdata[LZMA_PROPS_SIZE + HN_LZMA_SIZEOF_IMGSIZE];
193
194 /* Configure compressed patch data pointer and copy routine */
195 z->cdata = (unsigned char *)fota_patch_alloc(DECOMPRESSION_SIZE);
196 if (z->cdata == NULL) {
197 state->err_code = ERRCODE_MALLOC;
198 upg_log_err("[UPG] z->cdata alloc failure, err_code = 0x%x\r\n", state->err_code);
199 return state->err_code;
200 }
201 read_diff_data_to_ram(0, z->cdata, DECOMPRESSION_SIZE, state);
202
203 /* Decode the properties from the header */
204 success = read_diff_data_from_ram(z->cdata, cdata, LZMA_PROPS_SIZE + HN_LZMA_SIZEOF_IMGSIZE);
205 if (!success) {
206 state->err_code = ERRCODE_FAIL;
207 fota_patch_free(z->cdata);
208 upg_log_err("[UPG] zip_init_helper Decode the properties from the header false!");
209 return state->err_code;
210 }
211
212 sres = LzmaDec_Allocate(z->dec, cdata, LZMA_PROPS_SIZE, &state->lzma_alloc);
213 if (sres != SZ_OK) {
214 state->err_code = ERRCODE_FAIL;
215 fota_patch_free(z->cdata);
216 upg_log_err("[UPG] zip_init_helper LzmaDec_Allocate is false!");
217 return state->err_code;
218 }
219 LzmaDec_Init(z->dec);
220 z->offset = LZMA_PROPS_SIZE;
221 z->cdata_len = state->desc->patch_contents_len - (LZMA_PROPS_SIZE + HN_LZMA_SIZEOF_IMGSIZE);
222 z->unpacked_len = 0;
223 for (i = 0; i < HN_LZMA_SIZEOF_IMGSIZE; i++) {
224 z->unpacked_len += ((uint32_t)(cdata[(uint32_t)z->offset + i])) << (i * NUM_BITS_PER_BYTE);
225 }
226 z->unpacked_so_far = 0;
227 z->offset += HN_LZMA_SIZEOF_IMGSIZE;
228 return ERRCODE_SUCC;
229 }
230
zip_init(patch_state_t * state)231 STATIC zip_context_t *zip_init(patch_state_t *state)
232 {
233 errcode_t ret;
234 zip_context_t *z = fota_patch_alloc(sizeof(zip_context_t));
235 if (z == NULL) {
236 state->err_code = ERRCODE_MALLOC;
237 upg_log_err("[UPG] zip_init z alloc failure, err_code = 0x%x\r\n", state->err_code);
238 return z;
239 }
240
241 z->dec = fota_patch_alloc(sizeof(CLzmaDec));
242 if (z->dec == NULL) {
243 state->err_code = ERRCODE_MALLOC;
244 fota_patch_free(z);
245 z = NULL;
246 upg_log_err("[UPG] zip_init z->dec alloc failure, err_code = 0x%x\r\n", state->err_code);
247 return z;
248 }
249 LzmaDec_Construct(z->dec);
250 /* LZMA is absolute trash. Required to prevent a segfault */
251 z->dec->probs = NULL;
252
253 ret = zip_init_helper(z, state);
254 if (ret != ERRCODE_SUCC) {
255 fota_patch_free(z->dec);
256 fota_patch_free(z);
257 z = NULL;
258 }
259 return z;
260 }
261
zip_mem_read(patch_state_t * state,int32_t * error,zip_context_t * z,unsigned char * dest,int32_t len)262 STATIC int32_t zip_mem_read(patch_state_t *state, int32_t *error, zip_context_t *z, unsigned char *dest, int32_t len)
263 {
264 SizeT src_len, dest_len;
265 dest_len = (SizeT)len;
266 uint32_t done_len = 0;
267
268 while (done_len != (uint32_t)len) {
269 src_len = uapi_min(state->desc->patch_contents_len - (uint32_t)(z->offset), DECOMPRESSION_SIZE);
270 if (!read_diff_data_to_ram((uint32_t)z->offset, (uint8_t *)z->cdata, (uint32_t)src_len, state)) {
271 state->err_code = ERRCODE_UPG_FILE_READ_FAIL;
272 upg_log_err("[UPG] LZMA zip_mem_read: read diff error, err_code = 0x%x\r\n", state->err_code);
273 return 0;
274 }
275
276 ELzmaStatus status = 0;
277 SRes ret;
278 ret = LzmaDec_DecodeToBuf(z->dec, dest + done_len, &dest_len, z->cdata, &src_len, LZMA_FINISH_ANY, &status);
279 if (ret != SZ_OK) {
280 state->err_code = (errcode_t)ret;
281 upg_log_err("[UPG] LZMA zip_mem_read: Decode error, err_code = 0x%x\r\n", state->err_code);
282 return 0;
283 }
284
285 z->offset += (int32_t)src_len;
286 *error = (status == LZMA_STATUS_NOT_FINISHED) ? Z_OK : ZIP_STREAM_END;
287 z->unpacked_so_far += dest_len;
288 done_len += dest_len;
289 dest_len = (uint32_t)len - done_len;
290
291 if (status == LZMA_STATUS_FINISHED_WITH_MARK) {
292 break;
293 }
294 }
295
296 return (int32_t)done_len;
297 }
298
zip_end(patch_state_t * state,zip_context_t * z)299 STATIC void zip_end(patch_state_t *state, zip_context_t *z)
300 {
301 LzmaDec_Free(z->dec, &state->lzma_alloc);
302 fota_patch_free(z->cdata);
303 fota_patch_free(z->dec);
304 fota_patch_free(z);
305 }
306
read_image_block(patch_state_t * state,uint32_t size,int32_t location,uint8_t * dest)307 STATIC void read_image_block(patch_state_t *state, uint32_t size, int32_t location, uint8_t *dest)
308 {
309 if (state->err_code != ERRCODE_SUCC) {
310 upg_log_err("[UPG] read_image_block state err_code = 0x%x\r\n", state->err_code);
311 /* Do not process anything if an error occurred */
312 return;
313 }
314
315 /* Perform flash reads of the image using injected function to handle any decryption required. */
316 state->err_code = fota_pkg_flash_read_image(state->desc, size, location, dest);
317 if (state->err_code != ERRCODE_SUCC) {
318 upg_log_err("[UPG] ERROR read_image_block, err_code = 0x%x\r\n", state->err_code);
319 return;
320 }
321 }
322
write_image_block(patch_state_t * state,uint32_t size,int32_t location,const uint8_t * source)323 void write_image_block(patch_state_t *state, uint32_t size, int32_t location, const uint8_t *source)
324 {
325 if (state->err_code != ERRCODE_SUCC) {
326 upg_log_err("[UPG] write_image_block state err_code = 0x%x\r\n", state->err_code);
327 /* Do not process anything if an error occurred */
328 return;
329 }
330
331 if (upg_write_new_image_data((uint32_t)location, (uint8_t *)source, &size, state->desc->image_id, true) !=
332 ERRCODE_SUCC) {
333 state->err_code = ERRCODE_FAIL;
334 upg_log_err("[UPG] write_image_block write err_code = 0x%x\r\n", state->err_code);
335 return;
336 }
337
338 upg_calculate_and_notify_process((uint32_t)(state->page_last_written + 1));
339 }
340
341 /*
342 * buffer file contains
343 * 1. a page of buffer_size
344 * 2. a set of bytes, one byte per page.
345 * **N.B.** in a real, flash-based implementation, these bits would have
346 * to be spaced out in accordance with the flash's access rules.
347 */
fota_buffers_has_contents(patch_state_t * state)348 STATIC bool fota_buffers_has_contents(patch_state_t *state)
349 {
350 fota_buffers_t *buffer = NULL;
351 uint32_t i;
352 bool buffers_set = true;
353 errcode_t ret;
354
355 if (state->err_code != ERRCODE_SUCC) {
356 upg_log_err("[UPG] fota_buffers_has_contents state err_code = 0x%x\r\n", state->err_code);
357 /* Do not process anything if an error occurred */
358 return buffers_set;
359 }
360 buffer = fota_patch_alloc(sizeof(fota_buffers_t));
361 if (buffer == NULL) {
362 state->err_code = ERRCODE_MALLOC;
363 upg_log_err("[UPG] fota_buffers_has_contents: cannot allocate read buffer, err_code = 0x%x\r\n",
364 state->err_code);
365 goto ret_free;
366 }
367
368 ret = upg_flash_read(state->desc->buffers_flash_offset, sizeof(fota_buffers_t), (uint8_t*)(uintptr_t)buffer);
369 if (ret != ERRCODE_SUCC) {
370 state->err_code = ret;
371 upg_log_err("[UPG] fota_buffers_has_contents: cannot read buffers, err_code = 0x%x\r\n", state->err_code);
372 goto ret_free;
373 }
374
375 for (i = 0; i < (sizeof(fota_buffers_t) / WORD_WIDTH); i++) {
376 if (*((uint32_t *)(uintptr_t)buffer + i) != 0xffffffff) {
377 /* The buffer was not erased */
378 upg_log_err("[UPG] fota_buffers_has_contents: buffers are not erased i = %d, val = 0x%x\r\n",
379 i, *(((uint32_t*)(uintptr_t)buffer) + i));
380 goto ret_free;
381 }
382 }
383 /* The buffer has been erased */
384 buffers_set = false;
385
386 ret_free:
387 fota_patch_free(buffer);
388 return buffers_set;
389 }
390
read_page_buffer(patch_state_t * state,uint8_t * dest)391 STATIC void read_page_buffer(patch_state_t *state, uint8_t *dest)
392 {
393 if (state->err_code != ERRCODE_SUCC) {
394 upg_log_err("[UPG] read_page_buffer state err_code = 0x%x\r\n", state->err_code);
395 /* Do not process anything if an error occurred */
396 return;
397 }
398
399 if (upg_flash_read(state->desc->buffers_flash_offset, UPG_FLASH_PAGE_SIZE, dest) != ERRCODE_SUCC) {
400 state->err_code = ERRCODE_FAIL;
401 upg_log_err("[UPG] read_page_buffer: cannot read buffer, err_code = 0x%x\r\n", state->err_code);
402 return;
403 }
404 }
405
replace_page_buffer(patch_state_t * state,uint8_t * source)406 STATIC void replace_page_buffer(patch_state_t *state, uint8_t *source)
407 {
408 if (state->err_code != ERRCODE_SUCC) {
409 upg_log_err("[UPG] replace_page_buffer state err_code = 0x%x\r\n", state->err_code);
410 /* Do not process anything if an error occurred */
411 return;
412 }
413
414 if (upg_flash_write(state->desc->buffers_flash_offset, UPG_FLASH_PAGE_SIZE, source, true) != ERRCODE_SUCC) {
415 state->err_code = ERRCODE_FAIL;
416 upg_log_err("[UPG] replace_page_buffer: cannot write buffer, err_code = 0x%x\r\n", state->err_code);
417 return;
418 }
419 }
420
read_page_status(patch_state_t * state,int32_t page_no)421 STATIC uint8_t read_page_status(patch_state_t *state, int32_t page_no)
422 {
423 uint32_t val = 0;
424 uint32_t page_num = state->desc->image_flash_offset / UPG_FLASH_PAGE_SIZE + (uint32_t)page_no;
425 uint32_t offset =
426 state->desc->buffers_flash_offset + state->desc->buffers_length + ((uint32_t)sizeof(uint8_t) * page_num);
427
428 if (state->err_code != ERRCODE_SUCC) {
429 upg_log_err("[UPG] read_page_status state err_code = 0x%x\r\n", state->err_code);
430 /* Do not process anything if an error occurred */
431 return 0x00;
432 }
433
434 if (upg_flash_read(offset, sizeof(uint8_t), (uint8_t *)&val) != ERRCODE_SUCC) {
435 state->err_code = ERRCODE_FAIL;
436 upg_log_err("[UPG] read_page_status: cannot read status, err_code = 0x%x\r\n", state->err_code);
437 return 0x00;
438 }
439 return (uint8_t)val;
440 }
441
write_page_status(patch_state_t * state,int32_t page_no,uint8_t val)442 STATIC void write_page_status(patch_state_t *state, int32_t page_no, uint8_t val)
443 {
444 uint32_t page_num = state->desc->image_flash_offset / UPG_FLASH_PAGE_SIZE + (uint32_t)page_no;
445 uint32_t offset =
446 state->desc->buffers_flash_offset + state->desc->buffers_length + ((uint32_t)sizeof(val) * page_num);
447 uint32_t old = 0;
448
449 if (state->err_code != ERRCODE_SUCC) {
450 upg_log_err("[UPG] write_page_status state err_code = 0x%x\r\n", state->err_code);
451 /* Do not process anything if an error occurred */
452 return;
453 }
454
455 if (upg_flash_read(offset, sizeof(val), (uint8_t *)&old) != ERRCODE_SUCC) {
456 state->err_code = ERRCODE_FAIL;
457 upg_log_err("[UPG] write_page_status: cannot read old status, err_code = 0x%x\r\n", state->err_code);
458 return;
459 }
460 if ((val & ~((uint8_t)old)) != 0) {
461 upg_log_info("[UPG] write_page_status: Trying to set bits 0->1 at offset = 0x%x, with 0x%x -> 0x%x\r\n",
462 offset, (uint32_t)old, (uint32_t)val);
463 }
464 if (upg_flash_write(offset, sizeof(val), &val, false) != ERRCODE_SUCC) {
465 state->err_code = ERRCODE_FAIL;
466 upg_log_err("[UPG] write_page_status: cannot write status, err_code = 0x%x\r\n", state->err_code);
467 return;
468 }
469 }
470
erase_fota_buffers(patch_state_t * state)471 STATIC void erase_fota_buffers(patch_state_t *state)
472 {
473 if (state->err_code != ERRCODE_SUCC) {
474 upg_log_err("[UPG] erase_fota_buffers state err_code = 0x%x\r\n", state->err_code);
475 /* Do not process anything if an error occurred */
476 return;
477 }
478
479 if (upg_flash_erase(state->desc->buffers_flash_offset, state->desc->buffers_length) != ERRCODE_SUCC) {
480 state->err_code = ERRCODE_FAIL;
481 upg_log_err("[UPG] erase_fota_buffers: cannot erase the fota buffers, err_code = 0x%x\r\n",
482 state->err_code);
483 return;
484 }
485 }
486
erase_image_flash_page(patch_state_t * state,int32_t image_page)487 STATIC void erase_image_flash_page(patch_state_t *state, int32_t image_page)
488 {
489 if (state->err_code != ERRCODE_SUCC) {
490 upg_log_err("[UPG] erase_image_flash_page state err_code = 0x%x\r\n", state->err_code);
491 return;
492 }
493
494 errcode_t ret;
495 ret = upg_flash_erase(state->desc->image_flash_offset + (image_page * UPG_FLASH_PAGE_SIZE), UPG_FLASH_PAGE_SIZE);
496 if (ret != ERRCODE_SUCC) {
497 upg_log_err("[UPG] read_byte state err_code = 0x%x\r\n", state->err_code);
498 state->err_code = ERRCODE_FAIL;
499 return;
500 }
501 }
502
503 /*
504 * In applying an in-place patch, the flash writes get applied a page at a time.
505 * Sometimes the page gets written to more than once. In fact, an individual page can get
506 * written to up to 3 times. (Ok, there may be several updates within a page. But there
507 * will only be a maximum of 3 writes.
508 *
509 * here's a page:
510 * d d d d d d d d d d d d d d d d d d d
511
512 * here's the 3 types of write operations, a b and c
513 * a5 a4 a3 a2 a1 b1 b2 b3 b4 b5 b6 b7 b8 b9 c4 c3 c2 c2 c1
514 * (<--------) <----------a b---->----->->----------> <-----------c (<--------)
515 *
516 * so this function page_write_type() spots these different operations based on the first and
517 * last value used.
518 */
page_write_type(const patch_state_t * state,int32_t first,int32_t last)519 STATIC unsigned char page_write_type(const patch_state_t *state, int32_t first, int32_t last)
520 {
521 if (state->err_code != ERRCODE_SUCC) {
522 upg_log_err("[UPG] page_write_type state err_code = 0x%x\r\n", state->err_code);
523 /* Do not process anything if an error occurred */
524 return 0xff;
525 }
526
527 const int32_t limit = UPG_FLASH_PAGE_SIZE - 1;
528 if (((first == 0) && (last == limit)) || ((first == limit) && (last == 0))) {
529 /* it's a full page. */
530 upg_log_info("[UPG] STANDARD A\r\n");
531 return PAGE_WRITE_STANDARD;
532 }
533
534 if ((first > 0) && (first < limit) && (last > 0) && (last < limit)) {
535 /* it's a section from the middle */
536 upg_log_info("[UPG] STANDARD B\r\n");
537 return PAGE_WRITE_STANDARD;
538 }
539
540 if ((first == 0) || (last == 0)) {
541 upg_log_info("[UPG] PARTIAL_START\r\n");
542 return PAGE_WRITE_PARTIAL_START;
543 }
544 return PAGE_WRITE_PARTIAL_END;
545 }
546
write_flash_page_skip_done(patch_state_t * state)547 STATIC void write_flash_page_skip_done(patch_state_t *state)
548 {
549 if (state == NULL || state->err_code != ERRCODE_SUCC || state->desc == NULL) {
550 upg_log_err("[UPG] write_flash_page_skip_done state error");
551 /* Do not process anything if an error occurred */
552 return;
553 }
554
555 if (state->local_buffer_page != -1) {
556 const int32_t r = read_page_status(state, state->local_buffer_page);
557 const int32_t t = page_write_type(state, state->page_first_written, state->page_last_written);
558 if (((uint32_t)r & (uint32_t)t) == 0) {
559 upg_calculate_and_notify_process(UPG_FLASH_PAGE_SIZE);
560
561 upg_log_info("[UPG] Skipping! page = 0x%x\r\n", (uint32_t)state->local_buffer_page);
562 upg_log_info("[UPG] type = 0x%x permitted = 0x%x (first = 0x%x last = 0x%x)\r\n",
563 (uint32_t)t, (uint32_t)r, (uint32_t)state->page_first_written, (uint32_t)state->page_last_written);
564 if (state->done_skipping) {
565 upg_log_err("[UPG] Corrupt flash! We have written valid pages, but now we're back to skipping!");
566 }
567 } else if (((uint32_t)r & ((uint32_t)t >> 1)) == 0) {
568 /* So this means the W bit for the operation was set, but B was cleared. We should never be */
569 /* in this state; the recovery operation should mark this as completed. */
570 upg_log_err("[UPG] Corrupt flash!Page write bits are not as expected.page = 0x%x, status = 0x%x\r\n",
571 (uint32_t)state->local_buffer_page, (uint32_t)read_page_status(state, state->local_buffer_page));
572 } else {
573 const uint32_t unsigned_t = (uint32_t) t;
574 const uint32_t unsigned_r = (uint32_t) r;
575 const uint32_t val = unsigned_r & ~(unsigned_t>>1);
576 /* Prepare the image page contents for writing performing any encryption necessary. */
577 /* Any error returned put into the state err_code to be handled. */
578 state->err_code = fota_pkg_flash_prep_page_contents_for_write(state->desc,
579 (uint32_t)state->local_buffer_page,
580 state->local_buffer);
581 state->done_skipping = 1;
582 replace_page_buffer(state, state->local_buffer);
583 /* mark the bits to show the buffer is good. (Clear B) */
584
585 write_page_status(state, state->local_buffer_page, (uint8_t)val);
586
587 /* write the whole UPG_FLASH_PAGE_SIZE block */
588 write_image_block(state, UPG_FLASH_PAGE_SIZE,
589 state->local_buffer_page * UPG_FLASH_PAGE_SIZE, state->local_buffer);
590 if (state->err_code == ERRCODE_SUCC) {
591 /* mark the bits to show it's written. (Clear W (and B)) */
592 write_page_status(state, state->local_buffer_page,
593 (uint8_t)(unsigned_r & ~(unsigned_t | (unsigned_t >> 1))));
594 }
595 }
596 }
597 }
598
599 /*
600 * Note, in order to do the recovery thing, write_byte will SKIP those pages that
601 * have already been written, in an 'restartable' manner
602 * to permit recovery from an incomplete update operation.
603 */
write_byte(patch_state_t * state,int32_t dest_offset,unsigned char val)604 STATIC void write_byte(patch_state_t *state, int32_t dest_offset, unsigned char val)
605 {
606 int32_t dest_offset_page;
607 if (state->err_code != ERRCODE_SUCC) {
608 upg_log_err("[UPG] write_byte state err_code = 0x%x\r\n", state->err_code);
609 /* Do not process anything if an error occurred */
610 return;
611 }
612
613 dest_offset_page = dest_offset / UPG_FLASH_PAGE_SIZE;
614 if (dest_offset_page != state->local_buffer_page) {
615 /* write back the old page */
616 write_flash_page_skip_done(state);
617 /* check to see if we have a page to write back, AND if we have written this already. */
618 /* now populate state->local_buffer with the next page's values. */
619 read_image_block(state, UPG_FLASH_PAGE_SIZE, dest_offset_page * UPG_FLASH_PAGE_SIZE, state->local_buffer);
620 state->local_buffer_page = dest_offset_page;
621 state->page_first_written = dest_offset % UPG_FLASH_PAGE_SIZE;
622 }
623 state->local_buffer[dest_offset % UPG_FLASH_PAGE_SIZE] = val;
624 state->page_last_written = dest_offset % UPG_FLASH_PAGE_SIZE;
625 }
626
read_byte(patch_state_t * state,int32_t dest_offset)627 STATIC unsigned char read_byte(patch_state_t *state, int32_t dest_offset)
628 {
629 int32_t dest_offset_page;
630
631 if (state->err_code != ERRCODE_SUCC) {
632 upg_log_err("[UPG] read_byte state err_code = 0x%x\r\n", state->err_code);
633 /* Do not process anything if an error occurred */
634 return 0xff;
635 }
636
637 dest_offset_page = dest_offset / UPG_FLASH_PAGE_SIZE;
638 if (dest_offset_page == state->local_buffer_page) {
639 return state->local_buffer[dest_offset % UPG_FLASH_PAGE_SIZE];
640 } else {
641 uint32_t b = 0;
642 read_image_block(state, 1, dest_offset, (uint8_t *)&b);
643 return (uint8_t)b;
644 }
645 }
646
647
finish_write(patch_state_t * state)648 STATIC void finish_write(patch_state_t *state)
649 {
650 if (state->err_code != ERRCODE_SUCC) {
651 upg_log_err("[UPG] finish_write state err_code = 0x%x\r\n", state->err_code);
652 /* Do not process anything if an error occurred */
653 return;
654 }
655
656 write_flash_page_skip_done(state);
657 state->local_buffer_page = -1;
658 }
659
660 /**
661 * @brief Sanity check the diff after obtaining a control block.
662 *
663 * @param aps apply_patch(...) function state.
664 * @param state fota patching state.
665 * @return true if processing should proceed with this control block or false if processing should stop.
666 */
apply_patch_get_control_block_sanity_check(const apply_patch_state_t * aps,patch_state_t * state)667 STATIC bool apply_patch_get_control_block_sanity_check(const apply_patch_state_t *aps, patch_state_t *state)
668 {
669 if (aps->newpos + aps->cb.copy > (uint32_t)(state->desc->newsize)) {
670 state->err_code = ERRCODE_UPG_CHECK_FOTA_ERROR;
671 upg_log_err("[UPG] Corrupt patch 4, err_code = 0x%x\r\n", state->err_code);
672 return false;
673 }
674 if (aps->oldpos + aps->cb.copy > (uint32_t)(state->desc->maxsize)) {
675 state->err_code = ERRCODE_UPG_CHECK_FOTA_ERROR;
676 upg_log_err("[UPG] Corrupt patch 4a, err_code = 0x%x\r\n", state->err_code);
677 return false;
678 }
679 #if (UPG_CFG_DEBUG_PRINT_ENABLED == YES)
680 if (state->desc->bottom_up) {
681 if (aps->newpos <= aps->oldpos) {
682 upg_log_info("[UPG] NCkA\r\n");
683 } else {
684 upg_log_info("[UPG] RCkB\r\n");
685 }
686 } else {
687 if (aps->newpos <= aps->oldpos) {
688 upg_log_info("[UPG] NCkC\r\n");
689 } else {
690 upg_log_info("[UPG] RCkD\r\n");
691 }
692 }
693 #endif
694 return true;
695 }
696
697 /**
698 * @brief Fetch the control block from the diff.
699 *
700 * @param aps apply_patch(...) function state.
701 * @param state fota patching state.
702 * @return true if processing should proceed with this control block or false if processing should stop.
703 */
apply_patch_get_control_block(apply_patch_state_t * aps,patch_state_t * state)704 STATIC bool apply_patch_get_control_block(apply_patch_state_t *aps, patch_state_t *state)
705 {
706 /* Read control data */
707 aps->lenread =
708 (uint32_t)zip_mem_read(state, &(aps->cerror), aps->zcontext, (unsigned char *)&(aps->cb), sizeof(aps->cb));
709 if ((aps->lenread < sizeof(aps->cb)) || ((aps->cerror != Z_OK) && (aps->cerror != ZIP_STREAM_END))) {
710 state->err_code = ERRCODE_UPG_CHECK_FOTA_ERROR;
711 upg_log_err("[UPG] Corrupt patch 3a (data exhausted), err_code = 0x%x\r\n", state->err_code);
712 return false;
713 }
714 if (memcmp((unsigned char *)&(aps->cb), PATCH_KNVD_STR, PATCH_KNVD_STR_LEN) != 0) {
715 state->err_code = ERRCODE_UPG_CHECK_FOTA_ERROR;
716 upg_log_err("[UPG] Corrupt patch 3b (not magic number), err_code = 0x%x\r\n", state->err_code);
717 return false;
718 }
719 aps->blockcount++;
720
721 /* Sanity-check */
722 return apply_patch_get_control_block_sanity_check(aps, state);
723 }
724
725 /**
726 * @brief Apply a delta chunk for a bottom up patch
727 *
728 * @param aps apply_patch(...) function state.
729 * @param state fota patching state.
730 */
apply_patch_delta_chunk_bottom_up(apply_patch_state_t * aps,patch_state_t * state)731 STATIC void apply_patch_delta_chunk_bottom_up(apply_patch_state_t *aps, patch_state_t *state)
732 {
733 int32_t newsize = state->desc->newsize;
734 int32_t chunk_offset;
735 int32_t rpos;
736 int32_t wpos;
737
738 if (aps->newpos <= aps->oldpos) {
739 for (chunk_offset = 0; (chunk_offset < aps->chunk_size) && (state->err_code == ERRCODE_SUCC);
740 chunk_offset++) {
741 rpos = newsize - 1 - (aps->oldpos + chunk_offset + aps->chunk_start);
742 wpos = newsize - 1 - (aps->newpos + chunk_offset + aps->chunk_start);
743 write_byte(state, wpos, read_byte(state, rpos) + aps->unpackedbuf[chunk_offset]);
744 }
745 } else {
746 for (chunk_offset = 0; (chunk_offset < aps->chunk_size) && (state->err_code == ERRCODE_SUCC);
747 chunk_offset++) {
748 rpos = newsize - 1 - (aps->oldpos + ((int32_t)aps->cb.copy - 1 - (chunk_offset + aps->chunk_start)));
749 wpos = newsize - 1 - (aps->newpos + ((int32_t)aps->cb.copy - 1 - (chunk_offset + aps->chunk_start)));
750 write_byte(state, wpos, read_byte(state, rpos) + aps->unpackedbuf[chunk_offset]);
751 }
752 }
753 }
754
755 /**
756 * @brief Apply a delta chunk for a top down patch
757 *
758 * @param aps apply_patch(...) function state.
759 * @param state fota patching state.
760 */
apply_patch_delta_chunk_top_down(apply_patch_state_t * aps,patch_state_t * state)761 STATIC void apply_patch_delta_chunk_top_down(apply_patch_state_t *aps, patch_state_t *state)
762 {
763 int32_t chunk_offset;
764 int32_t rpos;
765 int32_t wpos;
766
767 if (aps->newpos <= aps->oldpos) {
768 for (chunk_offset = 0; (chunk_offset < aps->chunk_size) && (state->err_code == ERRCODE_SUCC);
769 chunk_offset++) {
770 rpos = aps->oldpos + chunk_offset + aps->chunk_start;
771 wpos = aps->newpos + chunk_offset + aps->chunk_start;
772 write_byte(state, wpos, read_byte(state, rpos) + aps->unpackedbuf[chunk_offset]);
773 }
774 } else {
775 for (chunk_offset = 0; (chunk_offset < aps->chunk_size) && (state->err_code == ERRCODE_SUCC);
776 chunk_offset++) {
777 rpos = aps->oldpos + ((int32_t)aps->cb.copy - 1 - (chunk_offset + aps->chunk_start));
778 wpos = aps->newpos + ((int32_t)aps->cb.copy - 1 - (chunk_offset + aps->chunk_start));
779 write_byte(state, wpos, read_byte(state, rpos) + aps->unpackedbuf[chunk_offset]);
780 }
781 }
782 }
783
784 /**
785 * @brief Process the code deltas within the diff for a section of the image.
786 *
787 * @param aps apply_patch(...) function state.
788 * @param state fota patching state.
789 * @return true if processing should be continue onto the next chunk or false if processing should stop.
790 */
apply_patch_delta_chunk(apply_patch_state_t * aps,patch_state_t * state,int32_t * cctotal)791 STATIC bool apply_patch_delta_chunk(apply_patch_state_t *aps, patch_state_t *state, int32_t *cctotal)
792 {
793 aps->chunk_size = uapi_min((int32_t)DECOMPRESSION_SIZE, (int32_t)aps->cb.copy - aps->chunk_start);
794 *cctotal += aps->chunk_size;
795
796 aps->unpackedbuf = fota_patch_alloc((uint32_t)aps->chunk_size);
797 if (aps->unpackedbuf == NULL) {
798 state->err_code = ERRCODE_MALLOC;
799 upg_log_err("[UPG] malloc failure, err_code = 0x%x\r\n", state->err_code);
800 /* Exit loop to immediately handle the error */
801 return false;
802 }
803
804 aps->lenread = (uint32_t)zip_mem_read(state, (int32_t *)&(aps->cerror), aps->zcontext, aps->unpackedbuf,
805 aps->chunk_size);
806 if (((int32_t)aps->lenread < aps->chunk_size) ||
807 ((aps->cerror != Z_OK) && (aps->cerror != ZIP_STREAM_END))) {
808 state->err_code = ERRCODE_UPG_CHECK_FOTA_ERROR;
809 fota_patch_free(aps->unpackedbuf);
810 aps->unpackedbuf = NULL;
811 upg_log_err("[UPG] Corrupt patch 5 (data exhausted), err_code = 0x%x\r\n", state->err_code);
812 /* Exit loop to immediately handle the error */
813 return false;
814 }
815
816 /* add diff data to previous data. It's IN PLACE!!!!! */
817 if (state->desc->bottom_up) {
818 apply_patch_delta_chunk_bottom_up(aps, state);
819 } else {
820 apply_patch_delta_chunk_top_down(aps, state);
821 }
822
823 /* Free any previously allocated memory */
824 fota_patch_free(aps->unpackedbuf);
825 aps->unpackedbuf = NULL;
826 upg_watchdog_kick();
827
828 return true;
829 }
830
831
832 /**
833 * @brief Process the code deltas within the diff for a section of code.
834 *
835 * @param aps apply_patch(...) function state.
836 * @param state fota patching state.
837 * @return true if processing should be continued or false if processing should stop.
838 */
apply_patch_deltas(apply_patch_state_t * aps,patch_state_t * state)839 STATIC bool apply_patch_deltas(apply_patch_state_t *aps, patch_state_t *state)
840 {
841 int32_t cctotal = 0;
842
843 for (aps->chunk_start = 0; (aps->chunk_start < (int32_t)(aps->cb.copy)) && (state->err_code == ERRCODE_SUCC);
844 aps->chunk_start += (int32_t)DECOMPRESSION_SIZE) {
845 if (!apply_patch_delta_chunk(aps, state, &cctotal)) {
846 break;
847 }
848 }
849 /* Ensure that any allocated memory has been freed even if there has been an error */
850 fota_patch_free(aps->unpackedbuf);
851 aps->unpackedbuf = NULL;
852 /* return if there has been an error */
853 if (state->err_code != ERRCODE_SUCC) {
854 upg_log_err("[UPG] apply_patch b state err_code = 0x%x\r\n", state->err_code);
855 return false;
856 }
857 /* Adjust pointers */
858 aps->newpos += (int32_t)aps->cb.copy;
859 aps->oldpos += (int32_t)aps->cb.copy;
860
861 /* Sanity-check */
862 if ((aps->newpos + (int32_t)aps->cb.extra) > state->desc->newsize) {
863 state->err_code = ERRCODE_UPG_CHECK_FOTA_ERROR;
864 upg_log_err("[UPG] Corrupt patch 6, err_code = 0x%x\r\n", state->err_code);
865 return false;
866 }
867
868 return true;
869 }
870
871 /**
872 * @brief Apply an extra chunk for a bottom up patch
873 *
874 * @param aps apply_patch(...) function state.
875 * @param state fota patching state.
876 */
apply_patch_extra_chunk_bottom_up(apply_patch_state_t * aps,patch_state_t * state)877 STATIC void apply_patch_extra_chunk_bottom_up(apply_patch_state_t *aps, patch_state_t *state)
878 {
879 int32_t newsize = state->desc->newsize;
880 int32_t chunk_offset;
881 int32_t wpos;
882
883 for (chunk_offset = 0; (chunk_offset < aps->chunk_size) && (state->err_code == ERRCODE_SUCC);
884 chunk_offset++) {
885 wpos = newsize - 1 - (aps->newpos + chunk_offset + aps->chunk_start);
886 write_byte(state, wpos, aps->unpackedbuf[chunk_offset]);
887 }
888 }
889
890 /**
891 * @brief Apply an extra chunk for a top down patch
892 *
893 * @param aps apply_patch(...) function state.
894 * @param state fota patching state.
895 */
apply_patch_extra_chunk_top_down(apply_patch_state_t * aps,patch_state_t * state)896 STATIC void apply_patch_extra_chunk_top_down(apply_patch_state_t *aps, patch_state_t *state)
897 {
898 int32_t chunk_offset;
899 int32_t wpos;
900
901 for (chunk_offset = 0; (chunk_offset < aps->chunk_size) && (state->err_code == ERRCODE_SUCC);
902 chunk_offset++) {
903 wpos = aps->newpos + chunk_offset + aps->chunk_start;
904 write_byte(state, wpos, aps->unpackedbuf[chunk_offset]);
905 }
906 }
907
908 /**
909 * @brief Process the code extras within the diff for a section of code.
910 *
911 * @param aps apply_patch(...) function state.
912 * @param state fota patching state.
913 * @return true if processing should be continued or false if processing should stop.
914 */
apply_patch_extra_chunk(apply_patch_state_t * aps,patch_state_t * state)915 STATIC bool apply_patch_extra_chunk(apply_patch_state_t *aps, patch_state_t *state)
916 {
917 aps->chunk_size = uapi_min((int32_t)DECOMPRESSION_SIZE, (int32_t)aps->cb.extra - aps->chunk_start);
918
919 aps->unpackedbuf = fota_patch_alloc((uint32_t)aps->chunk_size);
920 if (aps->unpackedbuf == NULL) {
921 state->err_code = ERRCODE_MALLOC;
922 upg_log_err("[UPG] malloc failure, err_code = 0x%x\r\n", state->err_code);
923 return false;
924 }
925
926 aps->lenread = (uint32_t)zip_mem_read(state, &(aps->cerror), aps->zcontext, aps->unpackedbuf, aps->chunk_size);
927 if ((int32_t)aps->lenread < aps->chunk_size) {
928 state->err_code = ERRCODE_UPG_CHECK_FOTA_ERROR;
929 fota_patch_free(aps->unpackedbuf);
930 aps->unpackedbuf = NULL;
931 upg_log_err("[UPG] Corrupt patch 7a (data exhausted), err_code = 0x%x\r\n", state->err_code);
932 return false;
933 }
934 if (((aps->cerror != Z_OK) && (aps->cerror != ZIP_STREAM_END))) {
935 state->err_code = ERRCODE_UPG_CHECK_FOTA_ERROR;
936 upg_log_err("[UPG] Corrupt patch 7, returned(data corrupted) = 0x%x, err_code = 0x%x\r\n",
937 (uint32_t)aps->cerror, state->err_code);
938 }
939 if (state->desc->bottom_up) {
940 apply_patch_extra_chunk_bottom_up(aps, state);
941 } else {
942 apply_patch_extra_chunk_top_down(aps, state);
943 }
944 fota_patch_free(aps->unpackedbuf);
945 aps->unpackedbuf = NULL;
946
947 return true;
948 }
949
950 /**
951 * @brief Process the code extras within the diff for a section of code.
952 *
953 * @param aps apply_patch(...) function state.
954 * @param state fota patching state.
955 * @return true if processing should be continued or false if processing should stop.
956 */
apply_patch_extras(apply_patch_state_t * aps,patch_state_t * state)957 STATIC bool apply_patch_extras(apply_patch_state_t *aps, patch_state_t *state)
958 {
959 for (aps->chunk_start = 0; (aps->chunk_start < (int32_t)(aps->cb.extra)) && (state->err_code == ERRCODE_SUCC);
960 aps->chunk_start += (int32_t)DECOMPRESSION_SIZE) {
961 if (!apply_patch_extra_chunk(aps, state)) {
962 break;
963 }
964 }
965 /* Ensure that any allocated memory has been freed even if there has been an error */
966 fota_patch_free(aps->unpackedbuf);
967 aps->unpackedbuf = NULL;
968
969 /* return if there has been an error */
970 if (state->err_code != ERRCODE_SUCC) {
971 upg_log_err("[UPG] apply_patch c state err_code = 0x%x\r\n", state->err_code);
972 return false;
973 }
974 /* Adjust pointers */
975 aps->newpos += (int32_t)aps->cb.extra;
976 aps->oldpos += aps->cb.seek;
977
978 /* more sanity */
979 if (aps->newpos > state->desc->newsize) {
980 state->err_code = ERRCODE_UPG_CHECK_FOTA_ERROR;
981 upg_log_err("[UPG] Corrupt patch 8 (overran destination), err_code = 0x%x\r\n", state->err_code);
982 return false;
983 }
984 if (aps->oldpos >= (state->desc->maxsize)) {
985 state->err_code = ERRCODE_UPG_CHECK_FOTA_ERROR;
986 upg_log_err("[UPG] Corrupt patch 9 (overran source), err_code = 0x%x\r\n", state->err_code);
987 return false;
988 }
989
990 return true;
991 }
992
apply_patch(patch_state_t * state)993 STATIC void apply_patch(patch_state_t *state)
994 {
995 apply_patch_state_t aps;
996
997 if (state == NULL || state->err_code != ERRCODE_SUCC || state->desc == NULL) {
998 upg_log_err("[UPG] apply_patch state error");
999 /* Do not process anything if an error occurred */
1000 return;
1001 }
1002
1003 aps.zcontext = zip_init(state);
1004 if ((aps.zcontext == NULL) || (state->err_code != ERRCODE_SUCC)) {
1005 upg_log_err("[UPG] aps.zcontext init state err_code = 0x%x\r\n", state->err_code);
1006 return;
1007 }
1008 aps.oldpos = 0;
1009 aps.newpos = 0;
1010 aps.blockcount = 0;
1011 aps.unpackedbuf = NULL;
1012
1013 /* main patching loop */
1014 while ((aps.newpos < state->desc->newsize) && (state->err_code == ERRCODE_SUCC)) {
1015 /* Get the next control block */
1016 if (!apply_patch_get_control_block(&aps, state)) {
1017 break;
1018 }
1019
1020 /* Apply diff deltas */
1021 if (!apply_patch_deltas(&aps, state)) {
1022 break;
1023 }
1024
1025 /* Read extra string */
1026 if (!apply_patch_extras(&aps, state)) {
1027 break;
1028 }
1029 };
1030 /* complete the write */
1031 finish_write(state);
1032 /* Ensure that any allocated memory has been freed even if there has been an error */
1033 fota_patch_free(aps.unpackedbuf);
1034 if (aps.zcontext != NULL) {
1035 /* Clean up the compressed reads */
1036 zip_end(state, aps.zcontext);
1037 }
1038 }
1039
erase_redundant_pages(patch_state_t * state)1040 STATIC void erase_redundant_pages(patch_state_t *state)
1041 {
1042 /* Erase any old image pages if new image is smaller */
1043 uint32_t num_old_pages = state->desc->num_old_pages;
1044 uint32_t num_new_pages = state->desc->num_new_pages;
1045 if (num_old_pages > num_new_pages) {
1046 for (uint32_t page = num_new_pages; page < num_old_pages; page++) {
1047 erase_image_flash_page(state, (int32_t)page);
1048 }
1049 }
1050 }
1051
process_patch_init(patch_state_t * state,patch * desc,process_patch_state_t * pps)1052 STATIC void process_patch_init(patch_state_t *state, patch *desc, process_patch_state_t *pps)
1053 {
1054 state->desc = desc;
1055 state->lzma_alloc.Alloc = lzma_malloc;
1056 state->lzma_alloc.Free = lzma_free;
1057 state->local_buffer = fota_patch_alloc(UPG_FLASH_PAGE_SIZE);
1058 if (state->local_buffer == NULL) {
1059 upg_log_err("[UPG] local_buffer malloc error");
1060 state->err_code = ERRCODE_MALLOC;
1061 } else {
1062 state->err_code = ERRCODE_SUCC;
1063 }
1064 state->local_buffer_page = -1;
1065 state->page_first_written = -1;
1066 state->page_last_written = -1;
1067 state->done_skipping = false;
1068
1069 pps->recovery_buffer = NULL;
1070 pps->recovery_found = false;
1071 #if (UPG_CFG_DEBUG_PRINT_ENABLED == YES)
1072 upg_log_info("[UPG] Starting patching process\r\n");
1073 upg_log_info("[UPG] desc->bottom_up = 0x%x\r\n", (uint32_t)desc->bottom_up);
1074 upg_log_info("[UPG] desc->buffers_flash_offset = 0x%x\r\n", desc->buffers_flash_offset);
1075 upg_log_info("[UPG] desc->buffers_length = 0x%x\r\n", desc->buffers_length);
1076 upg_log_info("[UPG] desc->failpoint = 0x%x\r\n", (uint32_t)desc->failpoint);
1077 upg_log_info("[UPG] desc->image_flash_offset = 0x%x\r\n", desc->image_flash_offset);
1078 upg_log_info("[UPG] desc->maxsize = 0x%x\r\n", (uint32_t)desc->maxsize);
1079 upg_log_info("[UPG] desc->newsize = 0x%x\r\n", (uint32_t)desc->newsize);
1080 upg_log_info("[UPG] desc->oldsize = 0x%x\r\n", (uint32_t)desc->oldsize);
1081 upg_log_info("[UPG] desc->patch_contents_flash_offset = 0x%x\r\n", desc->patch_contents_flash_offset);
1082 upg_log_info("[UPG] desc->patch_contents_len = 0x%x\r\n", desc->patch_contents_len);
1083 #endif
1084 }
1085
process_patch_recover_page(patch_state_t * state,process_patch_state_t * pps,uint32_t page_no,int32_t page_status,int32_t status_bit)1086 STATIC void process_patch_recover_page(patch_state_t *state, process_patch_state_t *pps, uint32_t page_no,
1087 int32_t page_status, int32_t status_bit)
1088 {
1089 if (pps->recovery_found) {
1090 state->err_code = ERRCODE_FAIL;
1091 upg_log_err("[UPG] Corrupt flash recovery - we can't have more than one page in progress!!!\r\n");
1092 upg_log_err("[UPG] page = 0x%x, bit = 0x%x, err_code = 0x%x\r\n",
1093 page_no, (uint32_t)status_bit, state->err_code);
1094 return;
1095 }
1096 pps->recovery_buffer = fota_patch_alloc(UPG_FLASH_PAGE_SIZE);
1097 if (pps->recovery_buffer == NULL) {
1098 state->err_code = ERRCODE_MALLOC;
1099 upg_log_err("[UPG] err_code = 0x%x\r\n", state->err_code);
1100 return;
1101 }
1102 /* extract contents to recovery_buffer */
1103 read_page_buffer(state, pps->recovery_buffer);
1104 if (state->err_code != ERRCODE_SUCC) {
1105 upg_log_err("[UPG] process_patch read_page_buffer err_code = 0x%x\r\n", state->err_code);
1106 fota_patch_free(pps->recovery_buffer);
1107 pps->recovery_buffer = NULL;
1108 return;
1109 }
1110
1111 /* write page */
1112 write_image_block(state, UPG_FLASH_PAGE_SIZE, (int32_t)page_no * UPG_FLASH_PAGE_SIZE, pps->recovery_buffer);
1113
1114 fota_patch_free(pps->recovery_buffer);
1115 pps->recovery_buffer = NULL;
1116
1117 const uint32_t page_status_unsigned = (uint32_t) page_status;
1118 const uint32_t status_bit_unsigned = (uint32_t) status_bit;
1119
1120 /* it's the new page now, so clear down this operation. */
1121 write_page_status(state, (int32_t)page_no,
1122 (uint8_t)(page_status_unsigned & ~((1UL << status_bit_unsigned) | (1UL << (status_bit_unsigned - 1)))));
1123 pps->recovery_found = true;
1124 }
1125
process_patch_check_page_buffer_recovery(patch_state_t * state,process_patch_state_t * pps)1126 STATIC void process_patch_check_page_buffer_recovery(patch_state_t *state, process_patch_state_t *pps)
1127 {
1128 int32_t page_no;
1129 int32_t status_bit;
1130
1131 /* pass through the bits, and if there's a buffer page written, with the corresponding page deleted,
1132 * then write the buffer to the duff page. */
1133 for (page_no = 0; (page_no < (int32_t)state->desc->num_maxsize_pages) && (state->err_code == ERRCODE_SUCC);
1134 page_no++) {
1135 const int32_t page_status = read_page_status(state, page_no);
1136 const uint32_t page_status_unsigned = (uint32_t)page_status;
1137 for (status_bit = PAGE_STATUS_BIT_SEARCH_START;
1138 (status_bit <= PAGE_STATUS_BIT_SEARCH_END) && (state->err_code == ERRCODE_SUCC);
1139 status_bit += PAGE_STATUS_BIT_SEARCH_INC) {
1140 const uint32_t status_bit_unsigned = (uint32_t)status_bit;
1141 if (((page_status_unsigned & (1UL << status_bit_unsigned)) != 0) &&
1142 ((page_status_unsigned & (1UL << (status_bit_unsigned - 1))) == 0)) {
1143 process_patch_recover_page(state, pps, (uint32_t)page_no, page_status, status_bit);
1144 }
1145 }
1146 }
1147 }
1148
process_patch_perform_recovery(patch_state_t * state,process_patch_state_t * pps)1149 STATIC void process_patch_perform_recovery(patch_state_t *state, process_patch_state_t *pps)
1150 {
1151 /* Cache the recovery image in RAM if required, determine if old signature page is encrypted */
1152 state->err_code = fota_pkg_plaintext_flash_cache_init(state->desc);
1153 if (state->err_code != ERRCODE_SUCC) {
1154 upg_log_err("[UPG] process_patch - caching recovery flash failure err_code = 0x%x\r\n", state->err_code);
1155 return;
1156 }
1157
1158 /* Check if there is a page buffer written that needs to be written back to flash. */
1159 process_patch_check_page_buffer_recovery(state, pps);
1160 if (state->err_code != ERRCODE_SUCC) {
1161 upg_log_err("[UPG] process_patch state err_code = 0x%x\r\n", state->err_code);
1162 return;
1163 }
1164 #if (UPG_CFG_DEBUG_PRINT_ENABLED == YES)
1165 if (!pps->recovery_found) {
1166 upg_log_info("[UPG] No buffer page required recovery.\r\n");
1167 upg_log_info("[UPG] (This implies that the failure must have occurred\r\n");
1168 upg_log_info("[UPG] while writing to the buffer, not while erasing or writing the target flash.\r\n");
1169 } else {
1170 upg_log_info("[UPG] Ready to continue patching\r\n");
1171 }
1172 upg_log_info("[UPG] Recovery complete\r\n");
1173 #endif
1174 }
1175
process_patch(patch * desc)1176 errcode_t process_patch(patch *desc)
1177 {
1178 patch_state_t state;
1179 process_patch_state_t pps;
1180 process_patch_init(&state, desc, &pps);
1181 if (state.err_code != ERRCODE_SUCC) {
1182 return state.err_code;
1183 }
1184
1185 /* check if there is a patch in progress and continue it if so. */
1186 if (fota_buffers_has_contents(&state)) {
1187 process_patch_perform_recovery(&state, &pps);
1188 if (state.err_code != ERRCODE_SUCC) {
1189 goto ret_free;
1190 }
1191 } else {
1192 /* Cache non-recovery SEMAIN as required */
1193 state.err_code = fota_pkg_plaintext_flash_cache_init(desc);
1194 if (state.err_code != ERRCODE_SUCC) {
1195 upg_log_err("[UPG] process_patch - caching flash failure err_code = 0x%x\r\n", state.err_code);
1196 goto ret_free;
1197 }
1198
1199 erase_fota_buffers(&state);
1200 }
1201 /* apply the zipped patch. This will in turn use the write_byte_skip_done functions
1202 * which means an interrupted write should resume and (potentially) complete ok. */
1203 apply_patch(&state);
1204
1205 erase_redundant_pages(&state);
1206 erase_fota_buffers(&state);
1207
1208 ret_free:
1209 fota_patch_free(state.local_buffer);
1210 fota_patch_free(pps.recovery_buffer);
1211 return state.err_code;
1212 }
1213
fota_pkg_task_code_diff_cleanup_actions(patch * patch_desc)1214 STATIC void fota_pkg_task_code_diff_cleanup_actions(patch *patch_desc)
1215 {
1216 /* Clean allocated cache, Freeing a NULL is benign so no check for FOTA_PKG_TASK_ID_SEMAIN_CODE needed */
1217 upg_free(patch_desc->image_cache);
1218 patch_desc->image_cache = NULL;
1219 }
1220
init_patch_description_with_task_info(const upg_image_header_t * image,patch * patch_desc)1221 STATIC void init_patch_description_with_task_info(const upg_image_header_t *image, patch *patch_desc)
1222 {
1223 /* This will panic if it fails so no need to check the return value. */
1224 (void)memset_s(patch_desc, sizeof(patch), 0, sizeof(patch));
1225
1226 patch_desc->image_id = image->image_id;
1227 patch_desc->maxsize = uapi_max((int32_t)image->new_image_len, (int32_t)image->old_image_len);
1228 patch_desc->newsize = (int32_t)image->new_image_len;
1229 patch_desc->oldsize = (int32_t)image->old_image_len;
1230 patch_desc->num_new_pages = (uint32_t)(patch_desc->newsize + (UPG_FLASH_PAGE_SIZE - 1)) / UPG_FLASH_PAGE_SIZE;
1231 patch_desc->num_old_pages = (uint32_t)(patch_desc->oldsize + (UPG_FLASH_PAGE_SIZE - 1)) / UPG_FLASH_PAGE_SIZE;
1232 patch_desc->num_maxsize_pages = uapi_max(patch_desc->num_new_pages, patch_desc->num_old_pages);
1233 patch_desc->new_sig_page = patch_desc->num_new_pages - 1;
1234 patch_desc->old_sig_page = patch_desc->num_old_pages - 1;
1235
1236 patch_desc->patch_contents_ram_copy = 0;
1237 patch_desc->patch_contents_flash_offset = (uint32_t)image->image_offset;
1238 patch_desc->patch_contents_len = image->image_len;
1239 patch_desc->bottom_up = image->old_image_len < image->new_image_len;
1240 patch_desc->image_encrypted = false;
1241 /* No failure injection */
1242 patch_desc->failpoint = 0;
1243 patch_desc->failfn = NULL;
1244 /* Image read and prepare for writing functions. */
1245 patch_desc->fetch_image_contents_fn = fota_pkg_flash_read_image;
1246 patch_desc->prep_image_contents_for_write_fn = fota_pkg_flash_prep_page_contents_for_write;
1247 patch_desc->plaintext_flash_cache_init_fn = fota_pkg_plaintext_flash_cache_init;
1248 patch_desc->copy_recovered_buffer_to_flash_cache_fn = NULL;
1249 patch_desc->encrypt_flash_page_fn = NULL;
1250 }
1251
fota_pkg_task_apply_code_diff(const upg_image_header_t * image)1252 errcode_t fota_pkg_task_apply_code_diff(const upg_image_header_t *image)
1253 {
1254 errcode_t ret;
1255 patch *desc;
1256 uint32_t fota_data_addr;
1257 uint32_t fota_data_len;
1258 if (image == NULL) {
1259 upg_log_err("[UPG] task_apply_code_diff image is NULL");
1260 return ERRCODE_FAIL;
1261 }
1262
1263 desc = fota_patch_alloc(sizeof(patch));
1264 if (desc == NULL) {
1265 upg_log_err("[UPG] patch *desc malloc failed");
1266 return ERRCODE_MALLOC;
1267 }
1268 init_patch_description_with_task_info(image, desc);
1269
1270 ret = upg_get_partition_info(image->image_id, &desc->image_flash_offset, &desc->image_flash_length);
1271 if (ret != ERRCODE_SUCC) {
1272 fota_patch_free(desc);
1273 return ret;
1274 }
1275
1276 /* Get the metadata buffer area */
1277 ret = upg_get_progress_status_start_addr(&fota_data_addr, &fota_data_len);
1278 if (ret != ERRCODE_SUCC) {
1279 upg_log_err("[UPG] fota_pkg_task_apply_code_diff get area addr faile, ret = 0x%x\r\n", ret);
1280 fota_patch_free(desc);
1281 return ret;
1282 }
1283 desc->buffers_flash_offset = fota_data_addr;
1284 desc->buffers_length = FOTA_DATA_BUFFER_AREA_LEN;
1285
1286 /* Update patch description structure with task specific parameters and run through
1287 * any required initialisation functions done on a per task basis */
1288 if (ret == ERRCODE_SUCC) {
1289 /* Attempt to apply the patch */
1290 ret = process_patch(desc);
1291 }
1292
1293 fota_pkg_task_code_diff_cleanup_actions(desc);
1294 fota_patch_free(desc);
1295 return ret;
1296 }