Skip to content

Commit 0df6d25

Browse files
authored
Don't expose PartitionTable struct in public APIs, simplify IdfBootloaderFormat constructor (#798)
* Simplify `IdfBootloaderFormat` constructor, make `default_partition_table` private * Move `parse_partition_table` to the `cli` module * Update `CHANGELOG.md`
1 parent f73fef4 commit 0df6d25

File tree

15 files changed

+76
-162
lines changed

15 files changed

+76
-162
lines changed

CHANGELOG.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
2424
- `write-bin` now works for files whose lengths are not divisible by 4 (#780, #788)
2525
- `get_usb_pid` is now `usb_pid` and no longer needlessly returns a `Result` (#795)
2626
- `CodeSegment` and `RomSegment` have been merged into a single `Segment` struct (#796)
27+
- `IdfBootloaderFormat` has had its constructor's parameters reduced/simplified (#798)
2728

2829
### Fixed
2930

@@ -36,6 +37,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
3637

3738
- Removed the `libudev` feature (#742)
3839
- The `FirmwareImage` trait no longer includes the `segments_with_load_addresses` function (#796)
40+
- Removed the `flasher::parse_partition_table` function (#798)
3941

4042
## [3.3.0] - 2025-01-13
4143

cargo-espflash/src/main.rs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,6 @@ use cargo_metadata::{Message, MetadataCommand};
88
use clap::{Args, CommandFactory, Parser, Subcommand};
99
use espflash::{
1010
cli::{self, config::Config, monitor::monitor, *},
11-
flasher::parse_partition_table,
1211
logging::initialize_logger,
1312
targets::{Chip, XtalFrequency},
1413
update::check_for_update,

espflash/src/bin/espflash.rs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@ use std::{fs, path::PathBuf};
33
use clap::{Args, CommandFactory, Parser, Subcommand};
44
use espflash::{
55
cli::{self, config::Config, monitor::monitor, *},
6-
flasher::parse_partition_table,
76
logging::initialize_logger,
87
targets::{Chip, XtalFrequency},
98
update::check_for_update,

espflash/src/cli/mod.rs

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,6 @@ use crate::{
3737
connection::reset::{ResetAfterOperation, ResetBeforeOperation},
3838
error::{ElfError, Error, MissingPartition, MissingPartitionTable},
3939
flasher::{
40-
parse_partition_table,
4140
FlashData,
4241
FlashFrequency,
4342
FlashMode,
@@ -898,6 +897,13 @@ pub fn partition_table(args: PartitionTableArgs) -> Result<()> {
898897
Ok(())
899898
}
900899

900+
/// Parse a [PartitionTable] from the provided path
901+
pub fn parse_partition_table(path: &Path) -> Result<PartitionTable, Error> {
902+
let data = fs::read(path).map_err(|e| Error::FileOpenError(path.display().to_string(), e))?;
903+
904+
Ok(PartitionTable::try_from(data)?)
905+
}
906+
901907
/// Pretty print a partition table
902908
fn pretty_print(table: PartitionTable) {
903909
let mut pretty = Table::new();

espflash/src/flasher/mod.rs

Lines changed: 7 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -500,9 +500,13 @@ impl FlashData {
500500

501501
// If the '-T' option is provided, load the partition table from
502502
// the CSV or binary file at the specified path.
503-
let partition_table = match partition_table {
504-
Some(path) => Some(parse_partition_table(path)?),
505-
None => None,
503+
let partition_table = if let Some(path) = partition_table {
504+
let data =
505+
fs::read(path).map_err(|e| Error::FileOpenError(path.display().to_string(), e))?;
506+
507+
Some(PartitionTable::try_from(data)?)
508+
} else {
509+
None
506510
};
507511

508512
Ok(FlashData {
@@ -629,13 +633,6 @@ pub struct DeviceInfo {
629633
pub mac_address: String,
630634
}
631635

632-
/// Parse a [PartitionTable] from the provided path
633-
pub fn parse_partition_table(path: &Path) -> Result<PartitionTable, Error> {
634-
let data = fs::read(path).map_err(|e| Error::FileOpenError(path.display().to_string(), e))?;
635-
636-
Ok(PartitionTable::try_from(data)?)
637-
}
638-
639636
/// Connect to and flash a target device
640637
#[cfg(feature = "serialport")]
641638
#[derive(Debug)]

espflash/src/image_format.rs

Lines changed: 52 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -3,23 +3,26 @@
33
use std::{borrow::Cow, io::Write, iter::once, mem::size_of};
44

55
use bytemuck::{bytes_of, from_bytes, Pod, Zeroable};
6-
use esp_idf_part::{Partition, PartitionTable, Type};
6+
use esp_idf_part::{AppType, DataType, Partition, PartitionTable, SubType, Type};
77
use log::debug;
88
use sha2::{Digest, Sha256};
99

1010
use crate::{
1111
elf::{FirmwareImage, Segment},
12-
flasher::{FlashFrequency, FlashMode, FlashSettings, FlashSize},
12+
flasher::{FlashData, FlashFrequency, FlashMode, FlashSize},
1313
targets::{Chip, Esp32Params},
1414
Error,
1515
};
1616

17-
const ESP_CHECKSUM_MAGIC: u8 = 0xef;
17+
const ESP_CHECKSUM_MAGIC: u8 = 0xEF;
1818
const ESP_MAGIC: u8 = 0xE9;
1919
const IROM_ALIGN: u32 = 0x10000;
2020
const SEG_HEADER_LEN: u32 = 8;
2121
const WP_PIN_DISABLED: u8 = 0xEE;
2222

23+
/// Max partition size is 16 MB
24+
const MAX_PARTITION_SIZE: u32 = 16 * 1000 * 1024;
25+
2326
/// Firmware header used by the ESP-IDF bootloader.
2427
///
2528
/// ## Header documentation:
@@ -115,22 +118,16 @@ pub struct IdfBootloaderFormat<'a> {
115118
}
116119

117120
impl<'a> IdfBootloaderFormat<'a> {
118-
#[allow(clippy::too_many_arguments)]
119121
pub fn new(
120122
image: &'a dyn FirmwareImage<'a>,
121123
chip: Chip,
122-
min_rev_full: u16,
124+
flash_data: FlashData,
123125
params: Esp32Params,
124-
partition_table: Option<PartitionTable>,
125-
partition_table_offset: Option<u32>,
126-
target_app_partition: Option<String>,
127-
bootloader: Option<Vec<u8>>,
128-
flash_settings: FlashSettings,
129126
) -> Result<Self, Error> {
130-
let partition_table = partition_table.unwrap_or_else(|| {
131-
params.default_partition_table(flash_settings.size.map(|v| v.size()))
127+
let partition_table = flash_data.partition_table.unwrap_or_else(|| {
128+
default_partition_table(&params, flash_data.flash_settings.size.map(|v| v.size()))
132129
});
133-
let mut bootloader = if let Some(bytes) = bootloader {
130+
let mut bootloader = if let Some(bytes) = flash_data.bootloader {
134131
Cow::Owned(bytes)
135132
} else {
136133
Cow::Borrowed(params.default_bootloader)
@@ -154,13 +151,13 @@ impl<'a> IdfBootloaderFormat<'a> {
154151
}
155152

156153
// update the header if a user has specified any custom arguments
157-
if let Some(mode) = flash_settings.mode {
154+
if let Some(mode) = flash_data.flash_settings.mode {
158155
header.flash_mode = mode as u8;
159156
}
160157

161158
header.write_flash_config(
162-
flash_settings.size.unwrap_or_default(),
163-
flash_settings.freq.unwrap_or(params.flash_freq),
159+
flash_data.flash_settings.size.unwrap_or_default(),
160+
flash_data.flash_settings.freq.unwrap_or(params.flash_freq),
164161
chip,
165162
)?;
166163

@@ -197,7 +194,7 @@ impl<'a> IdfBootloaderFormat<'a> {
197194

198195
header.wp_pin = WP_PIN_DISABLED;
199196
header.chip_id = params.chip_id;
200-
header.min_chip_rev_full = min_rev_full;
197+
header.min_chip_rev_full = flash_data.min_chip_rev;
201198
header.append_digest = 1;
202199

203200
let mut data = bytes_of(&header).to_vec();
@@ -267,17 +264,15 @@ impl<'a> IdfBootloaderFormat<'a> {
267264

268265
let target_app_partition: &Partition =
269266
// Use the target app partition if provided
270-
if let Some(target_partition) = target_app_partition {
267+
if let Some(target_partition) = flash_data.target_app_partition {
271268
partition_table
272269
.find(&target_partition)
273270
.ok_or(Error::AppPartitionNotFound)?
274271
} else {
275-
276272
// The default partition table contains the "factory" partition, and if a user
277273
// provides a partition table via command-line then the validation step confirms
278274
// that at least one "app" partition is present. We prefer the "factory"
279275
// partition, and use any available "app" partitions if not present.
280-
281276
partition_table
282277
.find("factory")
283278
.or_else(|| partition_table.find_by_type(Type::App))
@@ -301,7 +296,7 @@ impl<'a> IdfBootloaderFormat<'a> {
301296
// If the user did not specify a partition offset, we need to assume that the
302297
// partition offset is (first partition offset) - 0x1000, since this is
303298
// the most common case.
304-
let partition_table_offset = partition_table_offset.unwrap_or_else(|| {
299+
let partition_table_offset = flash_data.partition_table_offset.unwrap_or_else(|| {
305300
let partitions = partition_table.partitions();
306301
let first_partition = partitions
307302
.iter()
@@ -363,6 +358,42 @@ impl<'a> IdfBootloaderFormat<'a> {
363358
}
364359
}
365360

361+
/// Generates a default partition table.
362+
///
363+
/// `flash_size` is used to scale app partition when present, otherwise the
364+
/// paramameter defaults are used.
365+
fn default_partition_table(params: &Esp32Params, flash_size: Option<u32>) -> PartitionTable {
366+
PartitionTable::new(vec![
367+
Partition::new(
368+
String::from("nvs"),
369+
Type::Data,
370+
SubType::Data(DataType::Nvs),
371+
params.nvs_addr,
372+
params.nvs_size,
373+
false,
374+
),
375+
Partition::new(
376+
String::from("phy_init"),
377+
Type::Data,
378+
SubType::Data(DataType::Phy),
379+
params.phy_init_data_addr,
380+
params.phy_init_data_size,
381+
false,
382+
),
383+
Partition::new(
384+
String::from("factory"),
385+
Type::App,
386+
SubType::App(AppType::Factory),
387+
params.app_addr,
388+
core::cmp::min(
389+
flash_size.map_or(params.app_size, |size| size - params.app_addr),
390+
MAX_PARTITION_SIZE,
391+
),
392+
false,
393+
),
394+
])
395+
}
396+
366397
/// Actual alignment (in data bytes) required for a segment header: positioned
367398
/// so that after we write the next 8 byte header, file_offset % IROM_ALIGN ==
368399
/// segment.addr % IROM_ALIGN

espflash/src/targets/esp32.rs

Lines changed: 1 addition & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -183,17 +183,7 @@ impl Target for Esp32 {
183183
booloader,
184184
);
185185

186-
IdfBootloaderFormat::new(
187-
image,
188-
Chip::Esp32,
189-
flash_data.min_chip_rev,
190-
params,
191-
flash_data.partition_table,
192-
flash_data.partition_table_offset,
193-
flash_data.target_app_partition,
194-
flash_data.bootloader,
195-
flash_data.flash_settings,
196-
)
186+
IdfBootloaderFormat::new(image, Chip::Esp32, flash_data, params)
197187
}
198188

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

espflash/src/targets/esp32c2.rs

Lines changed: 1 addition & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -121,17 +121,7 @@ impl Target for Esp32c2 {
121121
booloader,
122122
);
123123

124-
IdfBootloaderFormat::new(
125-
image,
126-
Chip::Esp32c2,
127-
flash_data.min_chip_rev,
128-
params,
129-
flash_data.partition_table,
130-
flash_data.partition_table_offset,
131-
flash_data.target_app_partition,
132-
flash_data.bootloader,
133-
flash_data.flash_settings,
134-
)
124+
IdfBootloaderFormat::new(image, Chip::Esp32c2, flash_data, params)
135125
}
136126

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

espflash/src/targets/esp32c3.rs

Lines changed: 1 addition & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -90,17 +90,7 @@ impl Target for Esp32c3 {
9090
});
9191
}
9292

93-
IdfBootloaderFormat::new(
94-
image,
95-
Chip::Esp32c3,
96-
flash_data.min_chip_rev,
97-
PARAMS,
98-
flash_data.partition_table,
99-
flash_data.partition_table_offset,
100-
flash_data.target_app_partition,
101-
flash_data.bootloader,
102-
flash_data.flash_settings,
103-
)
93+
IdfBootloaderFormat::new(image, Chip::Esp32c3, flash_data, PARAMS)
10494
}
10595

10696
fn spi_registers(&self) -> SpiRegisters {

espflash/src/targets/esp32c6.rs

Lines changed: 1 addition & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -85,17 +85,7 @@ impl Target for Esp32c6 {
8585
});
8686
}
8787

88-
IdfBootloaderFormat::new(
89-
image,
90-
Chip::Esp32c6,
91-
flash_data.min_chip_rev,
92-
PARAMS,
93-
flash_data.partition_table,
94-
flash_data.partition_table_offset,
95-
flash_data.target_app_partition,
96-
flash_data.bootloader,
97-
flash_data.flash_settings,
98-
)
88+
IdfBootloaderFormat::new(image, Chip::Esp32c6, flash_data, PARAMS)
9989
}
10090

10191
fn spi_registers(&self) -> SpiRegisters {

0 commit comments

Comments
 (0)