Skip to content

Commit b568321

Browse files
committed
tool: split binary and library, make it easier to do unit tests
Signed-off-by: Zhouqi Jiang <luojia@hust.edu.cn>
1 parent b5900fb commit b568321

File tree

2 files changed

+146
-33
lines changed

2 files changed

+146
-33
lines changed

sophgo-rom-tool/src/lib.rs

Lines changed: 141 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,141 @@
1+
use core::mem::{size_of, size_of_val};
2+
use crc::{Crc, CRC_16_XMODEM};
3+
4+
#[derive(Debug)]
5+
pub enum Error {
6+
HeadLength {
7+
wrong_length: usize,
8+
},
9+
MagicNumber {
10+
wrong_magic: u32,
11+
},
12+
RawBlobMagic {
13+
wrong_magic: [u8; 32],
14+
},
15+
ImageContentLength {
16+
wrong_content_length: usize,
17+
wrong_full_length: usize,
18+
},
19+
OutputBufferLength {
20+
wrong_length: usize,
21+
},
22+
}
23+
24+
pub type Result<T> = core::result::Result<T, Error>;
25+
26+
pub struct Operations<'a> {
27+
pub refill_header: Option<HeaderInfo>,
28+
pub set_image_content: Option<&'a [u8]>,
29+
pub resize_image_full_length: usize,
30+
}
31+
32+
pub struct HeaderInfo {
33+
pub blcp_image_checksum: u32,
34+
pub bl2_image_checksum: u32,
35+
pub bl2_image_size: u32,
36+
}
37+
38+
// TODO: supports: 1. blob with magic 2. full fip.bin 3. ELF file
39+
// 1. blob with blob magic
40+
// - returns additional header content and padding size
41+
// 2. full fip.bin (BL2 FIP magic): returns
42+
// - repaired header if wrong checksum
43+
// - error if image truncated (image length + image offset > file length)
44+
// 3. ELF containing blob (ELF magic):
45+
// returns header and image content
46+
pub fn check(buf: &[u8]) -> Result<Operations> {
47+
if buf.len() < size_of::<u32>() {
48+
return Err(Error::HeadLength {
49+
wrong_length: buf.len(),
50+
});
51+
}
52+
let u32_magic = u32::from_le_bytes([buf[0], buf[1], buf[2], buf[3]]);
53+
match u32_magic {
54+
0x0200006F => check_raw_blob(buf),
55+
0x4C425643 => check_cvbl_fip(buf),
56+
0x7F454C46 => check_elf(buf),
57+
wrong_magic => Err(Error::MagicNumber { wrong_magic }),
58+
}
59+
}
60+
61+
const HEADER_LENGTH: usize = 0x1000;
62+
const BLOB_MAGIC: [u8; 32] = [
63+
0x6F, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
64+
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
65+
];
66+
67+
fn check_raw_blob(buf: &[u8]) -> Result<Operations> {
68+
if buf.len() < size_of_val(&BLOB_MAGIC) || buf.len() >= (u32::MAX - 512) as usize {
69+
return Err(Error::HeadLength {
70+
wrong_length: buf.len(),
71+
});
72+
}
73+
if buf[..BLOB_MAGIC.len()] != BLOB_MAGIC {
74+
return Err(Error::RawBlobMagic {
75+
wrong_magic: buf[..BLOB_MAGIC.len()].try_into().unwrap(),
76+
});
77+
}
78+
let crc = Crc::<u16>::new(&CRC_16_XMODEM);
79+
let padding_len = 512 - (buf.len() % 512);
80+
// TODO no allocations required
81+
let mut padded_buf = Vec::new();
82+
padded_buf.extend(buf);
83+
padded_buf.extend(core::iter::repeat(0).take(padding_len));
84+
let bl2_checksum_part = crc.checksum(&padded_buf);
85+
let bl2_checksum = 0xCAFE0000u32 + bl2_checksum_part as u32;
86+
// TODO no allocations required
87+
let bl2_padded_size = buf.len() + padding_len;
88+
Ok(Operations {
89+
refill_header: Some(HeaderInfo {
90+
blcp_image_checksum: 0xCAFE0000,
91+
bl2_image_checksum: bl2_checksum,
92+
bl2_image_size: bl2_padded_size as u32,
93+
}),
94+
set_image_content: Some(buf),
95+
resize_image_full_length: HEADER_LENGTH + bl2_padded_size,
96+
})
97+
}
98+
99+
const CVBL01_MAGIC: [u8; 12] = [
100+
0x43, 0x56, 0x42, 0x4C, 0x30, 0x31, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x00,
101+
]; // CVBL01
102+
103+
fn check_cvbl_fip(buf: &[u8]) -> Result<Operations> {
104+
todo!("{:?}", buf)
105+
}
106+
107+
fn check_elf(buf: &[u8]) -> Result<Operations> {
108+
todo!("{:?}", buf)
109+
}
110+
111+
pub fn process(buf: &mut [u8], ops: &Operations) -> Result<()> {
112+
if buf.len() < ops.resize_image_full_length {
113+
return Err(Error::OutputBufferLength {
114+
wrong_length: buf.len(),
115+
});
116+
}
117+
if let Some(header) = &ops.refill_header {
118+
buf[..CVBL01_MAGIC.len()].copy_from_slice(&CVBL01_MAGIC);
119+
buf[0xBC..0xC0].copy_from_slice(&0x2F8u32.to_le_bytes()); // chip_conf_size
120+
buf[0xC0..0xC4].copy_from_slice(&header.blcp_image_checksum.to_le_bytes());
121+
buf[0xD4..0xD8].copy_from_slice(&header.bl2_image_checksum.to_le_bytes());
122+
buf[0xD8..0xDC].copy_from_slice(&header.bl2_image_size.to_le_bytes());
123+
let crc = Crc::<u16>::new(&CRC_16_XMODEM);
124+
let param_checksum = 0xCAFE0000u32 + crc.checksum(&buf[0x10..0x800]) as u32;
125+
buf[0xC..0x10].copy_from_slice(&param_checksum.to_le_bytes())
126+
}
127+
if let Some(image) = &ops.set_image_content {
128+
if image.len() > u32::MAX as usize
129+
|| ops.resize_image_full_length > u32::MAX as usize
130+
|| ops.resize_image_full_length < HEADER_LENGTH
131+
|| image.len() + HEADER_LENGTH > ops.resize_image_full_length
132+
{
133+
return Err(Error::ImageContentLength {
134+
wrong_content_length: image.len(),
135+
wrong_full_length: ops.resize_image_full_length,
136+
});
137+
}
138+
buf[HEADER_LENGTH..][..image.len()].copy_from_slice(image);
139+
}
140+
Ok(())
141+
}

sophgo-rom-tool/src/main.rs

Lines changed: 5 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
use clap::Parser;
2-
use crc::{Crc, CRC_16_XMODEM};
32
use std::fs;
43

54
/// Generate a ROM image for Sophgo chips.
@@ -13,43 +12,16 @@ struct Args {
1312
output: String,
1413
}
1514

16-
const SIGNATURE: [u8; 32] = [
17-
0x6F, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
18-
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
19-
];
20-
21-
const MAGIC: [u8; 12] = [
22-
0x43, 0x56, 0x42, 0x4C, 0x30, 0x31, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x00,
23-
]; // CVBL01
24-
2515
fn main() {
2616
let args = Args::parse();
2717
let data = fs::read(&args.input).expect("Unable to read file");
28-
let data_len = data.len();
29-
if data_len < SIGNATURE.len() || data[..SIGNATURE.len()] != SIGNATURE {
30-
panic!("Invalid input file");
31-
}
32-
33-
let mut image = vec![0; 0x1000];
34-
image.extend(data);
35-
let padding_len = 512 - (data_len % 512);
36-
image.extend(core::iter::repeat(0).take(padding_len));
37-
38-
let crc = Crc::<u16>::new(&CRC_16_XMODEM);
39-
let bl2_checksum = crc.checksum(&image[0x1000..]);
4018

41-
image[..MAGIC.len()].copy_from_slice(&MAGIC);
42-
image[0xBC..0xC0].copy_from_slice(&0x2F8u32.to_le_bytes()); // chip_conf_size
43-
image[0xC0..0xC4].copy_from_slice(&0xCAFE0000u32.to_le_bytes()); // blcp_img_cksum
44-
image[0xD4..0xD8].copy_from_slice(&(0xCAFE0000u32 + bl2_checksum as u32).to_le_bytes()); // bl2_img_cksum
45-
image[0xD8..0xDC].copy_from_slice(&((data_len + padding_len) as u32).to_le_bytes()); // bl2_img_size
19+
// TODO handle error
20+
let ops = sophgo_rom_tool::check(&data).unwrap();
4621

47-
let param_checksum = crc.checksum(&image[0x10..0x800]);
48-
image[0xC..0x10].copy_from_slice(
49-
(0xCAFE0000u32 + param_checksum as u32)
50-
.to_le_bytes()
51-
.as_ref(),
52-
); // param_cksum
22+
let mut image = vec![0u8; ops.resize_image_full_length];
23+
// TODO handle error
24+
sophgo_rom_tool::process(&mut image, &ops).unwrap();
5325

5426
fs::write(&args.output, image).expect("Unable to write file");
5527
}

0 commit comments

Comments
 (0)