From bad4cd7072244a9bfb7911dbd810a7d9fef0a153 Mon Sep 17 00:00:00 2001 From: Mahavir Jain Date: Fri, 17 Mar 2023 09:39:43 +0530 Subject: [PATCH 1/3] spi_flash: RAM loadable ELF should have dangerous writes option allowed For RAM loadable ELF case, there is no application or the bootloader on the flash. And hence the check for getting current running OTA partition or looking up partition table fails during dangerous writes option. We are disabling the dangerous writes option for RAM loadable ELF case and allowing writes to entire flash memory. --- components/spi_flash/Kconfig | 1 + .../api-reference/peripherals/spi_flash/spi_flash_idf_vs_rom.rst | 1 + 2 files changed, 2 insertions(+) diff --git a/components/spi_flash/Kconfig b/components/spi_flash/Kconfig index 0560ed937e..1383f8b79d 100644 --- a/components/spi_flash/Kconfig +++ b/components/spi_flash/Kconfig @@ -74,6 +74,7 @@ menu "SPI Flash driver" choice SPI_FLASH_DANGEROUS_WRITE bool "Writing to dangerous flash regions" + default SPI_FLASH_DANGEROUS_WRITE_ALLOWED if APP_BUILD_TYPE_RAM default SPI_FLASH_DANGEROUS_WRITE_ABORTS help SPI flash APIs can optionally abort or return a failure code diff --git a/docs/en/api-reference/peripherals/spi_flash/spi_flash_idf_vs_rom.rst b/docs/en/api-reference/peripherals/spi_flash/spi_flash_idf_vs_rom.rst index 43a3ca7878..a51d0315d6 100644 --- a/docs/en/api-reference/peripherals/spi_flash/spi_flash_idf_vs_rom.rst +++ b/docs/en/api-reference/peripherals/spi_flash/spi_flash_idf_vs_rom.rst @@ -19,6 +19,7 @@ Feature Supported by ESP-IDF but not in Chip-ROM - :ref:`CONFIG_SPI_FLASH_VERIFY_WRITE`, enabling this option helps you detect bad writing. - :ref:`CONFIG_SPI_FLASH_LOG_FAILED_WRITE`, enabling this option will print the bad writing. - :ref:`CONFIG_SPI_FLASH_WARN_SETTING_ZERO_TO_ONE`, enabling this option will check if you're writing zero to one. + - :ref:`CONFIG_SPI_FLASH_DANGEROUS_WRITE`, enabling this option will check for flash programming to certain protected regions like bootloader, partition table or application itself. :esp32h2 or esp32c6: - Flash MMAP driver isn't ready in Chip-ROM. From 7b995355ba7241284b10d19d83c31bc7540b575b Mon Sep 17 00:00:00 2001 From: Mahavir Jain Date: Fri, 17 Mar 2023 09:41:54 +0530 Subject: [PATCH 2/3] startup: fix incorrect MMU configuration issue for the RAM loadable ELF For RAM loadable ELF, entire firmware is running from RAM and hence the IROM/DROM size must be treated as 0 (no cache mappings created for code/rodata). --- components/esp_system/port/cpu_start.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/components/esp_system/port/cpu_start.c b/components/esp_system/port/cpu_start.c index 3a5cf86494..7988d5d6e0 100644 --- a/components/esp_system/port/cpu_start.c +++ b/components/esp_system/port/cpu_start.c @@ -372,11 +372,19 @@ void IRAM_ATTR call_start_cpu0(void) } #if CONFIG_ESP_ROM_NEEDS_SET_CACHE_MMU_SIZE +#if CONFIG_APP_BUILD_TYPE_ELF_RAM + // For RAM loadable ELF case, we don't need to reserve IROM/DROM as instructions and data + // are all in internal RAM. If the RAM loadable ELF has any requirement to memory map the + // external flash then it should use flash or partition mmap APIs. + uint32_t cache_mmu_irom_size = 0; + __attribute__((unused)) uint32_t cache_mmu_drom_size = 0; +#else // CONFIG_APP_BUILD_TYPE_ELF_RAM uint32_t _instruction_size = (uint32_t)&_instruction_reserved_end - (uint32_t)&_instruction_reserved_start; uint32_t cache_mmu_irom_size = ((_instruction_size + SPI_FLASH_MMU_PAGE_SIZE - 1) / SPI_FLASH_MMU_PAGE_SIZE) * sizeof(uint32_t); uint32_t _rodata_size = (uint32_t)&_rodata_reserved_end - (uint32_t)&_rodata_reserved_start; __attribute__((unused)) uint32_t cache_mmu_drom_size = ((_rodata_size + SPI_FLASH_MMU_PAGE_SIZE - 1) / SPI_FLASH_MMU_PAGE_SIZE) * sizeof(uint32_t); +#endif // !CONFIG_APP_BUILD_TYPE_ELF_RAM /* Configure the Cache MMU size for instruction and rodata in flash. */ Cache_Set_IDROM_MMU_Size(cache_mmu_irom_size, CACHE_DROM_MMU_MAX_END - cache_mmu_irom_size); From d0c8b019562b2fda595c58b75ea12e916b891c07 Mon Sep 17 00:00:00 2001 From: Mahavir Jain Date: Fri, 17 Mar 2023 09:43:40 +0530 Subject: [PATCH 3/3] test_apps: add test case for flash mmap data integrity in ram loadable app --- .../main/ram_loadable_app_test.c | 30 +++++++++++++++++++ .../pytest_ram_loadable_app.py | 2 +- 2 files changed, 31 insertions(+), 1 deletion(-) diff --git a/tools/test_apps/system/ram_loadable_app/main/ram_loadable_app_test.c b/tools/test_apps/system/ram_loadable_app/main/ram_loadable_app_test.c index 6daa76aa67..fa96f283ee 100644 --- a/tools/test_apps/system/ram_loadable_app/main/ram_loadable_app_test.c +++ b/tools/test_apps/system/ram_loadable_app/main/ram_loadable_app_test.c @@ -5,6 +5,7 @@ */ #include +#include #include #include "sdkconfig.h" #include "freertos/FreeRTOS.h" @@ -12,6 +13,10 @@ #include "esp_chip_info.h" #include "hal/mmu_hal.h" #include "soc/soc.h" +#include "unity.h" +#include "spi_flash_mmap.h" +#include "esp_flash.h" +#include "esp_err.h" #if !CONFIG_APP_BUILD_TYPE_PURE_RAM_APP @@ -35,6 +40,30 @@ static void s_test_ext_vaddr(void) assert(my_var || my_var == 0); } } + +static void s_test_flash_mmap_data_integrity(void) +{ + char src_p_1[32] = "Test data pattern 123456789"; + char src_p_2[32] = "Test data pattern 987654321"; + char buf[32]; + const int addr = 0x10000; + + spi_flash_mmap_handle_t handle1; + const void *ptr1; + TEST_ESP_OK(spi_flash_mmap(addr, SPI_FLASH_SEC_SIZE, SPI_FLASH_MMAP_DATA, &ptr1, &handle1)); + TEST_ESP_OK(esp_flash_erase_region(NULL, addr, SPI_FLASH_SEC_SIZE)); + TEST_ESP_OK(esp_flash_write(NULL, src_p_1, addr, sizeof(src_p_1))); + memcpy(buf, ptr1, sizeof(buf)); + + TEST_ASSERT_EQUAL(0, memcmp(buf, src_p_1, sizeof(buf))); + TEST_ESP_OK(esp_flash_erase_region(NULL, addr, SPI_FLASH_SEC_SIZE)); + TEST_ESP_OK(esp_flash_write(NULL, src_p_2, addr, sizeof(src_p_2))); + memcpy(buf, ptr1, sizeof(buf)); + + TEST_ASSERT_EQUAL(0, memcmp(buf, src_p_2, sizeof(buf))); + spi_flash_munmap(handle1); +} + #endif //#if !CONFIG_APP_BUILD_TYPE_PURE_RAM_APP void app_main(void) @@ -56,6 +85,7 @@ void app_main(void) #if !CONFIG_APP_BUILD_TYPE_PURE_RAM_APP s_test_ext_vaddr(); + s_test_flash_mmap_data_integrity(); #endif uint32_t uptime = 0; diff --git a/tools/test_apps/system/ram_loadable_app/pytest_ram_loadable_app.py b/tools/test_apps/system/ram_loadable_app/pytest_ram_loadable_app.py index 8068351016..2d3eb0e223 100644 --- a/tools/test_apps/system/ram_loadable_app/pytest_ram_loadable_app.py +++ b/tools/test_apps/system/ram_loadable_app/pytest_ram_loadable_app.py @@ -27,4 +27,4 @@ def test_pure_ram_loadable_app(dut: IdfDut) -> None: @pytest.mark.parametrize('config', ['defaults',], indirect=True,) def test_ram_loadable_app(dut: IdfDut) -> None: dut.expect('spi_flash: detected chip', timeout=10) - dut.expect('Time since boot: 3 seconds...', timeout=10) + dut.expect('Time since boot: 3 seconds...', timeout=30)