use probe_rs_target::InstructionSet;
#[cfg(feature = "builtin-formats")]
use serde::{Deserialize, Serialize};
use std::{fs::File, path::Path};
use super::*;
use crate::session::Session;
#[derive(Debug, Serialize, Deserialize, PartialEq, Eq, Clone, Default)]
#[cfg(feature = "builtin-formats")]
pub struct BinOptions {
pub base_address: Option<u64>,
pub skip: u32,
}
#[derive(Debug, Serialize, Deserialize, PartialEq, Eq, Clone, Default)]
#[cfg(feature = "builtin-formats")]
pub struct ElfOptions {
pub skip_sections: Vec<String>,
}
#[derive(Debug, thiserror::Error, docsplay::Display)]
pub enum FileDownloadError {
#[ignore_extra_doc_attributes]
Flash(#[from] FlashError),
#[cfg(feature = "builtin-formats")]
IhexRead(#[from] ihex::ReaderError),
IO(#[from] std::io::Error),
Object(&'static str),
#[cfg(feature = "builtin-formats")]
Elf(#[from] object::read::Error),
ImageFormatSpecific {
format: String,
source: Box<dyn std::error::Error + Send + Sync>,
},
#[ignore_extra_doc_attributes]
NoLoadableSegments,
IncompatibleImage {
target: Vec<InstructionSet>,
image: InstructionSet,
},
IncompatibleImageChip {
target: String,
image_chips: Vec<String>,
},
Other(#[source] crate::Error),
}
fn print_instr_sets(instr_sets: &[InstructionSet]) -> String {
instr_sets
.iter()
.map(|instr_set| format!("{instr_set:?}"))
.collect::<Vec<_>>()
.join(", ")
}
#[derive(Default)]
#[non_exhaustive]
pub struct DownloadOptions<'p> {
pub progress: FlashProgress<'p>,
pub keep_unwritten_bytes: bool,
pub dry_run: bool,
pub do_chip_erase: bool,
pub skip_erase: bool,
pub preverify: bool,
pub verify: bool,
pub disable_double_buffering: bool,
pub preferred_algos: Vec<String>,
}
impl DownloadOptions<'_> {
pub fn new() -> Self {
Self::default()
}
}
pub fn build_loader(
session: &mut Session,
path: impl AsRef<Path>,
format: impl ImageLoader,
image_instruction_set: Option<InstructionSet>,
) -> Result<FlashLoader, FileDownloadError> {
let mut loader = session.target().flash_loader();
let mut file = File::open(path).map_err(FileDownloadError::IO)?;
loader.load_image(session, &mut file, format, image_instruction_set)?;
Ok(loader)
}
pub fn download_file(
session: &mut Session,
path: impl AsRef<Path>,
format: impl ImageLoader,
) -> Result<(), FileDownloadError> {
download_file_with_options(session, path, format, DownloadOptions::default())
}
pub fn download_file_with_options(
session: &mut Session,
path: impl AsRef<Path>,
format: impl ImageLoader,
options: DownloadOptions,
) -> Result<(), FileDownloadError> {
let loader = build_loader(session, path, format, None)?;
loader
.commit(session, options)
.map_err(FileDownloadError::Flash)
}