style: cargo fmt

This commit is contained in:
spacemeowx2 2020-12-05 00:47:46 +08:00
parent c8b3b6d923
commit b56d4215f4
11 changed files with 227 additions and 208 deletions

View File

@ -1,5 +1,8 @@
use super::{Chip, CodeSegment, RomSegment};
use crate::{Error, image::{PartitionCfg, BootHeaderCfg}};
use crate::{
image::{BootHeaderCfg, PartitionCfg},
Error,
};
use deku::prelude::*;
pub const DEFAULT_PARTITION_CFG: &'static [u8] = include_bytes!("cfg/partition_cfg_2M.toml");
@ -50,7 +53,10 @@ impl Chip for Bl602 {
fn get_flash_segment<'a>(&self, code_segment: CodeSegment<'a>) -> Option<RomSegment<'a>> {
if self.addr_is_flash(code_segment.addr) {
Some(RomSegment::from_code_segment(code_segment.addr - ROM_START, code_segment))
Some(RomSegment::from_code_segment(
code_segment.addr - ROM_START,
code_segment,
))
} else {
None
}

View File

@ -1,6 +1,6 @@
pub mod bl602;
pub use crate::elf::{CodeSegment, FirmwareImage, RomSegment};
pub use bl602::Bl602;
pub use crate::elf::{FirmwareImage, CodeSegment, RomSegment};
pub trait Chip {
fn get_eflash_loader(&self) -> &[u8];

View File

@ -31,4 +31,4 @@ impl Config {
Self::default()
}
}
}
}

View File

@ -1,8 +1,8 @@
use std::io::{Read, Write, Cursor};
use crate::{Error, RomError};
use byteorder::{LittleEndian, ReadBytesExt};
use std::io::{Cursor, Read, Write};
use std::thread::sleep;
use std::time::Duration;
use crate::{Error, RomError};
use byteorder::{ReadBytesExt, LittleEndian};
use serial::{BaudRate, SerialPort, SerialPortSettings};
@ -85,14 +85,14 @@ impl Connection {
} else {
Ok(vec![])
}
},
}
// FL
[0x46, 0x4c] => {
let code = self.read_exact(2)?;
let mut reader = Cursor::new(code);
let code = reader.read_u16::<LittleEndian>()?;
Err(Error::RomError(RomError::from(code)))
},
}
e => {
log::trace!("read_response err: {:x?}", e);
Err(Error::RespError)

View File

@ -1,112 +1,111 @@
use std::borrow::Cow;
use std::cmp::Ordering;
use xmas_elf::program::{SegmentData, Type};
use xmas_elf::ElfFile;
pub struct FirmwareImage<'a> {
pub entry: u32,
pub elf: ElfFile<'a>,
}
impl<'a> FirmwareImage<'a> {
pub fn from_data(data: &'a [u8]) -> Result<Self, &'static str> {
Ok(Self::from_elf(ElfFile::new(data)?))
}
pub fn from_elf(elf: ElfFile<'a>) -> Self {
FirmwareImage {
entry: elf.header.pt2.entry_point() as u32,
elf,
}
}
pub fn entry(&self) -> u32 {
self.elf.header.pt2.entry_point() as u32
}
pub fn segments(&'a self) -> impl Iterator<Item = CodeSegment<'a>> + 'a {
self.elf
.program_iter()
.filter(|header| {
header.file_size() > 0 && header.get_type() == Ok(Type::Load) && header.offset() > 0
})
.flat_map(move |header| {
let addr = header.virtual_addr() as u32;
let size = header.file_size() as u32;
let data = match header.get_data(&self.elf) {
Ok(SegmentData::Undefined(data)) => data,
_ => return None,
};
Some(CodeSegment { addr, data, size })
})
}
}
#[derive(Debug, Ord, Eq)]
/// A segment of code from the source elf
pub struct CodeSegment<'a> {
pub addr: u32,
pub size: u32,
pub data: &'a [u8],
}
impl<'a> CodeSegment<'a> {
pub fn from_slice<D: AsRef<[u8]>>(addr: u32, data: &'a D) -> Self {
let data = data.as_ref();
CodeSegment {
addr,
data: &data,
size: data.len() as u32,
}
}
}
impl<'a> AsRef<[u8]> for CodeSegment<'a> {
fn as_ref(&self) -> &[u8] {
self.data
}
}
impl PartialEq for CodeSegment<'_> {
fn eq(&self, other: &Self) -> bool {
self.addr.eq(&other.addr)
}
}
impl PartialOrd for CodeSegment<'_> {
fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
self.addr.partial_cmp(&other.addr)
}
}
/// A segment of data to write to the flash
pub struct RomSegment<'a> {
pub addr: u32,
pub data: Cow<'a, [u8]>,
}
impl<'a> RomSegment<'a> {
pub fn size(&self) -> u32 {
self.data.len() as u32
}
pub fn from_vec(addr: u32, data: Vec<u8>) -> Self {
RomSegment {
addr,
data: Cow::Owned(data),
}
}
pub fn from_slice(addr: u32, data: &'a [u8]) -> RomSegment<'a> {
RomSegment {
addr,
data: Cow::Borrowed(data),
}
}
pub fn from_code_segment(addr: u32, code_segment: CodeSegment<'a>) -> RomSegment<'a>
{
Self {
addr,
data: Cow::Borrowed(code_segment.data),
}
}
}
use std::borrow::Cow;
use std::cmp::Ordering;
use xmas_elf::program::{SegmentData, Type};
use xmas_elf::ElfFile;
pub struct FirmwareImage<'a> {
pub entry: u32,
pub elf: ElfFile<'a>,
}
impl<'a> FirmwareImage<'a> {
pub fn from_data(data: &'a [u8]) -> Result<Self, &'static str> {
Ok(Self::from_elf(ElfFile::new(data)?))
}
pub fn from_elf(elf: ElfFile<'a>) -> Self {
FirmwareImage {
entry: elf.header.pt2.entry_point() as u32,
elf,
}
}
pub fn entry(&self) -> u32 {
self.elf.header.pt2.entry_point() as u32
}
pub fn segments(&'a self) -> impl Iterator<Item = CodeSegment<'a>> + 'a {
self.elf
.program_iter()
.filter(|header| {
header.file_size() > 0 && header.get_type() == Ok(Type::Load) && header.offset() > 0
})
.flat_map(move |header| {
let addr = header.virtual_addr() as u32;
let size = header.file_size() as u32;
let data = match header.get_data(&self.elf) {
Ok(SegmentData::Undefined(data)) => data,
_ => return None,
};
Some(CodeSegment { addr, data, size })
})
}
}
#[derive(Debug, Ord, Eq)]
/// A segment of code from the source elf
pub struct CodeSegment<'a> {
pub addr: u32,
pub size: u32,
pub data: &'a [u8],
}
impl<'a> CodeSegment<'a> {
pub fn from_slice<D: AsRef<[u8]>>(addr: u32, data: &'a D) -> Self {
let data = data.as_ref();
CodeSegment {
addr,
data: &data,
size: data.len() as u32,
}
}
}
impl<'a> AsRef<[u8]> for CodeSegment<'a> {
fn as_ref(&self) -> &[u8] {
self.data
}
}
impl PartialEq for CodeSegment<'_> {
fn eq(&self, other: &Self) -> bool {
self.addr.eq(&other.addr)
}
}
impl PartialOrd for CodeSegment<'_> {
fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
self.addr.partial_cmp(&other.addr)
}
}
/// A segment of data to write to the flash
pub struct RomSegment<'a> {
pub addr: u32,
pub data: Cow<'a, [u8]>,
}
impl<'a> RomSegment<'a> {
pub fn size(&self) -> u32 {
self.data.len() as u32
}
pub fn from_vec(addr: u32, data: Vec<u8>) -> Self {
RomSegment {
addr,
data: Cow::Owned(data),
}
}
pub fn from_slice(addr: u32, data: &'a [u8]) -> RomSegment<'a> {
RomSegment {
addr,
data: Cow::Borrowed(data),
}
}
pub fn from_code_segment(addr: u32, code_segment: CodeSegment<'a>) -> RomSegment<'a> {
Self {
addr,
data: Cow::Borrowed(code_segment.data),
}
}
}

View File

@ -1,13 +1,19 @@
use crate::{connection::{Connection, DEFAULT_BAUDRATE}, elf::RomSegment};
use crate::Error;
use crate::chip::Chip;
use crate::elf::FirmwareImage;
use serial::{BaudRate, SerialPort};
use std::{time::{Duration, Instant}, io::{Cursor, Read}};
use crate::Error;
use crate::{
connection::{Connection, DEFAULT_BAUDRATE},
elf::RomSegment,
};
use deku::prelude::*;
use indicatif::HumanBytes;
use sha2::{Sha256, Digest};
use serial::{BaudRate, SerialPort};
use sha2::{Digest, Sha256};
use std::thread::sleep;
use std::{
io::{Cursor, Read},
time::{Duration, Instant},
};
pub struct Flasher {
connection: Connection,
@ -26,7 +32,9 @@ impl Flasher {
boot_info: protocol::BootInfo::default(),
chip: Box::new(chip),
};
flasher.connection.set_baud(speed.unwrap_or(DEFAULT_BAUDRATE))?;
flasher
.connection
.set_baud(speed.unwrap_or(DEFAULT_BAUDRATE))?;
flasher.start_connection()?;
flasher.connection.set_timeout(Duration::from_secs(10))?;
flasher.boot_info = flasher.get_boot_info()?;
@ -38,7 +46,11 @@ impl Flasher {
&self.boot_info
}
pub fn load_segments<'a>(&'a mut self, force: bool, segments: impl Iterator<Item=RomSegment<'a>>) -> Result<(), Error> {
pub fn load_segments<'a>(
&'a mut self,
force: bool,
segments: impl Iterator<Item = RomSegment<'a>>,
) -> Result<(), Error> {
self.load_eflash_loader()?;
self.connection.set_baud(BaudRate::BaudOther(2_000_000))?;
self.handshake()?;
@ -50,17 +62,25 @@ impl Flasher {
if !force {
let sha256 = self.sha256_read(segment.addr, segment.size())?;
if sha256 == &local_hash[..] {
log::info!("Skip segment addr: {:x} size: {} sha256 matches", segment.addr, segment.size());
continue
log::info!(
"Skip segment addr: {:x} size: {} sha256 matches",
segment.addr,
segment.size()
);
continue;
}
}
log::info!("Erase flash addr: {:x} size: {}", segment.addr, segment.size());
log::info!(
"Erase flash addr: {:x} size: {}",
segment.addr,
segment.size()
);
self.flash_erase(segment.addr, segment.addr + segment.size())?;
let mut reader = Cursor::new(&segment.data);
let mut cur = segment.addr;
let start = Instant::now();
log::info!("Program flash... {:x}", local_hash);
loop {
@ -68,11 +88,15 @@ impl Flasher {
// log::trace!("program {:x} {:x}", cur, size);
cur += size;
if size == 0 {
break
break;
}
}
let elapsed = start.elapsed();
log::info!("Program done {:?} {}/s", elapsed, HumanBytes((segment.size() as f64 / elapsed.as_millis() as f64 * 1000.0) as u64));
log::info!(
"Program done {:?} {}/s",
elapsed,
HumanBytes((segment.size() as f64 / elapsed.as_millis() as f64 * 1000.0) as u64)
);
let sha256 = self.sha256_read(segment.addr, segment.size())?;
if sha256 != &local_hash[..] {
@ -82,7 +106,10 @@ impl Flasher {
Ok(())
}
pub fn check_segments<'a>(&'a mut self, segments: impl Iterator<Item=RomSegment<'a>>) -> Result<(), Error> {
pub fn check_segments<'a>(
&'a mut self,
segments: impl Iterator<Item = RomSegment<'a>>,
) -> Result<(), Error> {
self.load_eflash_loader()?;
self.connection.set_baud(BaudRate::BaudOther(2_000_000))?;
self.handshake()?;
@ -92,7 +119,12 @@ impl Flasher {
let sha256 = self.sha256_read(segment.addr, segment.size())?;
if sha256 != &local_hash[..] {
log::warn!("{:x} sha256 not match: {:x?} != {:x?}", segment.addr, sha256, local_hash);
log::warn!(
"{:x} sha256 not match: {:x?} != {:x?}",
segment.addr,
sha256,
local_hash
);
} else {
log::info!("{:x} sha256 match", segment.addr);
}
@ -123,7 +155,7 @@ impl Flasher {
}
pub fn load_eflash_loader(&mut self) -> Result<(), Error> {
let input = self.chip.get_eflash_loader().to_vec();
let input = self.chip.get_eflash_loader().to_vec();
let len = input.len();
let mut reader = Cursor::new(input);
self.load_boot_header(&mut reader)?;
@ -134,11 +166,15 @@ impl Flasher {
loop {
let size = self.load_segment_data(&mut reader)?;
if size == 0 {
break
break;
}
}
let elapsed = start.elapsed();
log::info!("Finished {:?} {}/s", elapsed, HumanBytes((len as f64 / elapsed.as_millis() as f64 * 1000.0) as u64));
log::info!(
"Finished {:?} {}/s",
elapsed,
HumanBytes((len as f64 / elapsed.as_millis() as f64 * 1000.0) as u64)
);
self.check_image()?;
self.run_image()?;
@ -152,10 +188,7 @@ impl Flasher {
}
fn sha256_read(&mut self, addr: u32, len: u32) -> Result<[u8; 32], Error> {
let mut req = protocol::Sha256Read {
addr,
len,
};
let mut req = protocol::Sha256Read { addr, len };
req.update()?;
self.connection.write_all(&req.to_bytes()?)?;
self.connection.flush()?;
@ -170,7 +203,7 @@ impl Flasher {
let mut data = vec![0u8; 4000];
let size = reader.read(&mut data)?;
if size == 0 {
return Ok(0)
return Ok(0);
}
data.truncate(size);
let mut req = protocol::FlashProgram {
@ -187,10 +220,7 @@ impl Flasher {
}
fn flash_erase(&mut self, start: u32, end: u32) -> Result<(), Error> {
let mut req = protocol::FlashErase {
start,
end,
};
let mut req = protocol::FlashErase { start, end };
req.update()?;
self.connection.write_all(&req.to_bytes()?)?;
self.connection.flush()?;
@ -241,7 +271,11 @@ impl Flasher {
let resp = self.connection.read_response(18)?;
if &resp[2..] != req.segment_header {
log::warn!("Segment header not match req:{:x?} != resp:{:x?}", req.segment_header, &resp[2..])
log::warn!(
"Segment header not match req:{:x?} != resp:{:x?}",
req.segment_header,
&resp[2..]
)
}
Ok(())
@ -251,7 +285,7 @@ impl Flasher {
let mut segment_data = vec![0u8; 4000];
let size = reader.read(&mut segment_data)?;
if size == 0 {
return Ok(0)
return Ok(0);
}
segment_data.truncate(size);
let mut req = protocol::LoadSegmentData {
@ -279,15 +313,14 @@ impl Flasher {
.with_timeout(Duration::from_millis(200), |connection| {
let len = connection.calc_duration_length(Duration::from_millis(5));
log::trace!("5ms send count {}", len);
let data: Vec<u8> = std::iter::repeat(0x55u8)
.take(len).collect();
let data: Vec<u8> = std::iter::repeat(0x55u8).take(len).collect();
let start = Instant::now();
connection.write_all(&data)?;
connection.flush()?;
log::trace!("handshake sent elapsed {:?}", start.elapsed());
for _ in 0..10 {
if connection.read_response(0).is_ok() {
return Ok(())
return Ok(());
}
}
Err(Error::Timeout)
@ -308,7 +341,6 @@ impl Flasher {
}
Err(Error::ConnectionFailed)
}
}
mod protocol {

View File

@ -1,9 +1,9 @@
use serde::Deserialize;
use deku::prelude::*;
use std::io::Cursor;
use crate::Error;
use byteorder::{ReadBytesExt, NativeEndian};
use sha2::{Sha256, Digest};
use byteorder::{NativeEndian, ReadBytesExt};
use deku::prelude::*;
use serde::Deserialize;
use sha2::{Digest, Sha256};
use std::io::Cursor;
#[derive(Debug, Deserialize, Default, Clone)]
pub struct BootHeaderCfgFile {
@ -11,7 +11,6 @@ pub struct BootHeaderCfgFile {
pub boot_header_cfg: BootHeaderCfg,
}
#[derive(Debug, Deserialize, DekuWrite, Default, Clone)]
pub struct FlashCfg {
flashcfg_magic_code: u32,
@ -214,21 +213,21 @@ pub struct BootHeaderCfg {
impl FlashCfg {
fn checksum(&self) -> u32 {
let data = self.to_bytes().unwrap();
crc::crc32::checksum_ieee(&data[4..data.len()-4])
crc::crc32::checksum_ieee(&data[4..data.len() - 4])
}
}
impl ClkCfg {
fn checksum(&self) -> u32 {
let data = self.to_bytes().unwrap();
crc::crc32::checksum_ieee(&data[4..data.len()-4])
crc::crc32::checksum_ieee(&data[4..data.len() - 4])
}
}
impl BootHeaderCfg {
fn checksum(&self) -> u32 {
let data = self.to_bytes().unwrap();
crc::crc32::checksum_ieee(&data[0..data.len()-4])
crc::crc32::checksum_ieee(&data[0..data.len() - 4])
}
fn update_sha256(&mut self, hash: &[u8]) -> Result<(), Error> {
let mut reader = Cursor::new(hash);

View File

@ -1,5 +1,5 @@
mod bootheader;
mod partition;
pub use bootheader::{BootHeaderCfg, BootHeaderCfgFile};
pub use partition::PartitionCfg;
pub use bootheader::{BootHeaderCfgFile, BootHeaderCfg};

View File

@ -1,8 +1,7 @@
use serde::Deserialize;
use deku::prelude::*;
use std::iter;
use serde::Deserialize;
use std::io::Write;
use std::iter;
#[derive(Debug, Deserialize, DekuWrite, Default)]
#[deku(magic = b"\x42\x46\x50\x54\x00\x00")]
@ -52,17 +51,14 @@ impl PartitionCfg {
}
fn checksum(&self) -> u32 {
let data = self.to_bytes().unwrap();
crc::crc32::checksum_ieee(&data[16..16+36*self.pt_entry.len()])
crc::crc32::checksum_ieee(&data[16..16 + 36 * self.pt_entry.len()])
}
}
impl Entry {
fn write_name(
name: &str,
output: &mut BitVec<Msb0, u8>,
) -> Result<(), DekuError> {
fn write_name(name: &str, output: &mut BitVec<Msb0, u8>) -> Result<(), DekuError> {
if name.len() > 8 {
return Err(DekuError::Unexpected("name too long".to_string()))
return Err(DekuError::Unexpected("name too long".to_string()));
}
let bytes = name
.bytes()

View File

@ -1,11 +1,11 @@
mod config;
mod flasher;
mod connection;
pub mod chip;
mod error;
pub mod image;
mod config;
mod connection;
pub mod elf;
mod error;
mod flasher;
pub mod image;
pub use config::Config;
pub use flasher::Flasher;
pub use error::{Error, RomError};
pub use flasher::Flasher;

View File

@ -1,11 +1,15 @@
use std::fs::read;
use blflash::{Config, Flasher, Error, chip::bl602::{self, Bl602}, image::BootHeaderCfgFile};
use blflash::{
chip::bl602::{self, Bl602},
image::BootHeaderCfgFile,
Config, Error, Flasher,
};
use env_logger::Env;
use main_error::MainError;
use serial::BaudRate;
use env_logger::Env;
use structopt::StructOpt;
use std::path::PathBuf;
use structopt::StructOpt;
#[derive(StructOpt)]
struct FlashOpt {
@ -64,36 +68,24 @@ fn flash(opt: FlashOpt) -> Result<(), Error> {
let BootHeaderCfgFile { boot_header_cfg } = toml::from_slice(&boot_header_cfg)?;
let bin = read(&opt.image)?;
let segments = chip.with_boot2(
partition_cfg,
boot_header_cfg,
&bin,
)?;
let mut flasher = Flasher::connect(
chip,
serial,
Some(BaudRate::Baud115200)
)?;
let segments = chip.with_boot2(partition_cfg, boot_header_cfg, &bin)?;
let mut flasher = Flasher::connect(chip, serial, Some(BaudRate::Baud115200))?;
log::info!("Bootrom version: {}", flasher.boot_info().bootrom_version);
log::trace!("Boot info: {:x?}", flasher.boot_info());
flasher.load_segments(opt.force, segments.into_iter())?;
flasher.reset()?;
} else {
let mut flasher = Flasher::connect(
chip,
serial,
Some(BaudRate::Baud115200)
)?;
let mut flasher = Flasher::connect(chip, serial, Some(BaudRate::Baud115200))?;
log::info!("Bootrom version: {}", flasher.boot_info().bootrom_version);
log::trace!("Boot info: {:x?}", flasher.boot_info());
let input_bytes = read(&opt.image)?;
flasher.load_elf_to_flash(opt.force, &input_bytes)?;
flasher.reset()?;
}
@ -103,11 +95,7 @@ fn flash(opt: FlashOpt) -> Result<(), Error> {
fn check(opt: CheckOpt) -> Result<(), Error> {
let serial = serial::open(&opt.port)?;
let mut flasher = Flasher::connect(
Bl602,
serial,
Some(BaudRate::Baud115200),
)?;
let mut flasher = Flasher::connect(Bl602, serial, Some(BaudRate::Baud115200))?;
log::info!("Bootrom version: {}", flasher.boot_info().bootrom_version);
log::trace!("Boot info: {:x?}", flasher.boot_info());
@ -122,12 +110,11 @@ fn check(opt: CheckOpt) -> Result<(), Error> {
fn main(args: Opt) -> Result<(), MainError> {
env_logger::Builder::from_env(Env::default().default_filter_or("blflash=trace")).init();
let _config = Config::load();
match args {
Opt::Flash(opt) => flash(opt)?,
Opt::Check(opt) => check(opt)?,
};
Ok(())
}