diff --git a/components/esp_hw_support/port/esp32c5/cpu_region_protect.c b/components/esp_hw_support/port/esp32c5/cpu_region_protect.c index 7b3a6dc369..dd78e7f184 100644 --- a/components/esp_hw_support/port/esp32c5/cpu_region_protect.c +++ b/components/esp_hw_support/port/esp32c5/cpu_region_protect.c @@ -51,31 +51,45 @@ static void esp_cpu_configure_invalid_regions(void) PMA_RESET_AND_ENTRY_SET_TOR(3, SOC_IROM_MASK_LOW, PMA_NONE); PMA_RESET_AND_ENTRY_SET_TOR(4, SOC_DROM_MASK_HIGH, PMA_TOR | PMA_RX); - // 3. Gap between ROM & RAM - PMA_RESET_AND_ENTRY_SET_TOR(5, SOC_DROM_MASK_HIGH, PMA_NONE); - PMA_RESET_AND_ENTRY_SET_TOR(6, SOC_IRAM_LOW, PMA_TOR | PMA_NONE); + // 3. Gap between DRAM and I_Cache + PMA_RESET_AND_ENTRY_SET_TOR(5, SOC_IRAM_HIGH, PMA_NONE); + PMA_RESET_AND_ENTRY_SET_TOR(6, SOC_IROM_LOW, PMA_TOR | PMA_NONE); - // 4. Gap between DRAM and I_Cache - PMA_RESET_AND_ENTRY_SET_TOR(7, SOC_IRAM_HIGH, PMA_NONE); - PMA_RESET_AND_ENTRY_SET_TOR(8, SOC_IROM_LOW, PMA_TOR | PMA_NONE); - - // 5. ROM has configured the MSPI region with RX permission, we should add W attribute for psram and lock the configuration + // 4. ROM has configured the MSPI region with RX permission, we should add W attribute for psram and lock the configuration // This function sets invalid regions but this is a valid memory region configuration that could have // been configured using PMP as well, but due to insufficient PMP entries we are configuring this using PMA. // This entry is also required to be set using PMA because the region needs to be configured as cacheable. - PMA_RESET_AND_ENTRY_SET_NAPOT(9, SOC_IROM_LOW, (SOC_IROM_HIGH - SOC_IROM_LOW), PMA_NAPOT | PMA_RWX); + PMA_RESET_AND_ENTRY_SET_NAPOT(7, SOC_IROM_LOW, (SOC_IROM_HIGH - SOC_IROM_LOW), PMA_NAPOT | PMA_RWX); - // 6. Gap between D_Cache & LP_RAM - PMA_RESET_AND_ENTRY_SET_TOR(10, SOC_DROM_HIGH, PMA_NONE); - PMA_RESET_AND_ENTRY_SET_TOR(11, SOC_RTC_IRAM_LOW, PMA_TOR | PMA_NONE); + // 5. Gap between D_Cache & LP_RAM + PMA_RESET_AND_ENTRY_SET_TOR(8, SOC_DROM_HIGH, PMA_NONE); + PMA_RESET_AND_ENTRY_SET_TOR(9, SOC_RTC_IRAM_LOW, PMA_TOR | PMA_NONE); - // 7. Gap between LP memory & peripheral addresses - PMA_RESET_AND_ENTRY_SET_TOR(12, SOC_RTC_IRAM_HIGH, PMA_NONE); - PMA_RESET_AND_ENTRY_SET_TOR(13, SOC_PERIPHERAL_LOW, PMA_TOR | PMA_NONE); + // 6. End of address space + PMA_RESET_AND_ENTRY_SET_TOR(10, SOC_PERIPHERAL_HIGH, PMA_NONE); + PMA_RESET_AND_ENTRY_SET_TOR(11, UINT32_MAX, PMA_TOR | PMA_NONE); - // 8. End of address space - PMA_RESET_AND_ENTRY_SET_TOR(14, SOC_PERIPHERAL_HIGH, PMA_NONE); - PMA_RESET_AND_ENTRY_SET_TOR(15, UINT32_MAX, PMA_TOR | PMA_NONE); + /* NOTE: ESP-TEE [IDF-13827] + * + * Reserving some PMA entries to repurpose them for partitioning the + * TEE SRAM as IRAM (RX) and DRAM (RW). Thus, with ESP-TEE enabled, + * invalid region accesses to the LP memory → peripherals and + * ROM → RAM regions will not raise exceptions. (treated as no-ops) + */ +#if !CONFIG_SECURE_ENABLE_TEE + // 9. Gap between ROM & RAM + PMA_RESET_AND_ENTRY_SET_TOR(12, SOC_DROM_MASK_HIGH, PMA_NONE); + PMA_RESET_AND_ENTRY_SET_TOR(13, SOC_IRAM_LOW, PMA_TOR | PMA_NONE); + + // 10. Gap between LP memory & peripheral addresses + PMA_RESET_AND_ENTRY_SET_TOR(14, SOC_RTC_IRAM_HIGH, PMA_NONE); + PMA_RESET_AND_ENTRY_SET_TOR(15, SOC_PERIPHERAL_LOW, PMA_TOR | PMA_NONE); +#else + PMA_ENTRY_CFG_RESET(12); + PMA_ENTRY_CFG_RESET(13); + PMA_ENTRY_CFG_RESET(14); + PMA_ENTRY_CFG_RESET(15); +#endif } void esp_cpu_configure_region_protection(void) diff --git a/components/esp_tee/Kconfig.projbuild b/components/esp_tee/Kconfig.projbuild index e52ae6aacc..39552c1de6 100644 --- a/components/esp_tee/Kconfig.projbuild +++ b/components/esp_tee/Kconfig.projbuild @@ -19,8 +19,8 @@ menu "ESP-TEE (Trusted Execution Environment)" config SECURE_TEE_DRAM_SIZE hex "DRAM region size" - default 0x5000 - range 0x4000 0x7000 + default 0x4000 + range 0x3000 0x7000 help This configuration sets the DRAM size for the TEE module. This should be 256-byte (0x100) aligned. diff --git a/components/esp_tee/subproject/main/ld/elf_misc.ld.in b/components/esp_tee/subproject/main/ld/elf_misc.ld.in new file mode 100644 index 0000000000..f55edb267d --- /dev/null +++ b/components/esp_tee/subproject/main/ld/elf_misc.ld.in @@ -0,0 +1,74 @@ +#include "sdkconfig.h" + + /** + * This section is not included in the binary image; it is only present in the ELF file. + * It is used to keep certain symbols in the ELF file. + */ + .noload 0 (INFO) : + { + /* Reserve first 4 bytes as zero for vars pointed to NULL */ + . = 0; + LONG(0); + _noload_keep_in_elf_start = ABSOLUTE(.); + KEEP(*(.noload_keep_in_elf .noload_keep_in_elf.*)) + mapping[noload_keep_in_elf] + _noload_keep_in_elf_end = ABSOLUTE(.); + } + + /* DWARF 1 */ + .debug 0 : { *(.debug) } + .line 0 : { *(.line) } + /* GNU DWARF 1 extensions */ + .debug_srcinfo 0 : { *(.debug_srcinfo) } + .debug_sfnames 0 : { *(.debug_sfnames) } + /* DWARF 1.1 and DWARF 2 */ + .debug_aranges 0 : { *(.debug_aranges) } + .debug_pubnames 0 : { *(.debug_pubnames) } + /* DWARF 2 */ + .debug_info 0 : { *(.debug_info .gnu.linkonce.wi.*) } + .debug_abbrev 0 : { *(.debug_abbrev) } + .debug_line 0 : { *(.debug_line) } + .debug_frame 0 : { *(.debug_frame) } + .debug_str 0 : { *(.debug_str) } + .debug_loc 0 : { *(.debug_loc) } + .debug_macinfo 0 : { *(.debug_macinfo) } + .debug_pubtypes 0 : { *(.debug_pubtypes) } + /* DWARF 3 */ + .debug_ranges 0 : { *(.debug_ranges) } + /* SGI/MIPS DWARF 2 extensions */ + .debug_weaknames 0 : { *(.debug_weaknames) } + .debug_funcnames 0 : { *(.debug_funcnames) } + .debug_typenames 0 : { *(.debug_typenames) } + .debug_varnames 0 : { *(.debug_varnames) } + /* GNU DWARF 2 extensions */ + .debug_gnu_pubnames 0 : { *(.debug_gnu_pubnames) } + .debug_gnu_pubtypes 0 : { *(.debug_gnu_pubtypes) } + /* DWARF 4 */ + .debug_types 0 : { *(.debug_types) } + /* DWARF 5 */ + .debug_addr 0 : { *(.debug_addr) } + .debug_line_str 0 : { *(.debug_line_str) } + .debug_loclists 0 : { *(.debug_loclists) } + .debug_macro 0 : { *(.debug_macro) } + .debug_names 0 : { *(.debug_names) } + .debug_rnglists 0 : { *(.debug_rnglists) } + .debug_str_offsets 0 : { *(.debug_str_offsets) } + + .comment 0 : { *(.comment) } + .note.GNU-stack 0: { *(.note.GNU-stack) } + +#if CONFIG_IDF_TARGET_ARCH_RISCV + .riscv.attributes 0: { *(.riscv.attributes) } + + /DISCARD/ : + { + /** + * Discarding .rela.* sections results in the following mapping: + * .rela.text.* -> .text.* + * .rela.data.* -> .data.* + * And so forth... + */ + *(.rela.*) + *(.got .got.plt) /* TODO: GCC-382 */ + } +#endif diff --git a/components/esp_tee/subproject/main/ld/esp32c5/esp_tee.ld.in b/components/esp_tee/subproject/main/ld/esp32c5/esp_tee.ld.in index 426db2990d..73cc9a4599 100644 --- a/components/esp_tee/subproject/main/ld/esp32c5/esp_tee.ld.in +++ b/components/esp_tee/subproject/main/ld/esp32c5/esp_tee.ld.in @@ -1,32 +1,29 @@ /* - * SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2024-2025 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ #include "sdkconfig.h" +#include "ld.common" -#define SRAM_IRAM_START (0x40800000) -#define SRAM_IRAM_TEE_ORG (SRAM_IRAM_START) -#define SRAM_DRAM_TEE_ORG (SRAM_IRAM_START) +#define SRAM_TEE_SEG_START (0x40800000) +#define SRAM_REE_SEG_START (SRAM_TEE_SEG_START + CONFIG_SECURE_TEE_IRAM_SIZE + CONFIG_SECURE_TEE_DRAM_SIZE) -#define SRAM_IRAM_ORG (SRAM_IRAM_TEE_ORG + CONFIG_SECURE_TEE_IRAM_SIZE + CONFIG_SECURE_TEE_DRAM_SIZE) +#define SRAM_TEE_DRAM_SIZE (CONFIG_SECURE_TEE_DRAM_SIZE - CONFIG_SECURE_TEE_STACK_SIZE - CONFIG_SECURE_TEE_INTR_STACK_SIZE) +#define SRAM_TEE_DRAM_END (SRAM_TEE_SEG_START + CONFIG_SECURE_TEE_IRAM_SIZE + SRAM_TEE_DRAM_SIZE) -#define SRAM_DRAM_TEE_SIZE (CONFIG_SECURE_TEE_DRAM_SIZE - CONFIG_SECURE_TEE_STACK_SIZE - CONFIG_SECURE_TEE_INTR_STACK_SIZE) -#define SRAM_DRAM_TEE_END (SRAM_DRAM_TEE_ORG + CONFIG_SECURE_TEE_IRAM_SIZE + SRAM_DRAM_TEE_SIZE) - -#define I_D_SRAM_TEE_SIZE (CONFIG_SECURE_TEE_IRAM_SIZE + SRAM_DRAM_TEE_SIZE) +#define SRAM_TEE_SEG_SIZE (CONFIG_SECURE_TEE_IRAM_SIZE + SRAM_TEE_DRAM_SIZE) /* TEE interrupt stack is placed at the end of the TEE DRAM segment. * The top of the TEE stack is before the end of interrupt stack * and the bottom of the stack is at _heap_end. */ -#define SRAM_STACK_TEE_ORG (SRAM_DRAM_TEE_END) -#define SRAM_INTR_STACK_TEE_ORG (SRAM_DRAM_TEE_END + CONFIG_SECURE_TEE_STACK_SIZE) +#define SRAM_TEE_STACK_SEG_START (SRAM_TEE_DRAM_END) +#define SRAM_TEE_INTR_STACK_SEG_START (SRAM_TEE_DRAM_END + CONFIG_SECURE_TEE_STACK_SIZE) -#define FLASH_IROM_TEE_ORG (0x42000000) -#define FLASH_DROM_TEE_ORG (0x42000000) -#define I_D_FLASH_TEE_SIZE (CONFIG_SECURE_TEE_IROM_SIZE + CONFIG_SECURE_TEE_DROM_SIZE) +#define FLASH_TEE_SEG_START (0x42000000) +#define FLASH_TEE_SEG_SIZE (CONFIG_SECURE_TEE_IROM_SIZE + CONFIG_SECURE_TEE_DROM_SIZE) /** * These values are the same in every app binary for the same chip target. @@ -36,9 +33,9 @@ */ #if CONFIG_ESP_DEBUG_INCLUDE_OCD_STUB_BINS -PROVIDE ( esp_tee_app_config = SRAM_IRAM_ORG + 0x22b0 ); +PROVIDE ( esp_tee_app_config = SRAM_REE_SEG_START + 0x22b0 ); #else -PROVIDE ( esp_tee_app_config = SRAM_IRAM_ORG + 0x2b0 ); +PROVIDE ( esp_tee_app_config = SRAM_REE_SEG_START + 0x2b0 ); #endif PROVIDE ( GDMA = 0x60080000 ); @@ -48,60 +45,95 @@ ENTRY(esp_tee_init); MEMORY { -/* IRAM Configuration */ - iram_tee_seg (RX) : org = SRAM_IRAM_TEE_ORG, len = I_D_SRAM_TEE_SIZE +/* Flash text section */ + irom_tee_seg (RX): org = FLASH_TEE_SEG_START + 0x20, len = FLASH_TEE_SEG_SIZE - 0x20 -/* DRAM Configuration */ - dram_tee_seg (RW) : org = SRAM_DRAM_TEE_ORG, len = I_D_SRAM_TEE_SIZE +/* Flash data section */ + drom_tee_seg (R) : org = FLASH_TEE_SEG_START + 0x20, len = FLASH_TEE_SEG_SIZE - 0x20 -/* TEE Stack Configuration */ - stack_tee_seg (RW) : org = SRAM_STACK_TEE_ORG, len = CONFIG_SECURE_TEE_STACK_SIZE +/* I/DRAM section */ + sram_tee_seg (RWX) : org = SRAM_TEE_SEG_START, len = SRAM_TEE_SEG_SIZE -/* TEE Interrupt Stack Configuration */ - intr_stack_tee_seg (RW) : org = SRAM_INTR_STACK_TEE_ORG, len = CONFIG_SECURE_TEE_INTR_STACK_SIZE +/* Stack section */ + stack_tee_seg (RW) : org = SRAM_TEE_STACK_SEG_START, len = CONFIG_SECURE_TEE_STACK_SIZE -/* TEE flash data section */ - flash_data_seg (R) : org = FLASH_DROM_TEE_ORG + 0x20, len = I_D_FLASH_TEE_SIZE - 0x20 - -/* TEE flash text section */ - flash_text_seg (RX): org = FLASH_IROM_TEE_ORG + 0x20, len = I_D_FLASH_TEE_SIZE - 0x20 +/* Interrupt stack section */ + intr_stack_tee_seg (RW) : org = SRAM_TEE_INTR_STACK_SEG_START, len = CONFIG_SECURE_TEE_INTR_STACK_SIZE } SECTIONS { - /** - * This section is required to skip .iram.tee_text area because iram_tee_seg and - * dram_tee_seg reflect the same address space on different buses. - */ - .dram.tee_dummy (NOLOAD): + .iram.tee.text : { - . = ORIGIN(dram_tee_seg) + CONFIG_SECURE_TEE_IRAM_SIZE; - } > dram_tee_seg + /* Vectors go to start of IRAM */ + ASSERT(ABSOLUTE(.) % 0x100 == 0, "vector address must be 256 byte aligned"); + _tee_vec_start = ABSOLUTE(.); + KEEP(*(.exception_vectors_table.text)); + KEEP(*(.exception_vectors.text)); + ALIGNED_SYMBOL(4, _invalid_pc_placeholder) + _tee_vec_end = ABSOLUTE(.); - .dram.tee.bss (NOLOAD) : - { - . = ALIGN (8); - _tee_dram_start = ABSOLUTE(.); - _tee_bss_start = ABSOLUTE(.); - *(.bss .bss.*) - *(.sbss .sbss.*) - . = ALIGN (8); - _tee_bss_end = ABSOLUTE(.); - } > dram_tee_seg + /* Code marked as running out of IRAM */ + _tee_iram_start = ABSOLUTE(.); + *(.iram1 .iram1.*) + /* TEE initialization */ + *libmain.a:esp_tee_init.c*(.literal .text .literal.* .text.*) + *libmain.a:esp_tee_secure_sys_cfg.c*(.literal .text .literal.* .text.*) + *libmain.a:esp_tee_pmp_pma_prot_cfg.c*(.literal .text .literal.* .text.*) + *libmain.a:esp_tee_apm_prot_cfg.c*(.literal .text .literal.* .text.*) + *libmain.a:brownout.c*(.literal .text .literal.* .text.*) + *libmain.a:multi_heap.c*(.literal .text .literal.* .text.*) + /* Panic handler */ + *libmain.a:esp_tee_panic.c*(.literal .text .literal.* .text.*) + *libmain.a:panic_helper_riscv.c*(.literal .text .literal.* .text.*) + /* Service call execution */ + *libmain.a:esp_tee_vectors_clic.S*(.literal .text .literal.* .text.*) + *libmain.a:esp_secure_dispatcher.c*(.literal .text .literal.* .text.*) + *libmain.a:esp_secure_services_iram.c*(.literal .text .literal.* .text.*) + /* Interrupt configuration */ + *libmain.a:esp_tee_intr.c*(.literal .text .literal.* .text.*) + *libmain.a:esp_tee_apm_intr.c*(.literal .text .literal.* .text.*) + /* HAL */ + *libhal.a:mmu_hal.c*(.literal .text .literal.* .text.*) + *libhal.a:cache_hal.c*(.literal .text .literal.* .text.*) + *libhal.a:wdt_hal_iram.c*(.literal .text .literal.* .text.*) + *libhal.a:apm_hal.c*(.literal .text .literal.* .text.*) + /* IDF components */ + *libbootloader_support.a:*(.literal .text .literal.* .text.*) + *libesp_hw_support.a:*(.literal .text .literal.* .text.*) + *liblog.a:*(.literal .text .literal.* .text.*) + *libriscv.a:*(.literal .text .literal.* .text.*) + /* TEE services: Secure storage, OTA, attestation */ + *libtee_flash_mgr.a:*(.literal .text .literal.* .text.*) + *libtee_sec_storage.a:*(.literal .text .literal.* .text.*) + *libtee_ota_ops.a:*(.literal .text .literal.* .text.*) + *libtee_attestation.a:*(.literal .text .literal.* .text.*) + + /* Align the end of code region as per PMP region granularity */ + ALIGNED_SYMBOL(_esp_pmp_align_size, _tee_iram_end) + } > sram_tee_seg .dram.tee.data : { - _data_start = ABSOLUTE(.); + _tee_dram_start = ABSOLUTE(.); + _tee_data_start = ABSOLUTE(.); *(.data .data.*) *(.sdata .sdata.*) *(.dram1 .dram1.*) - . = ALIGN(4); - _data_end = ABSOLUTE(.); - } > dram_tee_seg + _tee_data_end = ABSOLUTE(.); + } > sram_tee_seg + + .dram.tee.bss (NOLOAD) : + { + ALIGNED_SYMBOL(8, _tee_bss_start) + *(.bss .bss.*) + *(.sbss .sbss.*) + ALIGNED_SYMBOL(8, _tee_bss_end) + } > sram_tee_seg .dram.tee.rodata : { - _rodata_start = ABSOLUTE(.); + _tee_rodata_start = ABSOLUTE(.); /* TEE flash manager */ *libtee_flash_mgr.a:*(.rodata .srodata .rodata.* .srodata.*) *libbootloader_support.a:bootloader_flash.*(.rodata .srodata .rodata.* .srodata.*) @@ -114,189 +146,69 @@ SECTIONS /* HAL (noflash) */ *libhal.a:mmu_hal.c*(.rodata .srodata .rodata.* .srodata.*) *libhal.a:cache_hal.c*(.rodata .srodata .rodata.* .srodata.*) - _rodata_end = ABSOLUTE(.); + _tee_rodata_end = ABSOLUTE(.); _tee_dram_end = ABSOLUTE(.); - } > dram_tee_seg + } > sram_tee_seg - .dram.tee.heap : + .dram.tee.heap (NOLOAD): ALIGN(0x10) { - . = ALIGN (16); _tee_heap_start = ABSOLUTE(.); - . = ORIGIN(dram_tee_seg) + LENGTH(dram_tee_seg); + . = ORIGIN(sram_tee_seg) + LENGTH(sram_tee_seg); _tee_heap_end = ABSOLUTE(.); - } > dram_tee_seg + } > sram_tee_seg - .dram.tee.stack : + .dram.tee.stack (NOLOAD): ALIGN(0x10) { - . = ALIGN (16); _tee_stack_bottom = ABSOLUTE(.); . = ORIGIN(stack_tee_seg) + LENGTH(stack_tee_seg); _tee_stack = ABSOLUTE(.); } > stack_tee_seg - .dram.tee.intr_stack : + .dram.tee.intr_stack (NOLOAD): ALIGN(0x10) { - . = ALIGN (16); _tee_intr_stack_bottom = ABSOLUTE(.); . = ORIGIN(intr_stack_tee_seg) + LENGTH(intr_stack_tee_seg); _tee_intr_stack = ABSOLUTE(.); } > intr_stack_tee_seg - .flash.rodata : + + .flash.tee.rodata : ALIGN(0x10) { - _tee_xip_data_start = ABSOLUTE(.); + _tee_flash_data_start = ABSOLUTE(.); *(.rodata_desc .rodata_desc.*) /* Should be the first. TEE App version info. DO NOT PUT ANYTHING BEFORE IT! */ *(.rodata .rodata.*) *(.srodata .srodata.*) *(.gcc_except_table .gcc_except_table.*) - _tee_xip_data_end = ABSOLUTE(.); - } > flash_data_seg + _tee_flash_data_end = ABSOLUTE(.); + } > drom_tee_seg - .flash.text_dummy (NOLOAD): + .flash.tee.text_dummy (NOLOAD): { - . = ALIGN(ALIGNOF(.flash.rodata)); - /* Create an empty gap as big as .flash.rodata section */ - . = . + SIZEOF(.flash.rodata); - /* Prepare the alignment of the section above. Few bytes (0x20) must be - * added for the mapping header. */ - . = ALIGN(CONFIG_MMU_PAGE_SIZE) + 0x20; - } > flash_text_seg + /* Create an empty gap as big as .flash.tee.rodata section */ + . = ALIGN(ALIGNOF(.flash.tee.rodata)) + SIZEOF(.flash.tee.rodata); + /* Add alignment of MMU page size + 0x20 bytes for the mapping header. */ + . = ALIGN(_esp_mmu_page_size) + 0x20; + } > irom_tee_seg - -/* HAL modules and their memory placement: - * - * +-----------+---------------+--------+ - * | Module | Section | Memory | - * +-----------+---------------+--------+ - * | MMU | text+rodata | SRAM | - * | CACHE | text+rodata | SRAM | - * | WDT | text | SRAM | - * | APM | text | Flash* | - * | AES | text | Flash | - * | SHA | text | Flash | - * | HMAC | text | Flash | - * | DS | text | Flash | - * | ECC | text | Flash | - * | BROWNOUT | text | Flash | - * | EFUSE | text | Flash | - * | LPTIMER | text | Flash | - * | SPI_FLASH | text | Flash | - * +-----------+---------------+--------+ - * - * By default, for ESP-TEE, text sections are placed in SRAM while rodata sections go to the flash. - * Therefore, only HAL modules that require SRAM placement for proper functionality are located there, - * while the remaining modules are placed in flash memory. - */ - - .flash.text : + .flash.tee.text : { - _tee_xip_text_start = ABSOLUTE(.); - /* Secure Services */ - *libmain.a:esp_secure_services.c*(.literal .text .literal.* .text.*) - /* HAL */ - *libhal.a:aes_hal.c*(.literal .text .literal.* .text.*) - *libhal.a:sha_hal.c*(.literal .text .literal.* .text.*) - *libhal.a:hmac_hal.c*(.literal .text .literal.* .text.*) - *libhal.a:ds_hal.c*(.literal .text .literal.* .text.*) - *libhal.a:ecc_hal.c*(.literal .text .literal.* .text.*) - /* NOTE: There is a possibility of APM violations (SPI1 flash protection) - * being triggered with the flash cache disabled */ -#if !CONFIG_SECURE_TEE_EXT_FLASH_MEMPROT_SPI1 - *libhal.a:apm_hal.c*(.literal .text .literal.* .text.*) -#endif - *libhal.a:brownout_hal.c*(.literal .text .literal.* .text.*) - *libesp_hal_mspi.a:spi_flash_hal.c*(.literal .text .literal.* .text.*) - /* These HAL modules have functions marked with the IRAM_ATTR attribute which get placed in the SRAM */ - *libhal.a:efuse_hal.c*(.literal .text .literal.* .text.*) - *libhal.a:lp_timer_hal.c*(.literal .text .literal.* .text.*) - /* Mbedtls for TEE */ - *libmbedtls.a:*(.literal .text .literal.* .text.*) - *libmbedcrypto.a:*(.literal .text .literal.* .text.*) - /* HMAC-DS layer */ - *libesp_security.a:*(.literal .text .literal.* .text.*) - /* NVS flash and related modules */ - *libnvs_flash.a:*(.literal .text .literal.* .text.*) - *libstdc++.a:*(.literal .text .literal.* .text.*) - *libgcc.a:*(.literal .text .literal.* .text.*) - /* esp_partition API */ - *libesp_partition.a:*(.literal .text .literal.* .text.*) - /* TEE attestation module */ - *libattestation.a:*(.literal .text .literal.* .text.*) - *json_generator.a:*(.literal .text .literal.* .text.*) - /* TEE test module */ - *libtest_sec_srv.a:*(.literal .text .literal.* .text.*) - _tee_xip_text_end = ABSOLUTE(.); - _tee_xip_end = ABSOLUTE(.); - } > flash_text_seg - - .iram.tee.text : - { - /* Vectors go to start of IRAM */ - ASSERT(ABSOLUTE(.) % 0x100 == 0, "vector address must be 256 byte aligned"); - _tee_vec_start = ABSOLUTE(.); - KEEP(*(.exception_vectors_table.text)); - KEEP(*(.exception_vectors.text)); - . = ALIGN(4); - _invalid_pc_placeholder = ABSOLUTE(.); - _tee_vec_end = ABSOLUTE(.); - - _tee_iram_start = ABSOLUTE(.); - *(.literal .text .iram1 .literal.* .text.* .iram1.*) + _tee_flash_text_start = ABSOLUTE(.); + *(.literal .text .literal.* .text.*) *(.stub .gnu.warning .gnu.linkonce.literal.* .gnu.linkonce.t.*.literal .gnu.linkonce.t.*) - _tee_iram_end = ABSOLUTE(.); - } > iram_tee_seg + /** + * CPU will try to prefetch up to 16 bytes of of instructions. + * This means that any configuration (e.g. MMU, PMS) must allow + * safe access to up to 16 bytes after the last real instruction, add + * dummy bytes to ensure this + */ + . += _esp_flash_mmap_prefetch_pad_size; + _tee_flash_text_end = ABSOLUTE(.); + } > irom_tee_seg - .riscv.attributes 0: { *(.riscv.attributes) } - - /* DWARF 1 */ - .debug 0 : { *(.debug) } - .line 0 : { *(.line) } - /* GNU DWARF 1 extensions */ - .debug_srcinfo 0 : { *(.debug_srcinfo) } - .debug_sfnames 0 : { *(.debug_sfnames) } - /* DWARF 1.1 and DWARF 2 */ - .debug_aranges 0 : { *(.debug_aranges) } - .debug_pubnames 0 : { *(.debug_pubnames) } - /* DWARF 2 */ - .debug_info 0 : { *(.debug_info .gnu.linkonce.wi.*) } - .debug_abbrev 0 : { *(.debug_abbrev) } - .debug_line 0 : { *(.debug_line) } - .debug_frame 0 : { *(.debug_frame) } - .debug_str 0 : { *(.debug_str) } - .debug_loc 0 : { *(.debug_loc) } - .debug_macinfo 0 : { *(.debug_macinfo) } - .debug_pubtypes 0 : { *(.debug_pubtypes) } - /* DWARF 3 */ - .debug_ranges 0 : { *(.debug_ranges) } - /* SGI/MIPS DWARF 2 extensions */ - .debug_weaknames 0 : { *(.debug_weaknames) } - .debug_funcnames 0 : { *(.debug_funcnames) } - .debug_typenames 0 : { *(.debug_typenames) } - .debug_varnames 0 : { *(.debug_varnames) } - /* GNU DWARF 2 extensions */ - .debug_gnu_pubnames 0 : { *(.debug_gnu_pubnames) } - .debug_gnu_pubtypes 0 : { *(.debug_gnu_pubtypes) } - /* DWARF 4 */ - .debug_types 0 : { *(.debug_types) } - /* DWARF 5 */ - .debug_addr 0 : { *(.debug_addr) } - .debug_line_str 0 : { *(.debug_line_str) } - .debug_loclists 0 : { *(.debug_loclists) } - .debug_macro 0 : { *(.debug_macro) } - .debug_names 0 : { *(.debug_names) } - .debug_rnglists 0 : { *(.debug_rnglists) } - .debug_str_offsets 0 : { *(.debug_str_offsets) } - - .comment 0 : { *(.comment) } - .note.GNU-stack 0: { *(.note.GNU-stack) } - - /** - * Discarding .rela.* sections results in the following mapping: - * .rela.text.* -> .text.* - * .rela.data.* -> .data.* - * And so forth... - */ - /DISCARD/ : { *(.rela.*) } +#include "elf_misc.ld.in" } -ASSERT ((_tee_iram_end < _tee_dram_start), "Error: TEE IRAM segment overflowed into the DRAM segment!"); +ASSERT ((_tee_iram_end <= _tee_dram_start), + "Error: TEE IRAM segment overflowed into the DRAM segment! Increase CONFIG_SECURE_TEE_IRAM_SIZE as required."); +ASSERT((_tee_heap_end >= _tee_heap_start + 0x2000), + "Error: TEE heap size is too small - minimum is 8KB (0x2000)! Increase CONFIG_SECURE_TEE_DRAM_SIZE as required."); diff --git a/components/esp_tee/subproject/main/ld/esp32c6/esp_tee.ld.in b/components/esp_tee/subproject/main/ld/esp32c6/esp_tee.ld.in index 9ba9197e1f..121f4f4b65 100644 --- a/components/esp_tee/subproject/main/ld/esp32c6/esp_tee.ld.in +++ b/components/esp_tee/subproject/main/ld/esp32c6/esp_tee.ld.in @@ -1,32 +1,29 @@ /* - * SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2024-2025 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ #include "sdkconfig.h" +#include "ld.common" -#define SRAM_IRAM_START (0x40800000) -#define SRAM_IRAM_TEE_ORG (SRAM_IRAM_START) -#define SRAM_DRAM_TEE_ORG (SRAM_IRAM_START) +#define SRAM_TEE_SEG_START (0x40800000) +#define SRAM_REE_SEG_START (SRAM_TEE_SEG_START + CONFIG_SECURE_TEE_IRAM_SIZE + CONFIG_SECURE_TEE_DRAM_SIZE) -#define SRAM_IRAM_ORG (SRAM_IRAM_TEE_ORG + CONFIG_SECURE_TEE_IRAM_SIZE + CONFIG_SECURE_TEE_DRAM_SIZE) +#define SRAM_TEE_DRAM_SIZE (CONFIG_SECURE_TEE_DRAM_SIZE - CONFIG_SECURE_TEE_STACK_SIZE - CONFIG_SECURE_TEE_INTR_STACK_SIZE) +#define SRAM_TEE_DRAM_END (SRAM_TEE_SEG_START + CONFIG_SECURE_TEE_IRAM_SIZE + SRAM_TEE_DRAM_SIZE) -#define SRAM_DRAM_TEE_SIZE (CONFIG_SECURE_TEE_DRAM_SIZE - CONFIG_SECURE_TEE_STACK_SIZE - CONFIG_SECURE_TEE_INTR_STACK_SIZE) -#define SRAM_DRAM_TEE_END (SRAM_DRAM_TEE_ORG + CONFIG_SECURE_TEE_IRAM_SIZE + SRAM_DRAM_TEE_SIZE) - -#define I_D_SRAM_TEE_SIZE (CONFIG_SECURE_TEE_IRAM_SIZE + SRAM_DRAM_TEE_SIZE) +#define SRAM_TEE_SEG_SIZE (CONFIG_SECURE_TEE_IRAM_SIZE + SRAM_TEE_DRAM_SIZE) /* TEE interrupt stack is placed at the end of the TEE DRAM segment. * The top of the TEE stack is before the end of interrupt stack * and the bottom of the stack is at _heap_end. */ -#define SRAM_STACK_TEE_ORG (SRAM_DRAM_TEE_END) -#define SRAM_INTR_STACK_TEE_ORG (SRAM_DRAM_TEE_END + CONFIG_SECURE_TEE_STACK_SIZE) +#define SRAM_TEE_STACK_SEG_START (SRAM_TEE_DRAM_END) +#define SRAM_TEE_INTR_STACK_SEG_START (SRAM_TEE_DRAM_END + CONFIG_SECURE_TEE_STACK_SIZE) -#define FLASH_IROM_TEE_ORG (0x42000000) -#define FLASH_DROM_TEE_ORG (0x42000000) -#define I_D_FLASH_TEE_SIZE (CONFIG_SECURE_TEE_IROM_SIZE + CONFIG_SECURE_TEE_DROM_SIZE) +#define FLASH_TEE_SEG_START (0x42000000) +#define FLASH_TEE_SEG_SIZE (CONFIG_SECURE_TEE_IROM_SIZE + CONFIG_SECURE_TEE_DROM_SIZE) /** * These values are the same in every app binary for the same chip target. @@ -36,9 +33,9 @@ */ #if CONFIG_ESP_DEBUG_INCLUDE_OCD_STUB_BINS -PROVIDE ( esp_tee_app_config = SRAM_IRAM_ORG + 0x22e0 ); +PROVIDE ( esp_tee_app_config = SRAM_REE_SEG_START + 0x22e0 ); #else -PROVIDE ( esp_tee_app_config = SRAM_IRAM_ORG + 0x2e0 ); +PROVIDE ( esp_tee_app_config = SRAM_REE_SEG_START + 0x2e0 ); #endif PROVIDE ( GDMA = 0x60080000 ); @@ -48,60 +45,95 @@ ENTRY(esp_tee_init); MEMORY { -/* IRAM Configuration */ - iram_tee_seg (RX) : org = SRAM_IRAM_TEE_ORG, len = I_D_SRAM_TEE_SIZE +/* Flash text section */ + irom_tee_seg (RX): org = FLASH_TEE_SEG_START + 0x20, len = FLASH_TEE_SEG_SIZE - 0x20 -/* DRAM Configuration */ - dram_tee_seg (RW) : org = SRAM_DRAM_TEE_ORG, len = I_D_SRAM_TEE_SIZE +/* Flash data section */ + drom_tee_seg (R) : org = FLASH_TEE_SEG_START + 0x20, len = FLASH_TEE_SEG_SIZE - 0x20 -/* TEE Stack Configuration */ - stack_tee_seg (RW) : org = SRAM_STACK_TEE_ORG, len = CONFIG_SECURE_TEE_STACK_SIZE +/* I/DRAM section */ + sram_tee_seg (RWX) : org = SRAM_TEE_SEG_START, len = SRAM_TEE_SEG_SIZE -/* TEE Interrupt Stack Configuration */ - intr_stack_tee_seg (RW) : org = SRAM_INTR_STACK_TEE_ORG, len = CONFIG_SECURE_TEE_INTR_STACK_SIZE +/* Stack section */ + stack_tee_seg (RW) : org = SRAM_TEE_STACK_SEG_START, len = CONFIG_SECURE_TEE_STACK_SIZE -/* TEE flash data section */ - flash_data_seg (R) : org = FLASH_DROM_TEE_ORG + 0x20, len = I_D_FLASH_TEE_SIZE - 0x20 - -/* TEE flash text section */ - flash_text_seg (RX): org = FLASH_IROM_TEE_ORG + 0x20, len = I_D_FLASH_TEE_SIZE - 0x20 +/* Interrupt stack section */ + intr_stack_tee_seg (RW) : org = SRAM_TEE_INTR_STACK_SEG_START, len = CONFIG_SECURE_TEE_INTR_STACK_SIZE } SECTIONS { - /** - * This section is required to skip .iram.tee_text area because iram_tee_seg and - * dram_tee_seg reflect the same address space on different buses. - */ - .dram.tee_dummy (NOLOAD): + .iram.tee.text : { - . = ORIGIN(dram_tee_seg) + CONFIG_SECURE_TEE_IRAM_SIZE; - } > dram_tee_seg + /* Vectors go to start of IRAM */ + ASSERT(ABSOLUTE(.) % 0x100 == 0, "vector address must be 256 byte aligned"); + _tee_vec_start = ABSOLUTE(.); + KEEP(*(.exception_vectors_table.text)); + KEEP(*(.exception_vectors.text)); + ALIGNED_SYMBOL(4, _invalid_pc_placeholder) + _tee_vec_end = ABSOLUTE(.); - .dram.tee.bss (NOLOAD) : - { - . = ALIGN (8); - _tee_dram_start = ABSOLUTE(.); - _tee_bss_start = ABSOLUTE(.); - *(.bss .bss.*) - *(.sbss .sbss.*) - . = ALIGN (8); - _tee_bss_end = ABSOLUTE(.); - } > dram_tee_seg + /* Code marked as running out of IRAM */ + _tee_iram_start = ABSOLUTE(.); + *(.iram1 .iram1.*) + /* TEE initialization */ + *libmain.a:esp_tee_init.c*(.literal .text .literal.* .text.*) + *libmain.a:esp_tee_secure_sys_cfg.c*(.literal .text .literal.* .text.*) + *libmain.a:esp_tee_pmp_pma_prot_cfg.c*(.literal .text .literal.* .text.*) + *libmain.a:esp_tee_apm_prot_cfg.c*(.literal .text .literal.* .text.*) + *libmain.a:brownout.c*(.literal .text .literal.* .text.*) + *libmain.a:multi_heap.c*(.literal .text .literal.* .text.*) + /* Panic handler */ + *libmain.a:esp_tee_panic.c*(.literal .text .literal.* .text.*) + *libmain.a:panic_helper_riscv.c*(.literal .text .literal.* .text.*) + /* Service call execution */ + *libmain.a:esp_tee_vectors_plic.S*(.literal .text .literal.* .text.*) + *libmain.a:esp_secure_dispatcher.c*(.literal .text .literal.* .text.*) + *libmain.a:esp_secure_services_iram.c*(.literal .text .literal.* .text.*) + /* Interrupt configuration */ + *libmain.a:esp_tee_intr.c*(.literal .text .literal.* .text.*) + *libmain.a:esp_tee_apm_intr.c*(.literal .text .literal.* .text.*) + /* HAL */ + *libhal.a:mmu_hal.c*(.literal .text .literal.* .text.*) + *libhal.a:cache_hal.c*(.literal .text .literal.* .text.*) + *libhal.a:wdt_hal_iram.c*(.literal .text .literal.* .text.*) + *libhal.a:apm_hal.c*(.literal .text .literal.* .text.*) + /* IDF components */ + *libbootloader_support.a:*(.literal .text .literal.* .text.*) + *libesp_hw_support.a:*(.literal .text .literal.* .text.*) + *liblog.a:*(.literal .text .literal.* .text.*) + *libriscv.a:*(.literal .text .literal.* .text.*) + /* TEE services: Secure storage, OTA, attestation */ + *libtee_flash_mgr.a:*(.literal .text .literal.* .text.*) + *libtee_sec_storage.a:*(.literal .text .literal.* .text.*) + *libtee_ota_ops.a:*(.literal .text .literal.* .text.*) + *libtee_attestation.a:*(.literal .text .literal.* .text.*) + + /* Align the end of code region as per PMP region granularity */ + ALIGNED_SYMBOL(_esp_pmp_align_size, _tee_iram_end) + } > sram_tee_seg .dram.tee.data : { - _data_start = ABSOLUTE(.); + _tee_dram_start = ABSOLUTE(.); + _tee_data_start = ABSOLUTE(.); *(.data .data.*) *(.sdata .sdata.*) *(.dram1 .dram1.*) - . = ALIGN(4); - _data_end = ABSOLUTE(.); - } > dram_tee_seg + _tee_data_end = ABSOLUTE(.); + } > sram_tee_seg + + .dram.tee.bss (NOLOAD) : + { + ALIGNED_SYMBOL(8, _tee_bss_start) + *(.bss .bss.*) + *(.sbss .sbss.*) + ALIGNED_SYMBOL(8, _tee_bss_end) + } > sram_tee_seg .dram.tee.rodata : { - _rodata_start = ABSOLUTE(.); + _tee_rodata_start = ABSOLUTE(.); /* TEE flash manager */ *libtee_flash_mgr.a:*(.rodata .srodata .rodata.* .srodata.*) *libbootloader_support.a:bootloader_flash.*(.rodata .srodata .rodata.* .srodata.*) @@ -114,189 +146,69 @@ SECTIONS /* HAL (noflash) */ *libhal.a:mmu_hal.c*(.rodata .srodata .rodata.* .srodata.*) *libhal.a:cache_hal.c*(.rodata .srodata .rodata.* .srodata.*) - _rodata_end = ABSOLUTE(.); + _tee_rodata_end = ABSOLUTE(.); _tee_dram_end = ABSOLUTE(.); - } > dram_tee_seg + } > sram_tee_seg - .dram.tee.heap : + .dram.tee.heap (NOLOAD): ALIGN(0x10) { - . = ALIGN (16); _tee_heap_start = ABSOLUTE(.); - . = ORIGIN(dram_tee_seg) + LENGTH(dram_tee_seg); + . = ORIGIN(sram_tee_seg) + LENGTH(sram_tee_seg); _tee_heap_end = ABSOLUTE(.); - } > dram_tee_seg + } > sram_tee_seg - .dram.tee.stack : + .dram.tee.stack (NOLOAD): ALIGN(0x10) { - . = ALIGN (16); _tee_stack_bottom = ABSOLUTE(.); . = ORIGIN(stack_tee_seg) + LENGTH(stack_tee_seg); _tee_stack = ABSOLUTE(.); } > stack_tee_seg - .dram.tee.intr_stack : + .dram.tee.intr_stack (NOLOAD): ALIGN(0x10) { - . = ALIGN (16); _tee_intr_stack_bottom = ABSOLUTE(.); . = ORIGIN(intr_stack_tee_seg) + LENGTH(intr_stack_tee_seg); _tee_intr_stack = ABSOLUTE(.); } > intr_stack_tee_seg - .flash.rodata : + + .flash.tee.rodata : ALIGN(0x10) { - _tee_xip_data_start = ABSOLUTE(.); + _tee_flash_data_start = ABSOLUTE(.); *(.rodata_desc .rodata_desc.*) /* Should be the first. TEE App version info. DO NOT PUT ANYTHING BEFORE IT! */ *(.rodata .rodata.*) *(.srodata .srodata.*) *(.gcc_except_table .gcc_except_table.*) - _tee_xip_data_end = ABSOLUTE(.); - } > flash_data_seg + _tee_flash_data_end = ABSOLUTE(.); + } > drom_tee_seg - .flash.text_dummy (NOLOAD): + .flash.tee.text_dummy (NOLOAD): { - . = ALIGN(ALIGNOF(.flash.rodata)); - /* Create an empty gap as big as .flash.rodata section */ - . = . + SIZEOF(.flash.rodata); - /* Prepare the alignment of the section above. Few bytes (0x20) must be - * added for the mapping header. */ - . = ALIGN(CONFIG_MMU_PAGE_SIZE) + 0x20; - } > flash_text_seg + /* Create an empty gap as big as .flash.tee.rodata section */ + . = ALIGN(ALIGNOF(.flash.tee.rodata)) + SIZEOF(.flash.tee.rodata); + /* Add alignment of MMU page size + 0x20 bytes for the mapping header. */ + . = ALIGN(_esp_mmu_page_size) + 0x20; + } > irom_tee_seg - -/* HAL modules and their memory placement: - * - * +-----------+---------------+--------+ - * | Module | Section | Memory | - * +-----------+---------------+--------+ - * | MMU | text+rodata | SRAM | - * | CACHE | text+rodata | SRAM | - * | WDT | text | SRAM | - * | APM | text | Flash* | - * | AES | text | Flash | - * | SHA | text | Flash | - * | HMAC | text | Flash | - * | DS | text | Flash | - * | ECC | text | Flash | - * | BROWNOUT | text | Flash | - * | EFUSE | text | Flash | - * | LPTIMER | text | Flash | - * | SPI_FLASH | text | Flash | - * +-----------+---------------+--------+ - * - * By default, for ESP-TEE, text sections are placed in SRAM while rodata sections go to the flash. - * Therefore, only HAL modules that require SRAM placement for proper functionality are located there, - * while the remaining modules are placed in flash memory. - */ - - .flash.text : + .flash.tee.text : { - _tee_xip_text_start = ABSOLUTE(.); - /* Secure Services */ - *libmain.a:esp_secure_services.c*(.literal .text .literal.* .text.*) - /* HAL */ - *libhal.a:aes_hal.c*(.literal .text .literal.* .text.*) - *libhal.a:sha_hal.c*(.literal .text .literal.* .text.*) - *libhal.a:hmac_hal.c*(.literal .text .literal.* .text.*) - *libhal.a:ds_hal.c*(.literal .text .literal.* .text.*) - *libhal.a:ecc_hal.c*(.literal .text .literal.* .text.*) - /* NOTE: There is a possibility of APM violations (SPI1 flash protection) - * being triggered with the flash cache disabled */ -#if !CONFIG_SECURE_TEE_EXT_FLASH_MEMPROT_SPI1 - *libhal.a:apm_hal.c*(.literal .text .literal.* .text.*) -#endif - *libhal.a:brownout_hal.c*(.literal .text .literal.* .text.*) - *libesp_hal_mspi.a:spi_flash_hal.c*(.literal .text .literal.* .text.*) - /* These HAL modules have functions marked with the IRAM_ATTR attribute which get placed in the SRAM */ - *libhal.a:efuse_hal.c*(.literal .text .literal.* .text.*) - *libhal.a:lp_timer_hal.c*(.literal .text .literal.* .text.*) - /* Mbedtls for TEE */ - *libmbedtls.a:*(.literal .text .literal.* .text.*) - *libmbedcrypto.a:*(.literal .text .literal.* .text.*) - /* HMAC-DS layer */ - *libesp_security.a:*(.literal .text .literal.* .text.*) - /* NVS flash and related modules */ - *libnvs_flash.a:*(.literal .text .literal.* .text.*) - *libstdc++.a:*(.literal .text .literal.* .text.*) - *libgcc.a:*(.literal .text .literal.* .text.*) - /* esp_partition API */ - *libesp_partition.a:*(.literal .text .literal.* .text.*) - /* TEE attestation module */ - *libattestation.a:*(.literal .text .literal.* .text.*) - *json_generator.a:*(.literal .text .literal.* .text.*) - /* TEE test module */ - *libtest_sec_srv.a:*(.literal .text .literal.* .text.*) - _tee_xip_text_end = ABSOLUTE(.); - _tee_xip_end = ABSOLUTE(.); - } > flash_text_seg - - .iram.tee.text : - { - /* Vectors go to start of IRAM */ - ASSERT(ABSOLUTE(.) % 0x100 == 0, "vector address must be 256 byte aligned"); - _tee_vec_start = ABSOLUTE(.); - KEEP(*(.exception_vectors_table.text)); - KEEP(*(.exception_vectors.text)); - . = ALIGN(4); - _invalid_pc_placeholder = ABSOLUTE(.); - _tee_vec_end = ABSOLUTE(.); - - _tee_iram_start = ABSOLUTE(.); - *(.literal .text .iram1 .literal.* .text.* .iram1.*) + _tee_flash_text_start = ABSOLUTE(.); + *(.literal .text .literal.* .text.*) *(.stub .gnu.warning .gnu.linkonce.literal.* .gnu.linkonce.t.*.literal .gnu.linkonce.t.*) - _tee_iram_end = ABSOLUTE(.); - } > iram_tee_seg + /** + * CPU will try to prefetch up to 16 bytes of of instructions. + * This means that any configuration (e.g. MMU, PMS) must allow + * safe access to up to 16 bytes after the last real instruction, add + * dummy bytes to ensure this + */ + . += _esp_flash_mmap_prefetch_pad_size; + _tee_flash_text_end = ABSOLUTE(.); + } > irom_tee_seg - .riscv.attributes 0: { *(.riscv.attributes) } - - /* DWARF 1 */ - .debug 0 : { *(.debug) } - .line 0 : { *(.line) } - /* GNU DWARF 1 extensions */ - .debug_srcinfo 0 : { *(.debug_srcinfo) } - .debug_sfnames 0 : { *(.debug_sfnames) } - /* DWARF 1.1 and DWARF 2 */ - .debug_aranges 0 : { *(.debug_aranges) } - .debug_pubnames 0 : { *(.debug_pubnames) } - /* DWARF 2 */ - .debug_info 0 : { *(.debug_info .gnu.linkonce.wi.*) } - .debug_abbrev 0 : { *(.debug_abbrev) } - .debug_line 0 : { *(.debug_line) } - .debug_frame 0 : { *(.debug_frame) } - .debug_str 0 : { *(.debug_str) } - .debug_loc 0 : { *(.debug_loc) } - .debug_macinfo 0 : { *(.debug_macinfo) } - .debug_pubtypes 0 : { *(.debug_pubtypes) } - /* DWARF 3 */ - .debug_ranges 0 : { *(.debug_ranges) } - /* SGI/MIPS DWARF 2 extensions */ - .debug_weaknames 0 : { *(.debug_weaknames) } - .debug_funcnames 0 : { *(.debug_funcnames) } - .debug_typenames 0 : { *(.debug_typenames) } - .debug_varnames 0 : { *(.debug_varnames) } - /* GNU DWARF 2 extensions */ - .debug_gnu_pubnames 0 : { *(.debug_gnu_pubnames) } - .debug_gnu_pubtypes 0 : { *(.debug_gnu_pubtypes) } - /* DWARF 4 */ - .debug_types 0 : { *(.debug_types) } - /* DWARF 5 */ - .debug_addr 0 : { *(.debug_addr) } - .debug_line_str 0 : { *(.debug_line_str) } - .debug_loclists 0 : { *(.debug_loclists) } - .debug_macro 0 : { *(.debug_macro) } - .debug_names 0 : { *(.debug_names) } - .debug_rnglists 0 : { *(.debug_rnglists) } - .debug_str_offsets 0 : { *(.debug_str_offsets) } - - .comment 0 : { *(.comment) } - .note.GNU-stack 0: { *(.note.GNU-stack) } - - /** - * Discarding .rela.* sections results in the following mapping: - * .rela.text.* -> .text.* - * .rela.data.* -> .data.* - * And so forth... - */ - /DISCARD/ : { *(.rela.*) } +#include "elf_misc.ld.in" } -ASSERT ((_tee_iram_end < _tee_dram_start), "Error: TEE IRAM segment overflowed into the DRAM segment!"); +ASSERT ((_tee_iram_end <= _tee_dram_start), + "Error: TEE IRAM segment overflowed into the DRAM segment! Increase CONFIG_SECURE_TEE_IRAM_SIZE as required."); +ASSERT((_tee_heap_end >= _tee_heap_start + 0x2000), + "Error: TEE heap size is too small - minimum is 8KB (0x2000)! Increase CONFIG_SECURE_TEE_DRAM_SIZE as required."); diff --git a/components/esp_tee/subproject/main/ld/esp32h2/esp_tee.ld.in b/components/esp_tee/subproject/main/ld/esp32h2/esp_tee.ld.in index 0c1b3e8e99..121f4f4b65 100644 --- a/components/esp_tee/subproject/main/ld/esp32h2/esp_tee.ld.in +++ b/components/esp_tee/subproject/main/ld/esp32h2/esp_tee.ld.in @@ -1,32 +1,29 @@ /* - * SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2024-2025 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ #include "sdkconfig.h" +#include "ld.common" -#define SRAM_IRAM_START (0x40800000) -#define SRAM_IRAM_TEE_ORG (SRAM_IRAM_START) -#define SRAM_DRAM_TEE_ORG (SRAM_IRAM_START) +#define SRAM_TEE_SEG_START (0x40800000) +#define SRAM_REE_SEG_START (SRAM_TEE_SEG_START + CONFIG_SECURE_TEE_IRAM_SIZE + CONFIG_SECURE_TEE_DRAM_SIZE) -#define SRAM_IRAM_ORG (SRAM_IRAM_TEE_ORG + CONFIG_SECURE_TEE_IRAM_SIZE + CONFIG_SECURE_TEE_DRAM_SIZE) +#define SRAM_TEE_DRAM_SIZE (CONFIG_SECURE_TEE_DRAM_SIZE - CONFIG_SECURE_TEE_STACK_SIZE - CONFIG_SECURE_TEE_INTR_STACK_SIZE) +#define SRAM_TEE_DRAM_END (SRAM_TEE_SEG_START + CONFIG_SECURE_TEE_IRAM_SIZE + SRAM_TEE_DRAM_SIZE) -#define SRAM_DRAM_TEE_SIZE (CONFIG_SECURE_TEE_DRAM_SIZE - CONFIG_SECURE_TEE_STACK_SIZE - CONFIG_SECURE_TEE_INTR_STACK_SIZE) -#define SRAM_DRAM_TEE_END (SRAM_DRAM_TEE_ORG + CONFIG_SECURE_TEE_IRAM_SIZE + SRAM_DRAM_TEE_SIZE) - -#define I_D_SRAM_TEE_SIZE (CONFIG_SECURE_TEE_IRAM_SIZE + SRAM_DRAM_TEE_SIZE) +#define SRAM_TEE_SEG_SIZE (CONFIG_SECURE_TEE_IRAM_SIZE + SRAM_TEE_DRAM_SIZE) /* TEE interrupt stack is placed at the end of the TEE DRAM segment. * The top of the TEE stack is before the end of interrupt stack * and the bottom of the stack is at _heap_end. */ -#define SRAM_STACK_TEE_ORG (SRAM_DRAM_TEE_END) -#define SRAM_INTR_STACK_TEE_ORG (SRAM_DRAM_TEE_END + CONFIG_SECURE_TEE_STACK_SIZE) +#define SRAM_TEE_STACK_SEG_START (SRAM_TEE_DRAM_END) +#define SRAM_TEE_INTR_STACK_SEG_START (SRAM_TEE_DRAM_END + CONFIG_SECURE_TEE_STACK_SIZE) -#define FLASH_IROM_TEE_ORG (0x42000000) -#define FLASH_DROM_TEE_ORG (0x42000000) -#define I_D_FLASH_TEE_SIZE (CONFIG_SECURE_TEE_IROM_SIZE + CONFIG_SECURE_TEE_DROM_SIZE) +#define FLASH_TEE_SEG_START (0x42000000) +#define FLASH_TEE_SEG_SIZE (CONFIG_SECURE_TEE_IROM_SIZE + CONFIG_SECURE_TEE_DROM_SIZE) /** * These values are the same in every app binary for the same chip target. @@ -36,9 +33,9 @@ */ #if CONFIG_ESP_DEBUG_INCLUDE_OCD_STUB_BINS -PROVIDE ( esp_tee_app_config = SRAM_IRAM_ORG + 0x22e0 ); +PROVIDE ( esp_tee_app_config = SRAM_REE_SEG_START + 0x22e0 ); #else -PROVIDE ( esp_tee_app_config = SRAM_IRAM_ORG + 0x2e0 ); +PROVIDE ( esp_tee_app_config = SRAM_REE_SEG_START + 0x2e0 ); #endif PROVIDE ( GDMA = 0x60080000 ); @@ -48,60 +45,95 @@ ENTRY(esp_tee_init); MEMORY { -/* IRAM Configuration */ - iram_tee_seg (RX) : org = SRAM_IRAM_TEE_ORG, len = I_D_SRAM_TEE_SIZE +/* Flash text section */ + irom_tee_seg (RX): org = FLASH_TEE_SEG_START + 0x20, len = FLASH_TEE_SEG_SIZE - 0x20 -/* DRAM Configuration */ - dram_tee_seg (RW) : org = SRAM_DRAM_TEE_ORG, len = I_D_SRAM_TEE_SIZE +/* Flash data section */ + drom_tee_seg (R) : org = FLASH_TEE_SEG_START + 0x20, len = FLASH_TEE_SEG_SIZE - 0x20 -/* TEE Stack Configuration */ - stack_tee_seg (RW) : org = SRAM_STACK_TEE_ORG, len = CONFIG_SECURE_TEE_STACK_SIZE +/* I/DRAM section */ + sram_tee_seg (RWX) : org = SRAM_TEE_SEG_START, len = SRAM_TEE_SEG_SIZE -/* TEE Interrupt Stack Configuration */ - intr_stack_tee_seg (RW) : org = SRAM_INTR_STACK_TEE_ORG, len = CONFIG_SECURE_TEE_INTR_STACK_SIZE +/* Stack section */ + stack_tee_seg (RW) : org = SRAM_TEE_STACK_SEG_START, len = CONFIG_SECURE_TEE_STACK_SIZE -/* TEE flash data section */ - flash_data_seg (R) : org = FLASH_DROM_TEE_ORG + 0x20, len = I_D_FLASH_TEE_SIZE - 0x20 - -/* TEE flash text section */ - flash_text_seg (RX): org = FLASH_IROM_TEE_ORG + 0x20, len = I_D_FLASH_TEE_SIZE - 0x20 +/* Interrupt stack section */ + intr_stack_tee_seg (RW) : org = SRAM_TEE_INTR_STACK_SEG_START, len = CONFIG_SECURE_TEE_INTR_STACK_SIZE } SECTIONS { - /** - * This section is required to skip .iram.tee_text area because iram_tee_seg and - * dram_tee_seg reflect the same address space on different buses. - */ - .dram.tee_dummy (NOLOAD): + .iram.tee.text : { - . = ORIGIN(dram_tee_seg) + CONFIG_SECURE_TEE_IRAM_SIZE; - } > dram_tee_seg + /* Vectors go to start of IRAM */ + ASSERT(ABSOLUTE(.) % 0x100 == 0, "vector address must be 256 byte aligned"); + _tee_vec_start = ABSOLUTE(.); + KEEP(*(.exception_vectors_table.text)); + KEEP(*(.exception_vectors.text)); + ALIGNED_SYMBOL(4, _invalid_pc_placeholder) + _tee_vec_end = ABSOLUTE(.); - .dram.tee.bss (NOLOAD) : - { - . = ALIGN (8); - _tee_dram_start = ABSOLUTE(.); - _tee_bss_start = ABSOLUTE(.); - *(.bss .bss.*) - *(.sbss .sbss.*) - . = ALIGN (8); - _tee_bss_end = ABSOLUTE(.); - } > dram_tee_seg + /* Code marked as running out of IRAM */ + _tee_iram_start = ABSOLUTE(.); + *(.iram1 .iram1.*) + /* TEE initialization */ + *libmain.a:esp_tee_init.c*(.literal .text .literal.* .text.*) + *libmain.a:esp_tee_secure_sys_cfg.c*(.literal .text .literal.* .text.*) + *libmain.a:esp_tee_pmp_pma_prot_cfg.c*(.literal .text .literal.* .text.*) + *libmain.a:esp_tee_apm_prot_cfg.c*(.literal .text .literal.* .text.*) + *libmain.a:brownout.c*(.literal .text .literal.* .text.*) + *libmain.a:multi_heap.c*(.literal .text .literal.* .text.*) + /* Panic handler */ + *libmain.a:esp_tee_panic.c*(.literal .text .literal.* .text.*) + *libmain.a:panic_helper_riscv.c*(.literal .text .literal.* .text.*) + /* Service call execution */ + *libmain.a:esp_tee_vectors_plic.S*(.literal .text .literal.* .text.*) + *libmain.a:esp_secure_dispatcher.c*(.literal .text .literal.* .text.*) + *libmain.a:esp_secure_services_iram.c*(.literal .text .literal.* .text.*) + /* Interrupt configuration */ + *libmain.a:esp_tee_intr.c*(.literal .text .literal.* .text.*) + *libmain.a:esp_tee_apm_intr.c*(.literal .text .literal.* .text.*) + /* HAL */ + *libhal.a:mmu_hal.c*(.literal .text .literal.* .text.*) + *libhal.a:cache_hal.c*(.literal .text .literal.* .text.*) + *libhal.a:wdt_hal_iram.c*(.literal .text .literal.* .text.*) + *libhal.a:apm_hal.c*(.literal .text .literal.* .text.*) + /* IDF components */ + *libbootloader_support.a:*(.literal .text .literal.* .text.*) + *libesp_hw_support.a:*(.literal .text .literal.* .text.*) + *liblog.a:*(.literal .text .literal.* .text.*) + *libriscv.a:*(.literal .text .literal.* .text.*) + /* TEE services: Secure storage, OTA, attestation */ + *libtee_flash_mgr.a:*(.literal .text .literal.* .text.*) + *libtee_sec_storage.a:*(.literal .text .literal.* .text.*) + *libtee_ota_ops.a:*(.literal .text .literal.* .text.*) + *libtee_attestation.a:*(.literal .text .literal.* .text.*) + + /* Align the end of code region as per PMP region granularity */ + ALIGNED_SYMBOL(_esp_pmp_align_size, _tee_iram_end) + } > sram_tee_seg .dram.tee.data : { - _data_start = ABSOLUTE(.); + _tee_dram_start = ABSOLUTE(.); + _tee_data_start = ABSOLUTE(.); *(.data .data.*) *(.sdata .sdata.*) *(.dram1 .dram1.*) - . = ALIGN(4); - _data_end = ABSOLUTE(.); - } > dram_tee_seg + _tee_data_end = ABSOLUTE(.); + } > sram_tee_seg + + .dram.tee.bss (NOLOAD) : + { + ALIGNED_SYMBOL(8, _tee_bss_start) + *(.bss .bss.*) + *(.sbss .sbss.*) + ALIGNED_SYMBOL(8, _tee_bss_end) + } > sram_tee_seg .dram.tee.rodata : { - _rodata_start = ABSOLUTE(.); + _tee_rodata_start = ABSOLUTE(.); /* TEE flash manager */ *libtee_flash_mgr.a:*(.rodata .srodata .rodata.* .srodata.*) *libbootloader_support.a:bootloader_flash.*(.rodata .srodata .rodata.* .srodata.*) @@ -114,191 +146,69 @@ SECTIONS /* HAL (noflash) */ *libhal.a:mmu_hal.c*(.rodata .srodata .rodata.* .srodata.*) *libhal.a:cache_hal.c*(.rodata .srodata .rodata.* .srodata.*) - _rodata_end = ABSOLUTE(.); + _tee_rodata_end = ABSOLUTE(.); _tee_dram_end = ABSOLUTE(.); - } > dram_tee_seg + } > sram_tee_seg - .dram.tee.heap : + .dram.tee.heap (NOLOAD): ALIGN(0x10) { - . = ALIGN (16); _tee_heap_start = ABSOLUTE(.); - . = ORIGIN(dram_tee_seg) + LENGTH(dram_tee_seg); + . = ORIGIN(sram_tee_seg) + LENGTH(sram_tee_seg); _tee_heap_end = ABSOLUTE(.); - } > dram_tee_seg + } > sram_tee_seg - .dram.tee.stack : + .dram.tee.stack (NOLOAD): ALIGN(0x10) { - . = ALIGN (16); _tee_stack_bottom = ABSOLUTE(.); . = ORIGIN(stack_tee_seg) + LENGTH(stack_tee_seg); _tee_stack = ABSOLUTE(.); } > stack_tee_seg - .dram.tee.intr_stack : + .dram.tee.intr_stack (NOLOAD): ALIGN(0x10) { - . = ALIGN (16); _tee_intr_stack_bottom = ABSOLUTE(.); . = ORIGIN(intr_stack_tee_seg) + LENGTH(intr_stack_tee_seg); _tee_intr_stack = ABSOLUTE(.); } > intr_stack_tee_seg - .flash.rodata : + + .flash.tee.rodata : ALIGN(0x10) { - _tee_xip_data_start = ABSOLUTE(.); + _tee_flash_data_start = ABSOLUTE(.); *(.rodata_desc .rodata_desc.*) /* Should be the first. TEE App version info. DO NOT PUT ANYTHING BEFORE IT! */ *(.rodata .rodata.*) *(.srodata .srodata.*) *(.gcc_except_table .gcc_except_table.*) - _tee_xip_data_end = ABSOLUTE(.); - } > flash_data_seg + _tee_flash_data_end = ABSOLUTE(.); + } > drom_tee_seg - .flash.text_dummy (NOLOAD): + .flash.tee.text_dummy (NOLOAD): { - . = ALIGN(ALIGNOF(.flash.rodata)); - /* Create an empty gap as big as .flash.rodata section */ - . = . + SIZEOF(.flash.rodata); - /* Prepare the alignment of the section above. Few bytes (0x20) must be - * added for the mapping header. */ - . = ALIGN(CONFIG_MMU_PAGE_SIZE) + 0x20; - } > flash_text_seg + /* Create an empty gap as big as .flash.tee.rodata section */ + . = ALIGN(ALIGNOF(.flash.tee.rodata)) + SIZEOF(.flash.tee.rodata); + /* Add alignment of MMU page size + 0x20 bytes for the mapping header. */ + . = ALIGN(_esp_mmu_page_size) + 0x20; + } > irom_tee_seg - -/* HAL modules and their memory placement: - * - * +-----------+---------------+--------+ - * | Module | Section | Memory | - * +-----------+---------------+--------+ - * | MMU | text+rodata | SRAM | - * | CACHE | text+rodata | SRAM | - * | WDT | text | SRAM | - * | APM | text | Flash* | - * | AES | text | Flash | - * | SHA | text | Flash | - * | HMAC | text | Flash | - * | DS | text | Flash | - * | ECC | text | Flash | - * | BROWNOUT | text | Flash | - * | EFUSE | text | Flash | - * | LPTIMER | text | Flash | - * | SPI_FLASH | text | Flash | - * +-----------+---------------+--------+ - * - * By default, for ESP-TEE, text sections are placed in SRAM while rodata sections go to the flash. - * Therefore, only HAL modules that require SRAM placement for proper functionality are located there, - * while the remaining modules are placed in flash memory. - */ - - .flash.text : + .flash.tee.text : { - _tee_xip_text_start = ABSOLUTE(.); - /* Secure Services */ - *libmain.a:esp_secure_services.c*(.literal .text .literal.* .text.*) - /* HAL */ - *libhal.a:aes_hal.c*(.literal .text .literal.* .text.*) - *libhal.a:sha_hal.c*(.literal .text .literal.* .text.*) - *libhal.a:hmac_hal.c*(.literal .text .literal.* .text.*) - *libhal.a:ds_hal.c*(.literal .text .literal.* .text.*) - *libhal.a:ecc_hal.c*(.literal .text .literal.* .text.*) - /* NOTE: There is a possibility of APM violations (SPI1 flash protection) - * being triggered with the flash cache disabled */ -#if !CONFIG_SECURE_TEE_EXT_FLASH_MEMPROT_SPI1 - *libhal.a:apm_hal.c*(.literal .text .literal.* .text.*) -#endif - *libhal.a:brownout_hal.c*(.literal .text .literal.* .text.*) - *libesp_hal_mspi.a:spi_flash_hal.c*(.literal .text .literal.* .text.*) - /* These HAL modules have functions marked with the IRAM_ATTR attribute which get placed in the SRAM */ - *libhal.a:efuse_hal.c*(.literal .text .literal.* .text.*) - *libhal.a:lp_timer_hal.c*(.literal .text .literal.* .text.*) - /* Mbedtls for TEE */ - *libmbedtls.a:*(.literal .text .literal.* .text.*) - *libmbedcrypto.a:*(.literal .text .literal.* .text.*) - /* HMAC-DS layer */ - *libesp_security.a:*(.literal .text .literal.* .text.*) - /* NVS flash and related modules */ - *libnvs_flash.a:*(.literal .text .literal.* .text.*) - *libstdc++.a:*(.literal .text .literal.* .text.*) - *libgcc.a:*(.literal .text .literal.* .text.*) - /* esp_partition API */ - *libesp_partition.a:*(.literal .text .literal.* .text.*) - /* TEE attestation module */ - *libattestation.a:*(.literal .text .literal.* .text.*) - *json_generator.a:*(.literal .text .literal.* .text.*) - /* snprintf-related functions */ - *libc_nano.a:(.literal .text .literal.* .text.*) - /* TEE test module */ - *libtest_sec_srv.a:*(.literal .text .literal.* .text.*) - _tee_xip_text_end = ABSOLUTE(.); - _tee_xip_end = ABSOLUTE(.); - } > flash_text_seg - - .iram.tee.text : - { - /* Vectors go to start of IRAM */ - ASSERT(ABSOLUTE(.) % 0x100 == 0, "vector address must be 256 byte aligned"); - _tee_vec_start = ABSOLUTE(.); - KEEP(*(.exception_vectors_table.text)); - KEEP(*(.exception_vectors.text)); - . = ALIGN(4); - _invalid_pc_placeholder = ABSOLUTE(.); - _tee_vec_end = ABSOLUTE(.); - - _tee_iram_start = ABSOLUTE(.); - *(.literal .text .iram1 .literal.* .text.* .iram1.*) + _tee_flash_text_start = ABSOLUTE(.); + *(.literal .text .literal.* .text.*) *(.stub .gnu.warning .gnu.linkonce.literal.* .gnu.linkonce.t.*.literal .gnu.linkonce.t.*) - _tee_iram_end = ABSOLUTE(.); - } > iram_tee_seg + /** + * CPU will try to prefetch up to 16 bytes of of instructions. + * This means that any configuration (e.g. MMU, PMS) must allow + * safe access to up to 16 bytes after the last real instruction, add + * dummy bytes to ensure this + */ + . += _esp_flash_mmap_prefetch_pad_size; + _tee_flash_text_end = ABSOLUTE(.); + } > irom_tee_seg - .riscv.attributes 0: { *(.riscv.attributes) } - - /* DWARF 1 */ - .debug 0 : { *(.debug) } - .line 0 : { *(.line) } - /* GNU DWARF 1 extensions */ - .debug_srcinfo 0 : { *(.debug_srcinfo) } - .debug_sfnames 0 : { *(.debug_sfnames) } - /* DWARF 1.1 and DWARF 2 */ - .debug_aranges 0 : { *(.debug_aranges) } - .debug_pubnames 0 : { *(.debug_pubnames) } - /* DWARF 2 */ - .debug_info 0 : { *(.debug_info .gnu.linkonce.wi.*) } - .debug_abbrev 0 : { *(.debug_abbrev) } - .debug_line 0 : { *(.debug_line) } - .debug_frame 0 : { *(.debug_frame) } - .debug_str 0 : { *(.debug_str) } - .debug_loc 0 : { *(.debug_loc) } - .debug_macinfo 0 : { *(.debug_macinfo) } - .debug_pubtypes 0 : { *(.debug_pubtypes) } - /* DWARF 3 */ - .debug_ranges 0 : { *(.debug_ranges) } - /* SGI/MIPS DWARF 2 extensions */ - .debug_weaknames 0 : { *(.debug_weaknames) } - .debug_funcnames 0 : { *(.debug_funcnames) } - .debug_typenames 0 : { *(.debug_typenames) } - .debug_varnames 0 : { *(.debug_varnames) } - /* GNU DWARF 2 extensions */ - .debug_gnu_pubnames 0 : { *(.debug_gnu_pubnames) } - .debug_gnu_pubtypes 0 : { *(.debug_gnu_pubtypes) } - /* DWARF 4 */ - .debug_types 0 : { *(.debug_types) } - /* DWARF 5 */ - .debug_addr 0 : { *(.debug_addr) } - .debug_line_str 0 : { *(.debug_line_str) } - .debug_loclists 0 : { *(.debug_loclists) } - .debug_macro 0 : { *(.debug_macro) } - .debug_names 0 : { *(.debug_names) } - .debug_rnglists 0 : { *(.debug_rnglists) } - .debug_str_offsets 0 : { *(.debug_str_offsets) } - - .comment 0 : { *(.comment) } - .note.GNU-stack 0: { *(.note.GNU-stack) } - - /** - * Discarding .rela.* sections results in the following mapping: - * .rela.text.* -> .text.* - * .rela.data.* -> .data.* - * And so forth... - */ - /DISCARD/ : { *(.rela.*) } +#include "elf_misc.ld.in" } -ASSERT ((_tee_iram_end < _tee_dram_start), "Error: TEE IRAM segment overflowed into the DRAM segment!"); +ASSERT ((_tee_iram_end <= _tee_dram_start), + "Error: TEE IRAM segment overflowed into the DRAM segment! Increase CONFIG_SECURE_TEE_IRAM_SIZE as required."); +ASSERT((_tee_heap_end >= _tee_heap_start + 0x2000), + "Error: TEE heap size is too small - minimum is 8KB (0x2000)! Increase CONFIG_SECURE_TEE_DRAM_SIZE as required."); diff --git a/components/esp_tee/subproject/main/ld/ld.common b/components/esp_tee/subproject/main/ld/ld.common new file mode 100644 index 0000000000..74ecbfe8c6 --- /dev/null +++ b/components/esp_tee/subproject/main/ld/ld.common @@ -0,0 +1,32 @@ +#include "sdkconfig.h" + +#define ALIGN_UP(SIZE, AL) (((SIZE) + (AL - 1)) & ~(AL - 1)) +#define ALIGN_DOWN(SIZE, AL) ((SIZE) & ~((AL) - 1)) + +/* CPU instruction prefetch padding size for flash mmap scenario */ +#define _esp_flash_mmap_prefetch_pad_size 16 + +/* + * PMP region granularity size + * Software may determine the PMP granularity by writing zero to pmp0cfg, then writing all ones + * to pmpaddr0, then reading back pmpaddr0. If G is the index of the least-significant bit set, + * the PMP granularity is 2^G+2 bytes. + */ +#ifdef CONFIG_SOC_CPU_PMP_REGION_GRANULARITY +#define _esp_pmp_align_size CONFIG_SOC_CPU_PMP_REGION_GRANULARITY +#else +#define _esp_pmp_align_size 0 +#endif + +#if CONFIG_APP_BUILD_TYPE_RAM +#define _esp_mmu_page_size 0 +#else +#define _esp_mmu_page_size CONFIG_MMU_PAGE_SIZE +#endif + +#define ALIGNED_SYMBOL(X, SYMBOL) . = ALIGN(X); SYMBOL = ABSOLUTE(.); + +#define QUOTED_STRING(STRING) #STRING +#define ASSERT_SECTIONS_GAP(PREV_SECTION, NEXT_SECTION) \ +ASSERT((ADDR(NEXT_SECTION) == ADDR(PREV_SECTION) + SIZEOF(PREV_SECTION)), \ + QUOTED_STRING(The gap between PREV_SECTION and NEXT_SECTION must not exist to produce the final bin image.)) diff --git a/components/esp_tee/subproject/main/soc/esp32c5/esp_tee_pmp_pma_prot_cfg.c b/components/esp_tee/subproject/main/soc/esp32c5/esp_tee_pmp_pma_prot_cfg.c index 4f08db8df8..f7d47af636 100644 --- a/components/esp_tee/subproject/main/soc/esp32c5/esp_tee_pmp_pma_prot_cfg.c +++ b/components/esp_tee/subproject/main/soc/esp32c5/esp_tee_pmp_pma_prot_cfg.c @@ -12,6 +12,59 @@ #include "esp32c5/rom/rom_layout.h" #include "esp_tee.h" +#define IS_PMA_ENTRY_UNLOCKED(ENTRY) \ + ((RV_READ_CSR((CSR_PMACFG0) + (ENTRY)) & PMA_L) == 0) + +static void esp_tee_configure_invalid_regions(void) +{ + const unsigned PMA_NONE = PMA_L | PMA_EN; + __attribute__((unused)) const unsigned PMA_RW = PMA_L | PMA_EN | PMA_R | PMA_W; + __attribute__((unused)) const unsigned PMA_RX = PMA_L | PMA_EN | PMA_R | PMA_X; + __attribute__((unused)) const unsigned PMA_RWX = PMA_L | PMA_EN | PMA_R | PMA_W | PMA_X; + + // ROM uses some PMA entries, so we need to clear them before using them in ESP-IDF + + // 0. Gap at bottom of address space + PMA_RESET_AND_ENTRY_SET_NAPOT(0, 0, SOC_CPU_SUBSYSTEM_LOW, PMA_NAPOT | PMA_NONE); + + // 1. Gap between debug region & IROM + PMA_RESET_AND_ENTRY_SET_TOR(1, SOC_CPU_SUBSYSTEM_HIGH, PMA_NONE); + PMA_RESET_AND_ENTRY_SET_TOR(2, SOC_IROM_MASK_LOW, PMA_TOR | PMA_NONE); + + // 2. ROM has configured the ROM region to be cacheable, so we just need to lock the configuration + PMA_RESET_AND_ENTRY_SET_TOR(3, SOC_IROM_MASK_LOW, PMA_NONE); + PMA_RESET_AND_ENTRY_SET_TOR(4, SOC_DROM_MASK_HIGH, PMA_TOR | PMA_RX); + + // 3. Gap between DRAM and I_Cache + PMA_RESET_AND_ENTRY_SET_TOR(5, SOC_IRAM_HIGH, PMA_NONE); + PMA_RESET_AND_ENTRY_SET_TOR(6, SOC_IROM_LOW, PMA_TOR | PMA_NONE); + + // 4. ROM has configured the MSPI region with RX permission, we should add W attribute for psram and lock the configuration + // This function sets invalid regions but this is a valid memory region configuration that could have + // been configured using PMP as well, but due to insufficient PMP entries we are configuring this using PMA. + // This entry is also required to be set using PMA because the region needs to be configured as cacheable. + PMA_RESET_AND_ENTRY_SET_NAPOT(7, SOC_IROM_LOW, (SOC_IROM_HIGH - SOC_IROM_LOW), PMA_NAPOT | PMA_RWX); + + // 5. Gap between D_Cache & LP_RAM + PMA_RESET_AND_ENTRY_SET_TOR(8, SOC_DROM_HIGH, PMA_NONE); + PMA_RESET_AND_ENTRY_SET_TOR(9, SOC_RTC_IRAM_LOW, PMA_TOR | PMA_NONE); + + // 6. End of address space + PMA_RESET_AND_ENTRY_SET_TOR(10, SOC_PERIPHERAL_HIGH, PMA_NONE); + PMA_RESET_AND_ENTRY_SET_TOR(11, UINT32_MAX, PMA_TOR | PMA_NONE); + + // 7. Using PMA to configure the TEE text and data section access attribute. */ + PMA_ENTRY_CFG_RESET(12); + assert(IS_PMA_ENTRY_UNLOCKED(13)); + assert(IS_PMA_ENTRY_UNLOCKED(14)); + assert(IS_PMA_ENTRY_UNLOCKED(15)); + + extern int _tee_iram_end; + PMA_RESET_AND_ENTRY_SET_TOR(13, SOC_S_IRAM_START, PMA_NONE); + PMA_RESET_AND_ENTRY_SET_TOR(14, (int)&_tee_iram_end, PMA_TOR | PMA_RX); + PMA_RESET_AND_ENTRY_SET_TOR(15, SOC_S_DRAM_END, PMA_TOR | PMA_RW); +} + void esp_tee_configure_region_protection(void) { /* Notes on implementation: @@ -33,6 +86,13 @@ void esp_tee_configure_region_protection(void) const unsigned RX = PMP_L | PMP_R | PMP_X; const unsigned RWX = PMP_L | PMP_R | PMP_W | PMP_X; + // + // Configure all the invalid address regions using PMA + // + // We lock the PMA entries since they mark the invalid regions and is applicable to both the privilege modes + // + esp_tee_configure_invalid_regions(); + // // Configure all the valid address regions using PMP // @@ -69,7 +129,6 @@ void esp_tee_configure_region_protection(void) PMP_ENTRY_SET(5, SOC_IRAM_HIGH, PMP_TOR | RWX); _Static_assert(SOC_IRAM_LOW < SOC_IRAM_HIGH, "Invalid RAM region"); } else { - // TODO: [IDF-13827] TEE SRAM region to be partitioned into text and data sections using APM // REE SRAM (D/IRAM) PMP_ENTRY_SET(4, (int)SOC_NS_IRAM_START, NONE); PMP_ENTRY_SET(5, (int)esp_tee_app_config.ns_iram_end, PMP_TOR | RX); diff --git a/components/esp_tee/subproject/main/soc/esp32c6/esp_tee_pmp_pma_prot_cfg.c b/components/esp_tee/subproject/main/soc/esp32c6/esp_tee_pmp_pma_prot_cfg.c index af6cf5e20b..bea234af03 100644 --- a/components/esp_tee/subproject/main/soc/esp32c6/esp_tee_pmp_pma_prot_cfg.c +++ b/components/esp_tee/subproject/main/soc/esp32c6/esp_tee_pmp_pma_prot_cfg.c @@ -66,8 +66,10 @@ static void esp_tee_configure_invalid_regions(void) assert(IS_PMA_ENTRY_UNLOCKED(13)); assert(IS_PMA_ENTRY_UNLOCKED(14)); assert(IS_PMA_ENTRY_UNLOCKED(15)); + + extern int _tee_iram_end; PMA_RESET_AND_ENTRY_SET_TOR(13, SOC_S_IRAM_START, PMA_NONE); - PMA_RESET_AND_ENTRY_SET_TOR(14, SOC_S_IRAM_END, PMA_TOR | PMA_RX); + PMA_RESET_AND_ENTRY_SET_TOR(14, (int)&_tee_iram_end, PMA_TOR | PMA_RX); PMA_RESET_AND_ENTRY_SET_TOR(15, SOC_S_DRAM_END, PMA_TOR | PMA_RW); } diff --git a/components/esp_tee/subproject/main/soc/esp32h2/esp_tee_pmp_pma_prot_cfg.c b/components/esp_tee/subproject/main/soc/esp32h2/esp_tee_pmp_pma_prot_cfg.c index ed21a9267a..8de916768c 100644 --- a/components/esp_tee/subproject/main/soc/esp32h2/esp_tee_pmp_pma_prot_cfg.c +++ b/components/esp_tee/subproject/main/soc/esp32h2/esp_tee_pmp_pma_prot_cfg.c @@ -68,8 +68,10 @@ static void esp_tee_configure_invalid_regions(void) assert(IS_PMA_ENTRY_UNLOCKED(13)); assert(IS_PMA_ENTRY_UNLOCKED(14)); assert(IS_PMA_ENTRY_UNLOCKED(15)); + + extern int _tee_iram_end; PMA_RESET_AND_ENTRY_SET_TOR(13, SOC_S_IRAM_START, PMA_NONE); - PMA_RESET_AND_ENTRY_SET_TOR(14, SOC_S_IRAM_END, PMA_TOR | PMA_RX); + PMA_RESET_AND_ENTRY_SET_TOR(14, (int)&_tee_iram_end, PMA_TOR | PMA_RX); PMA_RESET_AND_ENTRY_SET_TOR(15, SOC_S_DRAM_END, PMA_TOR | PMA_RW); } diff --git a/components/esp_tee/test_apps/tee_cli_app/sdkconfig.ci.minimal_tee b/components/esp_tee/test_apps/tee_cli_app/sdkconfig.ci.minimal_tee index c26a4dbadb..8fcb3a7614 100644 --- a/components/esp_tee/test_apps/tee_cli_app/sdkconfig.ci.minimal_tee +++ b/components/esp_tee/test_apps/tee_cli_app/sdkconfig.ci.minimal_tee @@ -2,11 +2,14 @@ CONFIG_SECURE_TEE_SEC_STG_MODE_RELEASE=y CONFIG_SECURE_TEE_SEC_STG_EFUSE_HMAC_KEY_ID=5 -# Reducing TEE DRAM and STACK sizes -# 21KB -CONFIG_SECURE_TEE_DRAM_SIZE=0x5400 -# 2.5KB -CONFIG_SECURE_TEE_STACK_SIZE=0xa00 +# Reducing TEE I/DRAM sizes +# 24KB +CONFIG_SECURE_TEE_IRAM_SIZE=0x6000 +# 12KB +CONFIG_SECURE_TEE_DRAM_SIZE=0x3000 + +# Disable TEE logs (also disable all panic logs) +CONFIG_SECURE_TEE_DEBUG_MODE=n # Disabling ATTESTATION CONFIG_SECURE_TEE_ATTESTATION=n diff --git a/components/esp_tee/test_apps/tee_cli_app/sdkconfig.ci.release b/components/esp_tee/test_apps/tee_cli_app/sdkconfig.ci.release new file mode 100644 index 0000000000..52e758739c --- /dev/null +++ b/components/esp_tee/test_apps/tee_cli_app/sdkconfig.ci.release @@ -0,0 +1,21 @@ +# Reducing TEE I/DRAM sizes +# 28KB +CONFIG_SECURE_TEE_IRAM_SIZE=0x7000 +# 16KB +CONFIG_SECURE_TEE_DRAM_SIZE=0x4000 + +# TEE Secure Storage: Release mode +CONFIG_SECURE_TEE_SEC_STG_MODE_RELEASE=y +CONFIG_SECURE_TEE_SEC_STG_EFUSE_HMAC_KEY_ID=5 + +# Disabling support for SECP192R1 signature +CONFIG_SECURE_TEE_SEC_STG_SUPPORT_SECP192R1_SIGN=n + +# Disabling flash protection over SPI1 +CONFIG_SECURE_TEE_EXT_FLASH_MEMPROT_SPI1=n + +# Secure Boot +CONFIG_PARTITION_TABLE_OFFSET=0xf000 +CONFIG_SECURE_BOOT=y +CONFIG_SECURE_BOOT_BUILD_SIGNED_BINARIES=y +CONFIG_SECURE_BOOT_SIGNING_KEY="test_keys/secure_boot_signing_key.pem" diff --git a/components/esp_tee/test_apps/tee_test_fw/main/test_esp_tee_panic.c b/components/esp_tee/test_apps/tee_test_fw/main/test_esp_tee_panic.c index 115ed26010..612c0d475b 100644 --- a/components/esp_tee/test_apps/tee_test_fw/main/test_esp_tee_panic.c +++ b/components/esp_tee/test_apps/tee_test_fw/main/test_esp_tee_panic.c @@ -116,8 +116,6 @@ TEST_CASE("Test TEE-TEE violation: Reserved-X1", "[exception]") TEST_FAIL_MESSAGE("Exception should have been generated"); } -// TODO: [IDF-13827] Enable when TEE SRAM is partitioned as IRAM (RX) and DRAM (RW) -#if !TEMPORARY_DISABLED_FOR_TARGETS(ESP32C5) /* TEE IRAM: Reserved/Vector-table boundary */ TEST_CASE("Test TEE-TEE violation: IRAM-W1", "[exception]") { @@ -145,7 +143,6 @@ TEST_CASE("Test TEE-TEE violation: DRAM-X2", "[exception]") esp_tee_service_call(1, SS_ESP_TEE_TEST_DRAM_REG2_EXEC_VIOLATION); TEST_FAIL_MESSAGE("Exception should have been generated"); } -#endif /* Illegal Instruction */ TEST_CASE("Test TEE-TEE violation: Illegal Instruction", "[exception]")