rockfile-0.1.1/.cargo_vcs_info.json0000644000000001460000000000100126320ustar { "git": { "sha1": "e165156723cfbf987a10b5fa5c242981db7552ab" }, "path_in_vcs": "rockfile" }rockfile-0.1.1/Cargo.lock0000644000000153550000000000100106150ustar # This file is automatically @generated by Cargo. # It is not intended for manual editing. version = 3 [[package]] name = "anstream" version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b1f58811cfac344940f1a400b6e6231ce35171f614f26439e80f8c1465c5cc0c" dependencies = [ "anstyle", "anstyle-parse", "anstyle-query", "anstyle-wincon", "colorchoice", "utf8parse", ] [[package]] name = "anstyle" version = "1.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b84bf0a05bbb2a83e5eb6fa36bb6e87baa08193c35ff52bbf6b38d8af2890e46" [[package]] name = "anstyle-parse" version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "938874ff5980b03a87c5524b3ae5b59cf99b1d6bc836848df7bc5ada9643c333" dependencies = [ "utf8parse", ] [[package]] name = "anstyle-query" version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5ca11d4be1bab0c8bc8734a9aa7bf4ee8316d462a08c6ac5052f888fef5b494b" dependencies = [ "windows-sys", ] [[package]] name = "anstyle-wincon" version = "2.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "58f54d10c6dfa51283a066ceab3ec1ab78d13fae00aa49243a45e4571fb79dfd" dependencies = [ "anstyle", "windows-sys", ] [[package]] name = "anyhow" version = "1.0.75" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a4668cab20f66d8d020e1fbc0ebe47217433c1b6c8f2040faf858554e394ace6" [[package]] name = "bytes" version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a2bd12c1caf447e69cd4528f47f94d203fd2582878ecb9e9465484c4148a8223" [[package]] name = "clap" version = "4.4.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b1d7b8d5ec32af0fadc644bf1fd509a688c2103b185644bb1e29d164e0703136" dependencies = [ "clap_builder", "clap_derive", ] [[package]] name = "clap_builder" version = "4.4.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5179bb514e4d7c2051749d8fcefa2ed6d06a9f4e6d69faf3805f5d80b8cf8d56" dependencies = [ "anstream", "anstyle", "clap_lex", "strsim", ] [[package]] name = "clap_derive" version = "4.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0862016ff20d69b84ef8247369fabf5c008a7417002411897d40ee1f4532b873" dependencies = [ "heck", "proc-macro2", "quote", "syn", ] [[package]] name = "clap_lex" version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cd7cc57abe963c6d3b9d8be5b06ba7c8957a930305ca90304f24ef040aa6f961" [[package]] name = "colorchoice" version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "acbf1af155f9b9ef647e42cdc158db4b64a1b61f743629225fde6f3e0be2a7c7" [[package]] name = "crc" version = "3.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "86ec7a15cbe22e59248fc7eadb1907dab5ba09372595da4d73dd805ed4417dfe" dependencies = [ "crc-catalog", ] [[package]] name = "crc-catalog" version = "2.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9cace84e55f07e7301bae1c519df89cdad8cc3cd868413d3fdbdeca9ff3db484" [[package]] name = "heck" version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "95505c38b4572b2d910cecb0281560f54b440a19336cbbcb27bf6ce6adc6f5a8" [[package]] name = "proc-macro2" version = "1.0.67" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3d433d9f1a3e8c1263d9456598b16fec66f4acc9a74dacffd35c7bb09b3a1328" dependencies = [ "unicode-ident", ] [[package]] name = "quote" version = "1.0.33" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5267fca4496028628a95160fc423a33e8b2e6af8a5302579e322e4b520293cae" dependencies = [ "proc-macro2", ] [[package]] name = "rockfile" version = "0.1.1" dependencies = [ "anyhow", "bytes", "clap", "crc", ] [[package]] name = "strsim" version = "0.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623" [[package]] name = "syn" version = "2.0.37" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7303ef2c05cd654186cb250d29049a24840ca25d2747c25c0381c8d9e2f582e8" dependencies = [ "proc-macro2", "quote", "unicode-ident", ] [[package]] name = "unicode-ident" version = "1.0.12" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b" [[package]] name = "utf8parse" version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "711b9620af191e0cdc7468a8d14e709c3dcdb115b36f838e601583af800a370a" [[package]] name = "windows-sys" version = "0.48.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9" dependencies = [ "windows-targets", ] [[package]] name = "windows-targets" version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9a2fa6e2155d7247be68c096456083145c183cbbbc2764150dda45a87197940c" dependencies = [ "windows_aarch64_gnullvm", "windows_aarch64_msvc", "windows_i686_gnu", "windows_i686_msvc", "windows_x86_64_gnu", "windows_x86_64_gnullvm", "windows_x86_64_msvc", ] [[package]] name = "windows_aarch64_gnullvm" version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8" [[package]] name = "windows_aarch64_msvc" version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc" [[package]] name = "windows_i686_gnu" version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e" [[package]] name = "windows_i686_msvc" version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406" [[package]] name = "windows_x86_64_gnu" version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e" [[package]] name = "windows_x86_64_gnullvm" version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc" [[package]] name = "windows_x86_64_msvc" version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538" rockfile-0.1.1/Cargo.toml0000644000000017430000000000100106340ustar # 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.1" authors = ["Sjoerd Simons "] 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" resolver = "1" [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.1/Cargo.toml.orig000064400000000000000000000010521046102023000143060ustar 00000000000000[package] name = "rockfile" version = "0.1.1" 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.1/README.md000064400000000000000000000003331046102023000126770ustar 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.1/examples/rockfile.rs000064400000000000000000000040741046102023000154100ustar 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::new(); data.resize(entry.data_size as usize, 0); 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.1/src/boot.rs000064400000000000000000000112141046102023000135200ustar 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.1/src/lib.rs000064400000000000000000000001251046102023000133220ustar 00000000000000#![doc = include_str!("../README.md")] /// Rockchip boot file parsers pub mod boot;