1
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
47
48
49
50
51
52
53
54
55
56
63
64
65
66
67
68
69
70
74
75
76
77
78
86
87
88
89
90
91
92
96
97
100
101
102
103
104
105
106
107
109
110
111
112
113
114
115
116
117
118
119
122
123
124
127
128
131
132
133
136
137
138
146
147
159
160
161
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
184
185
189
190
191
192
193
194
195
196
197
198
199
204
207
208
209
213
214
215
216
217
218
219
220
221
222
223
226
227
228
231
232
233
234
235
236
237
238
239
240
244
245
246
247
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
269
270
271
272
273
274
275
276
279
283
284
287
288
289
290
291
292
293
294
295
296
306
307
308
309
310
311
314
315
316
317
318
319
320
321
322
323
324
327
328
329
330
331
335
336
346
347
348
352
353
357
358
359
360
361
362
363
364
365
366
369
370
371
372
373
378
379
380
389
390
391
392
393
394
397
398
399
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
426
427
428
429
435
436
437
438
439
442
443
446
447
448
478
479
480
481
482
483
484
485
486
489
490
491
497
498
499
500
503
504
505
506
507
508
509
510
511
512
515
516
517
518
519
520
521
535
536
537
538
539
540
541
542
546
549
550
552
553
554
555
556
557
558
559
560
561
570
571
572
573
574
575
576
577
578
579
584
585
586
587
588
595
596
597
598
599
600
603
604
609
610
614
617
618
619
620
621
622
623
624
625
628
629
637
638
641
642
645
646
647
648
649
650
651
654
655
658
659
660
663
664
667
668
669
670
671
672
673
674
675
676
677
680
681
682
683
684
685
686
687
688
689
692
693
694
697
698
699
700
701
702
703
706
707
708
709
710
719
720
737
738
739
740
741
742
743
744
745
746
749
750
751
752
753
754
755
756
757
761
762
763
767
768
769
770
773
774
775
776
780
781
782
783
787
788
792
793
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
817
818
819
820
821
822
823
824
825
826
832
833
834
835
836
837
838
839
842
843
846
847
848
849
852
853
854
855
863
864
867
868
869
870
871
872
873
874
875
878
879
880
881
884
885
886
889
890
891
892
893
894
897
898
899
902
903
904
907
908
909
910
913
914
915
916
917
918
919
920
935
936
937
938
942
943
944
945
949
950
951
952
953
964
965
966
967
971
972
976
977
978
982
983
987
988
989
993
994
998
999
1000
1004
1005
1006
1007
/* ... */
#include <stdint.h>
#include <stdbool.h>
#include <stddef.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <assert.h>
#include "esp_err.h"
#include "esp_partition.h"
#include "esp_image_format.h"
#include "esp_secure_boot.h"
#include "esp_flash_encrypt.h"
#include "spi_flash_mmap.h"
#include "sdkconfig.h"
#include "esp_ota_ops.h"
#include "sys/queue.h"
#include "esp_log.h"
#include "esp_flash_partitions.h"
#include "bootloader_common.h"
#include "sys/param.h"
#include "esp_system.h"
#include "esp_efuse.h"
#include "esp_attr.h"
#include "esp_bootloader_desc.h"
#include "esp_flash.h"25 includes
#define SUB_TYPE_ID(i) (i & 0x0F)
typedef struct ota_ops_entry_ {
uint32_t handle;
const esp_partition_t *part;
bool need_erase;
uint32_t wrote_size;
uint8_t partial_bytes;
WORD_ALIGNED_ATTR uint8_t partial_data[16];
LIST_ENTRY(ota_ops_entry_) entries;
}{ ... } ota_ops_entry_t;
static LIST_HEAD(ota_ops_entries_head, ota_ops_entry_) s_ota_ops_entries_head =
LIST_HEAD_INITIALIZER(s_ota_ops_entries_head);
static uint32_t s_ota_ops_last_handle = 0;
const static char *TAG = "esp_ota_ops";
static bool is_ota_partition(const esp_partition_t *p)
{
return (p != NULL
&& p->type == ESP_PARTITION_TYPE_APP
&& p->subtype >= ESP_PARTITION_SUBTYPE_APP_OTA_0
&& p->subtype < ESP_PARTITION_SUBTYPE_APP_OTA_MAX);
}{ ... }
static const esp_partition_t *read_otadata(esp_ota_select_entry_t *two_otadata)
{
const esp_partition_t *otadata_partition = esp_partition_find_first(ESP_PARTITION_TYPE_DATA, ESP_PARTITION_SUBTYPE_DATA_OTA, NULL);
if (otadata_partition == NULL) {
ESP_LOGE(TAG, "not found otadata");
return NULL;
}{...}
esp_partition_mmap_handle_t ota_data_map;
const void *result = NULL;
esp_err_t err = esp_partition_mmap(otadata_partition, 0, otadata_partition->size, ESP_PARTITION_MMAP_DATA, &result, &ota_data_map);
if (err != ESP_OK) {
ESP_LOGE(TAG, "mmap otadata filed. Err=0x%8x", err);
return NULL;
}{...} else {
memcpy(&two_otadata[0], result, sizeof(esp_ota_select_entry_t));
memcpy(&two_otadata[1], result + otadata_partition->erase_size, sizeof(esp_ota_select_entry_t));
esp_partition_munmap(ota_data_map);
}{...}
return otadata_partition;
}{ ... }
static esp_err_t image_validate(const esp_partition_t *partition, esp_image_load_mode_t load_mode)
{
esp_image_metadata_t data;
const esp_partition_pos_t part_pos = {
.offset = partition->address,
.size = partition->size,
}{...};
if (esp_image_verify(load_mode, &part_pos, &data) != ESP_OK) {
return ESP_ERR_OTA_VALIDATE_FAILED;
}{...}
return ESP_OK;
}{ ... }
static esp_ota_img_states_t set_new_state_otadata(void)
{
#ifdef CONFIG_BOOTLOADER_APP_ROLLBACK_ENABLE
ESP_LOGD(TAG, "Monitoring the first boot of the app is enabled.");
return ESP_OTA_IMG_NEW;/* ... */
#else
return ESP_OTA_IMG_UNDEFINED;
#endif
}{ ... }
esp_err_t esp_ota_begin(const esp_partition_t *partition, size_t image_size, esp_ota_handle_t *out_handle)
{
ota_ops_entry_t *new_entry;
esp_err_t ret = ESP_OK;
if ((partition == NULL) || (out_handle == NULL)) {
return ESP_ERR_INVALID_ARG;
}{...}
partition = esp_partition_verify(partition);
if (partition == NULL) {
return ESP_ERR_NOT_FOUND;
}{...}
if (!is_ota_partition(partition)) {
return ESP_ERR_INVALID_ARG;
}{...}
const esp_partition_t* running_partition = esp_ota_get_running_partition();
if (partition == running_partition) {
return ESP_ERR_OTA_PARTITION_CONFLICT;
}{...}
#ifdef CONFIG_BOOTLOADER_APP_ROLLBACK_ENABLE
esp_ota_img_states_t ota_state_running_part;
if (esp_ota_get_state_partition(running_partition, &ota_state_running_part) == ESP_OK) {
if (ota_state_running_part == ESP_OTA_IMG_PENDING_VERIFY) {
ESP_LOGE(TAG, "Running app has not confirmed state (ESP_OTA_IMG_PENDING_VERIFY)");
return ESP_ERR_OTA_ROLLBACK_INVALID_STATE;
}{...}
}{...}
#endif/* ... */
if (image_size != OTA_WITH_SEQUENTIAL_WRITES) {
if ((image_size == 0) || (image_size == OTA_SIZE_UNKNOWN)) {
ret = esp_partition_erase_range(partition, 0, partition->size);
}{...} else {
const int aligned_erase_size = (image_size + partition->erase_size - 1) & ~(partition->erase_size - 1);
ret = esp_partition_erase_range(partition, 0, aligned_erase_size);
}{...}
if (ret != ESP_OK) {
return ret;
}{...}
}{...}
new_entry = (ota_ops_entry_t *) calloc(1, sizeof(ota_ops_entry_t));
if (new_entry == NULL) {
return ESP_ERR_NO_MEM;
}{...}
LIST_INSERT_HEAD(&s_ota_ops_entries_head, new_entry, entries);
new_entry->part = partition;
new_entry->handle = ++s_ota_ops_last_handle;
new_entry->need_erase = (image_size == OTA_WITH_SEQUENTIAL_WRITES);
*out_handle = new_entry->handle;
return ESP_OK;
}{ ... }
esp_err_t esp_ota_write(esp_ota_handle_t handle, const void *data, size_t size)
{
const uint8_t *data_bytes = (const uint8_t *)data;
esp_err_t ret;
ota_ops_entry_t *it;
if (data == NULL) {
ESP_LOGE(TAG, "write data is invalid");
return ESP_ERR_INVALID_ARG;
}{...}
if (size == 0) {
ESP_LOGD(TAG, "write data size is 0");
return ESP_OK;
}{...}
for (it = LIST_FIRST(&s_ota_ops_entries_head); it != NULL; it = LIST_NEXT(it, entries)) {
if (it->handle == handle) {
if (it->need_erase) {
uint32_t first_sector = it->wrote_size / it->part->erase_size;
uint32_t last_sector = (it->wrote_size + size - 1) / it->part->erase_size;
ret = ESP_OK;
if ((it->wrote_size % it->part->erase_size) == 0) {
ret = esp_partition_erase_range(it->part, it->wrote_size, ((last_sector - first_sector) + 1) * it->part->erase_size);
}{...} else if (first_sector != last_sector) {
ret = esp_partition_erase_range(it->part, (first_sector + 1) * it->part->erase_size, (last_sector - first_sector) * it->part->erase_size);
}{...}
if (ret != ESP_OK) {
return ret;
}{...}
}{...}
if (it->wrote_size == 0 && it->partial_bytes == 0 && size > 0 && data_bytes[0] != ESP_IMAGE_HEADER_MAGIC) {
ESP_LOGE(TAG, "OTA image has invalid magic byte (expected 0xE9, saw 0x%02x)", data_bytes[0]);
return ESP_ERR_OTA_VALIDATE_FAILED;
}{...}
if (esp_flash_encryption_enabled()) {
size_t copy_len;
if (it->partial_bytes != 0) {
copy_len = MIN(16 - it->partial_bytes, size);
memcpy(it->partial_data + it->partial_bytes, data_bytes, copy_len);
it->partial_bytes += copy_len;
if (it->partial_bytes != 16) {
return ESP_OK;
}{...}
ret = esp_partition_write(it->part, it->wrote_size, it->partial_data, 16);
if (ret != ESP_OK) {
return ret;
}{...}
it->partial_bytes = 0;
memset(it->partial_data, 0xFF, 16);
it->wrote_size += 16;
data_bytes += copy_len;
size -= copy_len;
}{...}
it->partial_bytes = size % 16;
if (it->partial_bytes != 0) {
size -= it->partial_bytes;
memcpy(it->partial_data, data_bytes + size, it->partial_bytes);
}{...}
}{...}
ret = esp_partition_write(it->part, it->wrote_size, data_bytes, size);
if(ret == ESP_OK){
it->wrote_size += size;
}{...}
return ret;
}{...}
}{...}
ESP_LOGE(TAG,"not found the handle");
return ESP_ERR_INVALID_ARG;
}{ ... }
esp_err_t esp_ota_write_with_offset(esp_ota_handle_t handle, const void *data, size_t size, uint32_t offset)
{
const uint8_t *data_bytes = (const uint8_t *)data;
esp_err_t ret;
ota_ops_entry_t *it;
if (data == NULL) {
ESP_LOGE(TAG, "write data is invalid");
return ESP_ERR_INVALID_ARG;
}{...}
for (it = LIST_FIRST(&s_ota_ops_entries_head); it != NULL; it = LIST_NEXT(it, entries)) {
if (it->handle == handle) {
assert(it->need_erase == 0 && "must erase the partition before writing to it");
/* ... */
if (esp_flash_encryption_enabled() && (size % 16)) {
ESP_LOGE(TAG, "Size should be 16byte aligned for flash encryption case");
return ESP_ERR_INVALID_ARG;
}{...}
ret = esp_partition_write(it->part, offset, data_bytes, size);
if (ret == ESP_OK) {
it->wrote_size += size;
}{...}
return ret;
}{...}
}{...}
ESP_LOGE(TAG,"OTA handle not found");
return ESP_ERR_INVALID_ARG;
}{ ... }
static ota_ops_entry_t *get_ota_ops_entry(esp_ota_handle_t handle)
{
ota_ops_entry_t *it = NULL;
for (it = LIST_FIRST(&s_ota_ops_entries_head); it != NULL; it = LIST_NEXT(it, entries)) {
if (it->handle == handle) {
break;
}{...}
}{...}
return it;
}{ ... }
esp_err_t esp_ota_abort(esp_ota_handle_t handle)
{
ota_ops_entry_t *it = get_ota_ops_entry(handle);
if (it == NULL) {
return ESP_ERR_NOT_FOUND;
}{...}
LIST_REMOVE(it, entries);
free(it);
return ESP_OK;
}{ ... }
esp_err_t esp_ota_end(esp_ota_handle_t handle)
{
ota_ops_entry_t *it = get_ota_ops_entry(handle);
esp_err_t ret = ESP_OK;
if (it == NULL) {
return ESP_ERR_NOT_FOUND;
}{...}
if (it->wrote_size == 0) {
ret = ESP_ERR_INVALID_ARG;
goto cleanup;
}{...}
if (it->partial_bytes > 0) {
ret = esp_partition_write(it->part, it->wrote_size, it->partial_data, 16);
if (ret != ESP_OK) {
ret = ESP_ERR_INVALID_STATE;
goto cleanup;
}{...}
it->wrote_size += 16;
it->partial_bytes = 0;
}{...}
esp_image_metadata_t data;
const esp_partition_pos_t part_pos = {
.offset = it->part->address,
.size = it->part->size,
}{...};
if (esp_image_verify(ESP_IMAGE_VERIFY, &part_pos, &data) != ESP_OK) {
ret = ESP_ERR_OTA_VALIDATE_FAILED;
goto cleanup;
}{...}
cleanup:
LIST_REMOVE(it, entries);
free(it);
return ret;
}{ ... }
static esp_err_t rewrite_ota_seq(esp_ota_select_entry_t *two_otadata, uint32_t seq, uint8_t sec_id, const esp_partition_t *ota_data_partition)
{
if (two_otadata == NULL || sec_id > 1) {
return ESP_ERR_INVALID_ARG;
}{...}
two_otadata[sec_id].ota_seq = seq;
two_otadata[sec_id].crc = bootloader_common_ota_select_crc(&two_otadata[sec_id]);
esp_err_t ret = esp_partition_erase_range(ota_data_partition, sec_id * ota_data_partition->erase_size, ota_data_partition->erase_size);
if (ret != ESP_OK) {
return ret;
}{...} else {
return esp_partition_write(ota_data_partition, ota_data_partition->erase_size * sec_id, &two_otadata[sec_id], sizeof(esp_ota_select_entry_t));
}{...}
}{ ... }
uint8_t esp_ota_get_app_partition_count(void)
{
uint16_t ota_app_count = 0;
while (esp_partition_find_first(ESP_PARTITION_TYPE_APP, ESP_PARTITION_SUBTYPE_APP_OTA_MIN + ota_app_count, NULL) != NULL) {
assert(ota_app_count < 16 && "must erase the partition before writing to it");
ota_app_count++;
}{...}
return ota_app_count;
}{ ... }
static esp_err_t esp_rewrite_ota_data(esp_partition_subtype_t subtype)
{
esp_ota_select_entry_t otadata[2];
const esp_partition_t *otadata_partition = read_otadata(otadata);
if (otadata_partition == NULL) {
return ESP_ERR_NOT_FOUND;
}{...}
uint8_t ota_app_count = esp_ota_get_app_partition_count();
if (SUB_TYPE_ID(subtype) >= ota_app_count) {
return ESP_ERR_INVALID_ARG;
}{...}
int active_otadata = bootloader_common_get_active_otadata(otadata);
if (active_otadata != -1) {
uint32_t seq = otadata[active_otadata].ota_seq;
uint32_t i = 0;
while (seq > (SUB_TYPE_ID(subtype) + 1) % ota_app_count + i * ota_app_count) {
i++;
}{...}
int next_otadata = (~active_otadata)&1;
otadata[next_otadata].ota_state = set_new_state_otadata();
return rewrite_ota_seq(otadata, (SUB_TYPE_ID(subtype) + 1) % ota_app_count + i * ota_app_count, next_otadata, otadata_partition);
}{...} else {
int next_otadata = 0;
otadata[next_otadata].ota_state = set_new_state_otadata();
return rewrite_ota_seq(otadata, SUB_TYPE_ID(subtype) + 1, next_otadata, otadata_partition);
}{...}
}{ ... }
esp_err_t esp_ota_set_boot_partition(const esp_partition_t *partition)
{
if (partition == NULL) {
return ESP_ERR_INVALID_ARG;
}{...}
if (image_validate(partition, ESP_IMAGE_VERIFY) != ESP_OK) {
return ESP_ERR_OTA_VALIDATE_FAILED;
}{...}
if (partition->type == ESP_PARTITION_TYPE_APP) {
if (partition->subtype == ESP_PARTITION_SUBTYPE_APP_FACTORY) {
const esp_partition_t *find_partition = esp_partition_find_first(ESP_PARTITION_TYPE_DATA, ESP_PARTITION_SUBTYPE_DATA_OTA, NULL);
if (find_partition != NULL) {
return esp_partition_erase_range(find_partition, 0, find_partition->size);
}{...} else {
return ESP_ERR_NOT_FOUND;
}{...}
}{...} else {
#ifdef CONFIG_BOOTLOADER_APP_ANTI_ROLLBACK
esp_app_desc_t partition_app_desc;
esp_err_t err = esp_ota_get_partition_description(partition, &partition_app_desc);
if (err != ESP_OK) {
return err;
}{...}
if (esp_efuse_check_secure_version(partition_app_desc.secure_version) == false) {
ESP_LOGE(TAG, "This a new partition can not be booted due to a secure version is lower than stored in efuse. Partition will be erased.");
esp_err_t err = esp_partition_erase_range(partition, 0, partition->size);
if (err != ESP_OK) {
return err;
}{...}
return ESP_ERR_OTA_SMALL_SEC_VER;
}{...}
#endif/* ... */
return esp_rewrite_ota_data(partition->subtype);
}{...}
}{...} else {
return ESP_ERR_INVALID_ARG;
}{...}
}{ ... }
static const esp_partition_t *find_default_boot_partition(void)
{
const esp_partition_t *result = esp_partition_find_first(ESP_PARTITION_TYPE_APP, ESP_PARTITION_SUBTYPE_APP_FACTORY, NULL);
if (result != NULL) {
return result;
}{...}
for (esp_partition_subtype_t s = ESP_PARTITION_SUBTYPE_APP_OTA_MIN; s != ESP_PARTITION_SUBTYPE_APP_OTA_MAX; s++) {
result = esp_partition_find_first(ESP_PARTITION_TYPE_APP, s, NULL);
if (result != NULL) {
return result;
}{...}
}{...}
result = esp_partition_find_first(ESP_PARTITION_TYPE_APP, ESP_PARTITION_SUBTYPE_APP_TEST, NULL);
if (result != NULL) {
return result;
}{...}
ESP_LOGE(TAG, "invalid partition table, no app partitions");
return NULL;
}{ ... }
const esp_partition_t *esp_ota_get_boot_partition(void)
{
esp_ota_select_entry_t otadata[2];
const esp_partition_t *otadata_partition = read_otadata(otadata);
if (otadata_partition == NULL) {
return NULL;
}{...}
int ota_app_count = esp_ota_get_app_partition_count();
ESP_LOGD(TAG, "found ota app max = %d", ota_app_count);
if ((bootloader_common_ota_select_invalid(&otadata[0]) &&
bootloader_common_ota_select_invalid(&otadata[1])) ||
ota_app_count == 0) {
ESP_LOGD(TAG, "finding factory app...");
return find_default_boot_partition();
}{...} else {
int active_otadata = bootloader_common_get_active_otadata(otadata);
if (active_otadata != -1) {
int ota_slot = (otadata[active_otadata].ota_seq - 1) % ota_app_count;
ESP_LOGD(TAG, "finding ota_%d app...", ESP_PARTITION_SUBTYPE_APP_OTA_MIN + ota_slot);
return esp_partition_find_first(ESP_PARTITION_TYPE_APP, ESP_PARTITION_SUBTYPE_APP_OTA_MIN + ota_slot, NULL);
}{...} else {
ESP_LOGE(TAG, "ota data invalid, no current app. Assuming factory");
return find_default_boot_partition();
}{...}
}{...}
}{ ... }
const esp_partition_t* esp_ota_get_running_partition(void)
{
static const esp_partition_t *curr_partition = NULL;
/* ... */
if (curr_partition != NULL) {
return curr_partition;
}{...}
/* ... */
size_t phys_offs = spi_flash_cache2phys(esp_ota_get_running_partition);
assert (phys_offs != SPI_FLASH_CACHE2PHYS_FAIL);
esp_partition_iterator_t it = esp_partition_find(ESP_PARTITION_TYPE_APP,
ESP_PARTITION_SUBTYPE_ANY,
NULL);
assert(it != NULL);
while (it != NULL) {
const esp_partition_t *p = esp_partition_get(it);
if (p->address <= phys_offs && p->address + p->size > phys_offs) {
esp_partition_iterator_release(it);
curr_partition = p;
return p;
}{...}
it = esp_partition_next(it);
}{...}
abort();
}{ ... }
const esp_partition_t* esp_ota_get_next_update_partition(const esp_partition_t *start_from)
{
const esp_partition_t *default_ota = NULL;
bool next_is_result = false;
if (start_from == NULL) {
start_from = esp_ota_get_running_partition();
}{...} else {
start_from = esp_partition_verify(start_from);
}{...}
assert (start_from != NULL);
/* ... */
for (esp_partition_subtype_t t = ESP_PARTITION_SUBTYPE_APP_OTA_0;
t != ESP_PARTITION_SUBTYPE_APP_OTA_MAX;
t++) {
const esp_partition_t *p = esp_partition_find_first(ESP_PARTITION_TYPE_APP, t, NULL);
if (p == NULL) {
continue;
}{...}
if (default_ota == NULL) {
/* ... */
default_ota = p;
}{...}
if (p == start_from) {
next_is_result = true;
}{...}
else if (next_is_result) {
return p;
}{...}
}{...}
return default_ota;
}{ ... }
esp_err_t esp_ota_get_bootloader_description(const esp_partition_t *bootloader_partition, esp_bootloader_desc_t *desc)
{
if (desc == NULL) {
return ESP_ERR_INVALID_ARG;
}{...}
esp_partition_t partition = { 0 };
if (bootloader_partition == NULL) {
partition.flash_chip = esp_flash_default_chip;
partition.encrypted = esp_flash_encryption_enabled();
partition.address = CONFIG_BOOTLOADER_OFFSET_IN_FLASH;
partition.size = CONFIG_PARTITION_TABLE_OFFSET - CONFIG_BOOTLOADER_OFFSET_IN_FLASH;
}{...} else {
memcpy(&partition, bootloader_partition, sizeof(partition));
}{...}
esp_err_t err = esp_partition_read(&partition, sizeof(esp_image_header_t) + sizeof(esp_image_segment_header_t), desc, sizeof(esp_bootloader_desc_t));
if (err != ESP_OK) {
return err;
}{...}
if (desc->magic_byte != ESP_BOOTLOADER_DESC_MAGIC_BYTE) {
return ESP_ERR_NOT_FOUND;
}{...}
return ESP_OK;
}{ ... }
esp_err_t esp_ota_get_partition_description(const esp_partition_t *partition, esp_app_desc_t *app_desc)
{
if (partition == NULL || app_desc == NULL) {
return ESP_ERR_INVALID_ARG;
}{...}
if(partition->type != ESP_PARTITION_TYPE_APP) {
return ESP_ERR_NOT_SUPPORTED;
}{...}
esp_err_t err = esp_partition_read(partition, sizeof(esp_image_header_t) + sizeof(esp_image_segment_header_t), app_desc, sizeof(esp_app_desc_t));
if (err != ESP_OK) {
return err;
}{...}
if (app_desc->magic_word != ESP_APP_DESC_MAGIC_WORD) {
return ESP_ERR_NOT_FOUND;
}{...}
return ESP_OK;
}{ ... }
#ifdef CONFIG_BOOTLOADER_APP_ANTI_ROLLBACK
static esp_err_t esp_ota_set_anti_rollback(void) {
const esp_partition_t* partition = esp_ota_get_running_partition();
esp_app_desc_t app_desc = {0};
esp_err_t err = esp_ota_get_partition_description(partition, &app_desc);
if (err == ESP_OK) {
return esp_efuse_update_secure_version(app_desc.secure_version);
}{...}
return err;
}{...}
/* ... */#endif
bool esp_ota_check_rollback_is_possible(void)
{
esp_ota_select_entry_t otadata[2];
if (read_otadata(otadata) == NULL) {
return false;
}{...}
int ota_app_count = esp_ota_get_app_partition_count();
if (ota_app_count == 0) {
return false;
}{...}
bool valid_otadata[2];
valid_otadata[0] = bootloader_common_ota_select_valid(&otadata[0]);
valid_otadata[1] = bootloader_common_ota_select_valid(&otadata[1]);
int active_ota = bootloader_common_select_otadata(otadata, valid_otadata, true);
if (active_ota == -1) {
return false;
}{...}
int last_active_ota = (~active_ota)&1;
const esp_partition_t *partition = NULL;
#ifndef CONFIG_BOOTLOADER_APP_ANTI_ROLLBACK
if (valid_otadata[last_active_ota] == false) {
partition = esp_partition_find_first(ESP_PARTITION_TYPE_APP, ESP_PARTITION_SUBTYPE_APP_FACTORY, NULL);
if (partition != NULL) {
if(image_validate(partition, ESP_IMAGE_VERIFY_SILENT) == ESP_OK) {
return true;
}{...}
}{...}
}{...}
#endif/* ... */
if (valid_otadata[last_active_ota] == true) {
int slot = (otadata[last_active_ota].ota_seq - 1) % ota_app_count;
partition = esp_partition_find_first(ESP_PARTITION_TYPE_APP, ESP_PARTITION_SUBTYPE_APP_OTA_MIN + slot, NULL);
if (partition != NULL) {
if(image_validate(partition, ESP_IMAGE_VERIFY_SILENT) == ESP_OK) {
#ifdef CONFIG_BOOTLOADER_APP_ANTI_ROLLBACK
esp_app_desc_t app_desc;
if (esp_ota_get_partition_description(partition, &app_desc) == ESP_OK &&
esp_efuse_check_secure_version(app_desc.secure_version) == true) {
return true;
}{...}
#else/* ... */
return true;
#endif
}{...}
}{...}
}{...}
return false;
}{ ... }
static esp_err_t esp_ota_current_ota_is_workable(bool valid)
{
esp_ota_select_entry_t otadata[2];
const esp_partition_t *otadata_partition = read_otadata(otadata);
if (otadata_partition == NULL) {
return ESP_ERR_NOT_FOUND;
}{...}
int active_otadata = bootloader_common_get_active_otadata(otadata);
if (active_otadata != -1 && esp_ota_get_app_partition_count() != 0) {
if (valid == true && otadata[active_otadata].ota_state != ESP_OTA_IMG_VALID) {
otadata[active_otadata].ota_state = ESP_OTA_IMG_VALID;
ESP_LOGD(TAG, "OTA[current] partition is marked as VALID");
esp_err_t err = rewrite_ota_seq(otadata, otadata[active_otadata].ota_seq, active_otadata, otadata_partition);
#ifdef CONFIG_BOOTLOADER_APP_ANTI_ROLLBACK
if (err == ESP_OK) {
return esp_ota_set_anti_rollback();
}{...}
#endif/* ... */
return err;
}{...} else if (valid == false) {
if (esp_ota_check_rollback_is_possible() == false) {
ESP_LOGE(TAG, "Rollback is not possible, do not have any suitable apps in slots");
return ESP_ERR_OTA_ROLLBACK_FAILED;
}{...}
ESP_LOGD(TAG, "OTA[current] partition is marked as INVALID");
otadata[active_otadata].ota_state = ESP_OTA_IMG_INVALID;
esp_err_t err = rewrite_ota_seq(otadata, otadata[active_otadata].ota_seq, active_otadata, otadata_partition);
if (err != ESP_OK) {
return err;
}{...}
ESP_LOGI(TAG, "Rollback to previously worked partition. Restart.");
esp_restart();
}{...}
}{...} else {
ESP_LOGE(TAG, "Running firmware is factory");
return ESP_FAIL;
}{...}
return ESP_OK;
}{ ... }
esp_err_t esp_ota_mark_app_valid_cancel_rollback(void)
{
return esp_ota_current_ota_is_workable(true);
}{ ... }
esp_err_t esp_ota_mark_app_invalid_rollback_and_reboot(void)
{
return esp_ota_current_ota_is_workable(false);
}{ ... }
static bool check_invalid_otadata (const esp_ota_select_entry_t *s) {
return s->ota_seq != UINT32_MAX &&
s->crc == bootloader_common_ota_select_crc(s) &&
(s->ota_state == ESP_OTA_IMG_INVALID ||
s->ota_state == ESP_OTA_IMG_ABORTED);
}{ ... }
static int get_last_invalid_otadata(const esp_ota_select_entry_t *two_otadata)
{
bool invalid_otadata[2];
invalid_otadata[0] = check_invalid_otadata(&two_otadata[0]);
invalid_otadata[1] = check_invalid_otadata(&two_otadata[1]);
int num_invalid_otadata = bootloader_common_select_otadata(two_otadata, invalid_otadata, false);
ESP_LOGD(TAG, "Invalid otadata[%d]", num_invalid_otadata);
return num_invalid_otadata;
}{ ... }
const esp_partition_t* esp_ota_get_last_invalid_partition(void)
{
esp_ota_select_entry_t otadata[2];
if (read_otadata(otadata) == NULL) {
return NULL;
}{...}
int invalid_otadata = get_last_invalid_otadata(otadata);
int ota_app_count = esp_ota_get_app_partition_count();
if (invalid_otadata != -1 && ota_app_count != 0) {
int ota_slot = (otadata[invalid_otadata].ota_seq - 1) % ota_app_count;
ESP_LOGD(TAG, "Find invalid ota_%d app", ESP_PARTITION_SUBTYPE_APP_OTA_MIN + ota_slot);
const esp_partition_t* invalid_partition = esp_partition_find_first(ESP_PARTITION_TYPE_APP, ESP_PARTITION_SUBTYPE_APP_OTA_MIN + ota_slot, NULL);
if (invalid_partition != NULL) {
if (image_validate(invalid_partition, ESP_IMAGE_VERIFY_SILENT) != ESP_OK) {
ESP_LOGD(TAG, "Last invalid partition has corrupted app");
return NULL;
}{...}
}{...}
return invalid_partition;
}{...}
return NULL;
}{ ... }
esp_err_t esp_ota_get_state_partition(const esp_partition_t *partition, esp_ota_img_states_t *ota_state)
{
if (partition == NULL || ota_state == NULL) {
return ESP_ERR_INVALID_ARG;
}{...}
if (!is_ota_partition(partition)) {
return ESP_ERR_NOT_SUPPORTED;
}{...}
esp_ota_select_entry_t otadata[2];
int ota_app_count = esp_ota_get_app_partition_count();
if (read_otadata(otadata) == NULL || ota_app_count == 0) {
return ESP_ERR_NOT_FOUND;
}{...}
int req_ota_slot = partition->subtype - ESP_PARTITION_SUBTYPE_APP_OTA_MIN;
bool not_found = true;
for (int i = 0; i < 2; ++i) {
int ota_slot = (otadata[i].ota_seq - 1) % ota_app_count;
if (ota_slot == req_ota_slot && otadata[i].crc == bootloader_common_ota_select_crc(&otadata[i])) {
*ota_state = otadata[i].ota_state;
not_found = false;
break;
}{...}
}{...}
if (not_found) {
return ESP_ERR_NOT_FOUND;
}{...}
return ESP_OK;
}{ ... }
esp_err_t esp_ota_erase_last_boot_app_partition(void)
{
esp_ota_select_entry_t otadata[2];
const esp_partition_t* ota_data_partition = read_otadata(otadata);
if (ota_data_partition == NULL) {
return ESP_FAIL;
}{...}
int active_otadata = bootloader_common_get_active_otadata(otadata);
int ota_app_count = esp_ota_get_app_partition_count();
if (active_otadata == -1 || ota_app_count == 0) {
return ESP_FAIL;
}{...}
int inactive_otadata = (~active_otadata)&1;
if (otadata[inactive_otadata].ota_seq == UINT32_MAX || otadata[inactive_otadata].crc != bootloader_common_ota_select_crc(&otadata[inactive_otadata])) {
return ESP_FAIL;
}{...}
int ota_slot = (otadata[inactive_otadata].ota_seq - 1) % ota_app_count;
ESP_LOGD(TAG, "finding last_boot_app_partition ota_%d app...", ESP_PARTITION_SUBTYPE_APP_OTA_MIN + ota_slot);
const esp_partition_t* last_boot_app_partition_from_otadata = esp_partition_find_first(ESP_PARTITION_TYPE_APP, ESP_PARTITION_SUBTYPE_APP_OTA_MIN + ota_slot, NULL);
if (last_boot_app_partition_from_otadata == NULL) {
return ESP_FAIL;
}{...}
const esp_partition_t* running_partition = esp_ota_get_running_partition();
if (running_partition == NULL || last_boot_app_partition_from_otadata == running_partition) {
return ESP_FAIL;
}{...}
esp_err_t err = esp_partition_erase_range(last_boot_app_partition_from_otadata, 0, last_boot_app_partition_from_otadata->size);
if (err != ESP_OK) {
return err;
}{...}
int sec_id = inactive_otadata;
err = esp_partition_erase_range(ota_data_partition, sec_id * ota_data_partition->erase_size, ota_data_partition->erase_size);
if (err != ESP_OK) {
return err;
}{...}
return ESP_OK;
}{ ... }
#if SOC_SUPPORT_SECURE_BOOT_REVOKE_KEY && CONFIG_SECURE_BOOT_V2_ENABLED
static bool validate_img(esp_ota_secure_boot_public_key_index_t revoked_key_index, esp_partition_pos_t *app_pos)
{
bool verified = false;
for (int i = 0; i < SOC_EFUSE_SECURE_BOOT_KEY_DIGESTS; i++) {
if (i == revoked_key_index) {
continue;
}{...}
if (esp_secure_boot_verify_with_efuse_digest_index(i, app_pos) == ESP_OK) {
verified = true;
ESP_LOGI(TAG, "Application successfully verified with public key digest %d", i);
break;
}{...}
}{...}
return verified;
}{...}
esp_err_t esp_ota_revoke_secure_boot_public_key(esp_ota_secure_boot_public_key_index_t index)
{
if (!esp_secure_boot_enabled()) {
ESP_LOGE(TAG, "Secure boot v2 has not been enabled.");
return ESP_FAIL;
}{...}
if (index != SECURE_BOOT_PUBLIC_KEY_INDEX_0 &&
index != SECURE_BOOT_PUBLIC_KEY_INDEX_1 &&
index != SECURE_BOOT_PUBLIC_KEY_INDEX_2) {
ESP_LOGE(TAG, "Invalid Index found for public key revocation %d.", index);
return ESP_ERR_INVALID_ARG;
}{...}
const esp_partition_t *running_app_part = esp_ota_get_running_partition();
esp_err_t ret = ESP_FAIL;
#ifdef CONFIG_BOOTLOADER_APP_ROLLBACK_ENABLE
esp_ota_img_states_t running_app_state;
ret = esp_ota_get_state_partition(running_app_part, &running_app_state);
if (ret != ESP_OK) {
ESP_LOGE(TAG, "esp_ota_get_state_partition returned: %s", esp_err_to_name(ret));
return ESP_FAIL;
}{...}
if (running_app_state != ESP_OTA_IMG_VALID) {
ESP_LOGE(TAG, "The current running application is not marked as a valid image. Aborting..");
return ESP_FAIL;
}{...}
/* ... */#endif
esp_secure_boot_key_digests_t trusted_keys;
ret = esp_secure_boot_read_key_digests(&trusted_keys);
if (ret != ESP_OK) {
ESP_LOGE(TAG, "Could not read the secure boot key digests from efuse. Aborting..");
return ESP_FAIL;
}{...}
if (trusted_keys.key_digests[index] == NULL) {
ESP_LOGI(TAG, "Given public key digest(%d) is already revoked.", index);
return ESP_OK;
}{...}
esp_partition_pos_t running_app_pos = {
.offset = running_app_part->address,
.size = running_app_part->size,
}{...};
if (!validate_img(index, &running_app_pos)) {
ESP_LOGE(TAG, "Application cannot be verified with any key other than the one being revoked");
return ESP_FAIL;
}{...}
esp_partition_pos_t bootloader_pos = {
.offset = ESP_BOOTLOADER_OFFSET,
.size = (ESP_PARTITION_TABLE_OFFSET - ESP_BOOTLOADER_OFFSET),
}{...};
if (!validate_img(index, &bootloader_pos)) {
ESP_LOGE(TAG, "Bootloader cannot be verified with any key other than the one being revoked");
return ESP_FAIL;
}{...}
esp_err_t err = esp_efuse_set_digest_revoke(index);
if (err != ESP_OK) {
ESP_LOGE(TAG, "Failed to revoke digest (0x%x).", err);
return ESP_FAIL;
}{...}
ESP_LOGI(TAG, "Revoked signature block %d.", index);
return ESP_OK;
}{...}
/* ... */#endif