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.)
This commit is contained in:
Angus Gratton 2018-07-19 15:27:35 +10:00 committed by Angus Gratton
parent a7d00f44ab
commit f0d74b1c64
4 changed files with 32 additions and 7 deletions

View file

@ -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

View file

@ -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);

View file

@ -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
}

View file

@ -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.