Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,2 +1,4 @@
/target
/Cargo.lock
*.swp
/.vscode
14 changes: 7 additions & 7 deletions espflash/src/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -314,7 +314,7 @@ pub enum PartitionTableError {
InvalidSubType(#[from] InvalidSubTypeError),
#[error(transparent)]
#[diagnostic(transparent)]
NoFactoryApp(#[from] NoFactoryAppError),
NoApp(#[from] NoAppError),
#[error(transparent)]
#[diagnostic(transparent)]
UnalignedPartitionError(#[from] UnalignedPartitionError),
Expand Down Expand Up @@ -469,19 +469,19 @@ impl InvalidSubTypeError {
}

#[derive(Debug, Error, Diagnostic)]
#[error("No factory app partition was found")]
#[error("No app partition was found")]
#[diagnostic(
code(espflash::partition_table::no_factory_app),
help("Partition table must contain a factory app partition")
code(espflash::partition_table::no_app),
help("Partition table must contain a factory or ota app partition")
)]
pub struct NoFactoryAppError {
pub struct NoAppError {
#[source_code]
source_code: String,
}

impl NoFactoryAppError {
impl NoAppError {
pub fn new(source: &str) -> Self {
NoFactoryAppError {
NoAppError {
source_code: source.into(),
}
}
Expand Down
9 changes: 7 additions & 2 deletions espflash/src/image_format/esp32bootloader.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ use crate::{
error::{Error, FlashDetectError},
flasher::FlashSize,
image_format::{EspCommonHeader, ImageFormat, SegmentHeader, ESP_MAGIC, WP_PIN_DISABLED},
partition_table::Type,
Chip, PartitionTable,
};

Expand Down Expand Up @@ -123,8 +124,12 @@ impl<'a> Esp32BootloaderFormat<'a> {

// The default partition table contains the "factory" partition, and if a user
// provides a partition table via command-line then the validation step confirms
// this is present, so it's safe to unwrap.
let factory_partition = partition_table.find("factory").unwrap();
// 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 flash_segment = RomSegment {
addr: factory_partition.offset(),
Expand Down
35 changes: 30 additions & 5 deletions espflash/src/partition_table.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ use regex::Regex;
use serde::{Deserialize, Deserializer, Serialize};

use crate::error::{
CSVError, DuplicatePartitionsError, InvalidSubTypeError, NoFactoryAppError,
CSVError, DuplicatePartitionsError, InvalidSubTypeError, NoAppError,
OverlappingPartitionsError, PartitionTableError, UnalignedPartitionError,
};

Expand Down Expand Up @@ -264,6 +264,10 @@ impl PartitionTable {
self.partitions.iter().find(|&p| p.name == name)
}

pub fn find_by_type(&self, ty: Type) -> Option<&Partition> {
self.partitions.iter().find(|&p| p.ty == ty)
}

fn validate(&self, source: &str) -> Result<(), PartitionTableError> {
for partition in &self.partitions {
if let Some(line) = &partition.line {
Expand Down Expand Up @@ -318,10 +322,8 @@ impl PartitionTable {
}
}

if self.find("factory").is_none() {
return Err(PartitionTableError::NoFactoryApp(NoFactoryAppError::new(
source,
)));
if self.find_by_type(Type::App).is_none() {
return Err(PartitionTableError::NoApp(NoAppError::new(source)));
}

Ok(())
Expand Down Expand Up @@ -590,6 +592,24 @@ phy_init, data, phy, 0xf000, 0x1000,
factory, app, factory, 0x10000, 1M,
a, data, spiffs, 0x110000, 1M,
b, data, spiffs, 0x210000, 1M,
";

const PTABLE_NO_FACTORY: &str = "
# ESP-IDF Partition Table
# Name, Type, SubType, Offset, Size, Flags
nvs, data, nvs, 0x9000, 0x4000,
otadata, data, ota, 0xd000, 0x2000,
phy_init, data, phy, 0xf000, 0x1000,
ota_0, app, ota_0, , 1M,
ota_1, app, ota_1, , 1M,
";

const PTABLE_NO_APP: &str = "
# ESP-IDF Partition Table
# Name, Type, SubType, Offset, Size, Flags
nvs, data, nvs, 0x9000, 0x4000,
otadata, data, ota, 0xd000, 0x2000,
phy_init, data, phy, 0xf000, 0x1000,
";

#[test]
Expand Down Expand Up @@ -629,6 +649,11 @@ b, data, spiffs, 0x210000, 1M,

let pt_spiffs = PartitionTable::try_from_str(PTABLE_SPIFFS);
assert!(pt_spiffs.is_ok());

PartitionTable::try_from_str(PTABLE_NO_FACTORY)
.expect("Failed to parse partition table without factory partition");
PartitionTable::try_from_str(PTABLE_NO_APP)
.expect_err("Failed to reject partition table without factory or ota partition");
}

#[test]
Expand Down