Skip to content

Commit 92a266d

Browse files
authored
Merge pull request #112 from bugadani/ota
Support flashing to partitions other than `factory`
2 parents a221364 + 8c9a2b1 commit 92a266d

File tree

4 files changed

+46
-14
lines changed

4 files changed

+46
-14
lines changed

.gitignore

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,4 @@
11
/target
2+
/Cargo.lock
23
*.swp
4+
/.vscode

espflash/src/error.rs

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -314,7 +314,7 @@ pub enum PartitionTableError {
314314
InvalidSubType(#[from] InvalidSubTypeError),
315315
#[error(transparent)]
316316
#[diagnostic(transparent)]
317-
NoFactoryApp(#[from] NoFactoryAppError),
317+
NoApp(#[from] NoAppError),
318318
#[error(transparent)]
319319
#[diagnostic(transparent)]
320320
UnalignedPartitionError(#[from] UnalignedPartitionError),
@@ -469,19 +469,19 @@ impl InvalidSubTypeError {
469469
}
470470

471471
#[derive(Debug, Error, Diagnostic)]
472-
#[error("No factory app partition was found")]
472+
#[error("No app partition was found")]
473473
#[diagnostic(
474-
code(espflash::partition_table::no_factory_app),
475-
help("Partition table must contain a factory app partition")
474+
code(espflash::partition_table::no_app),
475+
help("Partition table must contain a factory or ota app partition")
476476
)]
477-
pub struct NoFactoryAppError {
477+
pub struct NoAppError {
478478
#[source_code]
479479
source_code: String,
480480
}
481481

482-
impl NoFactoryAppError {
482+
impl NoAppError {
483483
pub fn new(source: &str) -> Self {
484-
NoFactoryAppError {
484+
NoAppError {
485485
source_code: source.into(),
486486
}
487487
}

espflash/src/image_format/esp32bootloader.rs

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ use crate::{
1212
error::{Error, FlashDetectError},
1313
flasher::FlashSize,
1414
image_format::{EspCommonHeader, ImageFormat, SegmentHeader, ESP_MAGIC, WP_PIN_DISABLED},
15+
partition_table::Type,
1516
Chip, PartitionTable,
1617
};
1718

@@ -123,8 +124,12 @@ impl<'a> Esp32BootloaderFormat<'a> {
123124

124125
// The default partition table contains the "factory" partition, and if a user
125126
// provides a partition table via command-line then the validation step confirms
126-
// this is present, so it's safe to unwrap.
127-
let factory_partition = partition_table.find("factory").unwrap();
127+
// that at least one "app" partition is present. We prefer the "factory" partition,
128+
// and use any available "app" partitions if not present.
129+
let factory_partition = partition_table
130+
.find("factory")
131+
.or_else(|| partition_table.find_by_type(Type::App))
132+
.unwrap();
128133

129134
let flash_segment = RomSegment {
130135
addr: factory_partition.offset(),

espflash/src/partition_table.rs

Lines changed: 30 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ use regex::Regex;
1010
use serde::{Deserialize, Deserializer, Serialize};
1111

1212
use crate::error::{
13-
CSVError, DuplicatePartitionsError, InvalidSubTypeError, NoFactoryAppError,
13+
CSVError, DuplicatePartitionsError, InvalidSubTypeError, NoAppError,
1414
OverlappingPartitionsError, PartitionTableError, UnalignedPartitionError,
1515
};
1616

@@ -264,6 +264,10 @@ impl PartitionTable {
264264
self.partitions.iter().find(|&p| p.name == name)
265265
}
266266

267+
pub fn find_by_type(&self, ty: Type) -> Option<&Partition> {
268+
self.partitions.iter().find(|&p| p.ty == ty)
269+
}
270+
267271
fn validate(&self, source: &str) -> Result<(), PartitionTableError> {
268272
for partition in &self.partitions {
269273
if let Some(line) = &partition.line {
@@ -318,10 +322,8 @@ impl PartitionTable {
318322
}
319323
}
320324

321-
if self.find("factory").is_none() {
322-
return Err(PartitionTableError::NoFactoryApp(NoFactoryAppError::new(
323-
source,
324-
)));
325+
if self.find_by_type(Type::App).is_none() {
326+
return Err(PartitionTableError::NoApp(NoAppError::new(source)));
325327
}
326328

327329
Ok(())
@@ -590,6 +592,24 @@ phy_init, data, phy, 0xf000, 0x1000,
590592
factory, app, factory, 0x10000, 1M,
591593
a, data, spiffs, 0x110000, 1M,
592594
b, data, spiffs, 0x210000, 1M,
595+
";
596+
597+
const PTABLE_NO_FACTORY: &str = "
598+
# ESP-IDF Partition Table
599+
# Name, Type, SubType, Offset, Size, Flags
600+
nvs, data, nvs, 0x9000, 0x4000,
601+
otadata, data, ota, 0xd000, 0x2000,
602+
phy_init, data, phy, 0xf000, 0x1000,
603+
ota_0, app, ota_0, , 1M,
604+
ota_1, app, ota_1, , 1M,
605+
";
606+
607+
const PTABLE_NO_APP: &str = "
608+
# ESP-IDF Partition Table
609+
# Name, Type, SubType, Offset, Size, Flags
610+
nvs, data, nvs, 0x9000, 0x4000,
611+
otadata, data, ota, 0xd000, 0x2000,
612+
phy_init, data, phy, 0xf000, 0x1000,
593613
";
594614

595615
#[test]
@@ -629,6 +649,11 @@ b, data, spiffs, 0x210000, 1M,
629649

630650
let pt_spiffs = PartitionTable::try_from_str(PTABLE_SPIFFS);
631651
assert!(pt_spiffs.is_ok());
652+
653+
PartitionTable::try_from_str(PTABLE_NO_FACTORY)
654+
.expect("Failed to parse partition table without factory partition");
655+
PartitionTable::try_from_str(PTABLE_NO_APP)
656+
.expect_err("Failed to reject partition table without factory or ota partition");
632657
}
633658

634659
#[test]

0 commit comments

Comments
 (0)