mirror of
https://github.com/Ap0dexMe0/unixtract.git
synced 2026-07-15 21:00:03 +02:00
Add new mtk pkg support and key, needed changes for LZHSfs , add LZ4 support.
This commit is contained in:
@@ -10,32 +10,4 @@ Please note that this project is still mostly under development and errors may o
|
||||
`[OUTPUT_FOLDER]` - Folder to save extracted files to.
|
||||
If an output folder is not provided, extracted files will be saved in folder `_<INPUT_TARGET>`.
|
||||
|
||||
# Supported formats
|
||||
Please note that some formats depend on decryption keys, and matching ones may not be provided in the tool. If you want to add your own keys, use the `keys.rs` file.
|
||||
| Format name | Used by | Notes | Thanks to |
|
||||
| ----------------------------- | --------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------- |
|
||||
| Android OTA payload.bin | Some Android MediaTek TVs | Some compression methods are not supported | https://android.googlesource.com/platform/system/update_engine/+/HEAD/update_metadata.proto |
|
||||
| BDL | HP Printers | All files should be supported. | - |
|
||||
| EPK v1 | LG TVs before ~2010 | All files should be supported. | https://github.com/openlgtv/epk2extract |
|
||||
| EPK v2 | LG TVs since ~2010 | **Depends on keys** - see keys.rs | https://github.com/openlgtv/epk2extract |
|
||||
| EPK v3 | LG webOS TVs | **Depends on keys** - see keys.rs | https://github.com/openlgtv/epk2extract |
|
||||
| Funai UPG | Some Funai TVs | Only supports unencrypted/unobfuscated files | - |
|
||||
| INVINCIBLE_IMAGE | LG Broadcom-based Blu-Ray players | Only version 3 is supported (2011+) | - |
|
||||
| MSD v1.0 | Samsung TVs 2013-2015 | **Depends on keys** - see keys.rs | https://github.com/bugficks/msddecrypt |
|
||||
| MSD v1.1 | Samsung TVs 2016+ | **Depends on keys** - see keys.rs | https://github.com/bugficks/msddecrypt |
|
||||
| Mstar upgrade bin | Many MStar-based TVs (Hisense, Toshiba..) | Most files should be supported | - |
|
||||
| Mediatek BDP | Many Mediatek-based Blu-Ray players (LG, Samsung, Philips, Panasonic...) | Some older files may not be supported | - |
|
||||
| Mediatek PKG (Old) | Older Mediatek-based TVs | All files should be supported | - |
|
||||
| Mediatek PKG | Many Mediatek-based TVs (Hisense, Sony, Panasonic, Philips...) | Newer files with larger header are not supported. **Depends on keys** - see keys.rs | https://github.com/openlgtv/epk2extract |
|
||||
| Novatek PKG (NFWB) | Some Novatek-based TVs (Philips, LG..) | All files should be supported | https://github.com/openlgtv/epk2extract |
|
||||
| Novatek TIMG | Later Novatek Based TVs (Philips TitanOS/Hisense) | All files should be supported | - |
|
||||
| Panasonic Blu-Ray (PANA_DVD) | Panasonic Blu-Ray Players/Recorders | **Depends on keys** - see keys.rs | - |
|
||||
| Philips UPG | Philips pre-TPVision TVS 2008-2013 | **Depends on keys** - see keys.rs | https://github.com/frederic/pflupg-tool |
|
||||
| PUP | Sony PlayStation 4/ PlayStation 5 | File has to be decrypted | https://github.com/Zer0xFF/ps4-pup-unpacker |
|
||||
| Roku | Roku TVs/players | Most files should work, but encrypted images contained within will not be decrypted. | - |
|
||||
| RUF | Samsung Broadcom-based Blu-Ray players | **Depends on keys** - see keys.rs | - |
|
||||
| RVP/MVP | Sharp Blu-Ray players/recorders | Only supports older files (XOR encrypted) | - |
|
||||
| Samsung | Old Samsung TV firmwares pre 2013 | **Depends on keys** - see keys.rs | https://github.com/george-hopkins/samygo-patcher |
|
||||
| SDDL.SEC | Panasonic TVs 2011+ | All files 2011+ are supported | https://github.com/theubusu/sddl_dec |
|
||||
| SLP | Samsung Tizen-based NX series cameras | All files should be supported | - |
|
||||
| Sony BDP | Sony Blu-Ray players | Only platforms up to MSB18 are supported | http://malcolmstagg.com/bdp/s390-firmware.html |
|
||||
# Supported formats
|
||||
+28
@@ -0,0 +1,28 @@
|
||||
| Format name | Used by | Notes | Thanks to |
|
||||
| ----------------------------- | --------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------- |
|
||||
| Android OTA payload.bin | Some Android MediaTek TVs | Some compression methods are not supported | https://android.googlesource.com/platform/system/update_engine/+/HEAD/update_metadata.proto |
|
||||
| BDL | HP Printers | All files should be supported. | - |
|
||||
| EPK v1 | LG TVs before ~2010 | All files should be supported. | https://github.com/openlgtv/epk2extract |
|
||||
| EPK v2 | LG TVs since ~2010 | **Depends on keys** - see keys.rs | https://github.com/openlgtv/epk2extract |
|
||||
| EPK v3 | LG webOS TVs | **Depends on keys** - see keys.rs | https://github.com/openlgtv/epk2extract |
|
||||
| Funai UPG | Some Funai TVs | Only supports unencrypted/unobfuscated files | - |
|
||||
| INVINCIBLE_IMAGE | LG Broadcom-based Blu-Ray players | Only version 3 is supported (2011+) | - |
|
||||
| MSD v1.0 | Samsung TVs 2013-2015 | **Depends on keys** - see keys.rs | https://github.com/bugficks/msddecrypt |
|
||||
| MSD v1.1 | Samsung TVs 2016+ | **Depends on keys** - see keys.rs | https://github.com/bugficks/msddecrypt |
|
||||
| Mstar upgrade bin | Many MStar-based TVs (Hisense, Toshiba..) | Most files should be supported | - |
|
||||
| Mediatek BDP | Many Mediatek-based Blu-Ray players (LG, Samsung, Philips, Panasonic...) | Some older files may not be supported | - |
|
||||
| Mediatek PKG (New) | Newer Mediatek-based TVs | **Depends on keys** - see keys.rs | - |
|
||||
| Mediatek PKG (Old) | Older Mediatek-based TVs | All files should be supported | - |
|
||||
| Mediatek PKG | Many Mediatek-based TVs (Hisense, Sony, Panasonic, Philips...) | Some firmwares **Depend on keys** - see keys.rs | https://github.com/openlgtv/epk2extract |
|
||||
| Novatek PKG (NFWB) | Some Novatek-based TVs (Philips, LG..) | All files should be supported | https://github.com/openlgtv/epk2extract |
|
||||
| Novatek TIMG | Later Novatek Based TVs (Philips TitanOS/Hisense) | All files should be supported | - |
|
||||
| Panasonic Blu-Ray (PANA_DVD) | Panasonic Blu-Ray Players/Recorders | **Depends on keys** - see keys.rs | - |
|
||||
| Philips UPG | Philips pre-TPVision TVS 2008-2013 | **Depends on keys** - see keys.rs | https://github.com/frederic/pflupg-tool |
|
||||
| PUP | Sony PlayStation 4/ PlayStation 5 | File has to be decrypted | https://github.com/Zer0xFF/ps4-pup-unpacker |
|
||||
| Roku | Roku TVs/players | Most files should work, but encrypted images contained within will not be decrypted. | - |
|
||||
| RUF | Samsung Broadcom-based Blu-Ray players | **Depends on keys** - see keys.rs | - |
|
||||
| RVP/MVP | Sharp Blu-Ray players/recorders | Only supports older files (XOR encrypted) | - |
|
||||
| Samsung | Old Samsung TV firmwares pre 2013 | **Depends on keys** - see keys.rs | https://github.com/george-hopkins/samygo-patcher |
|
||||
| SDDL.SEC | Panasonic TVs 2011+ | All files 2011+ are supported | https://github.com/theubusu/sddl_dec |
|
||||
| SLP | Samsung Tizen-based NX series cameras | All files should be supported | - |
|
||||
| Sony BDP | Sony Blu-Ray players | Only platforms up to MSB18 are supported | http://malcolmstagg.com/bdp/s390-firmware.html |
|
||||
@@ -28,4 +28,5 @@ pub mod epk3;
|
||||
|
||||
pub mod mtk_pkg;
|
||||
pub mod mtk_pkg_old;
|
||||
pub mod mtk_pkg_new;
|
||||
pub mod mtk_bdp;
|
||||
+15
-6
@@ -12,11 +12,12 @@ use crate::keys;
|
||||
struct Header {
|
||||
#[br(count = 4)] vendor_magic_bytes: Vec<u8>,
|
||||
#[br(count = 8)] _mtk_magic: Vec<u8>, //#DH@FiRm
|
||||
#[br(count = 60)] version_bytes: Vec<u8>,
|
||||
#[br(count = 56)] version_bytes: Vec<u8>,
|
||||
_unk: u32,
|
||||
file_size: u32,
|
||||
_platform: u32,
|
||||
_flags: u32,
|
||||
#[br(count = 32)] product_name_bytes: Vec<u8>,
|
||||
#[br(count = 32)] _unknown: Vec<u8>,
|
||||
#[br(count = 32)] _digest: Vec<u8>,
|
||||
}
|
||||
impl Header {
|
||||
fn vendor_magic(&self) -> String {
|
||||
@@ -165,9 +166,17 @@ pub fn extract_mtk_pkg(mut file: &File, output_folder: &str) -> Result<(), Box<d
|
||||
|
||||
if part_entry.is_compressed() {
|
||||
let lzhs_out_path = Path::new(&output_folder).join(part_entry.name() + ".bin");
|
||||
decompress_lzhs_fs_file2file(&out_file, lzhs_out_path)?;
|
||||
//after decompression remove the temporary .lzhs file
|
||||
fs::remove_file(&output_path)?;
|
||||
match decompress_lzhs_fs_file2file(&out_file, lzhs_out_path) {
|
||||
Ok(()) => {
|
||||
println!("- Decompressed Successfully!");
|
||||
//after successfull decompression remove the temporary .lzhs file
|
||||
fs::remove_file(&output_path)?;
|
||||
},
|
||||
Err(e) => {
|
||||
eprintln!("Failed to decompress partition!, Error: {}. Saving compressed data...", e);
|
||||
//if the decompression is not successfull leave out compressed data.
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
println!("-- Saved file!");
|
||||
|
||||
@@ -0,0 +1,168 @@
|
||||
use std::path::Path;
|
||||
use std::fs::{self, File, OpenOptions};
|
||||
use std::io::{Write, Cursor, Seek};
|
||||
use binrw::{BinRead, BinReaderExt};
|
||||
|
||||
use crate::utils::common;
|
||||
use crate::utils::aes::{decrypt_aes128_cbc_nopad};
|
||||
use crate::utils::lzhs::{decompress_lzhs_fs_file2file};
|
||||
use crate::keys;
|
||||
|
||||
#[derive(BinRead)]
|
||||
struct Header {
|
||||
#[br(count = 4)] vendor_magic_bytes: Vec<u8>,
|
||||
#[br(count = 8)] _mtk_magic: Vec<u8>, //#DH@FiRm
|
||||
#[br(count = 56)] version_bytes: Vec<u8>,
|
||||
_unk: u32,
|
||||
file_size: u32,
|
||||
_flags: u32,
|
||||
#[br(count = 32)] product_name_bytes: Vec<u8>,
|
||||
#[br(count = 256)] _digest: Vec<u8>,
|
||||
}
|
||||
impl Header {
|
||||
fn vendor_magic(&self) -> String {
|
||||
common::string_from_bytes(&self.vendor_magic_bytes)
|
||||
}
|
||||
fn version(&self) -> String {
|
||||
common::string_from_bytes(&self.version_bytes)
|
||||
}
|
||||
fn product_name(&self) -> String {
|
||||
common::string_from_bytes(&self.product_name_bytes)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#[derive(BinRead)]
|
||||
struct PartEntry {
|
||||
#[br(count = 4)] name_bytes: Vec<u8>,
|
||||
flags: u32,
|
||||
size: u32,
|
||||
}
|
||||
impl PartEntry {
|
||||
fn name(&self) -> String {
|
||||
common::string_from_bytes(&self.name_bytes)
|
||||
}
|
||||
fn is_valid(&self) -> bool {
|
||||
self.name().is_ascii()
|
||||
}
|
||||
fn is_encrypted(&self) -> bool {
|
||||
(self.flags & 1 << 0) != 0
|
||||
}
|
||||
fn is_compressed(&self) -> bool { //lzhs fs
|
||||
(self.flags & 1 << 8) != 0
|
||||
}
|
||||
}
|
||||
|
||||
pub fn is_mtk_pkg_new_file(file: &File) -> bool {
|
||||
let encrypted_header = common::read_file(&file, 0, 112).expect("Failed to read from file.");
|
||||
for (key_hex, iv_hex, _name) in keys::MTK_PKG_CUST {
|
||||
let key_array: [u8; 16] = hex::decode(key_hex).expect("Error").as_slice().try_into().expect("Error");
|
||||
let iv_array: [u8; 16] = hex::decode(iv_hex).expect("Error").as_slice().try_into().expect("Error");
|
||||
let try_decrypt = decrypt_aes128_cbc_nopad(&encrypted_header, &key_array, &iv_array).expect("Failed to decrypt.");
|
||||
|
||||
if &try_decrypt[4..12] == b"#DH@FiRm" {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
false
|
||||
}
|
||||
|
||||
pub fn extract_mtk_pkg_new(mut file: &File, output_folder: &str) -> Result<(), Box<dyn std::error::Error>> {
|
||||
let file_size = file.metadata()?.len();
|
||||
let encrypted_header = common::read_exact(&mut file, 368)?;
|
||||
|
||||
let mut header = Vec::new();
|
||||
let mut matching_key: Option<[u8; 16]> = None;
|
||||
let mut matching_iv: Option<[u8; 16]> = None;
|
||||
//find key, the header and data key will be the same
|
||||
for (key_hex, iv_hex, name) in keys::MTK_PKG_CUST {
|
||||
let key_array = hex::decode(key_hex)?.as_slice().try_into()?;
|
||||
let iv_array = hex::decode(iv_hex)?.as_slice().try_into()?;
|
||||
header = decrypt_aes128_cbc_nopad(&encrypted_header, &key_array, &iv_array)?;
|
||||
|
||||
if &header[4..12] == b"#DH@FiRm" {
|
||||
println!("Using key {}", name);
|
||||
matching_key = Some(key_array);
|
||||
matching_iv = Some(iv_array);
|
||||
break
|
||||
}
|
||||
}
|
||||
if matching_key.is_none() && matching_iv.is_none() {
|
||||
println!("Failed to find key!");
|
||||
return Ok(())
|
||||
}
|
||||
|
||||
let mut hdr_reader = Cursor::new(header);
|
||||
let hdr: Header = hdr_reader.read_le()?;
|
||||
|
||||
println!("File info:\nFile size: {}\nVendor magic: {}\nVersion info: {}\nProduct name: {}" ,
|
||||
hdr.file_size, hdr.vendor_magic(), hdr.version(), hdr.product_name());
|
||||
|
||||
let mut part_n = 0;
|
||||
while file.stream_position()? < file_size as u64 {
|
||||
part_n += 1;
|
||||
let part_entry: PartEntry = file.read_le()?;
|
||||
if !part_entry.is_valid() {
|
||||
break
|
||||
}
|
||||
|
||||
println!("\n#{} - {}, Size: {}{} {}",
|
||||
part_n, part_entry.name(), part_entry.size, if part_entry.is_compressed() {" [COMPRESSED]"} else {""}, if part_entry.is_encrypted() {"[ENCRYPTED]"} else {""} );
|
||||
|
||||
let data = common::read_exact(&mut file, part_entry.size as usize + 48)?;
|
||||
|
||||
if part_entry.size == 0 {
|
||||
println!("- Empty entry, skipping!");
|
||||
continue
|
||||
}
|
||||
|
||||
let out_data;
|
||||
if part_entry.is_encrypted() {
|
||||
println!("- Decrypting...");
|
||||
out_data = decrypt_aes128_cbc_nopad(&data[..data.len() & !15], &matching_key.unwrap(), &matching_iv.unwrap())?;
|
||||
} else {
|
||||
out_data = data;
|
||||
}
|
||||
|
||||
//strip iMtK thing and get version
|
||||
let extra_header_len = if &out_data[48..52] == b"iMtK" {
|
||||
let imtk_len = u32::from_le_bytes(out_data[52..56].try_into().unwrap());
|
||||
if &out_data[56..60] != b"iPAd" {
|
||||
let version_len = u32::from_le_bytes(out_data[56..60].try_into().unwrap());
|
||||
let version = common::string_from_bytes(&out_data[60..60 + version_len as usize]);
|
||||
println!("- Version: {}", version);
|
||||
}
|
||||
imtk_len + 8
|
||||
} else {
|
||||
0
|
||||
};
|
||||
|
||||
//for compressed part create temp file
|
||||
let output_path = Path::new(&output_folder).join(part_entry.name() + if part_entry.is_compressed() {".lzhs"} else {".bin"});
|
||||
fs::create_dir_all(&output_folder)?;
|
||||
let mut out_file = OpenOptions::new().write(true).read(true)/* for lzhs */.create(true).open(&output_path)?;
|
||||
out_file.write_all(&out_data[48 + extra_header_len as usize..])?;
|
||||
|
||||
if part_entry.is_compressed() {
|
||||
let lzhs_out_path = Path::new(&output_folder).join(part_entry.name() + ".bin");
|
||||
match decompress_lzhs_fs_file2file(&out_file, lzhs_out_path) {
|
||||
Ok(()) => {
|
||||
println!("-- Decompressed Successfully!");
|
||||
//after successfull decompression remove the temporary .lzhs file
|
||||
fs::remove_file(&output_path)?;
|
||||
},
|
||||
Err(e) => {
|
||||
eprintln!("Failed to decompress partition!, Error: {}. Saving compressed data...", e);
|
||||
//if the decompression is not successfull leave out compressed data.
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
println!("-- Saved file!");
|
||||
}
|
||||
|
||||
println!("\nExtraction finished!");
|
||||
|
||||
Ok(())
|
||||
}
|
||||
@@ -19,7 +19,7 @@ struct Header {
|
||||
file_size: u32,
|
||||
_flags: u32,
|
||||
#[br(count = 32)] product_name_bytes: Vec<u8>,
|
||||
#[br(count = 32)] _encrypted_digest: Vec<u8>,
|
||||
#[br(count = 32)] _digest: Vec<u8>,
|
||||
}
|
||||
impl Header {
|
||||
fn vendor_magic(&self) -> String {
|
||||
|
||||
@@ -98,4 +98,5 @@ pub static MTK_PKG_CUST: &[(&str, &str, &str)] = &[
|
||||
("47FBF8CAD62BB95AF3AD9509E5C2175D", "63120FB321B0410F216D6DC2D8641A11", "Philips 2013"),
|
||||
("1B569AA7D2E4CCE66584A7A3D8A45679", "A0E88D5D52A813260D3A34A14AA89416", "TPV_MTK2K17PLF_EU0"),
|
||||
("135AFB6DE91CD56496244BC7C0E08D63", "C6A38C89F0AF5637EB6E19D35E12E257", "TPV_MTK2K14PLF_EU1"),
|
||||
("B1BFAA407F70C80C650379DFEAFAA40F", "BC1443A0D17AAB2DB1EA0302EF280717", "Common"), //new mtk pkg, worked for Hisense/CVT/Changhong
|
||||
];
|
||||
@@ -144,6 +144,10 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {
|
||||
println!("MTK PKG (Old) file detected!");
|
||||
formats::mtk_pkg_old::extract_mtk_pkg_old(&file, &output_path)?;
|
||||
}
|
||||
else if formats::mtk_pkg_new::is_mtk_pkg_new_file(&file) {
|
||||
println!("MTK PKG (New) file detected!");
|
||||
formats::mtk_pkg_new::extract_mtk_pkg_new(&file, &output_path)?;
|
||||
}
|
||||
else if formats::mtk_bdp::is_mtk_bdp_file(&file) {
|
||||
println!("MTK BDP file detected!");
|
||||
formats::mtk_bdp::extract_mtk_bdp(&file, &output_path)?;
|
||||
|
||||
+41
-13
@@ -4,18 +4,19 @@ use binrw::{BinRead, BinReaderExt};
|
||||
use std::path::{PathBuf};
|
||||
|
||||
use crate::utils::huffman_tables::{CHARLEN, POS};
|
||||
use crate::utils::compression::{decompress_lz4};
|
||||
|
||||
#[derive(BinRead)]
|
||||
struct LzhsHeader {
|
||||
uncompressed_size: u32,
|
||||
compressed_size: u32,
|
||||
checksum_or_seg_idx: u16, //as checksum in normal lzhs header, as index in lzhs_fs header
|
||||
#[br(count = 6)] _padding: Vec<u8>,
|
||||
#[br(count = 6)] padding: Vec<u8>,
|
||||
}
|
||||
|
||||
pub fn decompress_lzhs_fs_file2file(mut file: &File, output_file: PathBuf) -> Result<(), Box<dyn std::error::Error>> {
|
||||
let file_size = file.metadata()?.len();
|
||||
let mut out_file = OpenOptions::new().append(true).create(true).open(output_file)?;
|
||||
let mut out_file = OpenOptions::new().append(true).create(true).open(&output_file)?;
|
||||
file.seek(SeekFrom::Start(0))?;
|
||||
|
||||
let mut uncompressed_heading = vec![0u8; 0x100000]; //first 1mb is uncompressed
|
||||
@@ -25,23 +26,50 @@ pub fn decompress_lzhs_fs_file2file(mut file: &File, output_file: PathBuf) -> Re
|
||||
while file.stream_position().unwrap() < file_size {
|
||||
let segment_header: LzhsHeader = file.read_le()?;
|
||||
let lzhs_header: LzhsHeader = file.read_le()?;
|
||||
println!("[LZHS] Segment {} - Compressed size: {}, Decompressed size: {}, Expected Checksum: 0x{:02x?}",
|
||||
segment_header.checksum_or_seg_idx, lzhs_header.compressed_size, lzhs_header.uncompressed_size, lzhs_header.checksum_or_seg_idx);
|
||||
|
||||
//lz4 type uses a 4 byte checksum instead of 1(2) byte , so the padding is not 0 anymore
|
||||
//maybe this method will be changed
|
||||
let is_lz4 = if lzhs_header.padding != b"\x00\x00\x00\x00\x00\x00" {true} else {false};
|
||||
|
||||
println!("[{}] Segment {} - Compressed size: {}, Decompressed size: {}, Expected Checksum: 0x{:02x?}",
|
||||
if is_lz4 {"LZ4"} else {"LZHS"}, segment_header.checksum_or_seg_idx, lzhs_header.compressed_size, lzhs_header.uncompressed_size, lzhs_header.checksum_or_seg_idx);
|
||||
|
||||
let mut compressed_data = vec![0u8; lzhs_header.compressed_size as usize];
|
||||
file.read_exact(&mut compressed_data)?;
|
||||
let mut out_data;
|
||||
if lzhs_header.compressed_size == 0 {
|
||||
//odd variant no.1: if the compressed size is 0 , the output is just zeros with the uncompressed size.
|
||||
out_data = vec![0; lzhs_header.uncompressed_size as usize];
|
||||
|
||||
println!("- Decompressing...");
|
||||
let out_huff = unhuff(&compressed_data);
|
||||
let mut out_data = unlzss(&out_huff, lzhs_header.uncompressed_size as usize);
|
||||
arm_thumb_convert(&mut out_data, 0, false);
|
||||
} else if (lzhs_header.uncompressed_size > segment_header.uncompressed_size) &&
|
||||
(lzhs_header.compressed_size == lzhs_header.uncompressed_size) &&
|
||||
lzhs_header.checksum_or_seg_idx == 0x00
|
||||
{
|
||||
//odd variant no.2: the lzhs header compressed size is for some reason bigger by 8 bytes (and those 8 bytes are zeros), the data is stored UNCOMPRESSED in these
|
||||
//the compressed and uncompressed size are the same and the checksum is 0.
|
||||
out_data = compressed_data[..segment_header.uncompressed_size as usize].to_vec();
|
||||
|
||||
let checksum = calc_checksum(&out_data);
|
||||
println!("-- Calculated checksum: 0x{:02x?}", checksum);
|
||||
if u16::from(checksum) != lzhs_header.checksum_or_seg_idx {
|
||||
println!("--- Checksum mismatch! Expected: 0x{:02x?}, Got: 0x{:02x?}!", lzhs_header.checksum_or_seg_idx, checksum);
|
||||
} else {
|
||||
println!("--- Checksum OK!")
|
||||
//normal variant
|
||||
println!("- Decompressing...");
|
||||
if is_lz4 {
|
||||
out_data = decompress_lz4(&compressed_data, lzhs_header.uncompressed_size as i32)?;
|
||||
} else {
|
||||
//lzhs
|
||||
let out_huff = unhuff(&compressed_data);
|
||||
out_data = unlzss(&out_huff, lzhs_header.uncompressed_size as usize);
|
||||
arm_thumb_convert(&mut out_data, 0, false);
|
||||
|
||||
let checksum = calc_checksum(&out_data);
|
||||
println!("-- Calculated checksum: 0x{:02x?}", checksum);
|
||||
if u16::from(checksum) != lzhs_header.checksum_or_seg_idx {
|
||||
println!("--- Checksum mismatch! Expected: 0x{:02x?}, Got: 0x{:02x?}!", lzhs_header.checksum_or_seg_idx, checksum);
|
||||
return Err("Checksum mismatch!".into());
|
||||
} else {
|
||||
println!("--- Checksum OK!")
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
out_file.write_all(&out_data)?;
|
||||
|
||||
Reference in New Issue
Block a user