Skip to content

Commit

Permalink
feat: Add support for Secure Download Mode
Browse files Browse the repository at this point in the history
This adds support for connecting in secure download mode, a special mode
in which the commands accepted by the boot ROM are limited to a
safe subset.

Closes #110
  • Loading branch information
DNedic committed Sep 19, 2024
1 parent 6fcd679 commit 46f3f0b
Show file tree
Hide file tree
Showing 2 changed files with 78 additions and 9 deletions.
34 changes: 33 additions & 1 deletion include/esp_loader.h
Original file line number Diff line number Diff line change
Expand Up @@ -154,6 +154,30 @@ target_chip_t esp_loader_get_target(void);
*/
esp_loader_error_t esp_loader_connect_with_stub(esp_loader_connect_args_t *connect_args);

#ifdef SERIAL_FLASHER_INTERFACE_UART
/**
* @brief Connects to the target running in secure download mode
*
* Secure download mode is a special mode in which the commands accepted by the boot ROM
* are limited to a safe subset. It is enabled by burning an efuse on the target.
* Read more about it here:
* https://docs.espressif.com/projects/esp-idf/en/stable/esp32/api-reference/kconfig.html#config-secure-uart-rom-dl-mode
*
* @param connect_args[in] Timing parameters to be used for connecting to target.
* @param flash_size Flash size of the target chip.
* @param target_chip Target chip. Used for the ESP32 and ESP8266, which do not support the
* GET_SECURITY_INFO command required to identify the target in secure
* download mode. Leave as ESP_UNKNOWN_CHIP for autodetection of newer chips.
*
* @return
* - ESP_LOADER_SUCCESS Success
* - ESP_LOADER_ERROR_TIMEOUT Timeout
* - ESP_LOADER_ERROR_INVALID_RESPONSE Internal error
*/
esp_loader_error_t esp_loader_connect_secure_download_mode(esp_loader_connect_args_t *connect_args,
uint32_t flash_size, target_chip_t target_chip);
#endif /* SERIAL_FLASHER_INTERFACE_UART */

/**
* @brief Initiates flash operation
*
Expand Down Expand Up @@ -209,6 +233,7 @@ esp_loader_error_t esp_loader_flash_finish(bool reboot);
* @return
* - ESP_LOADER_SUCCESS Success
* - ESP_LOADER_ERROR_UNSUPPORTED_CHIP The target flash chip is not known
* - ESP_LOADER_ERROR_UNSUPPORTED_FUNC The target chip is running in secure download mode
*/
esp_loader_error_t esp_loader_flash_detect_size(uint32_t *flash_size);

Expand Down Expand Up @@ -262,6 +287,7 @@ esp_loader_error_t esp_loader_get_security_info(esp_loader_target_security_info_
* - ESP_LOADER_SUCCESS Success
* - ESP_LOADER_ERROR_TIMEOUT Timeout
* - ESP_LOADER_ERROR_INVALID_RESPONSE Internal error
* - ESP_LOADER_ERROR_UNSUPPORTED_FUNC The target is running in secure download mode
*/
esp_loader_error_t esp_loader_mem_start(uint32_t offset, uint32_t size, uint32_t block_size);

Expand All @@ -280,6 +306,7 @@ esp_loader_error_t esp_loader_mem_start(uint32_t offset, uint32_t size, uint32_t
* - ESP_LOADER_SUCCESS Success
* - ESP_LOADER_ERROR_TIMEOUT Timeout
* - ESP_LOADER_ERROR_INVALID_RESPONSE Internal error
* - ESP_LOADER_ERROR_UNSUPPORTED_FUNC The target is running in secure download mode
*/
esp_loader_error_t esp_loader_mem_write(const void *payload, uint32_t size);

Expand All @@ -294,6 +321,7 @@ esp_loader_error_t esp_loader_mem_write(const void *payload, uint32_t size);
* - ESP_LOADER_SUCCESS Success
* - ESP_LOADER_ERROR_TIMEOUT Timeout
* - ESP_LOADER_ERROR_INVALID_RESPONSE Internal error
* - ESP_LOADER_ERROR_UNSUPPORTED_FUNC The target is running in secure download mode
*/
esp_loader_error_t esp_loader_mem_finish(uint32_t entrypoint);

Expand All @@ -307,6 +335,7 @@ esp_loader_error_t esp_loader_mem_finish(uint32_t entrypoint);
* - ESP_LOADER_SUCCESS Success
* - ESP_LOADER_ERROR_TIMEOUT Timeout
* - ESP_LOADER_ERROR_INVALID_RESPONSE Internal error
* - ESP_LOADER_ERROR_UNSUPPORTED_FUNC The target is running in secure download mode
*/
esp_loader_error_t esp_loader_read_mac(uint8_t *mac);

Expand All @@ -320,6 +349,7 @@ esp_loader_error_t esp_loader_read_mac(uint8_t *mac);
* - ESP_LOADER_SUCCESS Success
* - ESP_LOADER_ERROR_TIMEOUT Timeout
* - ESP_LOADER_ERROR_INVALID_RESPONSE Internal error
* - ESP_LOADER_ERROR_UNSUPPORTED_FUNC The target is running in secure download mode
*/
esp_loader_error_t esp_loader_write_register(uint32_t address, uint32_t reg_value);

Expand All @@ -333,6 +363,7 @@ esp_loader_error_t esp_loader_write_register(uint32_t address, uint32_t reg_valu
* - ESP_LOADER_SUCCESS Success
* - ESP_LOADER_ERROR_TIMEOUT Timeout
* - ESP_LOADER_ERROR_INVALID_RESPONSE Internal error
* - ESP_LOADER_ERROR_UNSUPPORTED_FUNC The target is running in secure download mode
*/
esp_loader_error_t esp_loader_read_register(uint32_t address, uint32_t *reg_value);

Expand All @@ -348,7 +379,8 @@ esp_loader_error_t esp_loader_read_register(uint32_t address, uint32_t *reg_valu
* - ESP_LOADER_SUCCESS Success
* - ESP_LOADER_ERROR_TIMEOUT Timeout
* - ESP_LOADER_ERROR_INVALID_RESPONSE Internal error
* - ESP_LOADER_ERROR_UNSUPPORTED_FUNC Unsupported on the target
* - ESP_LOADER_ERROR_UNSUPPORTED_FUNC Either the target is running in secure download
* mode or the stub is running on the target.
*/
esp_loader_error_t esp_loader_change_transmission_rate(uint32_t transmission_rate);

Expand Down
53 changes: 45 additions & 8 deletions src/esp_loader.c
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ typedef enum {

static const target_registers_t *s_reg = NULL;
static target_chip_t s_target = ESP_UNKNOWN_CHIP;
static uint32_t s_target_flash_size = 0;

#if MD5_ENABLED

Expand Down Expand Up @@ -75,6 +76,8 @@ esp_loader_error_t esp_loader_connect(esp_loader_connect_args_t *connect_args)
RETURN_ON_ERROR(loader_detect_chip(&s_target, &s_reg));

#if (defined SERIAL_FLASHER_INTERFACE_UART) || (defined SERIAL_FLASHER_INTERFACE_USB)
s_target_flash_size = 0;

if (s_target == ESP8266_CHIP) {
return loader_flash_begin_cmd(0, 0, 0, 0, s_target);
} else {
Expand All @@ -84,6 +87,7 @@ esp_loader_error_t esp_loader_connect(esp_loader_connect_args_t *connect_args)
return loader_spi_attach_cmd(spi_config);
}
#endif /* SERIAL_FLASHER_INTERFACE_UART || SERIAL_FLASHER_INTERFACE_USB */

return ESP_LOADER_SUCCESS;
}

Expand All @@ -97,6 +101,8 @@ static uint32_t s_flash_write_size = 0;

esp_loader_error_t esp_loader_connect_with_stub(esp_loader_connect_args_t *connect_args)
{
s_target_flash_size = 0;

loader_port_enter_bootloader();

RETURN_ON_ERROR(loader_initialize_conn(connect_args));
Expand All @@ -108,6 +114,34 @@ esp_loader_error_t esp_loader_connect_with_stub(esp_loader_connect_args_t *conne
return ESP_LOADER_SUCCESS;
}

#ifdef SERIAL_FLASHER_INTERFACE_UART
esp_loader_error_t esp_loader_connect_secure_download_mode(esp_loader_connect_args_t *connect_args,
const uint32_t flash_size, const target_chip_t target_chip)
{
s_target_flash_size = flash_size;
s_target = target_chip;

loader_port_enter_bootloader();

RETURN_ON_ERROR(loader_initialize_conn(connect_args));

if (s_target == ESP_UNKNOWN_CHIP) {
RETURN_ON_ERROR(loader_detect_chip(&s_target, &s_reg));
}

if (s_target == ESP8266_CHIP) {
return loader_flash_begin_cmd(0, 0, 0, 0, s_target);
} else {
uint32_t spi_config;
RETURN_ON_ERROR( loader_read_spi_config(s_target, &spi_config) );
loader_port_start_timer(DEFAULT_TIMEOUT);
return loader_spi_attach_cmd(spi_config);
}

return ESP_LOADER_SUCCESS;
}
#endif /* SERIAL_FLASHER_INTERFACE_UART */

static esp_loader_error_t spi_set_data_lengths(size_t mosi_bits, size_t miso_bits)
{
if (mosi_bits > 0) {
Expand Down Expand Up @@ -280,15 +314,18 @@ esp_loader_error_t esp_loader_flash_start(uint32_t offset, uint32_t image_size,
{
s_flash_write_size = block_size;

uint32_t flash_size = 0;
if (esp_loader_flash_detect_size(&flash_size) == ESP_LOADER_SUCCESS) {
if (image_size + offset > flash_size) {
return ESP_LOADER_ERROR_IMAGE_SIZE;
/* Flash size will be known in advance if we're in secure download mode or we already read it*/
if (s_target_flash_size == 0) {
if (esp_loader_flash_detect_size(&s_target_flash_size) == ESP_LOADER_SUCCESS) {
loader_port_start_timer(DEFAULT_TIMEOUT);
RETURN_ON_ERROR(loader_spi_parameters(s_target_flash_size));
} else {
loader_port_debug_print("Flash size detection failed, falling back to default");
}
loader_port_start_timer(DEFAULT_TIMEOUT);
RETURN_ON_ERROR( loader_spi_parameters(flash_size) );
} else {
loader_port_debug_print("Flash size detection failed, falling back to default");
}

if (image_size + offset > s_target_flash_size) {
return ESP_LOADER_ERROR_IMAGE_SIZE;
}

#if MD5_ENABLED
Expand Down

0 comments on commit 46f3f0b

Please sign in to comment.