rockfile-0.1.2/.cargo_vcs_info.json0000644000000001460000000000100126330ustar { "git": { "sha1": "172ec88119abb6f5a7f7dc2a4890b0d6e81389d2" }, "path_in_vcs": "rockfile" }rockfile-0.1.2/Cargo.lock0000644000000162750000000000100106200ustar # This file is automatically @generated by Cargo. # It is not intended for manual editing. version = 3 [[package]] name = "anstream" version = "0.6.15" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "64e15c1ab1f89faffbf04a634d5e1962e9074f2741eef6d97f3c4e322426d526" dependencies = [ "anstyle", "anstyle-parse", "anstyle-query", "anstyle-wincon", "colorchoice", "is_terminal_polyfill", "utf8parse", ] [[package]] name = "anstyle" version = "1.0.8" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1bec1de6f59aedf83baf9ff929c98f2ad654b97c9510f4e70cf6f661d49fd5b1" [[package]] name = "anstyle-parse" version = "0.2.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "eb47de1e80c2b463c735db5b217a0ddc39d612e7ac9e2e96a5aed1f57616c1cb" dependencies = [ "utf8parse", ] [[package]] name = "anstyle-query" version = "1.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6d36fc52c7f6c869915e99412912f22093507da8d9e942ceaf66fe4b7c14422a" dependencies = [ "windows-sys", ] [[package]] name = "anstyle-wincon" version = "3.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5bf74e1b6e971609db8ca7a9ce79fd5768ab6ae46441c572e46cf596f59e57f8" dependencies = [ "anstyle", "windows-sys", ] [[package]] name = "anyhow" version = "1.0.90" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "37bf3594c4c988a53154954629820791dde498571819ae4ca50ca811e060cc95" [[package]] name = "bytes" version = "1.7.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "428d9aa8fbc0670b7b8d6030a7fadd0f86151cae55e4dbbece15f3780a3dfaf3" [[package]] name = "clap" version = "4.5.20" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b97f376d85a664d5837dbae44bf546e6477a679ff6610010f17276f686d867e8" dependencies = [ "clap_builder", "clap_derive", ] [[package]] name = "clap_builder" version = "4.5.20" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "19bc80abd44e4bed93ca373a0704ccbd1b710dc5749406201bb018272808dc54" dependencies = [ "anstream", "anstyle", "clap_lex", "strsim", ] [[package]] name = "clap_derive" version = "4.5.18" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4ac6a0c7b1a9e9a5186361f67dfa1b88213572f427fb9ab038efb2bd8c582dab" dependencies = [ "heck", "proc-macro2", "quote", "syn", ] [[package]] name = "clap_lex" version = "0.7.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1462739cb27611015575c0c11df5df7601141071f07518d56fcc1be504cbec97" [[package]] name = "colorchoice" version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d3fd119d74b830634cea2a0f58bbd0d54540518a14397557951e79340abc28c0" [[package]] name = "crc" version = "3.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "69e6e4d7b33a94f0991c26729976b10ebde1d34c3ee82408fb536164fa10d636" dependencies = [ "crc-catalog", ] [[package]] name = "crc-catalog" version = "2.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "19d374276b40fb8bbdee95aef7c7fa6b5316ec764510eb64b8dd0e2ed0d7e7f5" [[package]] name = "heck" version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea" [[package]] name = "is_terminal_polyfill" version = "1.70.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7943c866cc5cd64cbc25b2e01621d07fa8eb2a1a23160ee81ce38704e97b8ecf" [[package]] name = "proc-macro2" version = "1.0.88" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7c3a7fc5db1e57d5a779a352c8cdb57b29aa4c40cc69c3a68a7fedc815fbf2f9" dependencies = [ "unicode-ident", ] [[package]] name = "quote" version = "1.0.37" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b5b9d34b8991d19d98081b46eacdd8eb58c6f2b201139f7c5f643cc155a633af" dependencies = [ "proc-macro2", ] [[package]] name = "rockfile" version = "0.1.2" dependencies = [ "anyhow", "bytes", "clap", "crc", ] [[package]] name = "strsim" version = "0.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f" [[package]] name = "syn" version = "2.0.80" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e6e185e337f816bc8da115b8afcb3324006ccc82eeaddf35113888d3bd8e44ac" dependencies = [ "proc-macro2", "quote", "unicode-ident", ] [[package]] name = "unicode-ident" version = "1.0.13" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e91b56cd4cadaeb79bbf1a5645f6b4f8dc5bde8834ad5894a8db35fda9efa1fe" [[package]] name = "utf8parse" version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821" [[package]] name = "windows-sys" version = "0.52.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" dependencies = [ "windows-targets", ] [[package]] name = "windows-targets" version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973" dependencies = [ "windows_aarch64_gnullvm", "windows_aarch64_msvc", "windows_i686_gnu", "windows_i686_gnullvm", "windows_i686_msvc", "windows_x86_64_gnu", "windows_x86_64_gnullvm", "windows_x86_64_msvc", ] [[package]] name = "windows_aarch64_gnullvm" version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3" [[package]] name = "windows_aarch64_msvc" version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469" [[package]] name = "windows_i686_gnu" version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b" [[package]] name = "windows_i686_gnullvm" version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66" [[package]] name = "windows_i686_msvc" version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66" [[package]] name = "windows_x86_64_gnu" version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78" [[package]] name = "windows_x86_64_gnullvm" version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d" [[package]] name = "windows_x86_64_msvc" version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" rockfile-0.1.2/Cargo.toml0000644000000022300000000000100106250ustar # THIS FILE IS AUTOMATICALLY GENERATED BY CARGO # # When uploading crates to the registry Cargo will automatically # "normalize" Cargo.toml files for maximal compatibility # with all versions of Cargo and also rewrite `path` dependencies # to registry (e.g., crates.io) dependencies. # # If you are reading this file be aware that the original Cargo.toml # will likely look very different (and much more reasonable). # See Cargo.toml.orig for the original contents. [package] edition = "2021" name = "rockfile" version = "0.1.2" authors = ["Sjoerd Simons "] build = false autobins = false autoexamples = false autotests = false autobenches = false description = "Rockchip specific file parsers" homepage = "https://github.com/collabora/rockchiprs" readme = "README.md" license = "MIT OR Apache-2.0" repository = "https://github.com/collabora/rockchiprs" [lib] name = "rockfile" path = "src/lib.rs" [[example]] name = "rockfile" path = "examples/rockfile.rs" [dependencies.bytes] version = "1.4.0" [dev-dependencies.anyhow] version = "1.0.69" [dev-dependencies.clap] version = "4.1.6" features = ["derive"] [dev-dependencies.crc] version = "3.0.1" rockfile-0.1.2/Cargo.toml.orig000064400000000000000000000010521046102023000143070ustar 00000000000000[package] name = "rockfile" version = "0.1.2" edition = "2021" authors = ["Sjoerd Simons "] license = "MIT OR Apache-2.0" description = "Rockchip specific file parsers" homepage = "https://github.com/collabora/rockchiprs" repository = "https://github.com/collabora/rockchiprs" readme = "README.md" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] bytes = "1.4.0" [dev-dependencies] anyhow = "1.0.69" clap = { version = "4.1.6", features = ["derive"] } crc = "3.0.1" rockfile-0.1.2/README.md000064400000000000000000000003331046102023000127000ustar 00000000000000# Rockchip file format parser Rockchip has various specific file formats to work with the SoCs; This crate is meant to parse those. Currently only implement "bootfiles" which embed various stages of the early loaders rockfile-0.1.2/examples/rockfile.rs000064400000000000000000000040411046102023000154030ustar 00000000000000use std::{ fs::File, io::{Read, Seek, SeekFrom}, path::{Path, PathBuf}, }; use anyhow::{anyhow, Result}; use clap::Parser; use rockfile::boot::{ RkBootEntry, RkBootEntryBytes, RkBootHeader, RkBootHeaderBytes, RkBootHeaderEntry, }; fn parse_entry(header: RkBootHeaderEntry, name: &str, file: &mut File) -> Result<()> { for i in 0..header.count { let mut entry: RkBootEntryBytes = [0; 57]; file.seek(SeekFrom::Start( header.offset as u64 + (header.size * i) as u64, ))?; file.read_exact(&mut entry)?; let entry = RkBootEntry::from_bytes(&entry); println!("== {} Entry {} ==", name, i); println!("Name: {}", String::from_utf16(entry.name.as_slice())?); println!("Raw: {:?}", entry); let mut data = vec![0; entry.data_size as usize]; file.seek(SeekFrom::Start(entry.data_offset as u64))?; file.read_exact(&mut data)?; let crc = crc::Crc::::new(&crc::CRC_16_IBM_3740); println!("Data CRC: {:x}", crc.checksum(&data)); } Ok(()) } fn parse_boot(path: &Path) -> Result<()> { let mut file = File::open(path)?; let mut header: RkBootHeaderBytes = [0; 102]; file.read_exact(&mut header)?; let header = RkBootHeader::from_bytes(&header).ok_or_else(|| anyhow!("Failed to parse header"))?; println!("Raw Header: {:?}", header); println!( "chip: {:?} - {}", header.supported_chip, String::from_utf8_lossy(&header.supported_chip) ); parse_entry(header.entry_471, "0x471", &mut file)?; parse_entry(header.entry_472, "0x472", &mut file)?; parse_entry(header.entry_loader, "loader", &mut file)?; Ok(()) } #[derive(Debug, clap::Subcommand)] enum Command { BootFile { path: PathBuf }, } #[derive(clap::Parser)] struct Opts { #[command(subcommand)] command: Command, } fn main() -> Result<()> { let opt = Opts::parse(); // Commands that don't talk a device match opt.command { Command::BootFile { path } => parse_boot(&path), } } rockfile-0.1.2/src/boot.rs000064400000000000000000000112141046102023000135210ustar 00000000000000use bytes::Buf; pub type RkTimeBytes = [u8; 7]; #[derive(Debug, Clone, PartialEq, Eq)] pub struct RkTime { year: u16, month: u8, day: u8, hour: u8, minute: u8, second: u8, } impl RkTime { pub fn from_bytes(bytes: &RkTimeBytes) -> RkTime { let mut bytes = &bytes[..]; let year = bytes.get_u16_le(); let month = bytes.get_u8(); let day = bytes.get_u8(); let hour = bytes.get_u8(); let minute = bytes.get_u8(); let second = bytes.get_u8(); RkTime { year, month, day, hour, minute, second, } } } pub type RkBootHeaderEntryBytes = [u8; 6]; /// Entry in the boot header /// /// Each boot header entry contains the count of [RkBootEntry]'s that are continous at the given /// offset in the boot file. #[derive(Debug, Clone, PartialEq, Eq)] pub struct RkBootHeaderEntry { pub count: u8, pub offset: u32, pub size: u8, } impl RkBootHeaderEntry { pub fn from_bytes(bytes: &RkBootHeaderEntryBytes) -> RkBootHeaderEntry { let mut bytes = &bytes[..]; let count = bytes.get_u8(); let offset = bytes.get_u32_le(); let size = bytes.get_u8(); RkBootHeaderEntry { count, offset, size, } } } pub type RkBootEntryBytes = [u8; 57]; /// Boot entry describing each data blob. data_offset and data_size define the range in the /// boot file. After uploading the blob to SoC a delay of data_delay miliseconds should be /// observed before uploading the next blob #[derive(Debug, Clone, PartialEq, Eq)] pub struct RkBootEntry { /// size of this entry pub size: u8, pub type_: u32, /// UTF-16 name pub name: [u16; 20], /// Offset of data in the boot file pub data_offset: u32, /// Size of data in the boot file pub data_size: u32, /// Delay to observe after uploading to SoC pub data_delay: u32, } impl RkBootEntry { pub fn from_bytes(bytes: &RkBootEntryBytes) -> RkBootEntry { let mut bytes = &bytes[..]; let size = bytes.get_u8(); let type_ = bytes.get_u32_le(); let mut name = [0u16; 20]; for n in &mut name { *n = bytes.get_u16_le() } let data_offset = bytes.get_u32_le(); let data_size = bytes.get_u32_le(); let data_delay = bytes.get_u32_le(); RkBootEntry { size, type_, name, data_offset, data_size, data_delay, } } } pub type RkBootHeaderBytes = [u8; 102]; /// Boot header which can be found at the start of a boot file /// /// The header contains three entry types; 0x471 which are the blobs that should be uploaded to the /// bootrom sram initially to setup ddr memory; 0x472 the blobs that should be uploaded to the /// bootrom ddr, typically implementing the complete usb protocol. And finally the loader entry /// which are the blobs meant to be used for a normal boot #[derive(Debug, Clone, PartialEq, Eq)] pub struct RkBootHeader { pub tag: [u8; 4], pub size: u16, pub version: u32, pub merge_version: u32, pub release: RkTime, pub supported_chip: [u8; 4], pub entry_471: RkBootHeaderEntry, pub entry_472: RkBootHeaderEntry, pub entry_loader: RkBootHeaderEntry, pub sign_flag: u8, pub rc4_flag: u8, } impl RkBootHeader { pub fn from_bytes(bytes: &RkBootHeaderBytes) -> Option { let mut bytes = &bytes[..]; let mut tag = [0u8; 4]; bytes.copy_to_slice(&mut tag); if &tag != b"BOOT" && &tag != b"LDR " { return None; } let size = bytes.get_u16_le(); let version = bytes.get_u32_le(); let merge_version = bytes.get_u32_le(); let release = RkTime::from_bytes(bytes[0..7].try_into().unwrap()); bytes.advance(7); let supported_chip = bytes.get_u32().to_le_bytes(); let entry_471 = RkBootHeaderEntry::from_bytes(bytes[0..6].try_into().unwrap()); bytes.advance(6); let entry_472 = RkBootHeaderEntry::from_bytes(bytes[0..6].try_into().unwrap()); bytes.advance(6); let entry_loader = RkBootHeaderEntry::from_bytes(bytes[0..6].try_into().unwrap()); bytes.advance(6); let sign_flag = bytes.get_u8(); let rc4_flag = bytes.get_u8(); Some(RkBootHeader { tag, size, version, merge_version, release, supported_chip, entry_471, entry_472, entry_loader, sign_flag, rc4_flag, }) } } rockfile-0.1.2/src/lib.rs000064400000000000000000000001251046102023000133230ustar 00000000000000#![doc = include_str!("../README.md")] /// Rockchip boot file parsers pub mod boot;