.iram_loader.text :
{
. = ALIGN (16);
- _stext = .;
_loader_text_start = ABSOLUTE(.);
*(.stub .gnu.warning .gnu.linkonce.literal.* .gnu.linkonce.t.*.literal .gnu.linkonce.t.*)
*(.iram1 .iram1.*) /* catch stray IRAM_ATTR */
*(.fini)
*(.gnu.version)
_loader_text_end = ABSOLUTE(.);
- _etext = .;
} > iram_loader_seg
.iram.text :
--- /dev/null
+// Copyright 2018 Espressif Systems (Shanghai) PTE LTD
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#pragma once
+
+#include <stddef.h>
+
+/**
+ * @brief Check if half-open intervals overlap
+ *
+ * @param start1 interval 1 start
+ * @param end1 interval 1 end
+ * @param start2 interval 2 start
+ * @param end2 interval 2 end
+ * @return true iff [start1; end1) overlaps [start2; end2)
+ */
+static inline bool bootloader_util_regions_overlap(
+ const intptr_t start1, const intptr_t end1,
+ const intptr_t start2, const intptr_t end2)
+{
+ return (end1 > start2 && end2 > start1) ||
+ !(end1 <= start2 || end2 <= start1);
+}
#include <bootloader_flash.h>
#include <bootloader_random.h>
#include <bootloader_sha.h>
+#include "bootloader_util.h"
/* Checking signatures as part of verifying images is necessary:
- Always if secure boot is enabled
(Means loaded code isn't executable until after the secure boot check.)
*/
static uint32_t ram_obfs_value[2];
+
+/* Range of IRAM used by the loader, defined in ld script */
+extern int _loader_text_start;
+extern int _loader_text_end;
#endif
/* Return true if load_addr is an address the bootloader should load into */
(do_load)?"load":(is_mapping)?"map":"");
}
+
+#ifdef BOOTLOADER_BUILD
+ /* Before loading segment, check it doesn't clobber bootloader RAM. */
if (do_load) {
- /* Before loading segment, check it doesn't clobber bootloader RAM... */
- uint32_t end_addr = load_addr + data_len;
- if (end_addr < 0x40000000) {
+ const intptr_t load_end = load_addr + data_len;
+ if (load_end <= (intptr_t) SOC_DIRAM_DRAM_HIGH) {
+ /* Writing to DRAM */
intptr_t sp = (intptr_t)get_sp();
- if (end_addr > sp - STACK_LOAD_HEADROOM) {
- ESP_LOGE(TAG, "Segment %d end address 0x%08x too high (bootloader stack 0x%08x liimit 0x%08x)",
- index, end_addr, sp, sp - STACK_LOAD_HEADROOM);
+ if (load_end > sp - STACK_LOAD_HEADROOM) {
+ /* Bootloader .data/.rodata/.bss is above the stack, so this
+ * also checks that we aren't overwriting these segments.
+ *
+ * TODO: This assumes specific arrangement of sections we have
+ * in the ESP32. Rewrite this in a generic way to support other
+ * layouts.
+ */
+ ESP_LOGE(TAG, "Segment %d end address 0x%08x too high (bootloader stack 0x%08x limit 0x%08x)",
+ index, load_end, sp, sp - STACK_LOAD_HEADROOM);
+ return ESP_ERR_IMAGE_INVALID;
+ }
+ } else {
+ /* Writing to IRAM */
+ const intptr_t loader_iram_start = (intptr_t) &_loader_text_start;
+ const intptr_t loader_iram_end = (intptr_t) &_loader_text_end;
+
+ if (bootloader_util_regions_overlap(loader_iram_start, loader_iram_end,
+ load_addr, load_end)) {
+ ESP_LOGE(TAG, "Segment %d (0x%08x-0x%08x) overlaps bootloader IRAM (0x%08x-0x%08x)",
+ index, load_addr, load_end, loader_iram_start, loader_iram_end);
return ESP_ERR_IMAGE_INVALID;
}
}
}
+#endif // BOOTLOADER_BUILD
+
#ifndef BOOTLOADER_BUILD
uint32_t free_page_count = spi_flash_mmap_get_free_pages(SPI_FLASH_MMAP_DATA);
ESP_LOGD(TAG, "free data page_count 0x%08x",free_page_count);
#include "freertos/xtensa_api.h"
#include "unity.h"
#include "bootloader_common.h"
+#include "bootloader_util.h"
#include "esp_partition.h"
#include "esp_ota_ops.h"
#include "esp_image_format.h"
check_label_search(25, "phy, 1234567890123456, nvs1", "12345678901234567", true);
}
+
+
+TEST_CASE("Test regions_overlap", "[bootloader_support]")
+{
+ TEST_ASSERT( bootloader_util_regions_overlap(1, 2, 1, 2) );
+
+ TEST_ASSERT( bootloader_util_regions_overlap(1, 2, 0, 2) );
+ TEST_ASSERT( bootloader_util_regions_overlap(1, 2, 1, 3) );
+ TEST_ASSERT( bootloader_util_regions_overlap(1, 2, 0, 3) );
+
+ TEST_ASSERT( bootloader_util_regions_overlap(0, 2, 1, 2) );
+ TEST_ASSERT( bootloader_util_regions_overlap(1, 3, 1, 2) );
+ TEST_ASSERT( bootloader_util_regions_overlap(0, 3, 1, 2) );
+
+ TEST_ASSERT( !bootloader_util_regions_overlap(2, 3, 1, 2) );
+ TEST_ASSERT( !bootloader_util_regions_overlap(1, 2, 2, 3) );
+
+ TEST_ASSERT( !bootloader_util_regions_overlap(3, 4, 1, 2) );
+ TEST_ASSERT( !bootloader_util_regions_overlap(1, 2, 3, 4) );
+}