diff --git a/cargo-espflash/src/main.rs b/cargo-espflash/src/main.rs index 98d7069a..753c813f 100644 --- a/cargo-espflash/src/main.rs +++ b/cargo-espflash/src/main.rs @@ -266,6 +266,7 @@ fn flash(args: FlashArgs, config: &Config) -> Result<()> { bootloader, partition_table, args.flash_args.partition_table_offset, + args.flash_args.target_app_partition, args.flash_args.format.or(metadata.format), args.build_args.flash_config_args.flash_mode, args.build_args.flash_config_args.flash_size, @@ -506,6 +507,7 @@ fn save_image(args: SaveImageArgs) -> Result<()> { args.save_image_args.merge, bootloader, partition_table, + args.save_image_args.target_app_partition, args.save_image_args.skip_padding, )?; diff --git a/espflash/src/bin/espflash.rs b/espflash/src/bin/espflash.rs index 0a0694dd..d395b7aa 100644 --- a/espflash/src/bin/espflash.rs +++ b/espflash/src/bin/espflash.rs @@ -234,6 +234,7 @@ fn flash(args: FlashArgs, config: &Config) -> Result<()> { bootloader, partition_table, args.flash_args.partition_table_offset, + args.flash_args.target_app_partition, args.flash_args.format, args.flash_config_args.flash_mode, args.flash_config_args.flash_size, @@ -295,6 +296,7 @@ fn save_image(args: SaveImageArgs) -> Result<()> { args.save_image_args.merge, args.save_image_args.bootloader, args.save_image_args.partition_table, + args.save_image_args.target_app_partition, args.save_image_args.skip_padding, )?; diff --git a/espflash/src/cli/mod.rs b/espflash/src/cli/mod.rs index a53d5bc6..632c8759 100644 --- a/espflash/src/cli/mod.rs +++ b/espflash/src/cli/mod.rs @@ -108,6 +108,9 @@ pub struct FlashArgs { pub partition_table: Option, #[arg(long)] pub partition_table_offset: Option, + /// Label of target app partition + #[arg(long, value_name = "LABEL")] + pub target_app_partition: Option, /// Load the application to RAM instead of Flash #[arg(long)] pub ram: bool, @@ -148,6 +151,9 @@ pub struct SaveImageArgs { /// Custom partition table for merging #[arg(long, short = 'T', requires = "merge", value_name = "FILE")] pub partition_table: Option, + /// Label of target app partition + #[arg(long, value_name = "LABEL")] + pub target_app_partition: Option, /// Don't pad the image to the flash size #[arg(long, short = 'P', requires = "merge")] pub skip_padding: bool, @@ -314,6 +320,7 @@ pub fn save_elf_as_image( merge: bool, bootloader_path: Option, partition_table_path: Option, + target_app_partition: Option, skip_padding: bool, ) -> Result<()> { let image = ElfFirmwareImage::try_from(elf_data)?; @@ -356,6 +363,7 @@ pub fn save_elf_as_image( bootloader, partition_table, None, + target_app_partition, image_format, None, flash_mode, @@ -397,6 +405,7 @@ pub fn save_elf_as_image( None, None, None, + None, image_format, None, flash_mode, @@ -479,6 +488,7 @@ pub fn flash_elf_image( bootloader: Option<&Path>, partition_table: Option, partition_table_offset: Option, + target_app_partition: Option, image_format: Option, flash_mode: Option, flash_size: Option, @@ -502,6 +512,7 @@ pub fn flash_elf_image( bootloader, partition_table, partition_table_offset, + target_app_partition, image_format, flash_mode, flash_size, diff --git a/espflash/src/error.rs b/espflash/src/error.rs index b23a30fa..d076e71a 100644 --- a/espflash/src/error.rs +++ b/espflash/src/error.rs @@ -22,6 +22,10 @@ use crate::{ #[derive(Debug, Diagnostic, Error)] #[non_exhaustive] pub enum Error { + #[error("App partition not found")] + #[diagnostic(code(espflash::app_partition_not_found))] + AppPartitionNotFound, + #[error("Operation was cancelled by the user")] #[diagnostic(code(espflash::cancelled))] Cancelled, diff --git a/espflash/src/flasher/mod.rs b/espflash/src/flasher/mod.rs index 8c413586..7adb9263 100644 --- a/espflash/src/flasher/mod.rs +++ b/espflash/src/flasher/mod.rs @@ -723,6 +723,7 @@ impl Flasher { bootloader: Option>, partition_table: Option, partition_table_offset: Option, + target_app_partition: Option, image_format: Option, flash_mode: Option, flash_size: Option, @@ -751,6 +752,7 @@ impl Flasher { bootloader, partition_table, partition_table_offset, + target_app_partition, image_format, chip_revision, flash_mode, @@ -800,6 +802,7 @@ impl Flasher { bootloader: Option>, partition_table: Option, partition_table_offset: Option, + target_app_partition: Option, flash_mode: Option, flash_size: Option, flash_freq: Option, @@ -810,6 +813,7 @@ impl Flasher { bootloader, partition_table, partition_table_offset, + target_app_partition, None, flash_mode, flash_size, diff --git a/espflash/src/image_format/idf_bootloader.rs b/espflash/src/image_format/idf_bootloader.rs index 5600ae3d..2ae825f1 100644 --- a/espflash/src/image_format/idf_bootloader.rs +++ b/espflash/src/image_format/idf_bootloader.rs @@ -1,7 +1,7 @@ use std::{borrow::Cow, io::Write, iter::once, mem::size_of}; use bytemuck::{bytes_of, from_bytes}; -use esp_idf_part::{PartitionTable, Type}; +use esp_idf_part::{Partition, PartitionTable, Type}; use sha2::{Digest, Sha256}; use crate::{ @@ -37,6 +37,7 @@ impl<'a> IdfBootloaderFormat<'a> { params: Esp32Params, partition_table: Option, partition_table_offset: Option, + target_app_partition: Option, bootloader: Option>, flash_mode: Option, flash_size: Option, @@ -148,17 +149,27 @@ impl<'a> IdfBootloaderFormat<'a> { let hash = hasher.finalize(); data.write_all(&hash)?; - // The default partition table contains the "factory" partition, and if a user - // provides a partition table via command-line then the validation step confirms - // that at least one "app" partition is present. We prefer the "factory" - // partition, and use any available "app" partitions if not present. - let factory_partition = partition_table - .find("factory") - .or_else(|| partition_table.find_by_type(Type::App)) - .unwrap(); + let target_app_partition: &Partition = + // Use the target app partition if provided + if let Some(target_partition) = target_app_partition { + partition_table + .find(&target_partition) + .ok_or_else(|| Error::AppPartitionNotFound)? + } else { + + // The default partition table contains the "factory" partition, and if a user + // provides a partition table via command-line then the validation step confirms + // that at least one "app" partition is present. We prefer the "factory" + // partition, and use any available "app" partitions if not present. + + partition_table + .find("factory") + .or_else(|| partition_table.find_by_type(Type::App)) + .ok_or_else(|| Error::AppPartitionNotFound)? + }; let app_size = data.len() as u32; - let part_size = factory_partition.size(); + let part_size = target_app_partition.size(); // The size of the application must not exceed the size of the factory // partition. @@ -167,7 +178,7 @@ impl<'a> IdfBootloaderFormat<'a> { } let flash_segment = RomSegment { - addr: factory_partition.offset(), + addr: target_app_partition.offset(), data: Cow::Owned(data), }; diff --git a/espflash/src/targets/esp32.rs b/espflash/src/targets/esp32.rs index 9a5b53c1..de0445da 100644 --- a/espflash/src/targets/esp32.rs +++ b/espflash/src/targets/esp32.rs @@ -156,6 +156,7 @@ impl Target for Esp32 { bootloader: Option>, partition_table: Option, partition_table_offset: Option, + target_app_partition: Option, image_format: Option, _chip_revision: Option<(u32, u32)>, flash_mode: Option, @@ -171,6 +172,7 @@ impl Target for Esp32 { PARAMS, partition_table, partition_table_offset, + target_app_partition, bootloader, flash_mode, flash_size, diff --git a/espflash/src/targets/esp32c2.rs b/espflash/src/targets/esp32c2.rs index 2e27d223..fc4eb0dc 100644 --- a/espflash/src/targets/esp32c2.rs +++ b/espflash/src/targets/esp32c2.rs @@ -90,6 +90,7 @@ impl Target for Esp32c2 { bootloader: Option>, partition_table: Option, partition_table_offset: Option, + target_app_partition: Option, image_format: Option, _chip_revision: Option<(u32, u32)>, flash_mode: Option, @@ -105,6 +106,7 @@ impl Target for Esp32c2 { PARAMS, partition_table, partition_table_offset, + target_app_partition, bootloader, flash_mode, flash_size, diff --git a/espflash/src/targets/esp32c3.rs b/espflash/src/targets/esp32c3.rs index a2eff4db..0eadffba 100644 --- a/espflash/src/targets/esp32c3.rs +++ b/espflash/src/targets/esp32c3.rs @@ -77,6 +77,7 @@ impl Target for Esp32c3 { bootloader: Option>, partition_table: Option, partition_table_offset: Option, + target_app_partition: Option, image_format: Option, chip_revision: Option<(u32, u32)>, flash_mode: Option, @@ -92,6 +93,7 @@ impl Target for Esp32c3 { PARAMS, partition_table, partition_table_offset, + target_app_partition, bootloader, flash_mode, flash_size, diff --git a/espflash/src/targets/esp32c6.rs b/espflash/src/targets/esp32c6.rs index 871895f7..47ef6371 100644 --- a/espflash/src/targets/esp32c6.rs +++ b/espflash/src/targets/esp32c6.rs @@ -74,6 +74,7 @@ impl Target for Esp32c6 { bootloader: Option>, partition_table: Option, partition_table_offset: Option, + target_app_partition: Option, image_format: Option, _chip_revision: Option<(u32, u32)>, flash_mode: Option, @@ -89,6 +90,7 @@ impl Target for Esp32c6 { PARAMS, partition_table, partition_table_offset, + target_app_partition, bootloader, flash_mode, flash_size, diff --git a/espflash/src/targets/esp32h2.rs b/espflash/src/targets/esp32h2.rs index 701b8264..bb7c4f27 100644 --- a/espflash/src/targets/esp32h2.rs +++ b/espflash/src/targets/esp32h2.rs @@ -82,6 +82,7 @@ impl Target for Esp32h2 { bootloader: Option>, partition_table: Option, partition_table_offset: Option, + target_app_partition: Option, image_format: Option, _chip_revision: Option<(u32, u32)>, flash_mode: Option, @@ -97,6 +98,7 @@ impl Target for Esp32h2 { PARAMS, partition_table, partition_table_offset, + target_app_partition, bootloader, flash_mode, flash_size, diff --git a/espflash/src/targets/esp32s2.rs b/espflash/src/targets/esp32s2.rs index 6022d977..f3b6f088 100644 --- a/espflash/src/targets/esp32s2.rs +++ b/espflash/src/targets/esp32s2.rs @@ -142,6 +142,7 @@ impl Target for Esp32s2 { bootloader: Option>, partition_table: Option, partition_table_offset: Option, + target_app_partition: Option, image_format: Option, _chip_revision: Option<(u32, u32)>, flash_mode: Option, @@ -157,6 +158,7 @@ impl Target for Esp32s2 { PARAMS, partition_table, partition_table_offset, + target_app_partition, bootloader, flash_mode, flash_size, diff --git a/espflash/src/targets/esp32s3.rs b/espflash/src/targets/esp32s3.rs index 8adf0ab8..0827f64a 100644 --- a/espflash/src/targets/esp32s3.rs +++ b/espflash/src/targets/esp32s3.rs @@ -96,6 +96,7 @@ impl Target for Esp32s3 { bootloader: Option>, partition_table: Option, partition_table_offset: Option, + target_app_partition: Option, image_format: Option, _chip_revision: Option<(u32, u32)>, flash_mode: Option, @@ -111,6 +112,7 @@ impl Target for Esp32s3 { PARAMS, partition_table, partition_table_offset, + target_app_partition, bootloader, flash_mode, flash_size, diff --git a/espflash/src/targets/esp8266.rs b/espflash/src/targets/esp8266.rs index 1a3bc822..9a36c8aa 100644 --- a/espflash/src/targets/esp8266.rs +++ b/espflash/src/targets/esp8266.rs @@ -75,6 +75,7 @@ impl Target for Esp8266 { _bootloader: Option>, _partition_table: Option, _partition_table_offset: Option, + _target_app_partition: Option, image_format: Option, _chip_revision: Option<(u32, u32)>, flash_mode: Option, diff --git a/espflash/src/targets/mod.rs b/espflash/src/targets/mod.rs index b768e70b..7682fe43 100644 --- a/espflash/src/targets/mod.rs +++ b/espflash/src/targets/mod.rs @@ -298,6 +298,7 @@ pub trait Target: ReadEFuse { bootloader: Option>, partition_table: Option, partition_table_offset: Option, + target_app_partition: Option, image_format: Option, chip_revision: Option<(u32, u32)>, flash_mode: Option,