]> granicus.if.org Git - esp-idf/commitdiff
bootloader: Check if DRAM segments are going to collide with stack
authorAngus Gratton <angus@espressif.com>
Tue, 20 Dec 2016 05:04:15 +0000 (16:04 +1100)
committerAngus Gratton <angus@espressif.com>
Tue, 20 Dec 2016 05:14:07 +0000 (16:14 +1100)
components/bootloader/src/main/bootloader_start.c
components/esp32/include/soc/cpu.h

index 44de10e87dde3fd0636b9fc6cab151ab82f93a08..bec45f7ce03c3827265027b3966099560e87590d 100644 (file)
@@ -59,7 +59,7 @@ extern void Cache_Flush(int);
 void bootloader_main();
 static void unpack_load_app(const esp_partition_pos_t *app_node);
 void print_flash_info(const esp_image_header_t* pfhdr);
-void set_cache_and_start_app(uint32_t drom_addr,
+static void set_cache_and_start_app(uint32_t drom_addr,
     uint32_t drom_load_addr,
     uint32_t drom_size,
     uint32_t irom_addr,
@@ -365,7 +365,6 @@ void bootloader_main()
     unpack_load_app(&load_part_pos);
 }
 
-
 static void unpack_load_app(const esp_partition_pos_t* partition)
 {
     esp_err_t err;
@@ -413,6 +412,9 @@ static void unpack_load_app(const esp_partition_pos_t* partition)
              image_header.spi_size,
              (unsigned)image_header.entry_addr);
 
+    /* Important: From here on this function cannot access any global data (bss/data segments),
+       as loading the app image may overwrite these.
+    */
     for (int segment = 0; segment < image_header.segment_count; segment++) {
         esp_image_segment_header_t segment_header;
         uint32_t data_offs;
@@ -468,6 +470,31 @@ static void unpack_load_app(const esp_partition_pos_t* partition)
                  segment_header.load_addr, segment_header.data_len, segment_header.data_len, (load)?"load":(map)?"map":"");
 
         if (load) {
+            intptr_t sp, start_addr, end_addr;
+            ESP_LOGV(TAG, "bootloader_mmap data_offs=%08x data_len=%08x", data_offs, segment_header.data_len);
+
+            start_addr = segment_header.load_addr;
+            end_addr = start_addr + segment_header.data_len;
+
+            /* Before loading segment, check it doesn't clobber
+               bootloader RAM... */
+
+            if (end_addr < 0x40000000) {
+                sp = (intptr_t)get_sp();
+                if (end_addr > sp) {
+                    ESP_LOGE(TAG, "Segment %d end address %08x overlaps bootloader stack %08x - can't load",
+                         segment, end_addr, sp);
+                    return;
+                }
+                if (end_addr > sp - 256) {
+                    /* We don't know for sure this is the stack high water mark, so warn if
+                       it seems like we may overflow.
+                    */
+                    ESP_LOGW(TAG, "Segment %d end address %08x close to stack pointer %08x",
+                             segment, end_addr, sp);
+                }
+            }
+
             const void *data = bootloader_mmap(data_offs, segment_header.data_len);
             if(!data) {
                 ESP_LOGE(TAG, "bootloader_mmap(0x%xc, 0x%x) failed",
@@ -488,7 +515,7 @@ static void unpack_load_app(const esp_partition_pos_t* partition)
         image_header.entry_addr);
 }
 
-void set_cache_and_start_app(
+static void set_cache_and_start_app(
     uint32_t drom_addr,
     uint32_t drom_load_addr,
     uint32_t drom_size,
index 4457c81a22c65b71591d0f6afa70d4748ff324d9..aa471a1739bf088700612cfe42d17ff4e38c5e24 100644 (file)
 #define WSR(reg, newval)  asm volatile ("wsr %0, " #reg : : "r" (newval));
 #define XSR(reg, swapval) asm volatile ("xsr %0, " #reg : "+r" (swapval));
 
+/** @brief Read current stack pointer address
+ *
+ */
+static inline void *get_sp()
+{
+    void *sp;
+    asm volatile ("mov %0, sp;" : "=r" (sp));
+    return sp;
+}
+
 /* Return true if the CPU is in an interrupt context
    (PS.UM == 0)
 */