Skip to content

Commit e5de4d2

Browse files
authored
Introduce FirmwareImage trait (esp-rs#188)
* Make fields of FirmwareImage private * Introduce FirmwareImage trait * Provide a default for rom_segments and ram_segments * Remove flash parameters from FirmwareImage * Implement TryFrom for ElfFirmwareImage
1 parent d54ad86 commit e5de4d2

File tree

12 files changed

+202
-153
lines changed

12 files changed

+202
-153
lines changed

espflash/src/chip/esp32/esp32.rs

Lines changed: 14 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,8 @@ use crate::error::UnsupportedImageFormatError;
55
use crate::{
66
chip::{bytes_to_mac_addr, Chip, ChipType, ReadEFuse, SpiRegisters},
77
connection::Connection,
8-
elf::FirmwareImage,
8+
elf::{FirmwareImage, FlashFrequency, FlashMode},
9+
flasher::FlashSize,
910
image_format::{Esp32BootloaderFormat, ImageFormat, ImageFormatId},
1011
Error, PartitionTable,
1112
};
@@ -114,11 +115,14 @@ impl ChipType for Esp32 {
114115
}
115116

116117
fn get_flash_segments<'a>(
117-
image: &'a FirmwareImage,
118+
image: &'a dyn FirmwareImage<'a>,
118119
bootloader: Option<Vec<u8>>,
119120
partition_table: Option<PartitionTable>,
120121
image_format: ImageFormatId,
121122
_chip_revision: Option<u32>,
123+
flash_mode: Option<FlashMode>,
124+
flash_size: Option<FlashSize>,
125+
flash_freq: Option<FlashFrequency>,
122126
) -> Result<Box<dyn ImageFormat<'a> + 'a>, Error> {
123127
match image_format {
124128
ImageFormatId::Bootloader => Ok(Box::new(Esp32BootloaderFormat::new(
@@ -127,6 +131,9 @@ impl ChipType for Esp32 {
127131
PARAMS,
128132
partition_table,
129133
bootloader,
134+
flash_mode,
135+
flash_size,
136+
flash_freq,
130137
)?)),
131138
_ => Err(UnsupportedImageFormatError::new(image_format, Chip::Esp32, None).into()),
132139
}
@@ -183,13 +190,15 @@ impl Esp32 {
183190
fn test_esp32_rom() {
184191
use std::fs::read;
185192

186-
use crate::elf::FirmwareImageBuilder;
193+
use crate::elf::ElfFirmwareImage;
187194

188195
let input_bytes = read("./tests/data/esp32").unwrap();
189196
let expected_bin = read("./tests/data/esp32.bin").unwrap();
190197

191-
let image = FirmwareImageBuilder::new(&input_bytes).build().unwrap();
192-
let flash_image = Esp32BootloaderFormat::new(&image, Chip::Esp32, PARAMS, None, None).unwrap();
198+
let image = ElfFirmwareImage::try_from(input_bytes.as_slice()).unwrap();
199+
let flash_image =
200+
Esp32BootloaderFormat::new(&image, Chip::Esp32, PARAMS, None, None, None, None, None)
201+
.unwrap();
193202

194203
let segments = flash_image.flash_segments().collect::<Vec<_>>();
195204

espflash/src/chip/esp32/esp32c3.rs

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,9 @@ use super::Esp32Params;
44
use crate::{
55
chip::{ChipType, ReadEFuse, SpiRegisters},
66
connection::Connection,
7-
elf::FirmwareImage,
7+
elf::{FirmwareImage, FlashFrequency, FlashMode},
88
error::UnsupportedImageFormatError,
9+
flasher::FlashSize,
910
image_format::{Esp32BootloaderFormat, Esp32DirectBootFormat, ImageFormat, ImageFormatId},
1011
Chip, Error, PartitionTable,
1112
};
@@ -70,11 +71,14 @@ impl ChipType for Esp32c3 {
7071
}
7172

7273
fn get_flash_segments<'a>(
73-
image: &'a FirmwareImage,
74+
image: &'a dyn FirmwareImage<'a>,
7475
bootloader: Option<Vec<u8>>,
7576
partition_table: Option<PartitionTable>,
7677
image_format: ImageFormatId,
7778
chip_revision: Option<u32>,
79+
flash_mode: Option<FlashMode>,
80+
flash_size: Option<FlashSize>,
81+
flash_freq: Option<FlashFrequency>,
7882
) -> Result<Box<dyn ImageFormat<'a> + 'a>, Error> {
7983
match (image_format, chip_revision) {
8084
(ImageFormatId::Bootloader, _) => Ok(Box::new(Esp32BootloaderFormat::new(
@@ -83,6 +87,9 @@ impl ChipType for Esp32c3 {
8387
PARAMS,
8488
partition_table,
8589
bootloader,
90+
flash_mode,
91+
flash_size,
92+
flash_freq,
8693
)?)),
8794
(ImageFormatId::DirectBoot, None | Some(3..)) => {
8895
Ok(Box::new(Esp32DirectBootFormat::new(image)?))

espflash/src/chip/esp32/esp32s2.rs

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,9 @@ use super::Esp32Params;
44
use crate::{
55
chip::{ChipType, ReadEFuse, SpiRegisters},
66
connection::Connection,
7-
elf::FirmwareImage,
7+
elf::{FirmwareImage, FlashFrequency, FlashMode},
88
error::UnsupportedImageFormatError,
9+
flasher::FlashSize,
910
image_format::{Esp32BootloaderFormat, ImageFormat, ImageFormatId},
1011
Chip, Error, PartitionTable,
1112
};
@@ -91,11 +92,14 @@ impl ChipType for Esp32s2 {
9192
}
9293

9394
fn get_flash_segments<'a>(
94-
image: &'a FirmwareImage,
95+
image: &'a dyn FirmwareImage<'a>,
9596
bootloader: Option<Vec<u8>>,
9697
partition_table: Option<PartitionTable>,
9798
image_format: ImageFormatId,
9899
_chip_revision: Option<u32>,
100+
flash_mode: Option<FlashMode>,
101+
flash_size: Option<FlashSize>,
102+
flash_freq: Option<FlashFrequency>,
99103
) -> Result<Box<dyn ImageFormat<'a> + 'a>, Error> {
100104
match image_format {
101105
ImageFormatId::Bootloader => Ok(Box::new(Esp32BootloaderFormat::new(
@@ -104,6 +108,9 @@ impl ChipType for Esp32s2 {
104108
PARAMS,
105109
partition_table,
106110
bootloader,
111+
flash_mode,
112+
flash_size,
113+
flash_freq,
107114
)?)),
108115
_ => Err(UnsupportedImageFormatError::new(image_format, Chip::Esp32s2, None).into()),
109116
}

espflash/src/chip/esp32/esp32s3.rs

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,8 @@ use super::Esp32Params;
44
use crate::{
55
chip::{ChipType, ReadEFuse, SpiRegisters},
66
connection::Connection,
7-
elf::FirmwareImage,
7+
elf::{FirmwareImage, FlashFrequency, FlashMode},
8+
flasher::FlashSize,
89
image_format::{Esp32BootloaderFormat, Esp32DirectBootFormat, ImageFormat, ImageFormatId},
910
Chip, Error, PartitionTable,
1011
};
@@ -65,11 +66,14 @@ impl ChipType for Esp32s3 {
6566
}
6667

6768
fn get_flash_segments<'a>(
68-
image: &'a FirmwareImage,
69+
image: &'a dyn FirmwareImage<'a>,
6970
bootloader: Option<Vec<u8>>,
7071
partition_table: Option<PartitionTable>,
7172
image_format: ImageFormatId,
7273
_chip_revision: Option<u32>,
74+
flash_mode: Option<FlashMode>,
75+
flash_size: Option<FlashSize>,
76+
flash_freq: Option<FlashFrequency>,
7377
) -> Result<Box<dyn ImageFormat<'a> + 'a>, Error> {
7478
match image_format {
7579
ImageFormatId::Bootloader => Ok(Box::new(Esp32BootloaderFormat::new(
@@ -78,6 +82,9 @@ impl ChipType for Esp32s3 {
7882
PARAMS,
7983
partition_table,
8084
bootloader,
85+
flash_mode,
86+
flash_size,
87+
flash_freq,
8188
)?)),
8289
ImageFormatId::DirectBoot => Ok(Box::new(Esp32DirectBootFormat::new(image)?)),
8390
}

espflash/src/chip/esp8266.rs

Lines changed: 12 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,9 @@ use super::{bytes_to_mac_addr, ChipType};
44
use crate::{
55
chip::{ReadEFuse, SpiRegisters},
66
connection::Connection,
7-
elf::FirmwareImage,
7+
elf::{FirmwareImage, FlashFrequency, FlashMode},
88
error::UnsupportedImageFormatError,
9+
flasher::FlashSize,
910
image_format::{Esp8266Format, ImageFormat, ImageFormatId},
1011
Chip, Error, PartitionTable,
1112
};
@@ -43,14 +44,19 @@ impl ChipType for Esp8266 {
4344
}
4445

4546
fn get_flash_segments<'a>(
46-
image: &'a FirmwareImage,
47+
image: &'a dyn FirmwareImage<'a>,
4748
_bootloader: Option<Vec<u8>>,
4849
_partition_table: Option<PartitionTable>,
4950
image_format: ImageFormatId,
5051
_chip_revision: Option<u32>,
52+
flash_mode: Option<FlashMode>,
53+
flash_size: Option<FlashSize>,
54+
flash_freq: Option<FlashFrequency>,
5155
) -> Result<Box<dyn ImageFormat<'a> + 'a>, Error> {
5256
match image_format {
53-
ImageFormatId::Bootloader => Ok(Box::new(Esp8266Format::new(image)?)),
57+
ImageFormatId::Bootloader => Ok(Box::new(Esp8266Format::new(
58+
image, flash_mode, flash_size, flash_freq,
59+
)?)),
5460
_ => Err(UnsupportedImageFormatError::new(image_format, Chip::Esp8266, None).into()),
5561
}
5662
}
@@ -90,13 +96,13 @@ impl ReadEFuse for Esp8266 {
9096
fn test_esp8266_rom() {
9197
use std::fs::read;
9298

93-
use crate::elf::FirmwareImageBuilder;
99+
use crate::elf::ElfFirmwareImage;
94100

95101
let input_bytes = read("./tests/data/esp8266").unwrap();
96102
let expected_bin = read("./tests/data/esp8266.bin").unwrap();
97103

98-
let image = FirmwareImageBuilder::new(&input_bytes).build().unwrap();
99-
let flash_image = Esp8266Format::new(&image).unwrap();
104+
let image = ElfFirmwareImage::try_from(input_bytes.as_slice()).unwrap();
105+
let flash_image = Esp8266Format::new(&image, None, None, None).unwrap();
100106

101107
let segments = flash_image.flash_segments().collect::<Vec<_>>();
102108

espflash/src/chip/mod.rs

Lines changed: 32 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -4,10 +4,10 @@ use strum_macros::Display;
44

55
use crate::{
66
connection::Connection,
7-
elf::FirmwareImage,
7+
elf::{FirmwareImage, FlashFrequency, FlashMode},
88
error::ChipDetectError,
99
flash_target::{Esp32Target, Esp8266Target, FlashTarget, RamTarget},
10-
flasher::SpiAttachParams,
10+
flasher::{FlashSize, SpiAttachParams},
1111
image_format::{ImageFormat, ImageFormatId},
1212
Error, PartitionTable,
1313
};
@@ -49,11 +49,14 @@ pub trait ChipType: ReadEFuse {
4949

5050
/// Get the firmware segments for writing an image to flash.
5151
fn get_flash_segments<'a>(
52-
image: &'a FirmwareImage,
52+
image: &'a dyn FirmwareImage<'a>,
5353
bootloader: Option<Vec<u8>>,
5454
partition_table: Option<PartitionTable>,
5555
image_format: ImageFormatId,
5656
chip_revision: Option<u32>,
57+
flash_mode: Option<FlashMode>,
58+
flash_size: Option<FlashSize>,
59+
flash_freq: Option<FlashFrequency>,
5760
) -> Result<Box<dyn ImageFormat<'a> + 'a>, Error>;
5861

5962
/// Read the MAC address of the connected chip.
@@ -189,11 +192,14 @@ impl Chip {
189192

190193
pub fn get_flash_image<'a>(
191194
&self,
192-
image: &'a FirmwareImage,
195+
image: &'a dyn FirmwareImage<'a>,
193196
bootloader: Option<Vec<u8>>,
194197
partition_table: Option<PartitionTable>,
195198
image_format: Option<ImageFormatId>,
196199
chip_revision: Option<u32>,
200+
flash_mode: Option<FlashMode>,
201+
flash_size: Option<FlashSize>,
202+
flash_freq: Option<FlashFrequency>,
197203
) -> Result<Box<dyn ImageFormat<'a> + 'a>, Error> {
198204
let image_format = image_format.unwrap_or_else(|| self.default_image_format());
199205

@@ -204,31 +210,50 @@ impl Chip {
204210
partition_table,
205211
image_format,
206212
chip_revision,
213+
flash_mode,
214+
flash_size,
215+
flash_freq,
207216
),
208217
Chip::Esp32c3 => Esp32c3::get_flash_segments(
209218
image,
210219
bootloader,
211220
partition_table,
212221
image_format,
213222
chip_revision,
223+
flash_mode,
224+
flash_size,
225+
flash_freq,
214226
),
215227
Chip::Esp32s2 => Esp32s2::get_flash_segments(
216228
image,
217229
bootloader,
218230
partition_table,
219231
image_format,
220232
chip_revision,
233+
flash_mode,
234+
flash_size,
235+
flash_freq,
221236
),
222237
Chip::Esp32s3 => Esp32s3::get_flash_segments(
223238
image,
224239
bootloader,
225240
partition_table,
226241
image_format,
227242
chip_revision,
243+
flash_mode,
244+
flash_size,
245+
flash_freq,
246+
),
247+
Chip::Esp8266 => Esp8266::get_flash_segments(
248+
image,
249+
None,
250+
None,
251+
image_format,
252+
chip_revision,
253+
flash_mode,
254+
flash_size,
255+
flash_freq,
228256
),
229-
Chip::Esp8266 => {
230-
Esp8266::get_flash_segments(image, None, None, image_format, chip_revision)
231-
}
232257
}
233258
}
234259

espflash/src/cli/mod.rs

Lines changed: 22 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ use strum::VariantNames;
1616

1717
use crate::{
1818
cli::serial::get_serial_port_info,
19-
elf::{FirmwareImageBuilder, FlashFrequency, FlashMode},
19+
elf::{ElfFirmwareImage, FlashFrequency, FlashMode},
2020
error::Error,
2121
flasher::FlashSize,
2222
Chip, Flasher, ImageFormatId, InvalidPartitionTable, PartitionTable,
@@ -134,11 +134,7 @@ pub fn save_elf_as_image(
134134
bootloader_path: Option<PathBuf>,
135135
partition_table_path: Option<PathBuf>,
136136
) -> Result<()> {
137-
let image = FirmwareImageBuilder::new(elf_data)
138-
.flash_mode(flash_mode)
139-
.flash_size(flash_size)
140-
.flash_freq(flash_freq)
141-
.build()?;
137+
let image = ElfFirmwareImage::try_from(elf_data)?;
142138

143139
if merge {
144140
// merge_bin is TRUE
@@ -174,8 +170,16 @@ pub fn save_elf_as_image(
174170

175171
// To get a chip revision, the connection is needed
176172
// For simplicity, the revision None is used
177-
let image =
178-
chip.get_flash_image(&image, bootloader, partition_table, image_format, None)?;
173+
let image = chip.get_flash_image(
174+
&image,
175+
bootloader,
176+
partition_table,
177+
image_format,
178+
None,
179+
flash_mode,
180+
flash_size,
181+
flash_freq,
182+
)?;
179183

180184
let mut file = fs::OpenOptions::new()
181185
.write(true)
@@ -202,7 +206,16 @@ pub fn save_elf_as_image(
202206
];
203207
file.write_all(&padding_bytes).into_diagnostic()?;
204208
} else {
205-
let flash_image = chip.get_flash_image(&image, None, None, image_format, None)?;
209+
let flash_image = chip.get_flash_image(
210+
&image,
211+
None,
212+
None,
213+
image_format,
214+
None,
215+
flash_mode,
216+
flash_size,
217+
flash_freq,
218+
)?;
206219
let parts: Vec<_> = flash_image.ota_segments().collect();
207220

208221
match parts.as_slice() {

0 commit comments

Comments
 (0)