Skip to content

Commit 299be2d

Browse files
committed
Crude POC for flash ESP app images instead of ELF files (esp-rs#770)
1 parent be1ff81 commit 299be2d

File tree

19 files changed

+243
-90
lines changed

19 files changed

+243
-90
lines changed

Cargo.lock

Lines changed: 104 additions & 9 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

espflash/Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ defmt-parser = { version = "=0.4.1", features = ["unstable"], optional = true
3838
dialoguer = { version = "0.11.0", optional = true }
3939
directories = { version = "5.0.1", optional = true }
4040
env_logger = { version = "0.11.6", optional = true }
41-
esp-idf-part = "0.5.0"
41+
esp-idf-part = { version = "0.5.0", git = "https://github.com/esp-rs/esp-idf-part", rev = "8cb16c0254d8299fe5a4a692e460f73844e024bf" }
4242
flate2 = "1.0.35"
4343
hex = { version = "0.4.3", features = ["serde"] }
4444
indicatif = { version = "0.17.9", optional = true }

espflash/src/bin/espflash.rs

Lines changed: 21 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
use espflash::image_format;
12
use std::{
23
fs::{self, File},
34
io::Read,
@@ -15,6 +16,9 @@ use espflash::{
1516
};
1617
use log::{debug, info, LevelFilter};
1718
use miette::{IntoDiagnostic, Result, WrapErr};
19+
use xmas_elf::header;
20+
use espflash::elf::{ElfFirmwareImage, FirmwareImage};
21+
use espflash::esp_firmware_image::EspFirmwareImage;
1822

1923
#[derive(Debug, Parser)]
2024
#[command(about, max_term_width = 100, propagate_version = true, version)]
@@ -259,10 +263,11 @@ fn flash(args: FlashArgs, config: &Config) -> Result<()> {
259263
let target_xtal_freq = target.crystal_freq(flasher.connection())?;
260264

261265
// Read the ELF data from the build path and load it to the target.
262-
let elf_data = fs::read(&args.image).into_diagnostic()?;
266+
let file_data = fs::read(&args.image).into_diagnostic()?;
267+
let image = image_from_bytes(&file_data)?;
263268

264269
if args.flash_args.ram {
265-
flasher.load_elf_to_ram(&elf_data, Some(&mut EspflashProgress::default()))?;
270+
flasher.load_elf_to_ram(image.as_ref(), Some(&mut EspflashProgress::default()))?;
266271
} else {
267272
let flash_data = make_flash_data(
268273
args.flash_args.image,
@@ -281,7 +286,7 @@ fn flash(args: FlashArgs, config: &Config) -> Result<()> {
281286
)?;
282287
}
283288

284-
flash_elf_image(&mut flasher, &elf_data, flash_data, target_xtal_freq)?;
289+
flash_elf_image(&mut flasher, image.as_ref(), flash_data, target_xtal_freq)?;
285290
}
286291

287292
if args.flash_args.monitor {
@@ -299,12 +304,24 @@ fn flash(args: FlashArgs, config: &Config) -> Result<()> {
299304

300305
monitor_args.elf = Some(args.image);
301306

302-
monitor(flasher.into_serial(), Some(&elf_data), pid, monitor_args)
307+
monitor(flasher.into_serial(), None, pid, monitor_args)
303308
} else {
304309
Ok(())
305310
}
306311
}
307312

313+
fn image_from_bytes<'a, 'b: 'a>(elf_data: &'b [u8]) -> Result<Box<dyn FirmwareImage<'a> + 'a>> {
314+
if elf_data.len() < 4 {
315+
todo!() // ERRORS
316+
} else if elf_data.starts_with(&header::MAGIC) {
317+
Ok(Box::new(ElfFirmwareImage::try_from(elf_data).unwrap()))
318+
} else if elf_data[0] == image_format::ESP_MAGIC {
319+
Ok(Box::new(EspFirmwareImage::new(elf_data)))
320+
} else {
321+
todo!()
322+
}
323+
}
324+
308325
fn save_image(args: SaveImageArgs, config: &Config) -> Result<()> {
309326
let elf_data = fs::read(&args.image)
310327
.into_diagnostic()

espflash/src/cli/mod.rs

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,7 @@ use crate::{
4949
},
5050
targets::{Chip, XtalFrequency},
5151
};
52+
use crate::elf::FirmwareImage;
5253

5354
pub mod config;
5455
pub mod monitor;
@@ -741,16 +742,16 @@ pub fn erase_region(args: EraseRegionArgs, config: &Config) -> Result<()> {
741742
}
742743

743744
/// Write an ELF image to a target device's flash
744-
pub fn flash_elf_image(
745+
pub fn flash_elf_image<'a: 'b, 'b>(
745746
flasher: &mut Flasher,
746-
elf_data: &[u8],
747+
image: &'b dyn FirmwareImage<'a>,
747748
flash_data: FlashData,
748749
xtal_freq: XtalFrequency,
749750
) -> Result<()> {
750751
// Load the ELF data, optionally using the provider bootloader/partition
751752
// table/image format, to the device's flash memory.
752753
flasher.load_elf_to_flash(
753-
elf_data,
754+
image,
754755
flash_data,
755756
Some(&mut EspflashProgress::default()),
756757
xtal_freq,

espflash/src/elf.rs

Lines changed: 5 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,6 @@ use std::{
99
};
1010

1111
use xmas_elf::{
12-
program::Type,
1312
sections::{SectionData, ShType},
1413
ElfFile,
1514
};
@@ -25,21 +24,18 @@ pub trait FirmwareImage<'a> {
2524
fn entry(&self) -> u32;
2625

2726
/// Firmware image segments
28-
fn segments(&'a self) -> Box<dyn Iterator<Item = CodeSegment<'a>> + 'a>;
29-
30-
/// Firmware image segments, with their associated load addresses
31-
fn segments_with_load_addresses(&'a self) -> Box<dyn Iterator<Item = CodeSegment<'a>> + 'a>;
27+
fn segments(&self) -> Box<dyn Iterator<Item = CodeSegment<'_>> + '_>;
3228

3329
/// Firmware image ROM segments
34-
fn rom_segments(&'a self, chip: Chip) -> Box<dyn Iterator<Item = CodeSegment<'a>> + 'a> {
30+
fn rom_segments(&self, chip: Chip) -> Box<dyn Iterator<Item = CodeSegment<'_>> + '_> {
3531
Box::new(
3632
self.segments()
3733
.filter(move |segment| chip.into_target().addr_is_flash(segment.addr)),
3834
)
3935
}
4036

4137
/// Firmware image RAM segments
42-
fn ram_segments(&'a self, chip: Chip) -> Box<dyn Iterator<Item = CodeSegment<'a>> + 'a> {
38+
fn ram_segments(&self, chip: Chip) -> Box<dyn Iterator<Item = CodeSegment<'_>> + '_> {
4339
Box::new(
4440
self.segments()
4541
.filter(move |segment| !chip.into_target().addr_is_flash(segment.addr)),
@@ -59,7 +55,7 @@ impl<'a> ElfFirmwareImage<'a> {
5955
}
6056
}
6157

62-
impl<'a> TryFrom<&'a [u8]> for ElfFirmwareImage<'a> {
58+
impl<'a, 'b: 'a> TryFrom<&'b [u8]> for ElfFirmwareImage<'a> {
6359
type Error = Error;
6460

6561
fn try_from(value: &'a [u8]) -> Result<Self, Self::Error> {
@@ -76,7 +72,7 @@ impl<'a> FirmwareImage<'a> for ElfFirmwareImage<'a> {
7672
self.elf.header.pt2.entry_point() as u32
7773
}
7874

79-
fn segments(&'a self) -> Box<dyn Iterator<Item = CodeSegment<'a>> + 'a> {
75+
fn segments(&self) -> Box<dyn Iterator<Item = CodeSegment<'_>> + '_> {
8076
Box::new(
8177
self.elf
8278
.section_iter()
@@ -96,25 +92,6 @@ impl<'a> FirmwareImage<'a> for ElfFirmwareImage<'a> {
9692
}),
9793
)
9894
}
99-
100-
fn segments_with_load_addresses(&'a self) -> Box<dyn Iterator<Item = CodeSegment<'a>> + 'a> {
101-
Box::new(
102-
self.elf
103-
.program_iter()
104-
.filter(|header| {
105-
header.file_size() > 0
106-
&& header.get_type() == Ok(Type::Load)
107-
&& header.offset() > 0
108-
})
109-
.flat_map(move |header| {
110-
let addr = header.physical_addr() as u32;
111-
let from = header.offset() as usize;
112-
let to = header.offset() as usize + header.file_size() as usize;
113-
let data = &self.elf.input[from..to];
114-
Some(CodeSegment::new(addr, data))
115-
}),
116-
)
117-
}
11895
}
11996

12097
#[derive(Eq, Clone, Default)]

0 commit comments

Comments
 (0)