Skip to content

Commit e6af2af

Browse files
authored
Align segment lengths after merging (#831)
* Align segment length after merging * Explain the need for pad_alignment
1 parent 8137c43 commit e6af2af

File tree

3 files changed

+18
-7
lines changed

3 files changed

+18
-7
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
4747
- Fixed typos in error variant names (#782)
4848
- Fix `read-flash` which didn't work with some lengths (#804)
4949
- espflash can now flash an ESP32-S2 in download mode over USB (#813)
50+
- Fixed a case where esplash transformed the firmware elf in a way that made it unbootable (#831)
5051

5152
### Removed
5253

espflash/src/image_format/esp_idf.rs

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -213,8 +213,14 @@ impl<'a> IdfBootloaderFormat<'a> {
213213

214214
let mut data = bytes_of(&header).to_vec();
215215

216-
let flash_segments: Vec<_> = merge_adjacent_segments(rom_segments(chip, &elf).collect());
217-
let mut ram_segments: Vec<_> = merge_adjacent_segments(ram_segments(chip, &elf).collect());
216+
// The bootloader needs segments to be 4-byte aligned, but ensuring that
217+
// alignment by padding segments might result in overlapping segments. We
218+
// need to merge adjacent segments first to avoid the possibility of them
219+
// overlapping, and then do the padding.
220+
let flash_segments: Vec<_> =
221+
pad_align_segments(merge_adjacent_segments(rom_segments(chip, &elf).collect()));
222+
let mut ram_segments: Vec<_> =
223+
pad_align_segments(merge_adjacent_segments(ram_segments(chip, &elf).collect()));
218224

219225
let mut checksum = ESP_CHECKSUM_MAGIC;
220226
let mut segment_count = 0;
@@ -446,6 +452,11 @@ fn merge_adjacent_segments(mut segments: Vec<Segment<'_>>) -> Vec<Segment<'_>> {
446452
merged
447453
}
448454

455+
fn pad_align_segments(mut segments: Vec<Segment<'_>>) -> Vec<Segment<'_>> {
456+
segments.iter_mut().for_each(|segment| segment.pad_align(4));
457+
segments
458+
}
459+
449460
/// Save a segment to the data buffer.
450461
fn save_flash_segment(
451462
data: &mut Vec<u8>,

espflash/src/image_format/mod.rs

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -33,13 +33,12 @@ pub struct Segment<'a> {
3333

3434
impl<'a> Segment<'a> {
3535
pub fn new(addr: u32, data: &'a [u8]) -> Self {
36-
let mut segment = Segment {
36+
// Do not pad the data here, as it might result in overlapping segments
37+
// in the ELF file. The padding should be done after merging adjacent segments.
38+
Segment {
3739
addr,
3840
data: Cow::Borrowed(data),
39-
};
40-
segment.pad_align(4);
41-
42-
segment
41+
}
4342
}
4443

4544
/// Split of the first `count` bytes into a new segment, adjusting the

0 commit comments

Comments
 (0)