diff --git a/components/esp_mm/port/esp32c6/ext_mem_layout.c b/components/esp_mm/port/esp32c6/ext_mem_layout.c index 9c0004bfdd..e8c200192c 100644 --- a/components/esp_mm/port/esp32c6/ext_mem_layout.c +++ b/components/esp_mm/port/esp32c6/ext_mem_layout.c @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2021-2022 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2021-2024 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -10,15 +10,40 @@ #include "../ext_mem_layout.h" #include "hal/mmu_types.h" +/* NOTE: With ESP-TEE enabled: + * - The start address is moved by the size of TEE IDROM segments since these + * segments are placed at the start of the linear address space + * - TEE IROM and DROM segments are both 64KB (CONFIG_SECURE_TEE_IROM_SIZE, + * CONFIG_SECURE_TEE_DROM_SIZE) for now. Thus, the number of reserved entries + * from the start would be (64KB + 64KB)/MMU_PAGE_SIZE + * - The last few MMU entries are reserved for TEE flash operations. The number + * of reserved entries matches the size of TEE IDROM segments (IROM + DROM) + * plus one additional entry, i.e. (64KB + 64KB)/MMU_PAGE_SIZE + 1 + */ +#if CONFIG_SECURE_ENABLE_TEE +#define TEE_MMU_MEM_REG_START_OFFS (CONFIG_SECURE_TEE_IROM_SIZE + CONFIG_SECURE_TEE_DROM_SIZE) +#define TEE_MMU_RESV_PAGES ((CONFIG_SECURE_TEE_IROM_SIZE + CONFIG_SECURE_TEE_DROM_SIZE) / CONFIG_MMU_PAGE_SIZE) +#define TEE_MMU_MEM_REG_END_OFFS ((TEE_MMU_RESV_PAGES + 1) * CONFIG_MMU_PAGE_SIZE) + +#define MMU_MEM_REG_START_ADDR_W_TEE (SOC_MMU_IRAM0_LINEAR_ADDRESS_LOW + TEE_MMU_MEM_REG_START_OFFS) +#define MMU_MEM_REG_END_ADDR_W_TEE (SOC_MMU_IRAM0_LINEAR_ADDRESS_HIGH - TEE_MMU_MEM_REG_END_OFFS) + +#define MMU_IRAM0_LINEAR_ADDRESS_LOW MMU_MEM_REG_START_ADDR_W_TEE +#define MMU_IRAM0_LINEAR_ADDRESS_HIGH MMU_MEM_REG_END_ADDR_W_TEE +#else +#define MMU_IRAM0_LINEAR_ADDRESS_LOW SOC_MMU_IRAM0_LINEAR_ADDRESS_LOW +#define MMU_IRAM0_LINEAR_ADDRESS_HIGH SOC_MMU_IRAM0_LINEAR_ADDRESS_HIGH +#endif + /** * The start addresses in this list should always be sorted from low to high, as MMU driver will need to * coalesce adjacent regions */ const mmu_mem_region_t g_mmu_mem_regions[SOC_MMU_LINEAR_ADDRESS_REGION_NUM] = { [0] = { - .start = SOC_MMU_IRAM0_LINEAR_ADDRESS_LOW, - .end = SOC_MMU_IRAM0_LINEAR_ADDRESS_HIGH, - .size = SOC_BUS_SIZE(SOC_MMU_IRAM0_LINEAR), + .start = MMU_IRAM0_LINEAR_ADDRESS_LOW, + .end = MMU_IRAM0_LINEAR_ADDRESS_HIGH, + .size = MMU_IRAM0_LINEAR_ADDRESS_HIGH - MMU_IRAM0_LINEAR_ADDRESS_LOW, .bus_id = CACHE_BUS_IBUS0 | CACHE_BUS_DBUS0, .targets = MMU_TARGET_FLASH0, .caps = MMU_MEM_CAP_EXEC | MMU_MEM_CAP_READ | MMU_MEM_CAP_32BIT | MMU_MEM_CAP_8BIT, diff --git a/components/esp_system/CMakeLists.txt b/components/esp_system/CMakeLists.txt index 1443e619d4..b99131ad99 100644 --- a/components/esp_system/CMakeLists.txt +++ b/components/esp_system/CMakeLists.txt @@ -1,4 +1,5 @@ idf_build_get_property(target IDF_TARGET) +idf_build_get_property(esp_tee_build ESP_TEE_BUILD) # On Linux, we only support a few features, hence this simple component registration if(${target} STREQUAL "linux") @@ -22,7 +23,7 @@ if(CONFIG_IDF_ENV_FPGA OR CONFIG_ESP_BRINGUP_BYPASS_RANDOM_SETTING) list(APPEND srcs "fpga_overrides_rng.c") endif() -if(BOOTLOADER_BUILD) +if(BOOTLOADER_BUILD OR esp_tee_build) # "_esp_error_check_failed()" requires spi_flash module # Bootloader relies on some Kconfig options defined in esp_system. idf_component_register(SRCS "${srcs}" REQUIRES spi_flash) diff --git a/components/esp_system/Kconfig b/components/esp_system/Kconfig index 504981640b..136d4616fc 100644 --- a/components/esp_system/Kconfig +++ b/components/esp_system/Kconfig @@ -121,7 +121,7 @@ menu "ESP System Settings" config ESP_SYSTEM_PMP_IDRAM_SPLIT bool "Enable IRAM/DRAM split protection" - depends on SOC_CPU_IDRAM_SPLIT_USING_PMP + depends on SOC_CPU_IDRAM_SPLIT_USING_PMP && !SECURE_ENABLE_TEE default "y" help If enabled, the CPU watches all the memory access and raises an exception in case @@ -141,6 +141,13 @@ menu "ESP System Settings" Warning: on ESP32-P4 this will also mark the memory area used for BOOTLOADER_RESERVE_RTC_MEM as executable. If you consider this a security risk then do not activate this option. + config ESP_SYSTEM_MEMPROT_FEATURE_VIA_TEE + bool "Enable memory protection (via TEE)" + depends on SECURE_ENABLE_TEE + default "y" + help + This option enables the default memory protection provided by TEE. + config ESP_SYSTEM_MEMPROT_FEATURE bool "Enable memory protection" depends on SOC_MEMPROT_SUPPORTED @@ -592,7 +599,8 @@ menu "ESP System Settings" config ESP_SYSTEM_HW_STACK_GUARD bool "Hardware stack guard" - depends on SOC_ASSIST_DEBUG_SUPPORTED + # TODO: [ESP-TEE] IDF-10770 + depends on SOC_ASSIST_DEBUG_SUPPORTED && !SECURE_ENABLE_TEE default y help This config allows to trigger a panic interrupt when Stack Pointer register goes out of allocated stack diff --git a/components/esp_system/ld/esp32c6/memory.ld.in b/components/esp_system/ld/esp32c6/memory.ld.in index 389113a128..4345cd201f 100644 --- a/components/esp_system/ld/esp32c6/memory.ld.in +++ b/components/esp_system/ld/esp32c6/memory.ld.in @@ -15,7 +15,13 @@ #include "sdkconfig.h" #include "ld.common" -#define SRAM_SEG_START 0x40800000 +#if !CONFIG_SECURE_ENABLE_TEE +#define SRAM_SEG_START (0x40800000) +#else +#define SRAM_SEG_START (0x40800000 + CONFIG_SECURE_TEE_IRAM_SIZE + CONFIG_SECURE_TEE_DRAM_SIZE) +#define FLASH_SEG_OFFSET (CONFIG_SECURE_TEE_IROM_SIZE + CONFIG_SECURE_TEE_DROM_SIZE) +#endif // CONFIG_SECURE_ENABLE_TEE + #define SRAM_SEG_END 0x4086E610 /* 2nd stage bootloader iram_loader_seg start address */ #define SRAM_SEG_SIZE SRAM_SEG_END - SRAM_SEG_START @@ -35,8 +41,14 @@ MEMORY */ #if CONFIG_APP_BUILD_USE_FLASH_SECTIONS +#if CONFIG_SECURE_ENABLE_TEE + /* Flash mapped instruction data */ + irom_seg (RX) : org = 0x42000020 + FLASH_SEG_OFFSET, + len = IDRAM0_2_SEG_SIZE - FLASH_SEG_OFFSET - 0x20 +#else /* Flash mapped instruction data */ irom_seg (RX) : org = 0x42000020, len = IDRAM0_2_SEG_SIZE - 0x20 +#endif /** * (0x20 offset above is a convenience for the app binary image generation. @@ -54,8 +66,14 @@ MEMORY sram_seg (RWX) : org = SRAM_SEG_START, len = SRAM_SEG_SIZE #if CONFIG_APP_BUILD_USE_FLASH_SECTIONS +#if CONFIG_SECURE_ENABLE_TEE /* Flash mapped constant data */ + drom_seg (R) : org = 0x42000020 + FLASH_SEG_OFFSET, + len = IDRAM0_2_SEG_SIZE - FLASH_SEG_OFFSET - 0x20 +#else + /* Flash mapped instruction data */ drom_seg (R) : org = 0x42000020, len = IDRAM0_2_SEG_SIZE - 0x20 +#endif /* (See irom_seg for meaning of 0x20 offset in the above.) */ #endif // CONFIG_APP_BUILD_USE_FLASH_SECTIONS diff --git a/components/esp_system/ld/esp32c6/sections.ld.in b/components/esp_system/ld/esp32c6/sections.ld.in index da8a695be4..407d34390a 100644 --- a/components/esp_system/ld/esp32c6/sections.ld.in +++ b/components/esp_system/ld/esp32c6/sections.ld.in @@ -173,11 +173,22 @@ SECTIONS /* Vectors go to start of IRAM */ ASSERT(ABSOLUTE(.) % 0x100 == 0, "vector address must be 256 byte aligned"); + _vector_table_start = ABSOLUTE(.); KEEP(*(.exception_vectors_table.text)); KEEP(*(.exception_vectors.text)); ALIGNED_SYMBOL(4, _invalid_pc_placeholder) + /* esp_tee_config_t structure: used to share information between the TEE and REE + * (e.g. interrupt handler addresses, REE flash text-rodata boundaries, etc.) + * This symbol is expected by the TEE at an offset of 0x300 from the vector table start. + */ +#if CONFIG_SECURE_ENABLE_TEE + ALIGNED_SYMBOL(0x10, _esp_tee_app_cfg) + ASSERT(ABSOLUTE(.) == _vector_table_start + 0x2e0, "esp_tee_app_cfg must be at an offset 0x2e0 from the vector table start"); + *libesp_tee.a:(.esp_tee_app_cfg); +#endif + /* Code marked as running out of IRAM */ _iram_text_start = ABSOLUTE(.); diff --git a/components/esp_system/port/cpu_start.c b/components/esp_system/port/cpu_start.c index 3303dfaf65..a65bb3a56b 100644 --- a/components/esp_system/port/cpu_start.c +++ b/components/esp_system/port/cpu_start.c @@ -419,6 +419,15 @@ void IRAM_ATTR call_start_cpu0(void) esp_cpu_intr_set_mtvt_addr(&_mtvt_table); #endif + /* NOTE: When ESP-TEE is enabled, this sets up the callback function + * which redirects all the interrupt management for the REE (user app) + * to the TEE by raising the appropriate service calls. + */ +#if CONFIG_SECURE_ENABLE_TEE + extern uint32_t esp_tee_service_call(int argc, ...); + esprv_int_setup_mgmt_cb((void *)esp_tee_service_call); +#endif + rst_reas[0] = esp_rom_get_reset_reason(0); #if !CONFIG_ESP_SYSTEM_SINGLE_CORE_MODE rst_reas[1] = esp_rom_get_reset_reason(1); @@ -606,8 +615,12 @@ void IRAM_ATTR call_start_cpu0(void) #else ESP_EARLY_LOGI(TAG, "Multicore app"); #endif - + /* NOTE: When ESP-TEE is enabled, it configures its own memory protection + * scheme using the CPU-inherent features PMP and PMA and the APM peripheral. + */ +#if !CONFIG_SECURE_ENABLE_TEE bootloader_init_mem(); +#endif #if !CONFIG_ESP_SYSTEM_SINGLE_CORE_MODE s_cpu_up[0] = true; diff --git a/components/esp_system/startup_funcs.c b/components/esp_system/startup_funcs.c index a4b33ba653..f57fff7a58 100644 --- a/components/esp_system/startup_funcs.c +++ b/components/esp_system/startup_funcs.c @@ -63,6 +63,12 @@ ESP_SYSTEM_INIT_FN(init_show_cpu_freq, CORE, BIT(0), 10) return ESP_OK; } +/* NOTE: When ESP-TEE is enabled, the Brownout Detection module is part + * of the TEE and is initialized in the TEE startup routine itself. + * It is protected from all REE accesses through memory protection mechanisms, + * as it is a critical module for device functioning. + */ +#if !CONFIG_SECURE_ENABLE_TEE ESP_SYSTEM_INIT_FN(init_brownout, CORE, BIT(0), 104) { // [refactor-todo] leads to call chain rtc_is_register (driver) -> esp_intr_alloc (esp32/esp32s2) -> @@ -76,6 +82,7 @@ ESP_SYSTEM_INIT_FN(init_brownout, CORE, BIT(0), 104) #endif // CONFIG_ESP_BROWNOUT_DET return ESP_OK; } +#endif ESP_SYSTEM_INIT_FN(init_newlib_time, CORE, BIT(0), 105) { diff --git a/components/heap/port/esp32c6/memory_layout.c b/components/heap/port/esp32c6/memory_layout.c index 3c0aceb7b0..05dadf5714 100644 --- a/components/heap/port/esp32c6/memory_layout.c +++ b/components/heap/port/esp32c6/memory_layout.c @@ -12,6 +12,11 @@ #include "heap_memory_layout.h" #include "esp_heap_caps.h" +#if CONFIG_SECURE_ENABLE_TEE +#define SRAM_DIRAM_TEE_ORG (SOC_DIRAM_IRAM_LOW) +#define SRAM_DIRAM_TEE_END (SRAM_DIRAM_TEE_ORG + CONFIG_SECURE_TEE_IRAM_SIZE + CONFIG_SECURE_TEE_DRAM_SIZE) +#endif + /** * @brief Memory type descriptors. These describe the capabilities of a type of memory in the SoC. * Each type of memory map consists of one or more regions in the address space. @@ -95,6 +100,14 @@ SOC_RESERVE_MEMORY_REGION((intptr_t)&_data_start, (intptr_t)&_heap_start, dram_d // Target has a shared D/IRAM virtual address, no need to calculate I_D_OFFSET like previous chips SOC_RESERVE_MEMORY_REGION((intptr_t)&_iram_start, (intptr_t)&_iram_end, iram_code); +/* NOTE: When ESP-TEE is enabled, the start of the internal SRAM + * is used by the TEE and is protected from any REE access using + * memory protection mechanisms employed by ESP-TEE. + */ +#if CONFIG_SECURE_ENABLE_TEE +SOC_RESERVE_MEMORY_REGION((intptr_t)SRAM_DIRAM_TEE_ORG, (intptr_t)(SRAM_DIRAM_TEE_END), tee_diram); +#endif + #ifdef CONFIG_ESP_SYSTEM_ALLOW_RTC_FAST_MEM_AS_HEAP SOC_RESERVE_MEMORY_REGION(SOC_RTC_DRAM_LOW, (intptr_t)&_rtc_force_slow_end, rtcram_data); #endif