use crate::flash_device::FlashDevice;
use probe_rs::config::{FlashProperties, RawFlashAlgorithm, SectorDescription};
use anyhow::{anyhow, Context, Result};
pub(crate) fn read_elf_bin_data<'a>(
elf: &'a goblin::elf::Elf<'_>,
buffer: &'a [u8],
address: u32,
size: u32,
) -> Option<&'a [u8]> {
for ph in &elf.program_headers {
let segment_address = ph.p_paddr as u32;
let segment_size = ph.p_memsz.min(ph.p_filesz) as u32;
log::debug!("Segment address: {:#010x}", segment_address);
log::debug!("Segment size: {} bytes", segment_size);
if address > segment_address + segment_size {
continue;
}
if address + size <= segment_address {
continue;
}
if address >= segment_address && address + size <= segment_address + segment_size {
let start = ph.p_offset as u32 + address - segment_address;
return Some(&buffer[start as usize..][..size as usize]);
}
}
None
}
fn extract_flash_device(elf: &goblin::elf::Elf, buffer: &[u8]) -> Result<FlashDevice> {
for sym in elf.syms.iter() {
let name = &elf.strtab[sym.st_name];
if let "FlashDevice" = name {
let address = sym.st_value as u32;
return FlashDevice::new(elf, buffer, address);
}
}
Err(anyhow!("Failed to find 'FlashDevice' symbol in ELF file."))
}
pub fn extract_flash_algo(
mut file: impl std::io::Read,
file_name: &std::path::Path,
default: bool,
) -> Result<RawFlashAlgorithm> {
let mut buffer = vec![];
file.read_to_end(&mut buffer)?;
let mut algo = RawFlashAlgorithm::default();
let elf = goblin::elf::Elf::parse(buffer.as_slice())?;
let flash_device = extract_flash_device(&elf, &buffer).context(format!(
"Failed to extract flash information from ELF file '{}'.",
file_name.display()
))?;
let algorithm_binary = crate::algorithm_binary::AlgorithmBinary::new(&elf, &buffer)?;
algo.instructions = algorithm_binary.blob();
let code_section_offset = algorithm_binary.code_section.start;
for sym in elf.syms.iter() {
let name = &elf.strtab[sym.st_name];
match name {
"Init" => algo.pc_init = Some(sym.st_value as u32 - code_section_offset),
"UnInit" => algo.pc_uninit = Some(sym.st_value as u32 - code_section_offset),
"EraseChip" => algo.pc_erase_all = Some(sym.st_value as u32 - code_section_offset),
"EraseSector" => algo.pc_erase_sector = sym.st_value as u32 - code_section_offset,
"ProgramPage" => algo.pc_program_page = sym.st_value as u32 - code_section_offset,
_ => {}
}
}
algo.description = flash_device.name;
algo.name = file_name
.file_stem()
.and_then(|f| f.to_str())
.unwrap()
.to_lowercase();
algo.default = default;
algo.data_section_offset = algorithm_binary.data_section.start;
let sectors = flash_device
.sectors
.iter()
.map(|si| SectorDescription {
address: si.address,
size: si.size,
})
.collect();
let properties = FlashProperties {
address_range: flash_device.start_address
..(flash_device.start_address + flash_device.device_size),
page_size: flash_device.page_size,
erased_byte_value: flash_device.erased_default_value,
program_page_timeout: flash_device.program_page_timeout,
erase_sector_timeout: flash_device.erase_sector_timeout,
sectors,
};
algo.flash_properties = properties;
Ok(algo)
}