flash_partitions.c 3.2 KB

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