Skip to content

Commit

Permalink
more limited and defined ihex handling (#5)
Browse files Browse the repository at this point in the history
* more limited and defined ihex handling

* error adjustments

* bump version
  • Loading branch information
carlossless authored Jul 19, 2023
1 parent 047efe4 commit 94ac0b6
Show file tree
Hide file tree
Showing 6 changed files with 110 additions and 69 deletions.
37 changes: 13 additions & 24 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 2 additions & 2 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -4,16 +4,16 @@ description = """
A utility for reading and writing flash contents on Sinowealth 8051-based devices
"""
repository = "https://github.com/carlossless/sinowealth-kb-tool"
version = "0.0.2"
version = "0.0.3"
edition = "2021"
license = "MIT"

[dependencies]
clap = "4.1"
rusb = "0.9"
ihex = "3.0"
ihex_ext = "1.0"
md5 = "0.7"
thiserror = "1.0"

[dependencies.log]
version = "0.4"
Expand Down
75 changes: 75 additions & 0 deletions src/ihex.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
use ihex::*;
use thiserror::Error;

#[derive(Debug, Error)]
pub enum UnpackingError {
#[error("Unsupported record type")]
UnsupportedRecordType(Record),
#[error("Error while parsing IHEX records")]
Parsing(#[from] ReaderError),
#[error("Address ({0}) greater than binary size ({1})")]
AddressTooHigh(usize, usize),
}

#[derive(Debug, Error)]
pub enum ConversionError {
#[error("Error while unpacking IHEX into array")]
Unpacking(#[from] UnpackingError),
#[error("Errow while writing IHEX to string")]
Serializing(#[from] WriterError)
}

pub fn to_ihex(byte_array: Vec<u8>) -> Result<String, ConversionError> {
let mut result: Vec<Record> = vec![];
for (i, chunk) in byte_array.chunks(16).enumerate() {
result.push(Record::Data {
offset: (i as u16) * 16,
value: chunk.to_vec(),
});
}
result.push(Record::EndOfFile);
return create_object_file_representation(&result)
.map_err(ConversionError::from);
}

pub fn from_ihex(ihex_string: &str, max_length: usize) -> Result<Vec<u8>, ConversionError> {
let mut reader = Reader::new(ihex_string);
return unpack_records(&mut reader, max_length)
.map_err(ConversionError::from);
}

fn unpack_records(
records: &mut impl Iterator<Item = Result<Record, ReaderError>>,
max_length: usize,
) -> Result<Vec<u8>, UnpackingError> {
let mut result: Vec<u8> = vec![];
for rec in records {
match rec {
Ok(rec) => match rec {
Record::Data { offset, value } => {
let end_addr = offset as usize + value.len();
if end_addr > max_length {
return Err(UnpackingError::AddressTooHigh(end_addr, max_length));
}
if end_addr > result.len() {
result.resize(end_addr, 0);
}

for (n, b) in value.iter().enumerate() {
result[offset as usize + n] = *b;
}
}
Record::ExtendedSegmentAddress(_base) => {
return Err(UnpackingError::UnsupportedRecordType(rec))
}
Record::ExtendedLinearAddress(_base) => {
return Err(UnpackingError::UnsupportedRecordType(rec))
}
Record::EndOfFile => break,
Record::StartLinearAddress(_) | Record::StartSegmentAddress { .. } => {}
},
Err(err) => return Err(UnpackingError::Parsing(err)),
}
}
return Ok(result);
}
8 changes: 1 addition & 7 deletions src/isp.rs
Original file line number Diff line number Diff line change
Expand Up @@ -98,18 +98,12 @@ impl ISPDevice<'static> {
pub fn write_cycle(&self, firmware: &mut Vec<u8>) -> Result<(), VerificationError> {
let length = firmware.len();

assert_eq!(
self.part.flash_size, length,
"Wrong firmware size. Expected {}, but got {}",
self.part.flash_size, length
);

self.erase();
self.write(&firmware);
let written = self.read(0, self.part.flash_size);

// ARCANE: the ISP will copy the LJMP instruction (if existing) from the end to the very start of memory.
// We need to make the modifications to the expected payload to account for this.
// We need to make modifications to the expected payload to account for this.
if firmware[length - 5] == LJMP_OPCODE {
firmware[0] = LJMP_OPCODE;
}
Expand Down
34 changes: 19 additions & 15 deletions src/main.rs
Original file line number Diff line number Diff line change
@@ -1,21 +1,20 @@
use clap::*;
use ihex::*;
use ihex_ext::*;
use log::*;
use simple_logger::SimpleLogger;
use std::io::Read;
use std::{fs, process};

mod part;
pub use part::*;

mod isp;
pub use isp::*;

mod hid;
mod util;
pub use util::*;
mod ihex;

mod hid;
pub use hid::*;
pub use crate::part::*;
pub use crate::isp::*;
pub use crate::hid::*;
pub use crate::ihex::*;
pub use crate::util::*;

fn cli() -> Command {
return Command::new("sinowealth-kb-tool")
Expand Down Expand Up @@ -87,11 +86,8 @@ fn main() {
let digest = md5::compute(&result);
println!("MD5: {:x}", digest);

let ihex = result.to_ihex();

let obj = create_object_file_representation(&ihex).unwrap();

fs::write(output_file, obj).expect("Unable to write file");
let ihex = to_ihex(result).expect("Failed converting to IHEX");
fs::write(output_file, ihex).expect("Unable to write file");
}
Some(("write", sub_matches)) => {
let input_file = sub_matches
Expand All @@ -106,7 +102,15 @@ fn main() {

let part = PARTS.get(part_name).unwrap();

let (mut firmware, _) = load_file_vec(input_file, part.flash_size, 0).unwrap();
let mut file = fs::File::open(input_file).unwrap();
let mut file_buf = Vec::new();
file.read_to_end(&mut file_buf).unwrap();
let file_str = String::from_utf8_lossy(&file_buf[..]);
let mut firmware = from_ihex(&file_str, part.flash_size).unwrap();

if firmware.len() < part.flash_size {
firmware.resize(part.flash_size, 0);
}

match ISPDevice::new(part).write_cycle(&mut firmware) {
Err(e) => {
Expand Down
21 changes: 0 additions & 21 deletions src/util.rs
Original file line number Diff line number Diff line change
@@ -1,24 +1,3 @@
use ihex::*;

pub trait IHexConversion {
// fn from_ihex() -> Self;
fn to_ihex(&self) -> Vec<Record>;
}

impl IHexConversion for Vec<u8> {
fn to_ihex(&self) -> Vec<Record> {
let mut result: Vec<Record> = vec![];
for (i, chunk) in self.chunks(16).enumerate() {
result.push(Record::Data {
offset: (i as u16) * 16,
value: chunk.to_vec(),
});
}
result.push(Record::EndOfFile);
return result;
}
}

#[derive(Debug, Clone)]
pub enum VerificationError {
ByteMismatch(usize, u8, u8),
Expand Down

0 comments on commit 94ac0b6

Please sign in to comment.