msd: add option to print ouith tree instead of static, some improvements to pfl_upg, mtk_pkg: add option to not delete decompressed lzhs part

This commit is contained in:
theubusu
2026-02-18 22:54:03 +01:00
parent ab727411dc
commit f4a146a389
11 changed files with 128 additions and 112 deletions
+27 -30
View File
@@ -5,9 +5,6 @@ use binrw::{BinRead, BinReaderExt};
use crate::utils::common;
// whether to print the tree
static CONFIG_PRINT_TREE: bool = false;
#[derive(BinRead)]
struct ChunkHeader {
size: u32,
@@ -92,7 +89,7 @@ pub struct MSDItem {
//pub secure_hash: Option<Vec<u8>>,
}
pub fn parse_ouith_blob(blob: &[u8]) -> Result<(Vec<MSDItem>, Option<OUSWImageVersionExDesc>), Box<dyn std::error::Error>> {
pub fn parse_ouith_blob(blob: &[u8], print_tree: bool) -> Result<(Vec<MSDItem>, Option<OUSWImageVersionExDesc>), Box<dyn std::error::Error>> {
let mut reader = Cursor::new(blob);
let mut items: Vec<MSDItem> = Vec::new();
let mut info: Option<OUSWImageVersionExDesc> = None;
@@ -103,31 +100,31 @@ pub fn parse_ouith_blob(blob: &[u8]) -> Result<(Vec<MSDItem>, Option<OUSWImageVe
while reader.stream_position()? < blob.len() as u64 {
chunk_n += 1;
let chunk: ChunkHeader = reader.read_be()?;
if CONFIG_PRINT_TREE { println!("\nChunk {} - Size: {}, Value: {}", chunk_n, chunk.size, chunk.value); };
if print_tree { println!("\nChunk {} - Size: {}, Value: {}", chunk_n, chunk.size, chunk.value); };
let chunk_end = reader.stream_position()? + chunk.size as u64;
//parse top level descriptor. it can only be ID 1(OUUpgradeItemDesc) or 2(OUGroupDesc)
let top_descriptor: DescriptorHeader = reader.read_be()?;
if top_descriptor.tag == 0x01 {
if CONFIG_PRINT_TREE { println!("OUUpgradeItemDesc(0x01) - Size: {}", top_descriptor.size); };
if print_tree { println!("OUUpgradeItemDesc(0x01) - Size: {}", top_descriptor.size); };
let item_id: u32 = reader.read_be()?;
if CONFIG_PRINT_TREE { println!(" Item ID: {}", item_id); };
if print_tree { println!(" Item ID: {}", item_id); };
//REQUIRED are items in order: OUDestinationDesc(0x03), OUDataProcessingDesc(0x07), OUGroupInfoDesc(0x13). OPTIONAL items: OUDependenciesDesc(0x04), OUDataPostProcessingDesc(0x08)
//In MSD files, no others seem to be used than the required ones. We will ignore all data after required descriptors.
let destination_descriptor: DescriptorHeader = reader.read_be()?;
if destination_descriptor.tag != 0x03 {return Err(format!("Unexpected descriptor type in OUUpgradeItemDesc, Expected: 0x03, Got: 0x{:02x}!", destination_descriptor.tag).into())}
if CONFIG_PRINT_TREE { println!(" OUDestinationDesc(0x03) - Size: {}", destination_descriptor.size); };
if print_tree { println!(" OUDestinationDesc(0x03) - Size: {}", destination_descriptor.size); };
let out_size: u32 = reader.read_be()?;
if CONFIG_PRINT_TREE { println!(" Out data size: {}", out_size); };
if print_tree { println!(" Out data size: {}", out_size); };
//OUDestinationDesc needs one of OUSWFileVersionDesc(0x0B), OUPartitionVersionDesc(0x0A), OUCMACDataDesc(0x11). Their structure is the same. so we can store the type
let type_descriptor: DescriptorHeader = reader.read_be()?;
if ![0x0B, 0xA, 0x11].contains(&type_descriptor.tag) {return Err(format!("Unexpected descriptor type in OUDestinationDesc, Expected: one of 0x0B, 0x0A, 0x11, Got: 0x{:02x}!", type_descriptor.tag).into())}
if CONFIG_PRINT_TREE { println!(" Type descriptor(0x{:02x}) - Size: {}", type_descriptor.tag, type_descriptor.size); };
if print_tree { println!(" Type descriptor(0x{:02x}) - Size: {}", type_descriptor.tag, type_descriptor.size); };
let destination_info: CommonDestinationInfo = reader.read_be()?;
if CONFIG_PRINT_TREE {
if print_tree {
println!(" Name lenght: {}", destination_info.name_len);
println!(" Name: {}", destination_info.name());
println!(" Version: {}", destination_info.version);
@@ -136,11 +133,11 @@ pub fn parse_ouith_blob(blob: &[u8]) -> Result<(Vec<MSDItem>, Option<OUSWImageVe
//OUDataProcessingDesc can have OUXOREncryptionDesc(0x0D), OUAESEncryptionDesc(0x0E), OUCompressionDesc(0x0F), OUSecureHashValidationDesc(0x18), OURSAValidationDesc(0x10), OUDataCopyDesc(0x16), OUKeepCurrentDataDesc(0x1E), OUCRC32ValidationDesc(0x12)
let data_processing_descriptor: DescriptorHeader = reader.read_be()?;
if data_processing_descriptor.tag != 0x07 {return Err(format!("Unexpected descriptor type in OUUpgradeItemDesc, Expected: 0x07, Got: 0x{:02x}!", data_processing_descriptor.tag).into())}
if CONFIG_PRINT_TREE { println!(" OUDataProcessingDesc(0x07) - Size: {}", data_processing_descriptor.size); };
if print_tree { println!(" OUDataProcessingDesc(0x07) - Size: {}", data_processing_descriptor.size); };
let heading_size: u32 = reader.read_be()?;
if CONFIG_PRINT_TREE { println!(" Heading size: {}", heading_size); };
if print_tree { println!(" Heading size: {}", heading_size); };
let data_size: u32 = reader.read_be()?;
if CONFIG_PRINT_TREE { println!(" Data size: {}", data_size); };
if print_tree { println!(" Data size: {}", data_size); };
let mut aes_encryption = false;
//let mut crc32_hash: Option<u32> = None;
@@ -152,9 +149,9 @@ pub fn parse_ouith_blob(blob: &[u8]) -> Result<(Vec<MSDItem>, Option<OUSWImageVe
if ![0x0D, 0x0E, 0x0F, 0x18, 0x10, 0x16, 0x1E, 0x12].contains(&descriptor.tag) {return Err(format!("Unexpected descriptor type in OUDataProcessingDesc, Expected: one of 0x0D, 0x0E, 0x0F, 0x18, 0x10, 0x16, 0x1E, 0x12, Got: 0x{:02x}!", descriptor.tag).into())}
if descriptor.tag == 0x0E {
//OUAESEncryptionDesc
if CONFIG_PRINT_TREE { println!(" OUAESEncryptionDesc(0x0E) - Size: {}", descriptor.size); };
if print_tree { println!(" OUAESEncryptionDesc(0x0E) - Size: {}", descriptor.size); };
let aes_encryption_desc: OUAESEncryptionDesc = reader.read_be()?;
if CONFIG_PRINT_TREE {
if print_tree {
println!(" Mode: {}", aes_encryption_desc.mode);
println!(" Key size: {}", aes_encryption_desc.key_size);
println!(" Salt size: {}", aes_encryption_desc.salt_size);
@@ -163,9 +160,9 @@ pub fn parse_ouith_blob(blob: &[u8]) -> Result<(Vec<MSDItem>, Option<OUSWImageVe
}
else if descriptor.tag == 0x10 {
//OURSAValidationDesc
if CONFIG_PRINT_TREE { println!(" OURSAValidationDesc(0x10) - Size: {}", descriptor.size); };
if print_tree { println!(" OURSAValidationDesc(0x10) - Size: {}", descriptor.size); };
let rsa_validation_desc: OURSAValidationDesc = reader.read_be()?;
if CONFIG_PRINT_TREE {
if print_tree {
println!(" Mode: {}", rsa_validation_desc.mode);
println!(" Field 2: {}", rsa_validation_desc._unknown);
println!(" Signature size: {}", rsa_validation_desc.signature_size);
@@ -173,16 +170,16 @@ pub fn parse_ouith_blob(blob: &[u8]) -> Result<(Vec<MSDItem>, Option<OUSWImageVe
}
else if descriptor.tag == 0x12 {
//OUCRC32ValidationDesc
if CONFIG_PRINT_TREE { println!(" OUCRC32ValidationDesc(0x12) - Size: {}", descriptor.size); };
if print_tree { println!(" OUCRC32ValidationDesc(0x12) - Size: {}", descriptor.size); };
let crc32: u32 = reader.read_be()?;
if CONFIG_PRINT_TREE { println!(" CRC32: {:02x}", crc32); };
if print_tree { println!(" CRC32: {:02x}", crc32); };
//crc32_hash = Some(crc32);
}
else if descriptor.tag == 0x18 {
//OUSecureHashValidationDesc
if CONFIG_PRINT_TREE { println!(" OUSecureHashValidationDesc(0x18) - Size: {}", descriptor.size); };
if print_tree { println!(" OUSecureHashValidationDesc(0x18) - Size: {}", descriptor.size); };
let secure_hash_validation_desc: OUSecureHashValidationDesc = reader.read_be()?;
if CONFIG_PRINT_TREE {
if print_tree {
println!(" Mode: {}", secure_hash_validation_desc.mode);
println!(" Hash size: {}", secure_hash_validation_desc.hash_size);
println!(" Hash: {}", hex::encode(&secure_hash_validation_desc.hash));
@@ -191,7 +188,7 @@ pub fn parse_ouith_blob(blob: &[u8]) -> Result<(Vec<MSDItem>, Option<OUSWImageVe
}
else {
//type not implemented, ignore the data
if CONFIG_PRINT_TREE { println!(" Unimplemented descriptor(0x{:02x}) - Size: {}", descriptor.tag, descriptor.size); };
if print_tree { println!(" Unimplemented descriptor(0x{:02x}) - Size: {}", descriptor.tag, descriptor.size); };
let _descriptor_data = common::read_exact(&mut reader, descriptor.size as usize);
}
}
@@ -199,9 +196,9 @@ pub fn parse_ouith_blob(blob: &[u8]) -> Result<(Vec<MSDItem>, Option<OUSWImageVe
//OUGroupInfoDesc
let group_info_descriptor: DescriptorHeader = reader.read_be()?;
if group_info_descriptor.tag != 0x13 {return Err(format!("Unexpected descriptor type in OUUpgradeItemDesc, Expected: 0x13, Got: 0x{:02x}!", group_info_descriptor.tag).into())}
if CONFIG_PRINT_TREE { println!(" OUGroupInfoDesc(0x13) - Size: {}", group_info_descriptor.size); };
if print_tree { println!(" OUGroupInfoDesc(0x13) - Size: {}", group_info_descriptor.size); };
let group_id: u32 = reader.read_be()?;
if CONFIG_PRINT_TREE { println!(" Group ID: {}", group_id); };
if print_tree { println!(" Group ID: {}", group_id); };
//create the msd item with all infos
let msd_item = MSDItem {
@@ -223,9 +220,9 @@ pub fn parse_ouith_blob(blob: &[u8]) -> Result<(Vec<MSDItem>, Option<OUSWImageVe
}
else if top_descriptor.tag == 0x02 {
if CONFIG_PRINT_TREE { println!("OUGroupDesc(0x02) - Size: {}", top_descriptor.size); };
if print_tree { println!("OUGroupDesc(0x02) - Size: {}", top_descriptor.size); };
let group_desc: OUGroupDesc = reader.read_be()?;
if CONFIG_PRINT_TREE {
if print_tree {
println!(" Group ID: {}", group_desc.group_id);
println!(" Field 2: {}", group_desc.field_2);
println!(" Field 3: {}", group_desc.field_3);
@@ -236,9 +233,9 @@ pub fn parse_ouith_blob(blob: &[u8]) -> Result<(Vec<MSDItem>, Option<OUSWImageVe
let version_descriptor: DescriptorHeader = reader.read_be()?;
if ![0x09, 0x19, 0x14, 0x15].contains(&version_descriptor.tag) {return Err(format!("Unexpected descriptor type in OUGroupDesc, Expected: one of 0x09, 0x19, 0x14, 0x15, Got: 0x{:02x}!", version_descriptor.tag).into())}
if version_descriptor.tag == 0x19 {
if CONFIG_PRINT_TREE { println!(" OUSWImageVersionExDesc(0x12) - Size: {}", version_descriptor.size); };
if print_tree { println!(" OUSWImageVersionExDesc(0x12) - Size: {}", version_descriptor.size); };
let sw_image_version_ex_desc: OUSWImageVersionExDesc = reader.read_be()?;
if CONFIG_PRINT_TREE {
if print_tree {
println!(" Name lenght: {}", sw_image_version_ex_desc.name_len);
println!(" Name: {}", sw_image_version_ex_desc.name());
println!(" Major version: {}", sw_image_version_ex_desc.major_ver);
@@ -252,7 +249,7 @@ pub fn parse_ouith_blob(blob: &[u8]) -> Result<(Vec<MSDItem>, Option<OUSWImageVe
}
else {
//type not implemented, ignore the data
if CONFIG_PRINT_TREE { println!(" Unimplemented descriptor(0x{:02x}) - Size: {}", version_descriptor.tag, version_descriptor.size); };
if print_tree { println!(" Unimplemented descriptor(0x{:02x}) - Size: {}", version_descriptor.tag, version_descriptor.size); };
let _descriptor_data = common::read_exact(&mut reader, version_descriptor.size as usize);
}