Skip to content

Commit dd480bc

Browse files
DNedicDzarda7
authored andcommitted
feat: Add a function to check flash regions against a known MD5
This adds a function that can check flash regions against a known MD5 checksum, which can avoid calculation when we already know the checksum or be used to prevent reflashing the same data, speeding up the flashing process and saving flash write cycles.
1 parent ab0ce64 commit dd480bc

File tree

2 files changed

+51
-14
lines changed

2 files changed

+51
-14
lines changed

include/esp_loader.h

Lines changed: 20 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -401,6 +401,23 @@ esp_loader_error_t esp_loader_read_register(uint32_t address, uint32_t *reg_valu
401401
esp_loader_error_t esp_loader_change_transmission_rate(uint32_t transmission_rate);
402402
#endif /* SERIAL_FLASHER_INTERFACE_SDIO */
403403

404+
#if MD5_ENABLED
405+
/**
406+
* @brief Verify target's flash integrity by checking with a known MD5 checksum
407+
* for a specified offset and length.
408+
*
409+
* @return
410+
* - ESP_LOADER_SUCCESS Success
411+
* - ESP_LOADER_ERROR_INVALID_MD5 MD5 does not match
412+
* - ESP_LOADER_ERROR_TIMEOUT Timeout
413+
* - ESP_LOADER_ERROR_INVALID_RESPONSE Internal error
414+
* - ESP_LOADER_ERROR_UNSUPPORTED_FUNC Unsupported on the target
415+
* - ESP_LOADER_ERROR_IMAGE_SIZE Flash region specified is beyond the flash end
416+
*/
417+
esp_loader_error_t esp_loader_flash_verify_known_md5(uint32_t address,
418+
uint32_t size,
419+
const uint8_t *expected_md5);
420+
404421
/**
405422
* @brief Verify target's flash integrity by checking MD5.
406423
* MD5 checksum is computed from data pushed to target's memory by calling
@@ -416,10 +433,11 @@ esp_loader_error_t esp_loader_change_transmission_rate(uint32_t transmission_rat
416433
* - ESP_LOADER_ERROR_TIMEOUT Timeout
417434
* - ESP_LOADER_ERROR_INVALID_RESPONSE Internal error
418435
* - ESP_LOADER_ERROR_UNSUPPORTED_FUNC Unsupported on the target
436+
* - ESP_LOADER_ERROR_IMAGE_SIZE Flash region specified is beyond the flash end
419437
*/
420-
#if MD5_ENABLED
421438
esp_loader_error_t esp_loader_flash_verify(void);
422-
#endif
439+
#endif /* MD5_ENABLED */
440+
423441
/**
424442
* @brief Toggles reset pin.
425443
*/

src/esp_loader.c

Lines changed: 31 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,6 @@ static inline void md5_final(uint8_t digets[16])
6767

6868
#endif
6969

70-
7170
static uint32_t timeout_per_mb(uint32_t size_bytes, uint32_t time_per_mb)
7271
{
7372
uint32_t timeout = time_per_mb * (size_bytes / 1e6);
@@ -687,7 +686,6 @@ esp_loader_error_t esp_loader_change_transmission_rate(uint32_t transmission_rat
687686
#endif /* SERIAL_FLASHER_INTERFACE_SDIO */
688687

689688
#if MD5_ENABLED
690-
691689
static void hexify(const uint8_t raw_md5[16], uint8_t hex_md5_out[32])
692690
{
693691
static const uint8_t dec_to_hex[] = {
@@ -700,36 +698,47 @@ static void hexify(const uint8_t raw_md5[16], uint8_t hex_md5_out[32])
700698
}
701699
}
702700

703-
esp_loader_error_t esp_loader_flash_verify(void)
701+
esp_loader_error_t esp_loader_flash_verify_known_md5(uint32_t address,
702+
uint32_t size,
703+
const uint8_t *expected_md5)
704704
{
705705
if (s_target == ESP8266_CHIP && !esp_stub_get_running()) {
706706
return ESP_LOADER_ERROR_UNSUPPORTED_FUNC;
707707
}
708708

709+
if (s_target_flash_size == 0) {
710+
if (esp_loader_flash_detect_size(&s_target_flash_size) == ESP_LOADER_SUCCESS) {
711+
loader_port_start_timer(DEFAULT_TIMEOUT);
712+
RETURN_ON_ERROR( loader_spi_parameters(s_target_flash_size) );
713+
} else {
714+
loader_port_debug_print("Flash size detection failed, falling back to default");
715+
s_target_flash_size = DEFAULT_FLASH_SIZE;
716+
}
717+
}
718+
719+
if (address + size > s_target_flash_size) {
720+
return ESP_LOADER_ERROR_IMAGE_SIZE;
721+
}
722+
709723
/* Zero termination require 1 byte */
710724
uint8_t received_md5[MAX(MD5_SIZE_ROM, MD5_SIZE_STUB) + 1] = {0};
711-
uint8_t calculated_md5[MAX(MD5_SIZE_ROM, MD5_SIZE_STUB) + 1] = {0};
712-
713-
uint8_t raw_md5[16] = {0};
714-
md5_final(raw_md5);
715725

716-
loader_port_start_timer(timeout_per_mb(s_image_size, MD5_TIMEOUT_PER_MB));
726+
loader_port_start_timer(timeout_per_mb(size, MD5_TIMEOUT_PER_MB));
717727

718-
RETURN_ON_ERROR( loader_md5_cmd(s_start_address, s_image_size, received_md5) );
728+
RETURN_ON_ERROR(loader_md5_cmd(address, size, received_md5));
719729

720-
hexify(raw_md5, calculated_md5);
721730
if (esp_stub_get_running()) {
722731
// Convert the received MD5 to hex, because stub returns it as 16 raw data bytes
723732
uint8_t rec_md5_hex[MAX(MD5_SIZE_ROM, MD5_SIZE_STUB) + 1] = {0};
724733
hexify(received_md5, rec_md5_hex);
725734
memcpy(received_md5, rec_md5_hex, MD5_SIZE_ROM);
726735
}
727736

728-
bool md5_match = memcmp(calculated_md5, received_md5, MD5_SIZE_ROM) == 0;
737+
bool md5_match = memcmp(expected_md5, received_md5, MD5_SIZE_ROM) == 0;
729738
if (!md5_match) {
730739
loader_port_debug_print("Error: MD5 checksum does not match");
731740
loader_port_debug_print("Expected:");
732-
loader_port_debug_print((char *)calculated_md5);
741+
loader_port_debug_print((char *)expected_md5);
733742
loader_port_debug_print("Actual:");
734743
loader_port_debug_print((char *)received_md5);
735744

@@ -739,6 +748,16 @@ esp_loader_error_t esp_loader_flash_verify(void)
739748
return ESP_LOADER_SUCCESS;
740749
}
741750

751+
esp_loader_error_t esp_loader_flash_verify(void)
752+
{
753+
uint8_t raw_md5[16] = {0};
754+
/* Zero termination require 1 byte */
755+
uint8_t hex_md5[MAX(MD5_SIZE_ROM, MD5_SIZE_STUB) + 1] = {0};
756+
md5_final(raw_md5);
757+
hexify(raw_md5, hex_md5);
758+
759+
return esp_loader_flash_verify_known_md5(s_start_address, s_image_size, hex_md5);
760+
}
742761
#endif
743762

744763
void esp_loader_reset_target(void)

0 commit comments

Comments
 (0)