Skip to content

Commit d886d33

Browse files
authored
Add handling for custom partition table offsets (#516)
* read flash locations from partition table * add partition table offset option * fix tests * fix cargo-espflash build * update changelog
1 parent 59a4bf0 commit d886d33

File tree

15 files changed

+84
-9
lines changed

15 files changed

+84
-9
lines changed

CHANGELOG.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,11 +13,13 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
1313
- Add --target-app-partition argument to flash command (#461)
1414
- Add --confirm-port argument to flash command (#455)
1515
- Add --chip argument for flash and write-bin commands (#514)
16+
- Add --partition-table-offset argument for specifying the partition table offset (#516)
1617

1718
### Fixed
1819

1920
- Fixed printing panic backtraces when using `esp-println` and `defmt` (#496)
2021
- Fixed defmt parsing when data is read in parts (#503)
22+
- Use partition table instead of hard-coded values for the location of partitions (#516)
2123

2224
### Changed
2325

cargo-espflash/src/main.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -328,6 +328,7 @@ fn flash(args: FlashArgs, config: &Config) -> Result<()> {
328328
args.build_args.flash_config_args.flash_mode,
329329
args.build_args.flash_config_args.flash_size,
330330
args.build_args.flash_config_args.flash_freq,
331+
args.flash_args.partition_table_offset,
331332
)?;
332333
}
333334

@@ -562,6 +563,7 @@ fn save_image(args: SaveImageArgs) -> Result<()> {
562563
args.build_args.flash_config_args.flash_mode,
563564
args.build_args.flash_config_args.flash_size,
564565
args.build_args.flash_config_args.flash_freq,
566+
args.save_image_args.partition_table_offset,
565567
args.save_image_args.merge,
566568
bootloader,
567569
partition_table,

espflash/src/bin/espflash.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -250,6 +250,7 @@ fn flash(args: FlashArgs, config: &Config) -> Result<()> {
250250
args.flash_config_args.flash_mode,
251251
args.flash_config_args.flash_size,
252252
args.flash_config_args.flash_freq,
253+
args.flash_args.partition_table_offset,
253254
)?;
254255
}
255256

@@ -305,6 +306,7 @@ fn save_image(args: SaveImageArgs) -> Result<()> {
305306
args.flash_config_args.flash_mode,
306307
args.flash_config_args.flash_size,
307308
args.flash_config_args.flash_freq,
309+
args.save_image_args.partition_table_offset,
308310
args.save_image_args.merge,
309311
args.save_image_args.bootloader,
310312
args.save_image_args.partition_table,

espflash/src/cli/mod.rs

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -145,6 +145,9 @@ pub struct FlashArgs {
145145
/// Label of target app partition
146146
#[arg(long, value_name = "LABEL")]
147147
pub target_app_partition: Option<String>,
148+
/// Partition table offset
149+
#[arg(long, value_name = "OFFSET")]
150+
pub partition_table_offset: Option<u32>,
148151
/// Load the application to RAM instead of Flash
149152
#[arg(long)]
150153
pub ram: bool,
@@ -185,6 +188,9 @@ pub struct SaveImageArgs {
185188
/// Custom partition table for merging
186189
#[arg(long, short = 'T', requires = "merge", value_name = "FILE")]
187190
pub partition_table: Option<PathBuf>,
191+
/// Partition table offset
192+
#[arg(long, value_name = "OFFSET")]
193+
pub partition_table_offset: Option<u32>,
188194
/// Label of target app partition
189195
#[arg(long, value_name = "LABEL")]
190196
pub target_app_partition: Option<String>,
@@ -333,6 +339,7 @@ pub fn save_elf_as_image(
333339
flash_mode: Option<FlashMode>,
334340
flash_size: Option<FlashSize>,
335341
flash_freq: Option<FlashFrequency>,
342+
partition_table_offset: Option<u32>,
336343
merge: bool,
337344
bootloader_path: Option<PathBuf>,
338345
partition_table_path: Option<PathBuf>,
@@ -384,6 +391,7 @@ pub fn save_elf_as_image(
384391
flash_mode,
385392
flash_size,
386393
flash_freq,
394+
partition_table_offset,
387395
)?;
388396

389397
display_image_size(image.app_size(), image.part_size());
@@ -425,6 +433,7 @@ pub fn save_elf_as_image(
425433
flash_mode,
426434
flash_size,
427435
flash_freq,
436+
partition_table_offset,
428437
)?;
429438

430439
display_image_size(image.app_size(), image.part_size());
@@ -538,6 +547,7 @@ pub fn flash_elf_image(
538547
flash_mode: Option<FlashMode>,
539548
flash_size: Option<FlashSize>,
540549
flash_freq: Option<FlashFrequency>,
550+
partition_table_offset: Option<u32>,
541551
) -> Result<()> {
542552
// If the '--bootloader' option is provided, load the binary file at the
543553
// specified path.
@@ -561,6 +571,7 @@ pub fn flash_elf_image(
561571
flash_mode,
562572
flash_size,
563573
flash_freq,
574+
partition_table_offset,
564575
Some(&mut EspflashProgress::default()),
565576
)?;
566577
info!("Flashing has completed!");

espflash/src/flasher/mod.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -783,6 +783,7 @@ impl Flasher {
783783
flash_mode: Option<FlashMode>,
784784
flash_size: Option<FlashSize>,
785785
flash_freq: Option<FlashFrequency>,
786+
partition_table_offset: Option<u32>,
786787
mut progress: Option<&mut dyn ProgressCallbacks>,
787788
) -> Result<(), Error> {
788789
let image = ElfFirmwareImage::try_from(elf_data)?;
@@ -812,6 +813,7 @@ impl Flasher {
812813
flash_mode,
813814
flash_size.or(Some(self.flash_size)),
814815
flash_freq,
816+
partition_table_offset,
815817
)?;
816818

817819
// When the `cli` feature is enabled, display the image size information.
@@ -869,6 +871,7 @@ impl Flasher {
869871
flash_mode: Option<FlashMode>,
870872
flash_size: Option<FlashSize>,
871873
flash_freq: Option<FlashFrequency>,
874+
partition_table_offset: Option<u32>,
872875
progress: Option<&mut dyn ProgressCallbacks>,
873876
) -> Result<(), Error> {
874877
self.load_elf_to_flash_with_format(
@@ -880,6 +883,7 @@ impl Flasher {
880883
flash_mode,
881884
flash_size,
882885
flash_freq,
886+
partition_table_offset,
883887
progress,
884888
)
885889
}

espflash/src/image_format/idf_bootloader.rs

Lines changed: 47 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ pub struct IdfBootloaderFormat<'a> {
2727
flash_segment: RomSegment<'a>,
2828
app_size: u32,
2929
part_size: u32,
30+
partition_table_offset: u32,
3031
}
3132

3233
impl<'a> IdfBootloaderFormat<'a> {
@@ -40,6 +41,7 @@ impl<'a> IdfBootloaderFormat<'a> {
4041
flash_mode: Option<FlashMode>,
4142
flash_size: Option<FlashSize>,
4243
flash_freq: Option<FlashFrequency>,
44+
partition_table_offset: Option<u32>,
4345
) -> Result<Self, Error> {
4446
let partition_table = partition_table
4547
.unwrap_or_else(|| params.default_partition_table(flash_size.map(|v| v.size())));
@@ -178,13 +180,25 @@ impl<'a> IdfBootloaderFormat<'a> {
178180
data: Cow::Owned(data),
179181
};
180182

183+
// If the user did not specify a partition offset, we need to assume that the partition
184+
// offset is (first partition offset) - 0x1000, since this is the most common case.
185+
let partition_table_offset = partition_table_offset.unwrap_or_else(|| {
186+
let partitions = partition_table.partitions();
187+
let first_partition = partitions
188+
.iter()
189+
.min_by(|a, b| a.offset().cmp(&b.offset()))
190+
.unwrap();
191+
first_partition.offset() - 0x1000
192+
});
193+
181194
Ok(Self {
182195
params,
183196
bootloader,
184197
partition_table,
185198
flash_segment,
186199
app_size,
187200
part_size,
201+
partition_table_offset,
188202
})
189203
}
190204
}
@@ -194,16 +208,39 @@ impl<'a> ImageFormat<'a> for IdfBootloaderFormat<'a> {
194208
where
195209
'a: 'b,
196210
{
211+
let bootloader_segment = RomSegment {
212+
addr: self.params.boot_addr,
213+
data: Cow::Borrowed(&self.bootloader),
214+
};
215+
216+
let partition_table_segment = RomSegment {
217+
addr: self.partition_table_offset,
218+
data: Cow::Owned(self.partition_table.to_bin().unwrap()),
219+
};
220+
221+
let app_partition = self
222+
.partition_table
223+
.find("factory")
224+
.or_else(|| self.partition_table.find_by_type(Type::App))
225+
.expect("no application partition found");
226+
227+
if self.flash_segment.data.len() > app_partition.size() as usize {
228+
panic!(
229+
"image size ({} bytes) is larger partition size ({} bytes)",
230+
self.flash_segment.data.len(),
231+
app_partition.size()
232+
);
233+
}
234+
235+
let app_segment = RomSegment {
236+
addr: app_partition.offset(),
237+
data: Cow::Borrowed(&self.flash_segment.data),
238+
};
239+
197240
Box::new(
198-
once(RomSegment {
199-
addr: self.params.boot_addr,
200-
data: Cow::Borrowed(&self.bootloader),
201-
})
202-
.chain(once(RomSegment {
203-
addr: self.params.partition_addr,
204-
data: Cow::Owned(self.partition_table.to_bin().unwrap()),
205-
}))
206-
.chain(once(self.flash_segment.borrow())),
241+
once(bootloader_segment)
242+
.chain(once(partition_table_segment))
243+
.chain(once(app_segment)),
207244
)
208245
}
209246

@@ -334,6 +371,7 @@ pub mod tests {
334371
None,
335372
None,
336373
None,
374+
None,
337375
)
338376
.unwrap();
339377

espflash/src/targets/esp32.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -161,6 +161,7 @@ impl Target for Esp32 {
161161
flash_mode: Option<FlashMode>,
162162
flash_size: Option<FlashSize>,
163163
flash_freq: Option<FlashFrequency>,
164+
partition_table_offset: Option<u32>,
164165
) -> Result<Box<dyn ImageFormat<'a> + 'a>, Error> {
165166
let image_format = image_format.unwrap_or(ImageFormatKind::EspBootloader);
166167

@@ -175,6 +176,7 @@ impl Target for Esp32 {
175176
flash_mode,
176177
flash_size,
177178
flash_freq,
179+
partition_table_offset,
178180
)?)),
179181
_ => Err(UnsupportedImageFormatError::new(image_format, Chip::Esp32, None).into()),
180182
}

espflash/src/targets/esp32c2.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -95,6 +95,7 @@ impl Target for Esp32c2 {
9595
flash_mode: Option<FlashMode>,
9696
flash_size: Option<FlashSize>,
9797
flash_freq: Option<FlashFrequency>,
98+
partition_table_offset: Option<u32>,
9899
) -> Result<Box<dyn ImageFormat<'a> + 'a>, Error> {
99100
let image_format = image_format.unwrap_or(ImageFormatKind::EspBootloader);
100101

@@ -109,6 +110,7 @@ impl Target for Esp32c2 {
109110
flash_mode,
110111
flash_size,
111112
flash_freq,
113+
partition_table_offset,
112114
)?)),
113115
ImageFormatKind::DirectBoot => Ok(Box::new(DirectBootFormat::new(image, 0)?)),
114116
}

espflash/src/targets/esp32c3.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,7 @@ impl Target for Esp32c3 {
8282
flash_mode: Option<FlashMode>,
8383
flash_size: Option<FlashSize>,
8484
flash_freq: Option<FlashFrequency>,
85+
partition_table_offset: Option<u32>,
8586
) -> Result<Box<dyn ImageFormat<'a> + 'a>, Error> {
8687
let image_format = image_format.unwrap_or(ImageFormatKind::EspBootloader);
8788

@@ -96,6 +97,7 @@ impl Target for Esp32c3 {
9697
flash_mode,
9798
flash_size,
9899
flash_freq,
100+
partition_table_offset,
99101
)?)),
100102
(ImageFormatKind::DirectBoot, None | Some((_, 3..))) => {
101103
Ok(Box::new(DirectBootFormat::new(image, 0)?))

espflash/src/targets/esp32c6.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,7 @@ impl Target for Esp32c6 {
7979
flash_mode: Option<FlashMode>,
8080
flash_size: Option<FlashSize>,
8181
flash_freq: Option<FlashFrequency>,
82+
partition_table_offset: Option<u32>,
8283
) -> Result<Box<dyn ImageFormat<'a> + 'a>, Error> {
8384
let image_format = image_format.unwrap_or(ImageFormatKind::EspBootloader);
8485

@@ -93,6 +94,7 @@ impl Target for Esp32c6 {
9394
flash_mode,
9495
flash_size,
9596
flash_freq,
97+
partition_table_offset,
9698
)?)),
9799
ImageFormatKind::DirectBoot => Ok(Box::new(DirectBootFormat::new(image, 0x0)?)),
98100
}

0 commit comments

Comments
 (0)