diff --git a/CHANGELOG.md b/CHANGELOG.md index 7b0dab5..69a53f5 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -47,6 +47,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Fixed typos in error variant names (#782) - Fix `read-flash` which didn't work with some lengths (#804) - espflash can now flash an ESP32-S2 in download mode over USB (#813) +- Fixed a case where esplash transformed the firmware elf in a way that made it unbootable (#831) ### Removed diff --git a/espflash/src/image_format/esp_idf.rs b/espflash/src/image_format/esp_idf.rs index ea6cdb1..a456893 100644 --- a/espflash/src/image_format/esp_idf.rs +++ b/espflash/src/image_format/esp_idf.rs @@ -213,8 +213,14 @@ impl<'a> IdfBootloaderFormat<'a> { let mut data = bytes_of(&header).to_vec(); - let flash_segments: Vec<_> = merge_adjacent_segments(rom_segments(chip, &elf).collect()); - let mut ram_segments: Vec<_> = merge_adjacent_segments(ram_segments(chip, &elf).collect()); + // The bootloader needs segments to be 4-byte aligned, but ensuring that + // alignment by padding segments might result in overlapping segments. We + // need to merge adjacent segments first to avoid the possibility of them + // overlapping, and then do the padding. + let flash_segments: Vec<_> = + pad_align_segments(merge_adjacent_segments(rom_segments(chip, &elf).collect())); + let mut ram_segments: Vec<_> = + pad_align_segments(merge_adjacent_segments(ram_segments(chip, &elf).collect())); let mut checksum = ESP_CHECKSUM_MAGIC; let mut segment_count = 0; @@ -446,6 +452,11 @@ fn merge_adjacent_segments(mut segments: Vec>) -> Vec> { merged } +fn pad_align_segments(mut segments: Vec>) -> Vec> { + segments.iter_mut().for_each(|segment| segment.pad_align(4)); + segments +} + /// Save a segment to the data buffer. fn save_flash_segment( data: &mut Vec, diff --git a/espflash/src/image_format/mod.rs b/espflash/src/image_format/mod.rs index d9208bd..54fd9c7 100644 --- a/espflash/src/image_format/mod.rs +++ b/espflash/src/image_format/mod.rs @@ -33,13 +33,12 @@ pub struct Segment<'a> { impl<'a> Segment<'a> { pub fn new(addr: u32, data: &'a [u8]) -> Self { - let mut segment = Segment { + // Do not pad the data here, as it might result in overlapping segments + // in the ELF file. The padding should be done after merging adjacent segments. + Segment { addr, data: Cow::Borrowed(data), - }; - segment.pad_align(4); - - segment + } } /// Split of the first `count` bytes into a new segment, adjusting the