Skip to content

Commit eb963d7

Browse files
authored
Refactoring: remove the FirmwareImage trait and eliminate the elf module (#802)
* Use `ElfFile` instead of `dyn FirmwareImage` where able * Convert the `image_format` module to a directory * Eliminate the `elf` module, move its contents to `image_format` * Eliminate the `FirmwareImage` trait * Update `CHANGELOG.md`
1 parent 6db4b06 commit eb963d7

File tree

18 files changed

+92
-101
lines changed

18 files changed

+92
-101
lines changed

CHANGELOG.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,8 +38,9 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
3838
### Removed
3939

4040
- Removed the `libudev` feature (#742)
41-
- The `FirmwareImage` trait no longer includes the `segments_with_load_addresses` function (#796)
4241
- Removed the `flasher::parse_partition_table` function (#798)
42+
- The `FirmwareImage` trait has been removed (#802)
43+
- The `elf` module has been removed, and its contents moved to the `image_format` module (#802)
4344

4445
## [3.3.0] - 2025-01-13
4546

espflash/src/cli/mod.rs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -607,9 +607,9 @@ pub fn save_elf_as_image(
607607
if merge {
608608
// To get a chip revision, the connection is needed
609609
// For simplicity, the revision None is used
610-
let image =
611-
chip.into_target()
612-
.get_flash_image(&elf, flash_data.clone(), None, xtal_freq)?;
610+
let image = chip
611+
.into_target()
612+
.get_flash_image(elf, flash_data.clone(), None, xtal_freq)?;
613613

614614
display_image_size(image.app_size(), image.part_size());
615615

@@ -643,7 +643,7 @@ pub fn save_elf_as_image(
643643
} else {
644644
let image = chip
645645
.into_target()
646-
.get_flash_image(&elf, flash_data, None, xtal_freq)?;
646+
.get_flash_image(elf, flash_data, None, xtal_freq)?;
647647

648648
display_image_size(image.app_size(), image.part_size());
649649

espflash/src/flasher/mod.rs

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -31,14 +31,14 @@ use crate::{
3131
Connection,
3232
Port,
3333
},
34-
elf::{FirmwareImage, Segment},
3534
error::{ConnectionError, ResultExt},
3635
flasher::stubs::{
3736
FlashStub,
3837
CHIP_DETECT_MAGIC_REG_ADDR,
3938
DEFAULT_TIMEOUT,
4039
EXPECTED_STUB_HANDSHAKE,
4140
},
41+
image_format::{ram_segments, rom_segments, Segment},
4242
};
4343
use crate::{
4444
error::{ElfError, Error},
@@ -1012,19 +1012,19 @@ impl Flasher {
10121012
mut progress: Option<&mut dyn ProgressCallbacks>,
10131013
) -> Result<(), Error> {
10141014
let elf = ElfFile::new(elf_data).map_err(ElfError::from)?;
1015-
if elf.rom_segments(self.chip).next().is_some() {
1015+
if rom_segments(self.chip, &elf).next().is_some() {
10161016
return Err(Error::ElfNotRamLoadable);
10171017
}
10181018

10191019
let mut target = self.chip.ram_target(
1020-
Some(elf.entry()),
1020+
Some(elf.header.pt2.entry_point() as u32),
10211021
self.chip
10221022
.into_target()
10231023
.max_ram_block_size(&mut self.connection)?,
10241024
);
10251025
target.begin(&mut self.connection).flashing()?;
10261026

1027-
for segment in elf.ram_segments(self.chip) {
1027+
for segment in ram_segments(self.chip, &elf) {
10281028
target
10291029
.write_segment(&mut self.connection, segment, &mut progress)
10301030
.flashing()?;
@@ -1057,7 +1057,7 @@ impl Flasher {
10571057
let image =
10581058
self.chip
10591059
.into_target()
1060-
.get_flash_image(&elf, flash_data, chip_revision, xtal_freq)?;
1060+
.get_flash_image(elf, flash_data, chip_revision, xtal_freq)?;
10611061

10621062
// When the `cli` feature is enabled, display the image size information.
10631063
#[cfg(feature = "cli")]

espflash/src/image_format.rs renamed to espflash/src/image_format/esp_idf.rs

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -6,9 +6,10 @@ use bytemuck::{bytes_of, from_bytes, Pod, Zeroable};
66
use esp_idf_part::{AppType, DataType, Partition, PartitionTable, SubType, Type};
77
use log::debug;
88
use sha2::{Digest, Sha256};
9+
use xmas_elf::ElfFile;
910

11+
use super::{ram_segments, rom_segments, Segment};
1012
use crate::{
11-
elf::{FirmwareImage, Segment},
1213
flasher::{FlashData, FlashFrequency, FlashMode, FlashSize},
1314
targets::{Chip, Esp32Params},
1415
Error,
@@ -119,7 +120,7 @@ pub struct IdfBootloaderFormat<'a> {
119120

120121
impl<'a> IdfBootloaderFormat<'a> {
121122
pub fn new(
122-
image: &'a dyn FirmwareImage<'a>,
123+
elf: ElfFile<'a>,
123124
chip: Chip,
124125
flash_data: FlashData,
125126
params: Esp32Params,
@@ -190,17 +191,16 @@ impl<'a> IdfBootloaderFormat<'a> {
190191
// write the header of the app
191192
// use the same settings as the bootloader
192193
// just update the entry point
193-
header.entry = image.entry();
194-
194+
header.entry = elf.header.pt2.entry_point() as u32;
195195
header.wp_pin = WP_PIN_DISABLED;
196196
header.chip_id = params.chip_id;
197197
header.min_chip_rev_full = flash_data.min_chip_rev;
198198
header.append_digest = 1;
199199

200200
let mut data = bytes_of(&header).to_vec();
201201

202-
let flash_segments: Vec<_> = merge_adjacent_segments(image.rom_segments(chip).collect());
203-
let mut ram_segments: Vec<_> = merge_adjacent_segments(image.ram_segments(chip).collect());
202+
let flash_segments: Vec<_> = merge_adjacent_segments(rom_segments(chip, &elf).collect());
203+
let mut ram_segments: Vec<_> = merge_adjacent_segments(ram_segments(chip, &elf).collect());
204204

205205
let mut checksum = ESP_CHECKSUM_MAGIC;
206206
let mut segment_count = 0;

espflash/src/elf.rs renamed to espflash/src/image_format/mod.rs

Lines changed: 38 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
//! ELF (Executable and Linkable Format) file operations
1+
//! Binary application image formats
22
33
use std::{
44
borrow::Cow,
@@ -13,58 +13,10 @@ use xmas_elf::{
1313
ElfFile,
1414
};
1515

16+
pub use self::esp_idf::IdfBootloaderFormat;
1617
use crate::targets::Chip;
1718

18-
/// Operations for working with firmware images
19-
pub trait FirmwareImage<'a> {
20-
/// Firmware image entry point
21-
fn entry(&self) -> u32;
22-
23-
/// Firmware image segments
24-
fn segments(&'a self) -> Box<dyn Iterator<Item = Segment<'a>> + 'a>;
25-
26-
/// Firmware image ROM segments
27-
fn rom_segments(&'a self, chip: Chip) -> Box<dyn Iterator<Item = Segment<'a>> + 'a> {
28-
Box::new(
29-
self.segments()
30-
.filter(move |segment| chip.into_target().addr_is_flash(segment.addr)),
31-
)
32-
}
33-
34-
/// Firmware image RAM segments
35-
fn ram_segments(&'a self, chip: Chip) -> Box<dyn Iterator<Item = Segment<'a>> + 'a> {
36-
Box::new(
37-
self.segments()
38-
.filter(move |segment| !chip.into_target().addr_is_flash(segment.addr)),
39-
)
40-
}
41-
}
42-
43-
impl<'a> FirmwareImage<'a> for ElfFile<'a> {
44-
fn entry(&self) -> u32 {
45-
self.header.pt2.entry_point() as u32
46-
}
47-
48-
fn segments(&'a self) -> Box<dyn Iterator<Item = Segment<'a>> + 'a> {
49-
Box::new(
50-
self.section_iter()
51-
.filter(|header| {
52-
header.size() > 0
53-
&& header.get_type() == Ok(ShType::ProgBits)
54-
&& header.offset() > 0
55-
&& header.address() > 0
56-
})
57-
.flat_map(move |header| {
58-
let addr = header.address() as u32;
59-
let data = match header.get_data(self) {
60-
Ok(SectionData::Undefined(data)) => data,
61-
_ => return None,
62-
};
63-
Some(Segment::new(addr, data))
64-
}),
65-
)
66-
}
67-
}
19+
mod esp_idf;
6820

6921
/// A segment of code from the source ELF
7022
#[derive(Default, Clone, Eq)]
@@ -192,3 +144,38 @@ impl Ord for Segment<'_> {
192144
self.addr.cmp(&other.addr)
193145
}
194146
}
147+
148+
/// Returns an iterator over all RAM segments for a given chip and ELF file.
149+
pub(crate) fn ram_segments<'a>(
150+
chip: Chip,
151+
elf: &'a ElfFile<'a>,
152+
) -> Box<dyn Iterator<Item = Segment<'a>> + 'a> {
153+
Box::new(segments(elf).filter(move |segment| !chip.into_target().addr_is_flash(segment.addr)))
154+
}
155+
156+
/// Returns an iterator over all ROM segments for a given chip and ELF file.
157+
pub(crate) fn rom_segments<'a>(
158+
chip: Chip,
159+
elf: &'a ElfFile<'a>,
160+
) -> Box<dyn Iterator<Item = Segment<'a>> + 'a> {
161+
Box::new(segments(elf).filter(move |segment| chip.into_target().addr_is_flash(segment.addr)))
162+
}
163+
164+
fn segments<'a>(elf: &'a ElfFile<'a>) -> Box<dyn Iterator<Item = Segment<'a>> + 'a> {
165+
Box::new(
166+
elf.section_iter()
167+
.filter(|header| {
168+
header.size() > 0
169+
&& header.get_type() == Ok(ShType::ProgBits)
170+
&& header.offset() > 0
171+
&& header.address() > 0
172+
})
173+
.flat_map(move |header| {
174+
let addr = header.address() as u32;
175+
match header.get_data(elf) {
176+
Ok(SectionData::Undefined(data)) => Some(Segment::new(addr, data)),
177+
_ => None,
178+
}
179+
}),
180+
)
181+
}

espflash/src/lib.rs

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -29,10 +29,7 @@
2929
#![cfg_attr(docsrs, feature(doc_cfg))]
3030
#![deny(missing_debug_implementations, rust_2018_idioms)]
3131

32-
pub use self::{
33-
elf::{FirmwareImage, Segment},
34-
error::Error,
35-
};
32+
pub use self::{error::Error, image_format::Segment};
3633

3734
#[cfg(feature = "serialport")]
3835
#[cfg_attr(docsrs, doc(cfg(feature = "serialport")))]
@@ -41,7 +38,6 @@ pub mod flasher;
4138
pub mod image_format;
4239
pub mod targets;
4340

44-
mod elf;
4541
mod error;
4642

4743
// Command-line interface

espflash/src/targets/esp32.rs

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,10 @@
11
use std::ops::Range;
22

3+
use xmas_elf::ElfFile;
4+
35
#[cfg(feature = "serialport")]
46
use crate::{connection::Connection, targets::bytes_to_mac_addr};
57
use crate::{
6-
elf::FirmwareImage,
78
flasher::{FlashData, FlashFrequency},
89
image_format::IdfBootloaderFormat,
910
targets::{Chip, Esp32Params, ReadEFuse, SpiRegisters, Target, XtalFrequency},
@@ -154,7 +155,7 @@ impl Target for Esp32 {
154155

155156
fn get_flash_image<'a>(
156157
&self,
157-
image: &'a dyn FirmwareImage<'a>,
158+
elf: ElfFile<'a>,
158159
flash_data: FlashData,
159160
_chip_revision: Option<(u32, u32)>,
160161
xtal_freq: XtalFrequency,
@@ -183,7 +184,7 @@ impl Target for Esp32 {
183184
booloader,
184185
);
185186

186-
IdfBootloaderFormat::new(image, Chip::Esp32, flash_data, params)
187+
IdfBootloaderFormat::new(elf, Chip::Esp32, flash_data, params)
187188
}
188189

189190
#[cfg(feature = "serialport")]

espflash/src/targets/esp32c2.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,11 @@
11
use std::{collections::HashMap, ops::Range};
22

33
use log::debug;
4+
use xmas_elf::ElfFile;
45

56
#[cfg(feature = "serialport")]
67
use crate::{connection::Connection, targets::bytes_to_mac_addr};
78
use crate::{
8-
elf::FirmwareImage,
99
flasher::{FlashData, FlashFrequency},
1010
image_format::IdfBootloaderFormat,
1111
targets::{Chip, Esp32Params, ReadEFuse, SpiRegisters, Target, XtalFrequency},
@@ -90,7 +90,7 @@ impl Target for Esp32c2 {
9090

9191
fn get_flash_image<'a>(
9292
&self,
93-
image: &'a dyn FirmwareImage<'a>,
93+
elf: ElfFile<'a>,
9494
flash_data: FlashData,
9595
_chip_revision: Option<(u32, u32)>,
9696
xtal_freq: XtalFrequency,
@@ -121,7 +121,7 @@ impl Target for Esp32c2 {
121121
booloader,
122122
);
123123

124-
IdfBootloaderFormat::new(image, Chip::Esp32c2, flash_data, params)
124+
IdfBootloaderFormat::new(elf, Chip::Esp32c2, flash_data, params)
125125
}
126126

127127
#[cfg(feature = "serialport")]

espflash/src/targets/esp32c3.rs

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,10 @@
11
use std::ops::Range;
22

3+
use xmas_elf::ElfFile;
4+
35
#[cfg(feature = "serialport")]
46
use crate::connection::Connection;
57
use crate::{
6-
elf::FirmwareImage,
78
flasher::{FlashData, FlashFrequency},
89
image_format::IdfBootloaderFormat,
910
targets::{Chip, Esp32Params, ReadEFuse, SpiRegisters, Target, XtalFrequency},
@@ -78,7 +79,7 @@ impl Target for Esp32c3 {
7879

7980
fn get_flash_image<'a>(
8081
&self,
81-
image: &'a dyn FirmwareImage<'a>,
82+
elf: ElfFile<'a>,
8283
flash_data: FlashData,
8384
_chip_revision: Option<(u32, u32)>,
8485
xtal_freq: XtalFrequency,
@@ -90,7 +91,7 @@ impl Target for Esp32c3 {
9091
});
9192
}
9293

93-
IdfBootloaderFormat::new(image, Chip::Esp32c3, flash_data, PARAMS)
94+
IdfBootloaderFormat::new(elf, Chip::Esp32c3, flash_data, PARAMS)
9495
}
9596

9697
fn spi_registers(&self) -> SpiRegisters {

espflash/src/targets/esp32c6.rs

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,10 @@
11
use std::ops::Range;
22

3+
use xmas_elf::ElfFile;
4+
35
#[cfg(feature = "serialport")]
46
use crate::connection::Connection;
57
use crate::{
6-
elf::FirmwareImage,
78
flasher::{FlashData, FlashFrequency},
89
image_format::IdfBootloaderFormat,
910
targets::{Chip, Esp32Params, ReadEFuse, SpiRegisters, Target, XtalFrequency},
@@ -73,7 +74,7 @@ impl Target for Esp32c6 {
7374

7475
fn get_flash_image<'a>(
7576
&self,
76-
image: &'a dyn FirmwareImage<'a>,
77+
elf: ElfFile<'a>,
7778
flash_data: FlashData,
7879
_chip_revision: Option<(u32, u32)>,
7980
xtal_freq: XtalFrequency,
@@ -85,7 +86,7 @@ impl Target for Esp32c6 {
8586
});
8687
}
8788

88-
IdfBootloaderFormat::new(image, Chip::Esp32c6, flash_data, PARAMS)
89+
IdfBootloaderFormat::new(elf, Chip::Esp32c6, flash_data, PARAMS)
8990
}
9091

9192
fn spi_registers(&self) -> SpiRegisters {

0 commit comments

Comments
 (0)