Skip to content

Commit

Permalink
Rename and clean up the image formats module, move some functions aro…
Browse files Browse the repository at this point in the history
…und (#249)
  • Loading branch information
jessebraham authored Oct 5, 2022
1 parent fee2762 commit d9aa971
Show file tree
Hide file tree
Showing 10 changed files with 134 additions and 116 deletions.
26 changes: 0 additions & 26 deletions espflash/src/elf.rs
Original file line number Diff line number Diff line change
Expand Up @@ -244,29 +244,3 @@ impl<'a> From<CodeSegment<'a>> for RomSegment<'a> {
}
}
}

pub fn update_checksum(data: &[u8], mut checksum: u8) -> u8 {
for byte in data {
checksum ^= *byte;
}

checksum
}

pub fn merge_adjacent_segments(mut segments: Vec<CodeSegment>) -> Vec<CodeSegment> {
segments.sort();

let mut merged: Vec<CodeSegment> = Vec::with_capacity(segments.len());
for segment in segments {
match merged.last_mut() {
Some(last) if last.addr + last.size() == segment.addr => {
*last += segment.data();
}
_ => {
merged.push(segment);
}
}
}

merged
}
Original file line number Diff line number Diff line change
@@ -1,35 +1,37 @@
use crate::elf::CodeSegment;
use std::iter::once;

use super::ImageFormat;
use crate::{
elf::{FirmwareImage, RomSegment},
elf::{CodeSegment, FirmwareImage, RomSegment},
error::Error,
image_format::ImageFormat,
};
use std::iter::once;

/// Image format for esp32 family chips not using a 2nd stage bootloader
pub struct Esp32DirectBootFormat<'a> {
const DIRECT_BOOT_MAGIC: &[u8] = &[0x1d, 0x04, 0xdb, 0xae, 0x1d, 0x04, 0xdb, 0xae];

/// Image format for ESP32 family chips not using a second-stage bootloader
pub struct DirectBootFormat<'a> {
segment: RomSegment<'a>,
}

impl<'a> Esp32DirectBootFormat<'a> {
impl<'a> DirectBootFormat<'a> {
pub fn new(image: &'a dyn FirmwareImage<'a>, magic_offset: usize) -> Result<Self, Error> {
let mut segment = image
.segments_with_load_addresses()
.map(|mut segment| {
// map address to the first 4MB
segment.addr %= 0x400000;
// Map the address to the first 4MB of address space
segment.addr %= 0x40_0000;
segment
})
.fold(CodeSegment::default(), |mut a, b| {
a += &b;
a
});

segment.pad_align(4);

if segment.addr != 0
|| (segment.data().len() >= magic_offset + 8
&& segment.data()[magic_offset..][..8]
!= [0x1d, 0x04, 0xdb, 0xae, 0x1d, 0x04, 0xdb, 0xae])
&& &segment.data()[magic_offset..][..8] != DIRECT_BOOT_MAGIC)
{
return Err(Error::InvalidDirectBootBinary);
}
Expand All @@ -40,7 +42,7 @@ impl<'a> Esp32DirectBootFormat<'a> {
}
}

impl<'a> ImageFormat<'a> for Esp32DirectBootFormat<'a> {
impl<'a> ImageFormat<'a> for DirectBootFormat<'a> {
fn flash_segments<'b>(&'b self) -> Box<dyn Iterator<Item = RomSegment<'b>> + 'b>
where
'a: 'b,
Expand Down
29 changes: 19 additions & 10 deletions espflash/src/image_format/esp8266.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,16 +2,17 @@ use std::{borrow::Cow, io::Write, iter::once, mem::size_of};

use bytemuck::bytes_of;

use super::encode_flash_frequency;
use super::{
encode_flash_frequency, update_checksum, EspCommonHeader, ImageFormat, SegmentHeader, ESP_MAGIC,
};
use crate::{
elf::{update_checksum, CodeSegment, FirmwareImage, RomSegment, ESP_CHECKSUM_MAGIC},
elf::{CodeSegment, FirmwareImage, RomSegment, ESP_CHECKSUM_MAGIC},
error::{Error, FlashDetectError},
flasher::{FlashFrequency, FlashMode, FlashSize},
image_format::{EspCommonHeader, ImageFormat, SegmentHeader, ESP_MAGIC},
targets::Chip,
};

/// Image format for flashing to esp8266 chips
/// Image format for flashing to the ESP8266
pub struct Esp8266Format<'a> {
irom_data: Option<RomSegment<'a>>,
flash_segment: RomSegment<'a>,
Expand All @@ -35,15 +36,18 @@ impl<'a> Esp8266Format<'a> {
);

// Common header
let flash_size = flash_size.unwrap_or(FlashSize::Flash4Mb);
let flash_mode = flash_mode.unwrap_or(FlashMode::Dio) as u8;
let flash_freq = flash_freq.unwrap_or(FlashFrequency::Flash40M);
let flash_size = flash_size.unwrap_or(FlashSize::Flash4Mb);
let flash_config =
encode_flash_size(flash_size)? + encode_flash_frequency(Chip::Esp8266, flash_freq)?;
let segment_count = image.ram_segments(Chip::Esp8266).count() as u8;

let header = EspCommonHeader {
magic: ESP_MAGIC,
segment_count: image.ram_segments(Chip::Esp8266).count() as u8,
flash_mode: flash_mode.unwrap_or(FlashMode::Dio) as u8,
flash_config: encode_flash_size(flash_size)?
+ encode_flash_frequency(Chip::Esp8266, flash_freq)?,
segment_count,
flash_mode,
flash_config,
entry: image.entry(),
};
common_data.write_all(bytes_of(&header))?;
Expand All @@ -54,21 +58,26 @@ impl<'a> Esp8266Format<'a> {
for segment in image.ram_segments(Chip::Esp8266) {
let data = segment.data();
let padding = 4 - data.len() % 4;

let segment_header = SegmentHeader {
addr: segment.addr,
length: (data.len() + padding) as u32,
};

total_len += size_of::<SegmentHeader>() as u32 + segment_header.length;

common_data.write_all(bytes_of(&segment_header))?;
common_data.write_all(data)?;

let padding = &[0u8; 4][0..padding];
common_data.write_all(padding)?;

checksum = update_checksum(data, checksum);
}

let padding = 15 - (total_len % 16);
let padding = &[0u8; 16][0..padding as usize];

common_data.write_all(padding)?;
common_data.write_all(&[checksum])?;

Expand Down Expand Up @@ -113,7 +122,7 @@ impl<'a> ImageFormat<'a> for Esp8266Format<'a> {
fn merge_rom_segments<'a>(
mut segments: impl Iterator<Item = CodeSegment<'a>>,
) -> Option<RomSegment<'a>> {
const IROM_MAP_START: u32 = 0x40200000;
const IROM_MAP_START: u32 = 0x4020_0000;

let first = segments.next()?;
let data = if let Some(second) = segments.next() {
Expand Down
Loading

0 comments on commit d9aa971

Please sign in to comment.