mirror of
https://github.com/Ap0dexMe0/unixtract.git
synced 2026-07-15 21:00:03 +02:00
mtk_pkg: add ZSTD decompression support, decomp part in memory, pfl_upg: add Q5521 key
This commit is contained in:
Generated
+29
@@ -937,6 +937,7 @@ dependencies = [
|
||||
"sha1",
|
||||
"simd-adler32",
|
||||
"tar",
|
||||
"zstd",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -1087,3 +1088,31 @@ name = "zeroize"
|
||||
version = "1.8.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ced3678a2879b30306d323f4542626697a464a97c0a07c9aebf7ebca65cd4dde"
|
||||
|
||||
[[package]]
|
||||
name = "zstd"
|
||||
version = "0.13.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e91ee311a569c327171651566e07972200e76fcfe2242a4fa446149a3881c08a"
|
||||
dependencies = [
|
||||
"zstd-safe",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "zstd-safe"
|
||||
version = "7.2.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8f49c4d5f0abb602a93fb8736af2a4f4dd9512e36f7f570d66e65ff867ed3b9d"
|
||||
dependencies = [
|
||||
"zstd-sys",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "zstd-sys"
|
||||
version = "2.0.16+zstd.1.5.7"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "91e19ebc2adc8f83e43039e79776e3fda8ca919132d68a1fed6a5faca2683748"
|
||||
dependencies = [
|
||||
"cc",
|
||||
"pkg-config",
|
||||
]
|
||||
|
||||
+2
-1
@@ -23,4 +23,5 @@ prost = "0.14.1"
|
||||
prost-types = "0.14.1"
|
||||
bzip2 = "0.6.1"
|
||||
liblzma = "0.4.5"
|
||||
des = "0.8.1"
|
||||
des = "0.8.1"
|
||||
zstd = "0.13.3"
|
||||
@@ -25,7 +25,7 @@ pub struct Header {
|
||||
_mtk_magic: [u8; 8], //#DH@FiRm
|
||||
version_bytes: [u8; 60],
|
||||
pub file_size: u32,
|
||||
_flags: u32,
|
||||
_flags: [u8; 4], // 3rd is possibly the compression type in new mtk pkg
|
||||
product_name_bytes: [u8; 32],
|
||||
}
|
||||
impl Header {
|
||||
@@ -57,7 +57,7 @@ impl PartEntry {
|
||||
pub fn is_encrypted(&self) -> bool {
|
||||
(self.flags & 1 << 0) != 0
|
||||
}
|
||||
pub fn is_compressed(&self) -> bool { //lzhs fs
|
||||
pub fn is_compressed(&self) -> bool {
|
||||
(self.flags & 1 << 8) != 0
|
||||
}
|
||||
}
|
||||
+64
-48
@@ -1,17 +1,25 @@
|
||||
use std::fs::{File, OpenOptions};
|
||||
use std::fs::OpenOptions;
|
||||
use std::io::{Write, Cursor, Seek, SeekFrom, Read};
|
||||
use binrw::{BinRead, BinReaderExt};
|
||||
use std::path::{PathBuf};
|
||||
|
||||
use super::huffman_tables::{CHARLEN, POS};
|
||||
use crate::utils::compression::{decompress_lz4};
|
||||
use crate::utils::common;
|
||||
use crate::utils::compression::{decompress_lz4, decompress_zstd};
|
||||
|
||||
#[derive(PartialEq, Debug)]
|
||||
enum CompressionType {
|
||||
LZHS,
|
||||
LZ4,
|
||||
ZSTD,
|
||||
}
|
||||
|
||||
#[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
|
||||
padding: [u8; 6],
|
||||
checksum_or_seg_idx: u32, //as checksum in normal lzhs header, as index in lzhs_fs header
|
||||
_padding: [u8; 4],
|
||||
}
|
||||
|
||||
#[derive(BinRead)]
|
||||
@@ -20,36 +28,42 @@ struct LzhsOldSegmentHdr {
|
||||
_compressed_size: u32,
|
||||
}
|
||||
|
||||
pub fn decompress_lzhs_fs_file2file(mut file: &File, output_file: PathBuf) -> Result<(), Box<dyn std::error::Error>> {
|
||||
let file_size = file.metadata()?.len();
|
||||
pub fn decompress_mtk_to_file(data: &[u8], output_file: &PathBuf) -> Result<(), Box<dyn std::error::Error>> {
|
||||
let mut out_file = OpenOptions::new().append(true).create(true).open(&output_file)?;
|
||||
file.seek(SeekFrom::Start(0))?;
|
||||
let mut data_reader = Cursor::new(data);
|
||||
|
||||
let mut uncompressed_heading = vec![0u8; 0x100000]; //first 1mb is uncompressed
|
||||
file.read_exact(&mut uncompressed_heading)?;
|
||||
let uncompressed_heading = common::read_exact(&mut data_reader, 0x100000)?; //first 1mb is uncompressed
|
||||
out_file.write_all(&uncompressed_heading)?;
|
||||
|
||||
while file.stream_position().unwrap() < file_size {
|
||||
let segment_header: LzhsHeader = file.read_le()?;
|
||||
let lzhs_header: LzhsHeader = file.read_le()?;
|
||||
while data_reader.stream_position().unwrap() < data_reader.get_ref().len() as u64{
|
||||
let segment_header: LzhsHeader = data_reader.read_le()?;
|
||||
let comp_header: LzhsHeader = data_reader.read_le()?;
|
||||
|
||||
//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!("[cmp] Segment {} - Compressed size: {}, Decompressed size: {}",
|
||||
segment_header.checksum_or_seg_idx, comp_header.compressed_size, comp_header.uncompressed_size);
|
||||
|
||||
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 compressed_data = common::read_exact(&mut data_reader, comp_header.compressed_size as usize)?;
|
||||
|
||||
//set comp method
|
||||
let compression_type: CompressionType;
|
||||
if comp_header.checksum_or_seg_idx & 0xFFFFFF00 != 0 { //LZHS uses only a 8 bit checksum, and other use 32 bit(although the type is unknown).
|
||||
if compressed_data.starts_with(b"\x28\xB5\x2F\xFD") { //ZSTD magic
|
||||
compression_type = CompressionType::ZSTD;
|
||||
} else {
|
||||
compression_type = CompressionType::LZ4;
|
||||
}
|
||||
} else {
|
||||
compression_type = CompressionType::LZHS;
|
||||
}
|
||||
|
||||
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 {
|
||||
if comp_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];
|
||||
out_data = vec![0; comp_header.uncompressed_size as usize];
|
||||
|
||||
} 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
|
||||
} else if (comp_header.uncompressed_size > segment_header.uncompressed_size) &&
|
||||
(comp_header.compressed_size == comp_header.uncompressed_size) &&
|
||||
comp_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.
|
||||
@@ -57,56 +71,58 @@ pub fn decompress_lzhs_fs_file2file(mut file: &File, output_file: PathBuf) -> Re
|
||||
|
||||
} else {
|
||||
//normal variant
|
||||
println!("- Decompressing...");
|
||||
if is_lz4 {
|
||||
out_data = decompress_lz4(&compressed_data, lzhs_header.uncompressed_size as i32)?;
|
||||
} else {
|
||||
//lzhs
|
||||
println!("- Decompressing {:?}...", compression_type);
|
||||
if compression_type == CompressionType::LZ4 {
|
||||
out_data = decompress_lz4(&compressed_data, comp_header.uncompressed_size as i32)?;
|
||||
}
|
||||
else if compression_type == CompressionType::ZSTD {
|
||||
out_data = decompress_zstd(&compressed_data)?;
|
||||
}
|
||||
else if compression_type == CompressionType::LZHS {
|
||||
let out_huff = unhuff(&compressed_data);
|
||||
out_data = unlzss(&out_huff, lzhs_header.uncompressed_size as usize);
|
||||
out_data = unlzss(&out_huff, comp_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());
|
||||
if u32::from(checksum) != comp_header.checksum_or_seg_idx {
|
||||
println!("--- Checksum mismatch! Expected: 0x{:02x?}, Got: 0x{:02x?}!", comp_header.checksum_or_seg_idx, checksum);
|
||||
return Err("LZHS checksum mismatch".into());
|
||||
} else {
|
||||
println!("--- Checksum OK!")
|
||||
}
|
||||
}
|
||||
|
||||
else {
|
||||
return Err("undefined compression type".into());
|
||||
}
|
||||
}
|
||||
|
||||
out_file.write_all(&out_data)?;
|
||||
|
||||
//padded to 16 bytes
|
||||
let pad_pos = (file.stream_position().unwrap() + 15) & !15;
|
||||
file.seek(SeekFrom::Start(pad_pos))?;
|
||||
let pad_pos = (data_reader.stream_position().unwrap() + 15) & !15;
|
||||
data_reader.seek(SeekFrom::Start(pad_pos))?;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
// OLD VARIANT use in old mtk pkg
|
||||
pub fn decompress_lzhs_fs_file2file_old(mut file: &File, output_file: PathBuf) -> Result<(), Box<dyn std::error::Error>> {
|
||||
let file_size = file.metadata()?.len();
|
||||
pub fn decompress_mtk_to_file_old(data: &[u8], output_file: &PathBuf) -> Result<(), Box<dyn std::error::Error>> {
|
||||
let mut out_file = OpenOptions::new().append(true).create(true).open(&output_file)?;
|
||||
file.seek(SeekFrom::Start(0))?;
|
||||
let mut data_reader = Cursor::new(data);
|
||||
|
||||
let mut uncompressed_heading = vec![0u8; 0x200]; //first 512b is uncompressed
|
||||
file.read_exact(&mut uncompressed_heading)?;
|
||||
let uncompressed_heading = common::read_exact(&mut data_reader, 0x200)?; //first 1mb is uncompressed
|
||||
out_file.write_all(&uncompressed_heading)?;
|
||||
|
||||
while file.stream_position().unwrap() < file_size {
|
||||
let _segment_header: LzhsOldSegmentHdr = file.read_le()?;
|
||||
let lzhs_header: LzhsHeader = file.read_le()?;
|
||||
while data_reader.stream_position().unwrap() < data_reader.get_ref().len() as u64{
|
||||
let _segment_header: LzhsOldSegmentHdr = data_reader.read_le()?;
|
||||
let lzhs_header: LzhsHeader = data_reader.read_le()?;
|
||||
|
||||
println!("[LZHS] Segment - Compressed size: {}, Decompressed size: {}, Expected Checksum: 0x{:02x?}",
|
||||
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 compressed_data = common::read_exact(&mut data_reader, lzhs_header.compressed_size as usize)?;
|
||||
let mut out_data;
|
||||
let out_huff = unhuff(&compressed_data);
|
||||
out_data = unlzss(&out_huff, lzhs_header.uncompressed_size as usize);
|
||||
@@ -114,9 +130,9 @@ pub fn decompress_lzhs_fs_file2file_old(mut file: &File, output_file: PathBuf) -
|
||||
|
||||
let checksum = calc_checksum(&out_data);
|
||||
println!("-- Calculated checksum: 0x{:02x?}", checksum);
|
||||
if u16::from(checksum) != lzhs_header.checksum_or_seg_idx {
|
||||
if u32::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());
|
||||
return Err("LZHS checksum mismatch".into());
|
||||
} else {
|
||||
println!("--- Checksum OK!")
|
||||
}
|
||||
|
||||
+10
-14
@@ -13,7 +13,7 @@ use crate::utils::common;
|
||||
use crate::utils::global::opt_dump_dec_hdr;
|
||||
use crate::utils::aes::{decrypt_aes128_cbc_nopad};
|
||||
use crate::keys;
|
||||
use lzhs::{decompress_lzhs_fs_file2file};
|
||||
use lzhs::{decompress_mtk_to_file};
|
||||
use include::*;
|
||||
|
||||
pub struct MtkPkgContext {
|
||||
@@ -140,31 +140,27 @@ pub fn extract_mtk_pkg(app_ctx: &AppContext, ctx: Box<dyn Any>) -> Result<(), Bo
|
||||
} else {
|
||||
0
|
||||
};
|
||||
let fin_data = &out_data[CRYPTED_HEADER_SIZE + extra_header_len as usize..];
|
||||
|
||||
//for compressed part create temp file
|
||||
let output_path = Path::new(&app_ctx.output_dir).join(part_entry.name() + if part_entry.is_compressed() {".lzhs"} else {".bin"});
|
||||
let output_path = Path::new(&app_ctx.output_dir).join(format!("{}.bin", part_entry.name()));
|
||||
fs::create_dir_all(&app_ctx.output_dir)?;
|
||||
let mut out_file = OpenOptions::new().write(true).read(true)/* for lzhs */.create(true).open(&output_path)?;
|
||||
out_file.write_all(&out_data[CRYPTED_HEADER_SIZE + extra_header_len as usize..])?;
|
||||
|
||||
if part_entry.is_compressed() {
|
||||
let lzhs_out_path = Path::new(&app_ctx.output_dir).join(part_entry.name() + ".bin");
|
||||
match decompress_lzhs_fs_file2file(&out_file, lzhs_out_path) {
|
||||
match decompress_mtk_to_file(&fin_data, &output_path) {
|
||||
Ok(()) => {
|
||||
println!("- Decompressed Successfully!");
|
||||
if !app_ctx.has_option("mtk_pkg:no_del_comp") {
|
||||
//after successfull decompression remove the temporary .lzhs file
|
||||
fs::remove_file(&output_path)?;
|
||||
}
|
||||
println!("-- Decompressed Successfully, Saved file!");
|
||||
continue
|
||||
},
|
||||
Err(e) => {
|
||||
eprintln!("Failed to decompress partition!, Error: {}. Saving compressed data...", e);
|
||||
//if the decompression is not successfull leave out compressed data.
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
let mut out_file = OpenOptions::new().write(true).create(true).open(&output_path)?;
|
||||
out_file.write_all(&fin_data)?;
|
||||
println!("-- Saved file!");
|
||||
|
||||
}
|
||||
|
||||
Ok(())
|
||||
|
||||
@@ -11,7 +11,7 @@ use crate::utils::common;
|
||||
use crate::utils::global::opt_dump_dec_hdr;
|
||||
use crate::utils::aes::{decrypt_aes128_cbc_nopad};
|
||||
use crate::keys;
|
||||
use crate::formats::mtk_pkg::lzhs::{decompress_lzhs_fs_file2file};
|
||||
use crate::formats::mtk_pkg::lzhs::{decompress_mtk_to_file};
|
||||
use crate::formats::mtk_pkg::include::{Header, PartEntry, MTK_HEADER_MAGIC, MTK_META_MAGIC, MTK_META_PAD_MAGIC};
|
||||
use include::*;
|
||||
|
||||
@@ -110,29 +110,25 @@ pub fn extract_mtk_pkg_new(app_ctx: &AppContext, ctx: Box<dyn Any>) -> Result<()
|
||||
0
|
||||
};
|
||||
|
||||
//for compressed part create temp file
|
||||
let output_path = Path::new(&app_ctx.output_dir).join(part_entry.name() + if part_entry.is_compressed() {".lzhs"} else {".bin"});
|
||||
let fin_data = &out_data[48 + extra_header_len as usize..];
|
||||
|
||||
let output_path = Path::new(&app_ctx.output_dir).join(format!("{}.bin", part_entry.name()));
|
||||
fs::create_dir_all(&app_ctx.output_dir)?;
|
||||
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(&app_ctx.output_dir).join(part_entry.name() + ".bin");
|
||||
match decompress_lzhs_fs_file2file(&out_file, lzhs_out_path) {
|
||||
match decompress_mtk_to_file(&fin_data, &output_path) {
|
||||
Ok(()) => {
|
||||
println!("-- Decompressed Successfully!");
|
||||
if !app_ctx.has_option("mtk_pkg:no_del_comp") {
|
||||
//after successfull decompression remove the temporary .lzhs file
|
||||
fs::remove_file(&output_path)?;
|
||||
}
|
||||
println!("-- Decompressed Successfully, Saved file!");
|
||||
continue
|
||||
},
|
||||
Err(e) => {
|
||||
eprintln!("Failed to decompress partition!, Error: {}. Saving compressed data...", e);
|
||||
//if the decompression is not successfull leave out compressed data.
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
let mut out_file = OpenOptions::new().write(true).create(true).open(&output_path)?;
|
||||
out_file.write_all(&fin_data)?;
|
||||
println!("-- Saved file!");
|
||||
}
|
||||
|
||||
|
||||
@@ -10,7 +10,7 @@ use binrw::BinReaderExt;
|
||||
|
||||
use crate::utils::common;
|
||||
use crate::utils::global::opt_dump_dec_hdr;
|
||||
use crate::formats::mtk_pkg::lzhs::{decompress_lzhs_fs_file2file_old};
|
||||
use crate::formats::mtk_pkg::lzhs::{decompress_mtk_to_file_old};
|
||||
use crate::formats::mtk_pkg::include::{PartEntry, MTK_HEADER_MAGIC, MTK_META_MAGIC, MTK_META_PAD_MAGIC};
|
||||
use mtk_crypto::{decrypt};
|
||||
use include::*;
|
||||
@@ -85,30 +85,25 @@ pub fn extract_mtk_pkg_old(app_ctx: &AppContext, ctx: Box<dyn Any>) -> Result<()
|
||||
} else {
|
||||
0
|
||||
};
|
||||
|
||||
//for compressed part create temp file
|
||||
let output_path = Path::new(&app_ctx.output_dir).join(part_entry.name() + if part_entry.is_compressed() {".lzhs"} else {".bin"});
|
||||
let fin_data = &out_data[extra_header_len as usize..];
|
||||
|
||||
let output_path = Path::new(&app_ctx.output_dir).join(format!("{}.bin", part_entry.name()));
|
||||
fs::create_dir_all(&app_ctx.output_dir)?;
|
||||
let mut out_file = OpenOptions::new().write(true).read(true)/* for lzhs */.create(true).open(&output_path)?;
|
||||
out_file.write_all(&out_data[extra_header_len as usize..])?;
|
||||
|
||||
if part_entry.is_compressed() {
|
||||
let lzhs_out_path = Path::new(&app_ctx.output_dir).join(part_entry.name() + ".bin");
|
||||
match decompress_lzhs_fs_file2file_old(&out_file, lzhs_out_path) {
|
||||
match decompress_mtk_to_file_old(&fin_data, &output_path) {
|
||||
Ok(()) => {
|
||||
println!("- Decompressed Successfully!");
|
||||
if !app_ctx.has_option("mtk_pkg:no_del_comp") {
|
||||
//after successfull decompression remove the temporary .lzhs file
|
||||
fs::remove_file(&output_path)?;
|
||||
}
|
||||
println!("-- Decompressed Successfully, Saved file!");
|
||||
continue
|
||||
},
|
||||
Err(e) => {
|
||||
eprintln!("Failed to decompress partition!, Error: {}. Saving compressed data...", e);
|
||||
//if the decompression is not successfull leave out compressed data.
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
let mut out_file = OpenOptions::new().write(true).create(true).open(&output_path)?;
|
||||
out_file.write_all(&fin_data)?;
|
||||
println!("-- Saved file!");
|
||||
}
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@ use std::any::Any;
|
||||
use crate::{AppContext, InputTarget};
|
||||
|
||||
use std::path::Path;
|
||||
use std::io::{Cursor, Write};
|
||||
use std::io::{Cursor, Seek, SeekFrom, Write};
|
||||
use std::fs::{self, File, OpenOptions};
|
||||
use binrw::BinReaderExt;
|
||||
|
||||
@@ -28,7 +28,7 @@ pub fn extract_pfl_upg(app_ctx: &AppContext, _ctx: Box<dyn Any>) -> Result<(), B
|
||||
let signature = common::read_exact(&mut file, 128)?;
|
||||
let _ = common::read_exact(&mut file, 32)?; //unknown
|
||||
|
||||
let version_bytes = common::read_exact(&mut file, header.header_size as usize - 704)?; //704 is base header size
|
||||
let version_bytes = common::read_exact(&mut file, 28)?;
|
||||
let version = common::string_from_bytes(&version_bytes);
|
||||
|
||||
println!("\nVersion: {}", version);
|
||||
@@ -38,6 +38,8 @@ pub fn extract_pfl_upg(app_ctx: &AppContext, _ctx: Box<dyn Any>) -> Result<(), B
|
||||
}
|
||||
println!("Data size: {}", header.data_size);
|
||||
|
||||
file.seek(SeekFrom::Start(header.header_size as u64))?;
|
||||
|
||||
let mut data;
|
||||
if header.is_encrypted() {
|
||||
println!("\nFile is encrypted.");
|
||||
|
||||
+7
-3
@@ -48,12 +48,16 @@ pub static RUF: &[(&str, &str)] = &[
|
||||
|
||||
//pfl upg pubkeys
|
||||
pub static PFLUPG: &[(&str, &str)] = &[
|
||||
("TV520_1", "C41BE92C212BAC76B48261E2A1704028287DD7E121C11DA25F709E864FBDC1BD8C7F226F57605A4B42D768CDD629AF9E54011A0967AFC2826331406FB1E90321620738526EA0BEA59F1A0E612AE891C396112F13531F423DF02F94D1C871429549F4D5B30D9CA3EFDCC6D7A96849F7C1788DE8FAAEDD36560337008DF06D612F"),
|
||||
("TV520_2", "AFAF89062747CBB29343C4E4EA775E4CFDF5FAFCD92C9DD858A8725201BA54AB973BEFEE04EBF3046910FBBC78B10120AE16D80BA734931E97248BC6B1D4A909F087D37BC0A9C2210FF8A2BE44C00F31E4DD8713A364623637FF75EBBCE9D3A840DB67E0FA910F127F679496F6C21112E3E3AD4ACA459FDE1CC58E300682E6F9"),
|
||||
("TV520_1", "AFAF89062747CBB29343C4E4EA775E4CFDF5FAFCD92C9DD858A8725201BA54AB973BEFEE04EBF3046910FBBC78B10120AE16D80BA734931E97248BC6B1D4A909F087D37BC0A9C2210FF8A2BE44C00F31E4DD8713A364623637FF75EBBCE9D3A840DB67E0FA910F127F679496F6C21112E3E3AD4ACA459FDE1CC58E300682E6F9"),
|
||||
("TV520_2", "C41BE92C212BAC76B48261E2A1704028287DD7E121C11DA25F709E864FBDC1BD8C7F226F57605A4B42D768CDD629AF9E54011A0967AFC2826331406FB1E90321620738526EA0BEA59F1A0E612AE891C396112F13531F423DF02F94D1C871429549F4D5B30D9CA3EFDCC6D7A96849F7C1788DE8FAAEDD36560337008DF06D612F"),
|
||||
|
||||
("TV543_Q543", "C5FD937B301A5CEF4B6C25F187728C99636515D058895FEA469496E2B24907FC7721648841F8AE4C618E215673D0C029752FA970B6F9A7F48C9331293D3B1D43E4DFC7B52914973642CD3E4EE0AD11F5254505038F95CACE0DF21FC769B34E134435D88AB617D2981F66EF45BBC7796CFB1086C5D5672E837204991FE53BC1CF"),
|
||||
("TV543_Q548", "9E7DA389815251E82A84A1182807702E72A0B0E0FF707C8E73E2EA71F79D5FAAFFC6E0B90ED16E13A4289C78A7D3BDA90626162AAE169D7BE28D6A635585CC10639C4E312E288EB8F7C5A44518B7E8A26A45C5023C5078A972A4CC219CA020BAF524F7429257B7AD76E1B15390879064C6ED59CC1F20CC04EEC26C9CF7FC0727"),
|
||||
("TV543_Q549", "F28ED197C5C40B7F7356D4EDD5526BC238C812EB59400087BBA2D6402B41BBE695EAAE5F6051F1B5EBAC1756F17FED9DA0678F2E6EE59ABF530847DB9249DD025D00FFC67B2ECFF320E99F5DA8A46B1E41479BA3B5CDC110D247B7AF31E887463C8E7A9929BE511C724FB7B4BACBF055F276ED53687E24543815D5437405B0CB"),
|
||||
("TV550", "D7EE8ED11AC048ED225D4F5F53F8509E55C5D94256A703C79E4CA78AE93ECE1639FE466363AD962BD6D6DE0C46FD19F363687C1D8A21820740A6E7FF87F41C4900DCE1E26EC122E5D4DFA76BFC8F296816B8D0910325E9DC5CBCC9579CF15FC0253EF7CF4919B7613491A5D7BF75DC1888531C458967FD1CF64B33139550BAA5"),
|
||||
|
||||
("TV550_Q552", "DEA689548D2C3542E1395063B9ED14F2A779B34237265E408B43DDBD57FC86260B7865C6BFA3A5F7D249F6BC82B5D8BD0FA31C8C094D3376241ADE1BD81D26354A4366F170073588BA23676CC7DCCD686C91C99C38290E2D27DA4BAE7E49FA3665DF2895D0BF81824287EDF131771E73380F45A4F6C5FF1C669154A6DD063BEB"),
|
||||
("TV550_Q555", "D7EE8ED11AC048ED225D4F5F53F8509E55C5D94256A703C79E4CA78AE93ECE1639FE466363AD962BD6D6DE0C46FD19F363687C1D8A21820740A6E7FF87F41C4900DCE1E26EC122E5D4DFA76BFC8F296816B8D0910325E9DC5CBCC9579CF15FC0253EF7CF4919B7613491A5D7BF75DC1888531C458967FD1CF64B33139550BAA5"),
|
||||
|
||||
("Fusion", "ACD684155C7CCCB04372A8808514489FA9EE75D305987D1337420241FDBE0AE1F7CDFBB931C9D56C91D36F2CE79D222695B484FF42BCA12CE362C7C9ABBDEEC8E5D6107FADCF2D4DA5DF0693E13ACE54A18AEB21C051F6B62C075A1791985547C1CFF4FB5B6EA7E0A9405A1B2BB71EB89A9B209E0F62BF9794D673179C0E60F1"),
|
||||
|
||||
//sony
|
||||
|
||||
@@ -6,6 +6,7 @@ use lzma_rs::lzma_decompress;
|
||||
use lz4::block::decompress;
|
||||
use bzip2::read::BzDecoder;
|
||||
use liblzma::read::XzDecoder;
|
||||
use zstd::stream::read::Decoder;
|
||||
|
||||
use crate::utils::common;
|
||||
|
||||
@@ -65,4 +66,11 @@ pub fn decompress_xz(compressed: &[u8]) -> std::io::Result<Vec<u8>> {
|
||||
let mut decompressed = Vec::new();
|
||||
decoder.read_to_end(&mut decompressed)?;
|
||||
Ok(decompressed)
|
||||
}
|
||||
|
||||
pub fn decompress_zstd(compressed: &[u8]) -> io::Result<Vec<u8>> {
|
||||
let mut decoder = Decoder::new(compressed)?;
|
||||
let mut output = Vec::new();
|
||||
decoder.read_to_end(&mut output)?;
|
||||
Ok(output)
|
||||
}
|
||||
Reference in New Issue
Block a user