1 /*
2 * SPDX-FileCopyrightText: 2015-2023 Espressif Systems (Shanghai) CO LTD
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 */
6 #include <string.h>
7 #include "esp_flash_partitions.h"
8 #include "esp_log.h"
9 #include "esp_rom_md5.h"
10 #include "esp_rom_spiflash.h"
11
12 static const char *TAG = "flash_parts";
13
esp_partition_table_verify(const esp_partition_info_t * partition_table,bool log_errors,int * num_partitions)14 esp_err_t esp_partition_table_verify(const esp_partition_info_t *partition_table, bool log_errors, int *num_partitions)
15 {
16 int md5_found = 0;
17 size_t num_parts;
18 uint32_t chip_size = g_rom_flashchip.chip_size;
19 *num_partitions = 0;
20
21 for (num_parts = 0; num_parts < ESP_PARTITION_TABLE_MAX_ENTRIES; num_parts++) {
22 const esp_partition_info_t *part = &partition_table[num_parts];
23
24 if (part->magic == ESP_PARTITION_MAGIC) {
25 const esp_partition_pos_t *pos = &part->pos;
26 if (pos->offset > chip_size || pos->offset + pos->size > chip_size) {
27 if (log_errors) {
28 ESP_LOGE(TAG, "partition %d invalid - offset 0x%"PRIx32" size 0x%"PRIx32" exceeds flash chip size 0x%"PRIx32,
29 num_parts, pos->offset, pos->size, chip_size);
30 }
31 return ESP_ERR_INVALID_SIZE;
32 }
33 } else if (part->magic == ESP_PARTITION_MAGIC_MD5) {
34 if (md5_found) {
35 if (log_errors) {
36 ESP_LOGE(TAG, "Only one MD5 checksum is allowed");
37 }
38 return ESP_ERR_INVALID_STATE;
39 }
40
41 md5_context_t context;
42 unsigned char digest[16];
43 esp_rom_md5_init(&context);
44 esp_rom_md5_update(&context, (unsigned char *) partition_table, num_parts * sizeof(esp_partition_info_t));
45 esp_rom_md5_final(digest, &context);
46
47 unsigned char *md5sum = ((unsigned char *) part) + ESP_PARTITION_MD5_OFFSET;
48
49 if (memcmp(md5sum, digest, sizeof(digest)) != 0) {
50 if (log_errors) {
51 ESP_LOGE(TAG, "Incorrect MD5 checksum");
52 }
53 return ESP_ERR_INVALID_STATE;
54 }
55 //MD5 checksum matches and we continue with the next interation in
56 //order to detect the end of the partition table
57 md5_found = 1;
58 } else if (part->magic == 0xFFFF
59 && part->type == PART_TYPE_END
60 && part->subtype == PART_SUBTYPE_END) {
61 ESP_LOGD(TAG, "partition table verified, %d entries", num_parts);
62 *num_partitions = num_parts - md5_found; //do not count the partition where the MD5 checksum is held
63 return ESP_OK;
64 } else {
65 if (log_errors) {
66 ESP_LOGE(TAG, "partition %d invalid magic number 0x%x", num_parts, part->magic);
67 }
68 return ESP_ERR_INVALID_STATE;
69 }
70 }
71
72 if (log_errors) {
73 ESP_LOGE(TAG, "partition table has no terminating entry, not valid");
74 }
75 return ESP_ERR_INVALID_STATE;
76 }
77