This is an automated email from the ASF dual-hosted git repository.

xiaoxiang781216 pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/nuttx.git


The following commit(s) were added to refs/heads/master by this push:
     new 5dafb683e41 xtensa/esp32: Let a protected build boot from simple boot.
5dafb683e41 is described below

commit 5dafb683e412ce23a64284fe743931767f617a7f
Author: Marco Casaroli <[email protected]>
AuthorDate: Tue Aug 11 11:13:02 2026 +0200

    xtensa/esp32: Let a protected build boot from simple boot.
    
    A protected build on the ESP32 could only use the legacy IDF image format.
    Kconfig allowed simple boot to be selected with BUILD_PROTECTED, because the
    legacy format is only a default and not a select, but the result did not 
link
    and then did not boot.
    
    Simple boot has no second-stage bootloader.  __start() maps the flash 
itself,
    so everything it reaches must already be in RAM.  kernel-space.ld pinned 
none
    of it, and it did not place esp32_start at all, so the entry point went to 
the
    flash the code was about to map.  The chip loaded the RAM segments, jumped 
to
    0x400d0ba4 and took an IllegalInstruction on the first instruction.
    
    So this pins the bootloader, flash, ROM, clock and log objects that
    bootloader_init() and map_rom_segments() reach, along with esp32_start 
itself,
    and defines the six _image_* symbols that __start() needs.  All of it is
    behind CONFIG_ESPRESSIF_SIMPLE_BOOT, so a legacy build gets the same IRAM it
    had before.
    
    kernel-space.ld also had no `#include <nuttx/config.h>'.  It held no
    conditionals until now, so nothing showed the omission:  the new blocks
    compiled away silently and the link failed as if the file had not been
    changed.
    
    The default is unchanged.  A protected build still selects the legacy format
    unless the user clears CONFIG_ESP32_APP_FORMAT_LEGACY.
    
    Verified on an ESP32-DevKitC V4, ESP32-D0WD-V3 revision 3.1, with
    esp32-devkitc:knsh and the legacy format turned off.  The kernel flashes at
    0x1000 and the user image at 0x90000, with no bootloader and no partition
    table.  It maps seven segments, reaches NSH, and runs ostest to the same 
point
    as the legacy build.
    
    Assisted-by: Claude Opus 5 (1M context) <[email protected]>
    Signed-off-by: Marco Casaroli <[email protected]>
---
 boards/xtensa/esp32/common/scripts/kernel-space.ld | 159 +++++++++++++++++++++
 1 file changed, 159 insertions(+)

diff --git a/boards/xtensa/esp32/common/scripts/kernel-space.ld 
b/boards/xtensa/esp32/common/scripts/kernel-space.ld
index 4a98e369ce3..940f90f80bd 100644
--- a/boards/xtensa/esp32/common/scripts/kernel-space.ld
+++ b/boards/xtensa/esp32/common/scripts/kernel-space.ld
@@ -20,6 +20,8 @@
  *
  ****************************************************************************/
 
+#include <nuttx/config.h>
+
 /* Provide these so there is no need for using config files for this */
 
 __uirom_start = ORIGIN(UIROM);
@@ -159,6 +161,85 @@ SECTIONS
     *libkarch.a:interrupt.*(.literal.intr_get_item .text.intr_get_item)
     *libkarch.a:interrupt.*(.literal.intr_handler_get_arg 
.text.intr_handler_get_arg)
 
+#ifdef CONFIG_ESPRESSIF_SIMPLE_BOOT
+    /* Simple boot has no second-stage bootloader.  __start() runs
+     * bootloader_init() and map_rom_segments() before any flash mapping
+     * exists, so everything they reach must be resident in RAM.
+     */
+
+    /* __start() itself runs before the mapping it creates, so it cannot
+     * live in the flash it is about to map.
+     */
+
+    esp32_start.*(.literal .text .literal.* .text.*)
+
+    *libkarch.a:*esp_loader.*(.literal .text .literal.* .text.*)
+    *libkarch.a:*bootloader_init.*(.text .text.* .literal .literal.*)
+    *libkarch.a:*bootloader_common.*(.text .text.* .literal .literal.*)
+    *libkarch.a:*bootloader_common_loader.*(.text .text.* .literal .literal.*)
+    *libkarch.a:*bootloader_console.*(.text .text.* .literal .literal.*)
+    *libkarch.a:*bootloader_console_loader.*(.text .text.* .literal .literal.*)
+    *libkarch.a:*bootloader_banner_wrap.*(.text .text.* .literal .literal.*)
+    *libkarch.a:*bootloader_clock_init.*(.text .text.* .literal .literal.*)
+    *libkarch.a:*bootloader_clock_loader.*(.text .text.* .literal .literal.*)
+    *libkarch.a:*bootloader_efuse.*(.text .text.* .literal .literal.*)
+    *libkarch.a:*bootloader_esp32.*(.text .text.* .literal .literal.*)
+    *libkarch.a:*bootloader_flash.*(.text .text.* .literal .literal.*)
+    *libkarch.a:*bootloader_flash_config_esp32.*(.text .text.* .literal 
.literal.*)
+    *libkarch.a:*bootloader_mem.*(.text .text.* .literal .literal.*)
+    *libkarch.a:*bootloader_panic.*(.text .text.* .literal .literal.*)
+    *libkarch.a:*bootloader_random.*(.text .text.* .literal .literal.*)
+    *libkarch.a:*bootloader_random_esp32.*(.text .text.* .literal .literal.*)
+    *libkarch.a:*bootloader_sha.*(.text .text.* .literal .literal.*)
+    *libkarch.a:*bootloader_soc.*(.text .text.* .literal .literal.*)
+    *libkarch.a:*esp_image_format.*(.text .text.* .literal .literal.*)
+    *libkarch.a:*flash_encrypt.*(.text .text.* .literal .literal.*)
+    *libkarch.a:*flash_qio_mode.*(.text .text.* .literal .literal.*)
+    *libkarch.a:*brownout_hal.*(.text .text.* .literal .literal.*)
+    *libkarch.a:*cpu.*(.text .text.* .literal .literal.*)
+    *libkarch.a:*cpu_region_protect.*(.text .text.* .literal .literal.*)
+    *libkarch.a:*gpio_hal.*(.text .text.* .literal .literal.*)
+    *libkarch.a:*periph_ctrl.*(.text .text.* .literal .literal.*)
+    *libkarch.a:*clk.*(.text .text.* .literal .literal.*)
+    *libkarch.a:*clk_tree_hal.*(.text .text.* .literal .literal.*)
+    *libkarch.a:*esp_clk_tree.*(.text .text.* .literal .literal.*)
+    *libkarch.a:*esp_clk_tree_common.*(.text .text.* .literal .literal.*)
+    *libkarch.a:*rtc_init.*(.text .text.* .literal .literal.*)
+    *libkarch.a:*rtc_clk.*(.text .text.* .literal .literal.*)
+    *libkarch.a:*rtc_clk_init.*(.text .text.* .literal .literal.*)
+    *libkarch.a:*rtc_sleep.*(.text .text.* .literal .literal.*)
+    *libkarch.a:*rtc_time.*(.text .text.* .literal .literal.*)
+    *libkarch.a:*regi2c_ctrl.*(.text .text.* .literal .literal.*)
+    *libkarch.a:*efuse_hal.*(.text .text.* .literal .literal.*)
+    *libkarch.a:*efuse_utility.*(.text .text.* .literal .literal.*)
+    *libkarch.a:*mmu_hal.*(.text .text.* .literal .literal.*)
+    *libkarch.a:*mpu_hal.*(.text .text.* .literal .literal.*)
+    *libkarch.a:*cache_esp32.*(.text .text.* .literal .literal.*)
+    *libkarch.a:*cache_hal_esp32.*(.text .text.* .literal .literal.*)
+    *libkarch.a:*uart_hal.*(.text .text.* .literal .literal.*)
+    *libkarch.a:*uart_hal_iram.*(.text .text.* .literal .literal.*)
+    *libkarch.a:*uart_periph.*(.text .text.* .literal .literal.*)
+    *libkarch.a:*wdt_hal_iram.*(.text .text.* .literal .literal.*)
+    *libkarch.a:*esp_rom_uart.*(.text .text.* .literal .literal.*)
+    *libkarch.a:*esp_rom_sys.*(.text .text.* .literal .literal.*)
+    *libkarch.a:*esp_rom_spiflash.*(.text .text.* .literal .literal.*)
+    *libkarch.a:*esp_rom_wdt.*(.text .text.* .literal .literal.*)
+    *libkarch.a:*log.*(.text .text.* .literal .literal.*)
+    *libkarch.a:*log_lock.*(.literal .literal.* .text .text.*)
+    *libkarch.a:*log_print.*(.literal .literal.* .text .text.*)
+    *libkarch.a:*log_timestamp.*(.literal .literal.* .text .text.*)
+    *libkarch.a:*log_timestamp_common.*(.literal .literal.* .text .text.*)
+    *libkarch.a:*log_write.*(.literal .literal.* .text .text.*)
+    *libkarch.a:esp_app_desc.*(.literal .literal.* .text .text.*)
+    *libkarch.a:esp_flash_api.*(.text .text.* .literal .literal.*)
+    *libkarch.a:esp_flash_spi_init.*(.text .text.* .literal .literal.*)
+    *libkarch.a:spi_flash_hal_gpspi.*(.literal .literal.* .text .text.*)
+    *libkarch.a:spi_flash_encrypt_hal_iram.*(.text .text.* .literal .literal.*)
+    *libkarch.a:spi_flash_os_func_noos.*(.literal .literal.* .text .text.*)
+    *libkarch.a:spi_flash_os_func_app.*(.literal .literal.* .text .text.*)
+    *libkarch.a:spi_flash_wrap.*(.literal .literal.* .text .text.*)
+#endif
+
     *(.wifirxiram .wifirxiram.*)
     *(.wifi0iram  .wifi0iram.*)
     *(.wifislpiram .wifislpiram.*)
@@ -270,6 +351,67 @@ SECTIONS
     *libkarch.a:os.*(.rodata.g_int_flags_count .rodata.g_int_flags)
     *libkc.a:arch_atomic.*(.rodata .rodata.*)
 
+#ifdef CONFIG_ESPRESSIF_SIMPLE_BOOT
+    /* The read-only data of everything pinned into IRAM above. */
+
+    esp32_start.*(.rodata .rodata.*)
+
+    *libkarch.a:*esp_loader.*(.rodata .rodata.*)
+    *libkarch.a:*bootloader_init.*(.rodata .rodata.*)
+    *libkarch.a:*bootloader_common.*(.rodata .rodata.*)
+    *libkarch.a:*bootloader_common_loader.*(.rodata .rodata.*)
+    *libkarch.a:*bootloader_console.*(.rodata .rodata.*)
+    *libkarch.a:*bootloader_console_loader.*(.rodata .rodata.*)
+    *libkarch.a:*bootloader_banner_wrap.*(.rodata .rodata.*)
+    *libkarch.a:*bootloader_clock_init.*(.rodata .rodata.*)
+    *libkarch.a:*bootloader_clock_loader.*(.rodata .rodata.*)
+    *libkarch.a:*bootloader_efuse.*(.rodata .rodata.*)
+    *libkarch.a:*bootloader_esp32.*(.rodata .rodata.*)
+    *libkarch.a:*bootloader_flash.*(.rodata .rodata.*)
+    *libkarch.a:*bootloader_flash_config_esp32.*(.rodata .rodata.*)
+    *libkarch.a:*bootloader_mem.*(.rodata .rodata.*)
+    *libkarch.a:*bootloader_panic.*(.rodata .rodata.*)
+    *libkarch.a:*bootloader_random.*(.rodata .rodata.*)
+    *libkarch.a:*bootloader_random_esp32.*(.rodata .rodata.*)
+    *libkarch.a:*bootloader_sha.*(.rodata .rodata.*)
+    *libkarch.a:*bootloader_soc.*(.rodata .rodata.*)
+    *libkarch.a:*esp_image_format.*(.rodata .rodata.*)
+    *libkarch.a:*flash_encrypt.*(.rodata .rodata.*)
+    *libkarch.a:*flash_qio_mode.*(.rodata .rodata.*)
+    *libkarch.a:*brownout_hal.*(.rodata .rodata.*)
+    *libkarch.a:*cpu.*(.rodata .rodata.*)
+    *libkarch.a:*cpu_region_protect.*(.rodata .rodata.*)
+    *libkarch.a:*gpio_hal.*(.rodata .rodata.*)
+    *libkarch.a:*periph_ctrl.*(.rodata .rodata.*)
+    *libkarch.a:*clk.*(.rodata .rodata.*)
+    *libkarch.a:*clk_tree_hal.*(.rodata .rodata.*)
+    *libkarch.a:*esp_clk_tree.*(.rodata .rodata.*)
+    *libkarch.a:*esp_clk_tree_common.*(.rodata .rodata.*)
+    *libkarch.a:*rtc_init.*(.rodata .rodata.*)
+    *libkarch.a:*rtc_clk.*(.rodata .rodata.*)
+    *libkarch.a:*rtc_clk_init.*(.rodata .rodata.*)
+    *libkarch.a:*rtc_time.*(.rodata .rodata.*)
+    *libkarch.a:*regi2c_ctrl.*(.rodata .rodata.*)
+    *libkarch.a:*efuse_hal.*(.rodata .rodata.*)
+    *libkarch.a:*efuse_utility.*(.rodata .rodata.*)
+    *libkarch.a:*mmu_hal.*(.rodata .rodata.*)
+    *libkarch.a:*mpu_hal.*(.rodata .rodata.*)
+    *libkarch.a:*cache_esp32.*(.rodata .rodata.*)
+    *libkarch.a:*cache_hal_esp32.*(.rodata .rodata.*)
+    *libkarch.a:*uart_hal.*(.rodata .rodata.*)
+    *libkarch.a:*uart_hal_iram.*(.rodata .rodata.*)
+    *libkarch.a:*uart_periph.*(.rodata .rodata.*)
+    *libkarch.a:*wdt_hal_iram.*(.rodata .rodata.*)
+    *libkarch.a:*esp_rom_uart.*(.rodata .rodata.*)
+    *libkarch.a:*esp_rom_sys.*(.rodata .rodata.*)
+    *libkarch.a:*esp_rom_spiflash.*(.rodata .rodata.*)
+    *libkarch.a:*esp_rom_wdt.*(.rodata .rodata.*)
+    *libkarch.a:*log.*(.rodata .rodata.*)
+    *libkarch.a:esp_app_desc.*(.rodata .rodata.*)
+    *libkarch.a:esp_flash_api.*(.rodata .rodata.*)
+    *libkarch.a:esp_flash_spi_init.*(.rodata .rodata.*)
+#endif
+
     *libsched.a:sched_suspendscheduler.*(.rodata  .rodata.*)
     *libsched.a:sched_thistask.*(.rodata  .rodata.*)
     *libsched.a:sched_note.*(.rodata  .rodata.*)
@@ -367,6 +509,23 @@ SECTIONS
     _etext = .;
   } >KIROM
 
+#ifdef CONFIG_ESPRESSIF_SIMPLE_BOOT
+  /* Simple boot has no second-stage bootloader to map the flash, so __start()
+   * does it.  map_rom_segments() reads the segment table out of the image in
+   * flash, but the entry point still needs these to be defined.
+   */
+
+  _image_irom_vma = ADDR(.flash.text);
+  _image_irom_lma = LOADADDR(.flash.text);
+  _image_irom_size = LOADADDR(.flash.text) + SIZEOF(.flash.text) -
+                     _image_irom_lma;
+
+  _image_drom_vma = ADDR(.flash.rodata);
+  _image_drom_lma = LOADADDR(.flash.rodata);
+  _image_drom_size = LOADADDR(.flash.rodata) + SIZEOF(.flash.rodata) -
+                     _image_drom_lma;
+#endif
+
   .rtc.text :
   {
     . = ALIGN(4);

Reply via email to