Skip to content

Commit 94ac0b6

Browse files
authored
more limited and defined ihex handling (#5)
* more limited and defined ihex handling * error adjustments * bump version
1 parent 047efe4 commit 94ac0b6

File tree

6 files changed

+110
-69
lines changed

6 files changed

+110
-69
lines changed

Cargo.lock

Lines changed: 13 additions & 24 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,16 +4,16 @@ description = """
44
A utility for reading and writing flash contents on Sinowealth 8051-based devices
55
"""
66
repository = "https://github.com/carlossless/sinowealth-kb-tool"
7-
version = "0.0.2"
7+
version = "0.0.3"
88
edition = "2021"
99
license = "MIT"
1010

1111
[dependencies]
1212
clap = "4.1"
1313
rusb = "0.9"
1414
ihex = "3.0"
15-
ihex_ext = "1.0"
1615
md5 = "0.7"
16+
thiserror = "1.0"
1717

1818
[dependencies.log]
1919
version = "0.4"

src/ihex.rs

Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
use ihex::*;
2+
use thiserror::Error;
3+
4+
#[derive(Debug, Error)]
5+
pub enum UnpackingError {
6+
#[error("Unsupported record type")]
7+
UnsupportedRecordType(Record),
8+
#[error("Error while parsing IHEX records")]
9+
Parsing(#[from] ReaderError),
10+
#[error("Address ({0}) greater than binary size ({1})")]
11+
AddressTooHigh(usize, usize),
12+
}
13+
14+
#[derive(Debug, Error)]
15+
pub enum ConversionError {
16+
#[error("Error while unpacking IHEX into array")]
17+
Unpacking(#[from] UnpackingError),
18+
#[error("Errow while writing IHEX to string")]
19+
Serializing(#[from] WriterError)
20+
}
21+
22+
pub fn to_ihex(byte_array: Vec<u8>) -> Result<String, ConversionError> {
23+
let mut result: Vec<Record> = vec![];
24+
for (i, chunk) in byte_array.chunks(16).enumerate() {
25+
result.push(Record::Data {
26+
offset: (i as u16) * 16,
27+
value: chunk.to_vec(),
28+
});
29+
}
30+
result.push(Record::EndOfFile);
31+
return create_object_file_representation(&result)
32+
.map_err(ConversionError::from);
33+
}
34+
35+
pub fn from_ihex(ihex_string: &str, max_length: usize) -> Result<Vec<u8>, ConversionError> {
36+
let mut reader = Reader::new(ihex_string);
37+
return unpack_records(&mut reader, max_length)
38+
.map_err(ConversionError::from);
39+
}
40+
41+
fn unpack_records(
42+
records: &mut impl Iterator<Item = Result<Record, ReaderError>>,
43+
max_length: usize,
44+
) -> Result<Vec<u8>, UnpackingError> {
45+
let mut result: Vec<u8> = vec![];
46+
for rec in records {
47+
match rec {
48+
Ok(rec) => match rec {
49+
Record::Data { offset, value } => {
50+
let end_addr = offset as usize + value.len();
51+
if end_addr > max_length {
52+
return Err(UnpackingError::AddressTooHigh(end_addr, max_length));
53+
}
54+
if end_addr > result.len() {
55+
result.resize(end_addr, 0);
56+
}
57+
58+
for (n, b) in value.iter().enumerate() {
59+
result[offset as usize + n] = *b;
60+
}
61+
}
62+
Record::ExtendedSegmentAddress(_base) => {
63+
return Err(UnpackingError::UnsupportedRecordType(rec))
64+
}
65+
Record::ExtendedLinearAddress(_base) => {
66+
return Err(UnpackingError::UnsupportedRecordType(rec))
67+
}
68+
Record::EndOfFile => break,
69+
Record::StartLinearAddress(_) | Record::StartSegmentAddress { .. } => {}
70+
},
71+
Err(err) => return Err(UnpackingError::Parsing(err)),
72+
}
73+
}
74+
return Ok(result);
75+
}

src/isp.rs

Lines changed: 1 addition & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -98,18 +98,12 @@ impl ISPDevice<'static> {
9898
pub fn write_cycle(&self, firmware: &mut Vec<u8>) -> Result<(), VerificationError> {
9999
let length = firmware.len();
100100

101-
assert_eq!(
102-
self.part.flash_size, length,
103-
"Wrong firmware size. Expected {}, but got {}",
104-
self.part.flash_size, length
105-
);
106-
107101
self.erase();
108102
self.write(&firmware);
109103
let written = self.read(0, self.part.flash_size);
110104

111105
// ARCANE: the ISP will copy the LJMP instruction (if existing) from the end to the very start of memory.
112-
// We need to make the modifications to the expected payload to account for this.
106+
// We need to make modifications to the expected payload to account for this.
113107
if firmware[length - 5] == LJMP_OPCODE {
114108
firmware[0] = LJMP_OPCODE;
115109
}

src/main.rs

Lines changed: 19 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,20 @@
11
use clap::*;
2-
use ihex::*;
3-
use ihex_ext::*;
42
use log::*;
53
use simple_logger::SimpleLogger;
4+
use std::io::Read;
65
use std::{fs, process};
76

87
mod part;
9-
pub use part::*;
10-
118
mod isp;
12-
pub use isp::*;
13-
9+
mod hid;
1410
mod util;
15-
pub use util::*;
11+
mod ihex;
1612

17-
mod hid;
18-
pub use hid::*;
13+
pub use crate::part::*;
14+
pub use crate::isp::*;
15+
pub use crate::hid::*;
16+
pub use crate::ihex::*;
17+
pub use crate::util::*;
1918

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

90-
let ihex = result.to_ihex();
91-
92-
let obj = create_object_file_representation(&ihex).unwrap();
93-
94-
fs::write(output_file, obj).expect("Unable to write file");
89+
let ihex = to_ihex(result).expect("Failed converting to IHEX");
90+
fs::write(output_file, ihex).expect("Unable to write file");
9591
}
9692
Some(("write", sub_matches)) => {
9793
let input_file = sub_matches
@@ -106,7 +102,15 @@ fn main() {
106102

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

109-
let (mut firmware, _) = load_file_vec(input_file, part.flash_size, 0).unwrap();
105+
let mut file = fs::File::open(input_file).unwrap();
106+
let mut file_buf = Vec::new();
107+
file.read_to_end(&mut file_buf).unwrap();
108+
let file_str = String::from_utf8_lossy(&file_buf[..]);
109+
let mut firmware = from_ihex(&file_str, part.flash_size).unwrap();
110+
111+
if firmware.len() < part.flash_size {
112+
firmware.resize(part.flash_size, 0);
113+
}
110114

111115
match ISPDevice::new(part).write_cycle(&mut firmware) {
112116
Err(e) => {

src/util.rs

Lines changed: 0 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1,24 +1,3 @@
1-
use ihex::*;
2-
3-
pub trait IHexConversion {
4-
// fn from_ihex() -> Self;
5-
fn to_ihex(&self) -> Vec<Record>;
6-
}
7-
8-
impl IHexConversion for Vec<u8> {
9-
fn to_ihex(&self) -> Vec<Record> {
10-
let mut result: Vec<Record> = vec![];
11-
for (i, chunk) in self.chunks(16).enumerate() {
12-
result.push(Record::Data {
13-
offset: (i as u16) * 16,
14-
value: chunk.to_vec(),
15-
});
16-
}
17-
result.push(Record::EndOfFile);
18-
return result;
19-
}
20-
}
21-
221
#[derive(Debug, Clone)]
232
pub enum VerificationError {
243
ByteMismatch(usize, u8, u8),

0 commit comments

Comments
 (0)