From 0dc907c820f15ac954cbbfa0455d80ebba205cdc Mon Sep 17 00:00:00 2001 From: Konstantin Kondrashov Date: Thu, 23 Apr 2026 14:22:38 +0300 Subject: [PATCH] fix(bootloader_hooks): Fix log_v2 support in bootloader hooks Closes https://github.com/espressif/esp-idf/issues/18482 --- components/esp_rom/patches/esp_rom_sys.c | 14 ++++++++++++-- .../bootloader_components/my_boot_hooks/hooks.c | 5 +++-- .../pytest_custom_bootloader_hooks.py | 13 ++++++++++++- .../bootloader_hooks/sdkconfig.ci.default | 1 + .../bootloader_hooks/sdkconfig.ci.log_v2 | 2 ++ 5 files changed, 30 insertions(+), 5 deletions(-) create mode 100644 examples/custom_bootloader/bootloader_hooks/sdkconfig.ci.default create mode 100644 examples/custom_bootloader/bootloader_hooks/sdkconfig.ci.log_v2 diff --git a/components/esp_rom/patches/esp_rom_sys.c b/components/esp_rom/patches/esp_rom_sys.c index efac5a47d59..77c0616a3be 100644 --- a/components/esp_rom/patches/esp_rom_sys.c +++ b/components/esp_rom/patches/esp_rom_sys.c @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2010-2025 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2010-2026 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -29,8 +29,18 @@ void esp_rom_output_putc(char c) #endif // !ESP_ROM_HAS_OUTPUT_PUTC_FUNC #if !ESP_ROM_HAS_OUTPUT_TO_CHANNELS_FUNC +static void esp_rom_output_noop(char c) +{ + (void)c; +} + void (* _putc1)(char c) = esp_rom_output_putc; -void (* _putc2)(char c) = NULL; +/* Initialize _putc2 to a noop function (not NULL) so it is safe to call even before + * bootloader BSS is cleared, e.g. from bootloader hooks (bootloader_before_init). + * In log_v2, ESP_LOG routes output through esp_rom_output_to_channels() which calls + * _putc2 directly. If _putc2 were NULL or uninitialised at that point, it would crash. + * Channel 2 output is disabled later (set to NULL) once startup determines it is unused. */ +void (* _putc2)(char c) = esp_rom_output_noop; void esp_rom_output_to_channels(char c) { diff --git a/examples/custom_bootloader/bootloader_hooks/bootloader_components/my_boot_hooks/hooks.c b/examples/custom_bootloader/bootloader_hooks/bootloader_components/my_boot_hooks/hooks.c index 688a500bbe8..4f1ccec9792 100644 --- a/examples/custom_bootloader/bootloader_hooks/bootloader_components/my_boot_hooks/hooks.c +++ b/examples/custom_bootloader/bootloader_hooks/bootloader_components/my_boot_hooks/hooks.c @@ -8,9 +8,10 @@ void bootloader_hooks_include(void){ void bootloader_before_init(void) { - /* Keep in my mind that a lot of functions cannot be called from here + /* Keep in mind that a lot of functions cannot be called from here * as system initialization has not been performed yet, including - * BSS, SPI flash, or memory protection. */ + * BSS, SPI flash, or memory protection. + */ ESP_LOGI("HOOK", "This hook is called BEFORE bootloader initialization"); } diff --git a/examples/custom_bootloader/bootloader_hooks/pytest_custom_bootloader_hooks.py b/examples/custom_bootloader/bootloader_hooks/pytest_custom_bootloader_hooks.py index 81a4bb75bdb..cbacbdf35bc 100644 --- a/examples/custom_bootloader/bootloader_hooks/pytest_custom_bootloader_hooks.py +++ b/examples/custom_bootloader/bootloader_hooks/pytest_custom_bootloader_hooks.py @@ -1,4 +1,4 @@ -# SPDX-FileCopyrightText: 2021-2025 Espressif Systems (Shanghai) CO LTD +# SPDX-FileCopyrightText: 2021-2026 Espressif Systems (Shanghai) CO LTD # SPDX-License-Identifier: CC0-1.0 import pytest from pytest_embedded import Dut @@ -6,6 +6,17 @@ from pytest_embedded_idf.utils import idf_parametrize @pytest.mark.generic +@pytest.mark.parametrize( + 'config', + [ + 'default', + # log_v2 routes ESP_LOG through esp_rom_output_to_channels() -> _putc2. This config + # verifies that logging works correctly in bootloader hooks (before BSS is cleared), + # where _putc2 must be initialized to a safe noop rather than left as NULL/garbage. + 'log_v2', + ], + indirect=True, +) @idf_parametrize('target', ['esp32s3', 'esp32c3'], indirect=['target']) def test_custom_bootloader_hooks_example(dut: Dut) -> None: # Expect to read both hooks messages diff --git a/examples/custom_bootloader/bootloader_hooks/sdkconfig.ci.default b/examples/custom_bootloader/bootloader_hooks/sdkconfig.ci.default new file mode 100644 index 00000000000..e3b1b390696 --- /dev/null +++ b/examples/custom_bootloader/bootloader_hooks/sdkconfig.ci.default @@ -0,0 +1 @@ +# This is left intentionally blank. It inherits all configurations from sdkconfig.defaults. diff --git a/examples/custom_bootloader/bootloader_hooks/sdkconfig.ci.log_v2 b/examples/custom_bootloader/bootloader_hooks/sdkconfig.ci.log_v2 new file mode 100644 index 00000000000..87c28b7dfc2 --- /dev/null +++ b/examples/custom_bootloader/bootloader_hooks/sdkconfig.ci.log_v2 @@ -0,0 +1,2 @@ +CONFIG_LOG_VERSION_2=y +CONFIG_ESPTOOLPY_FLASHSIZE_4MB=y