Преглед изворни кода

Merge branch 'bugfix/secure_boot_enable_image_verify' into 'master'

Fix secure boot enable - can verify bootloader image

Secure boot enable would fail because esp_image_basic_verify() would fail to verify the bootloader image.

* Failure prevented secure boot from enabling.
* Also adds unit test cases for esp_image_basic_verify()

Ref https://esp32.com/viewtopic.php?f=2&t=1602
TW11878

See merge request !693

Angus Gratton пре 8 година
родитељ
комит
32fc0a62b9

+ 1 - 8
components/bootloader/src/main/bootloader_config.h

@@ -22,16 +22,9 @@ extern "C"
 #endif
 #endif
 
 
 #include "esp_flash_data_types.h"
 #include "esp_flash_data_types.h"
+#include "soc/soc.h"
 
 
 #define SPI_SEC_SIZE 0x1000
 #define SPI_SEC_SIZE 0x1000
-#define IROM_LOW    0x400D0000
-#define IROM_HIGH   0x40400000
-#define DROM_LOW    0x3F400000
-#define DROM_HIGH   0x3F800000
-#define RTC_IRAM_LOW  0x400C0000
-#define RTC_IRAM_HIGH 0x400C2000
-#define RTC_DATA_LOW  0x50000000
-#define RTC_DATA_HIGH 0x50002000
 
 
 #define SPI_ERROR_LOG "spi flash error"
 #define SPI_ERROR_LOG "spi flash error"
 
 

+ 13 - 5
components/bootloader/src/main/bootloader_start.c

@@ -14,6 +14,7 @@
 #include <string.h>
 #include <string.h>
 #include <stdint.h>
 #include <stdint.h>
 #include <limits.h>
 #include <limits.h>
+#include <sys/param.h>
 
 
 #include "esp_attr.h"
 #include "esp_attr.h"
 #include "esp_log.h"
 #include "esp_log.h"
@@ -312,11 +313,15 @@ void bootloader_main()
         memcpy(&sa, ota_select_map, sizeof(esp_ota_select_entry_t));
         memcpy(&sa, ota_select_map, sizeof(esp_ota_select_entry_t));
         memcpy(&sb, (uint8_t *)ota_select_map + SPI_SEC_SIZE, sizeof(esp_ota_select_entry_t));
         memcpy(&sb, (uint8_t *)ota_select_map + SPI_SEC_SIZE, sizeof(esp_ota_select_entry_t));
         bootloader_munmap(ota_select_map);
         bootloader_munmap(ota_select_map);
+        ESP_LOGD(TAG, "OTA sequence values A 0x%08x B 0x%08x", sa.ota_seq, sb.ota_seq);
         if(sa.ota_seq == 0xFFFFFFFF && sb.ota_seq == 0xFFFFFFFF) {
         if(sa.ota_seq == 0xFFFFFFFF && sb.ota_seq == 0xFFFFFFFF) {
+            ESP_LOGD(TAG, "OTA sequence numbers both empty (all-0xFF");
             // init status flash
             // init status flash
             if (bs.factory.offset != 0) {        // if have factory bin,boot factory bin
             if (bs.factory.offset != 0) {        // if have factory bin,boot factory bin
+                ESP_LOGD(TAG, "Defaulting to factory image");
                 load_part_pos = bs.factory;
                 load_part_pos = bs.factory;
             } else {
             } else {
+                ESP_LOGD(TAG, "No factory image, defaulting to OTA 0");
                 load_part_pos = bs.ota[0];
                 load_part_pos = bs.ota[0];
                 sa.ota_seq = 0x01;
                 sa.ota_seq = 0x01;
                 sa.crc = ota_select_crc(&sa);
                 sa.crc = ota_select_crc(&sa);
@@ -341,10 +346,13 @@ void bootloader_main()
             //TODO:write data in ota info
             //TODO:write data in ota info
         } else  {
         } else  {
             if(ota_select_valid(&sa) && ota_select_valid(&sb)) {
             if(ota_select_valid(&sa) && ota_select_valid(&sb)) {
-                load_part_pos = bs.ota[(((sa.ota_seq > sb.ota_seq)?sa.ota_seq:sb.ota_seq) - 1)%bs.app_count];
+                ESP_LOGD(TAG, "Both OTA sequence valid, using OTA slot %d", MAX(sa.ota_seq, sb.ota_seq)-1);
+                load_part_pos = bs.ota[(MAX(sa.ota_seq, sb.ota_seq) - 1)%bs.app_count];
             } else if(ota_select_valid(&sa)) {
             } else if(ota_select_valid(&sa)) {
+                ESP_LOGD(TAG, "Only OTA sequence A is valid, using OTA slot %d", sa.ota_seq - 1);
                 load_part_pos = bs.ota[(sa.ota_seq - 1) % bs.app_count];
                 load_part_pos = bs.ota[(sa.ota_seq - 1) % bs.app_count];
             } else if(ota_select_valid(&sb)) {
             } else if(ota_select_valid(&sb)) {
+                ESP_LOGD(TAG, "Only OTA sequence B is valid, using OTA slot %d", sa.ota_seq - 1);
                 load_part_pos = bs.ota[(sb.ota_seq - 1) % bs.app_count];
                 load_part_pos = bs.ota[(sb.ota_seq - 1) % bs.app_count];
             } else if (bs.factory.offset != 0) {
             } else if (bs.factory.offset != 0) {
                 ESP_LOGE(TAG, "ota data partition invalid, falling back to factory");
                 ESP_LOGE(TAG, "ota data partition invalid, falling back to factory");
@@ -475,7 +483,7 @@ static void unpack_load_app(const esp_partition_pos_t* partition)
             // TODO: actually check md5
             // TODO: actually check md5
         }
         }
 
 
-        if (address >= DROM_LOW && address < DROM_HIGH) {
+        if (address >= SOC_DROM_LOW && address < SOC_DROM_HIGH) {
             ESP_LOGD(TAG, "found drom segment, map from %08x to %08x", data_offs,
             ESP_LOGD(TAG, "found drom segment, map from %08x to %08x", data_offs,
                       segment_header.load_addr);
                       segment_header.load_addr);
             drom_addr = data_offs;
             drom_addr = data_offs;
@@ -485,7 +493,7 @@ static void unpack_load_app(const esp_partition_pos_t* partition)
             map = true;
             map = true;
         }
         }
 
 
-        if (address >= IROM_LOW && address < IROM_HIGH) {
+        if (address >= SOC_IROM_LOW && address < SOC_IROM_HIGH) {
             ESP_LOGD(TAG, "found irom segment, map from %08x to %08x", data_offs,
             ESP_LOGD(TAG, "found irom segment, map from %08x to %08x", data_offs,
                       segment_header.load_addr);
                       segment_header.load_addr);
             irom_addr = data_offs;
             irom_addr = data_offs;
@@ -495,12 +503,12 @@ static void unpack_load_app(const esp_partition_pos_t* partition)
             map = true;
             map = true;
         }
         }
 
 
-        if (!load_rtc_memory && address >= RTC_IRAM_LOW && address < RTC_IRAM_HIGH) {
+        if (!load_rtc_memory && address >= SOC_RTC_IRAM_LOW && address < SOC_RTC_IRAM_HIGH) {
             ESP_LOGD(TAG, "Skipping RTC code segment at %08x\n", data_offs);
             ESP_LOGD(TAG, "Skipping RTC code segment at %08x\n", data_offs);
             load = false;
             load = false;
         }
         }
 
 
-        if (!load_rtc_memory && address >= RTC_DATA_LOW && address < RTC_DATA_HIGH) {
+        if (!load_rtc_memory && address >= SOC_RTC_DATA_LOW && address < SOC_RTC_DATA_HIGH) {
             ESP_LOGD(TAG, "Skipping RTC data segment at %08x\n", data_offs);
             ESP_LOGD(TAG, "Skipping RTC data segment at %08x\n", data_offs);
             load = false;
             load = false;
         }
         }

+ 15 - 10
components/bootloader_support/src/esp_image_format.c

@@ -108,16 +108,6 @@ esp_err_t esp_image_basic_verify(uint32_t src_addr, bool log_errors, uint32_t *p
         *p_length = 0;
         *p_length = 0;
     }
     }
 
 
-    if (src_addr % SPI_FLASH_MMU_PAGE_SIZE != 0) {
-        /* Image must start on a 64KB boundary
-
-           (This is not a technical limitation, only the flash mapped regions need to be 64KB aligned.  But the most
-           consistent way to do this is to have all the offsets internal to the image correctly 64KB aligned, and then
-           start the image on a 64KB boundary also.)
-         */
-        return ESP_ERR_INVALID_ARG;
-    }
-
     err = esp_image_load_header(src_addr, log_errors, &image_header);
     err = esp_image_load_header(src_addr, log_errors, &image_header);
     if (err != ESP_OK) {
     if (err != ESP_OK) {
         return err;
         return err;
@@ -133,6 +123,21 @@ esp_err_t esp_image_basic_verify(uint32_t src_addr, bool log_errors, uint32_t *p
             return err;
             return err;
         }
         }
 
 
+        uint32_t load_addr = segment_header.load_addr;
+        bool map_segment = (load_addr >= SOC_DROM_LOW && load_addr < SOC_DROM_HIGH)
+            || (load_addr >= SOC_IROM_LOW && load_addr < SOC_IROM_HIGH);
+
+
+        /* Check that flash cache mapped segment aligns correctly from flash it's mapped address,
+           relative to the 64KB page mapping size.
+        */
+        ESP_LOGV(TAG, "segment %d map_segment %d segment_data_offs 0x%x load_addr 0x%x",
+                 i, map_segment, segment_data_offs, load_addr);
+        if (map_segment && ((segment_data_offs % SPI_FLASH_MMU_PAGE_SIZE) != (load_addr % SPI_FLASH_MMU_PAGE_SIZE))) {
+            ESP_LOGE(TAG, "Segment %d has load address 0x%08x, conflict with segment data at 0x%08x",
+                     i, load_addr, segment_data_offs);
+        }
+
         for (int i = 0; i < segment_header.data_len; i += sizeof(buf)) {
         for (int i = 0; i < segment_header.data_len; i += sizeof(buf)) {
             err = bootloader_flash_read(segment_data_offs + i, buf, sizeof(buf), true);
             err = bootloader_flash_read(segment_data_offs + i, buf, sizeof(buf), true);
             if (err != ESP_OK) {
             if (err != ESP_OK) {

+ 4 - 0
components/bootloader_support/test/component.mk

@@ -0,0 +1,4 @@
+#
+#Component Makefile
+#
+COMPONENT_ADD_LDFLAGS = -Wl,--whole-archive -l$(COMPONENT_NAME) -Wl,--no-whole-archive

+ 37 - 0
components/bootloader_support/test/test_verify_image.c

@@ -0,0 +1,37 @@
+/*
+ * Tests for bootloader_support esp_image_basic_verify()
+ */
+
+#include <esp_types.h>
+#include <stdio.h>
+#include "rom/ets_sys.h"
+
+#include "freertos/FreeRTOS.h"
+#include "freertos/task.h"
+#include "freertos/semphr.h"
+#include "freertos/queue.h"
+#include "freertos/xtensa_api.h"
+#include "unity.h"
+
+#include "esp_partition.h"
+#include "esp_ota_ops.h"
+#include "esp_image_format.h"
+
+TEST_CASE("Verify bootloader image in flash", "[bootloader_support]")
+{
+    uint32_t image_len = 0;
+    TEST_ASSERT_EQUAL_HEX(ESP_OK, esp_image_basic_verify(0x1000, true, &image_len));
+    TEST_ASSERT_NOT_EQUAL(0, image_len);
+}
+
+TEST_CASE("Verify unit test app image", "[bootloader_support]")
+{
+    uint32_t image_len = 0;
+    const esp_partition_t *running = esp_ota_get_running_partition();
+    TEST_ASSERT_NOT_EQUAL(NULL, running);
+
+    TEST_ASSERT_EQUAL_HEX(ESP_OK, esp_image_basic_verify(running->address, true, &image_len));
+    TEST_ASSERT_NOT_EQUAL(0, image_len);
+    TEST_ASSERT_TRUE(image_len <= running->size);
+}
+

+ 10 - 0
components/soc/esp32/include/soc/soc.h

@@ -149,6 +149,16 @@
 #define  TICKS_PER_US_ROM                            26              // CPU is 80MHz
 #define  TICKS_PER_US_ROM                            26              // CPU is 80MHz
 //}}
 //}}
 
 
+/* Overall memory map */
+#define SOC_IROM_LOW    0x400D0000
+#define SOC_IROM_HIGH   0x40400000
+#define SOC_DROM_LOW    0x3F400000
+#define SOC_DROM_HIGH   0x3F800000
+#define SOC_RTC_IRAM_LOW  0x400C0000
+#define SOC_RTC_IRAM_HIGH 0x400C2000
+#define SOC_RTC_DATA_LOW  0x50000000
+#define SOC_RTC_DATA_HIGH 0x50002000
+
 #define DR_REG_DPORT_BASE                       0x3ff00000
 #define DR_REG_DPORT_BASE                       0x3ff00000
 #define DR_REG_RSA_BASE                         0x3ff02000
 #define DR_REG_RSA_BASE                         0x3ff02000
 #define DR_REG_SHA_BASE                         0x3ff03000
 #define DR_REG_SHA_BASE                         0x3ff03000