fix(bootloader_hooks): Fix log_v2 support in bootloader hooks

Closes https://github.com/espressif/esp-idf/issues/18482
This commit is contained in:
Konstantin Kondrashov
2026-05-06 13:47:59 +03:00
parent 67d1536ec2
commit 0dc907c820
5 changed files with 30 additions and 5 deletions
+12 -2
View File
@@ -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 * SPDX-License-Identifier: Apache-2.0
*/ */
@@ -29,8 +29,18 @@ void esp_rom_output_putc(char c)
#endif // !ESP_ROM_HAS_OUTPUT_PUTC_FUNC #endif // !ESP_ROM_HAS_OUTPUT_PUTC_FUNC
#if !ESP_ROM_HAS_OUTPUT_TO_CHANNELS_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 (* _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) void esp_rom_output_to_channels(char c)
{ {
@@ -8,9 +8,10 @@ void bootloader_hooks_include(void){
void bootloader_before_init(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 * 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"); ESP_LOGI("HOOK", "This hook is called BEFORE bootloader initialization");
} }
@@ -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 # SPDX-License-Identifier: CC0-1.0
import pytest import pytest
from pytest_embedded import Dut from pytest_embedded import Dut
@@ -6,6 +6,17 @@ from pytest_embedded_idf.utils import idf_parametrize
@pytest.mark.generic @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']) @idf_parametrize('target', ['esp32s3', 'esp32c3'], indirect=['target'])
def test_custom_bootloader_hooks_example(dut: Dut) -> None: def test_custom_bootloader_hooks_example(dut: Dut) -> None:
# Expect to read both hooks messages # Expect to read both hooks messages
@@ -0,0 +1 @@
# This is left intentionally blank. It inherits all configurations from sdkconfig.defaults.
@@ -0,0 +1,2 @@
CONFIG_LOG_VERSION_2=y
CONFIG_ESPTOOLPY_FLASHSIZE_4MB=y