From f0d74b1c64138d24997df6d30cef25cfc850bab9 Mon Sep 17 00:00:00 2001 From: Angus Gratton Date: Thu, 19 Jul 2018 15:27:35 +1000 Subject: [PATCH] bootloader: Ensure bootloader never returns to caller * Fixes some "noreturn" functions in bootloader utils which did return (causing fatal CPU exceptions). * Marks bootloader entry as "noreturn", preventing "user code done" from stalling boot Partial fix for https://github.com/espressif/esp-idf/issues/1814 TW20016 (Comprehensive fix for this issue will be enabling WDT during bootloader, coming shortly.) --- .../subproject/main/bootloader_start.c | 6 +++--- .../include_priv/bootloader_utility.h | 10 +++++++++ .../src/bootloader_utility.c | 21 ++++++++++++++++--- components/esp32/include/rom/rtc.h | 2 +- 4 files changed, 32 insertions(+), 7 deletions(-) diff --git a/components/bootloader/subproject/main/bootloader_start.c b/components/bootloader/subproject/main/bootloader_start.c index d7c314b2e..6f7edc42e 100644 --- a/components/bootloader/subproject/main/bootloader_start.c +++ b/components/bootloader/subproject/main/bootloader_start.c @@ -34,18 +34,18 @@ static int selected_boot_partition(const bootloader_state_t *bs); * The hardware is mostly uninitialized, flash cache is down and the app CPU is in reset. * We do have a stack, so we can do the initialization in C. */ -void call_start_cpu0() +void __attribute__((noreturn)) call_start_cpu0() { // 1. Hardware initialization if (bootloader_init() != ESP_OK) { - return; + bootloader_reset(); } // 2. Select the number of boot partition bootloader_state_t bs = { 0 }; int boot_index = select_partition_number(&bs); if (boot_index == INVALID_INDEX) { - return; + bootloader_reset(); } // 3. Load the app image for booting diff --git a/components/bootloader_support/include_priv/bootloader_utility.h b/components/bootloader_support/include_priv/bootloader_utility.h index d7231e685..31213a016 100644 --- a/components/bootloader_support/include_priv/bootloader_utility.h +++ b/components/bootloader_support/include_priv/bootloader_utility.h @@ -52,3 +52,13 @@ int bootloader_utility_get_selected_boot_partition(const bootloader_state_t *bs) * @param[in] start_index The index from which the search for images begins. */ __attribute__((noreturn)) void bootloader_utility_load_boot_image(const bootloader_state_t *bs, int start_index); + + +/** + * @brief Software reset the ESP32 + * + * Bootloader code should call this in the case that it cannot proceed. + * + * It is not recommended to call this function from an app (if called, the app will abort). + */ +__attribute__((noreturn)) void bootloader_reset(void); diff --git a/components/bootloader_support/src/bootloader_utility.c b/components/bootloader_support/src/bootloader_utility.c index 6b0145a62..b079e90cc 100644 --- a/components/bootloader_support/src/bootloader_utility.c +++ b/components/bootloader_support/src/bootloader_utility.c @@ -49,6 +49,7 @@ #include "bootloader_random.h" #include "bootloader_config.h" #include "bootloader_common.h" +#include "bootloader_utility.h" static const char* TAG = "boot"; @@ -287,7 +288,7 @@ void bootloader_utility_load_boot_image(const bootloader_state_t *bs, int start_ load_image(&image_data); } else { ESP_LOGE(TAG, "No bootable test partition in the partition table"); - return; + bootloader_reset(); } } @@ -324,6 +325,7 @@ void bootloader_utility_load_boot_image(const bootloader_state_t *bs, int start_ ESP_LOGE(TAG, "No bootable app partitions in the partition table"); bzero(&image_data, sizeof(esp_image_metadata_t)); + bootloader_reset(); } // Copy loaded segments to RAM, set up caches for mapped segments, and start application. @@ -360,8 +362,7 @@ static void load_image(const esp_image_metadata_t* image_data) so issue a system reset to ensure flash encryption cache resets properly */ ESP_LOGI(TAG, "Resetting with flash encryption enabled..."); - REG_WRITE(RTC_CNTL_OPTIONS0_REG, RTC_CNTL_SW_SYS_RST); - return; + bootloader_reset(); } #endif @@ -462,3 +463,17 @@ static void set_cache_and_start_app( // use "movsp" instruction to reset stack back to where ROM stack starts. (*entry)(); } + + +void bootloader_reset(void) +{ +#ifdef BOOTLOADER_BUILD + uart_tx_flush(0); /* Ensure any buffered log output is displayed */ + uart_tx_flush(1); + ets_delay_us(1000); /* Allow last byte to leave FIFO */ + REG_WRITE(RTC_CNTL_OPTIONS0_REG, RTC_CNTL_SW_SYS_RST); + while (1) { } /* This line will never be reached, used to keep gcc happy */ +#else + abort(); /* This function should really not be called from application code */ +#endif +} diff --git a/components/esp32/include/rom/rtc.h b/components/esp32/include/rom/rtc.h index 3161fb274..08d8ace09 100644 --- a/components/esp32/include/rom/rtc.h +++ b/components/esp32/include/rom/rtc.h @@ -192,7 +192,7 @@ void set_rtc_memory_crc(void); * * @return None */ -void software_reset(void); +void __attribute__((noreturn)) software_reset(void); /** * @brief Software Reset digital core.