Skip to content

Commit 3e7c94a

Browse files
committed
Add support for providing custom partition tables
1 parent 27b2f32 commit 3e7c94a

File tree

10 files changed

+273
-74
lines changed

10 files changed

+273
-74
lines changed

cargo-espflash/src/main.rs

Lines changed: 25 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,11 @@
11
use anyhow::{anyhow, bail, Context};
22
use cargo_metadata::Message;
33
use clap::{App, Arg, SubCommand};
4-
use espflash::{Config, Flasher};
4+
use espflash::{Config, Flasher, PartitionTable};
55
use serial::{BaudRate, SerialPort};
66

77
use std::{
8-
fs::read,
8+
fs,
99
path::PathBuf,
1010
process::{exit, Command, ExitStatus, Stdio},
1111
string::ToString,
@@ -51,6 +51,13 @@ fn main() -> anyhow::Result<()> {
5151
.value_name("FEATURES")
5252
.help("Comma delimited list of build features"),
5353
)
54+
.arg(
55+
Arg::with_name("partition_table")
56+
.long("partition-table")
57+
.takes_value(true)
58+
.value_name("PATH")
59+
.help("Path to a CSV file containing partition table"),
60+
)
5461
.arg(
5562
Arg::with_name("speed")
5663
.long("speed")
@@ -128,12 +135,26 @@ fn main() -> anyhow::Result<()> {
128135
return Ok(());
129136
}
130137

138+
// If the '--partition-table' option is provided, load the partition table from
139+
// the CSV at the specified path.
140+
let partition_table = if let Some(path) = matches.value_of("partition_table") {
141+
let path = fs::canonicalize(path)?;
142+
let data = fs::read_to_string(path)?;
143+
144+
match PartitionTable::try_from_str(data) {
145+
Ok(t) => Some(t),
146+
Err(e) => bail!("{}", e),
147+
}
148+
} else {
149+
None
150+
};
151+
131152
// Read the ELF data from the build path and load it to the target.
132-
let elf_data = read(path.unwrap())?;
153+
let elf_data = fs::read(path.unwrap())?;
133154
if matches.is_present("ram") {
134155
flasher.load_elf_to_ram(&elf_data)?;
135156
} else {
136-
flasher.load_elf_to_flash(&elf_data)?;
157+
flasher.load_elf_to_flash(&elf_data, partition_table)?;
137158
}
138159

139160
// We're all done!

espflash/Cargo.toml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,8 @@ directories-next = "2.0.0"
3030
color-eyre = "0.5"
3131
strum = "0.21.0"
3232
strum_macros = "0.21.1"
33+
csv = "1.1.6"
34+
regex = "1.5.4"
3335

3436
[dev-dependencies]
3537
pretty_assertions = "0.7.1"

espflash/src/chip/esp32.rs

Lines changed: 16 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,7 @@ use crate::{
88
WP_PIN_DISABLED,
99
},
1010
elf::{FirmwareImage, RomSegment, ESP_CHECKSUM_MAGIC},
11-
partition_table::PartitionTable,
12-
Error,
11+
Error, PartitionTable,
1312
};
1413

1514
use std::{borrow::Cow, io::Write, iter::once};
@@ -52,18 +51,23 @@ impl ChipType for Esp32 {
5251

5352
fn get_flash_segments<'a>(
5453
image: &'a FirmwareImage,
54+
partition_table: Option<PartitionTable>,
5555
) -> Box<dyn Iterator<Item = Result<RomSegment<'a>, Error>> + 'a> {
5656
let bootloader = include_bytes!("../../bootloader/esp32-bootloader.bin");
5757

58-
let partition_table = PartitionTable::basic(
59-
NVS_ADDR,
60-
NVS_SIZE,
61-
PHY_INIT_DATA_ADDR,
62-
PHY_INIT_DATA_SIZE,
63-
APP_ADDR,
64-
APP_SIZE,
65-
)
66-
.to_bytes();
58+
let partition_table = if let Some(table) = partition_table {
59+
table
60+
} else {
61+
PartitionTable::basic(
62+
NVS_ADDR,
63+
NVS_SIZE,
64+
PHY_INIT_DATA_ADDR,
65+
PHY_INIT_DATA_SIZE,
66+
APP_ADDR,
67+
APP_SIZE,
68+
)
69+
};
70+
let partition_table = partition_table.to_bytes();
6771

6872
fn get_data<'a>(image: &'a FirmwareImage) -> Result<RomSegment<'a>, Error> {
6973
let mut data = Vec::new();
@@ -177,7 +181,7 @@ fn test_esp32_rom() {
177181

178182
let image = FirmwareImage::from_data(&input_bytes).unwrap();
179183

180-
let segments = Esp32::get_flash_segments(&image)
184+
let segments = Esp32::get_flash_segments(&image, None)
181185
.collect::<Result<Vec<_>, Error>>()
182186
.unwrap();
183187

espflash/src/chip/esp32c3.rs

Lines changed: 15 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,7 @@ use crate::{
88
WP_PIN_DISABLED,
99
},
1010
elf::{FirmwareImage, RomSegment, ESP_CHECKSUM_MAGIC},
11-
partition_table::PartitionTable,
12-
Error,
11+
Error, PartitionTable,
1312
};
1413

1514
use std::{borrow::Cow, io::Write, iter::once};
@@ -53,18 +52,23 @@ impl ChipType for Esp32c3 {
5352

5453
fn get_flash_segments<'a>(
5554
image: &'a FirmwareImage,
55+
partition_table: Option<PartitionTable>,
5656
) -> Box<dyn Iterator<Item = Result<RomSegment<'a>, Error>> + 'a> {
5757
let bootloader = include_bytes!("../../bootloader/esp32c3-bootloader.bin");
5858

59-
let partition_table = PartitionTable::basic(
60-
NVS_ADDR,
61-
NVS_SIZE,
62-
PHY_INIT_DATA_ADDR,
63-
PHY_INIT_DATA_SIZE,
64-
APP_ADDR,
65-
APP_SIZE,
66-
)
67-
.to_bytes();
59+
let partition_table = if let Some(table) = partition_table {
60+
table
61+
} else {
62+
PartitionTable::basic(
63+
NVS_ADDR,
64+
NVS_SIZE,
65+
PHY_INIT_DATA_ADDR,
66+
PHY_INIT_DATA_SIZE,
67+
APP_ADDR,
68+
APP_SIZE,
69+
)
70+
};
71+
let partition_table = partition_table.to_bytes();
6872

6973
fn get_data<'a>(image: &'a FirmwareImage) -> Result<RomSegment<'a>, Error> {
7074
let mut data = Vec::new();

espflash/src/chip/esp8266.rs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ use crate::{
55
chip::{Chip, SpiRegisters},
66
elf::{update_checksum, CodeSegment, FirmwareImage, RomSegment, ESP_CHECKSUM_MAGIC},
77
flasher::FlashSize,
8-
Error,
8+
Error, PartitionTable,
99
};
1010

1111
use std::{borrow::Cow, io::Write, iter::once, mem::size_of};
@@ -34,6 +34,7 @@ impl ChipType for Esp8266 {
3434

3535
fn get_flash_segments<'a>(
3636
image: &'a FirmwareImage,
37+
_partition_table: Option<PartitionTable>,
3738
) -> Box<dyn Iterator<Item = Result<RomSegment<'a>, Error>> + 'a> {
3839
// irom goes into a separate plain bin
3940
let irom_data = merge_rom_segments(image.rom_segments(Chip::Esp8266))
@@ -143,7 +144,7 @@ fn test_esp8266_rom() {
143144

144145
let image = FirmwareImage::from_data(&input_bytes).unwrap();
145146

146-
let segments = Esp8266::get_flash_segments(&image)
147+
let segments = Esp8266::get_flash_segments(&image, None)
147148
.collect::<Result<Vec<_>, Error>>()
148149
.unwrap();
149150

espflash/src/chip/mod.rs

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ use strum_macros::Display;
44
use crate::{
55
elf::{update_checksum, CodeSegment, FirmwareImage, RomSegment},
66
flasher::FlashSize,
7-
Error,
7+
Error, PartitionTable,
88
};
99

1010
use std::{io::Write, str::FromStr};
@@ -29,6 +29,7 @@ pub trait ChipType {
2929
/// Get the firmware segments for writing an image to flash
3030
fn get_flash_segments<'a>(
3131
image: &'a FirmwareImage,
32+
partition_table: Option<PartitionTable>,
3233
) -> Box<dyn Iterator<Item = Result<RomSegment<'a>, Error>> + 'a>;
3334

3435
fn addr_is_flash(addr: u32) -> bool;
@@ -112,11 +113,12 @@ impl Chip {
112113
pub fn get_flash_segments<'a>(
113114
&self,
114115
image: &'a FirmwareImage,
116+
partition_table: Option<PartitionTable>,
115117
) -> Box<dyn Iterator<Item = Result<RomSegment<'a>, Error>> + 'a> {
116118
match self {
117-
Chip::Esp32 => Esp32::get_flash_segments(image),
118-
Chip::Esp32c3 => Esp32c3::get_flash_segments(image),
119-
Chip::Esp8266 => Esp8266::get_flash_segments(image),
119+
Chip::Esp32 => Esp32::get_flash_segments(image, partition_table),
120+
Chip::Esp32c3 => Esp32c3::get_flash_segments(image, partition_table),
121+
Chip::Esp8266 => Esp8266::get_flash_segments(image, None),
120122
}
121123
}
122124

espflash/src/flasher.rs

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ use std::{mem::size_of, thread::sleep};
77

88
use crate::{
99
chip::Chip, connection::Connection, elf::FirmwareImage, encoder::SlipEncoder, error::RomError,
10-
Error,
10+
Error, PartitionTable,
1111
};
1212

1313
type Encoder<'a> = SlipEncoder<'a, Box<dyn SerialPort>>;
@@ -551,12 +551,16 @@ impl Flasher {
551551
}
552552

553553
/// Load an elf image to flash and execute it
554-
pub fn load_elf_to_flash(&mut self, elf_data: &[u8]) -> Result<(), Error> {
554+
pub fn load_elf_to_flash(
555+
&mut self,
556+
elf_data: &[u8],
557+
partition_table: Option<PartitionTable>,
558+
) -> Result<(), Error> {
555559
self.enable_flash(self.spi_params)?;
556560
let mut image = FirmwareImage::from_data(elf_data).map_err(|_| Error::InvalidElf)?;
557561
image.flash_size = self.flash_size();
558562

559-
for segment in self.chip.get_flash_segments(&image) {
563+
for segment in self.chip.get_flash_segments(&image, partition_table) {
560564
let segment = segment?;
561565
let addr = segment.addr;
562566
let block_count = (segment.data.len() + FLASH_WRITE_SIZE - 1) / FLASH_WRITE_SIZE;

espflash/src/lib.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,3 +11,4 @@ pub use chip::Chip;
1111
pub use config::Config;
1212
pub use error::Error;
1313
pub use flasher::Flasher;
14+
pub use partition_table::PartitionTable;

espflash/src/main.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,7 @@ fn main() -> Result<()> {
6262
if ram {
6363
flasher.load_elf_to_ram(&input_bytes)?;
6464
} else {
65-
flasher.load_elf_to_flash(&input_bytes)?;
65+
flasher.load_elf_to_flash(&input_bytes, None)?;
6666
}
6767

6868
Ok(())

0 commit comments

Comments
 (0)