mirror of
https://github.com/Ap0dexMe0/unixtract.git
synced 2026-07-15 21:00:03 +02:00
Add Android OTA payload extractor
This commit is contained in:
Generated
+144
-1
@@ -69,6 +69,12 @@ dependencies = [
|
||||
"windows-sys",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "anyhow"
|
||||
version = "1.0.100"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a23eb6b1614318a8071c9b2521f36b424b2c83db5eb3a0fead4a6c0809af6e61"
|
||||
|
||||
[[package]]
|
||||
name = "array-init"
|
||||
version = "2.1.0"
|
||||
@@ -147,6 +153,21 @@ version = "1.5.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b"
|
||||
|
||||
[[package]]
|
||||
name = "bytes"
|
||||
version = "1.11.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b35204fbdc0b3f4446b89fc1ac2cf84a8a68971995d0bf2e925ec7cd960f9cb3"
|
||||
|
||||
[[package]]
|
||||
name = "bzip2"
|
||||
version = "0.6.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f3a53fac24f34a81bc9954b5d6cfce0c21e18ec6959f44f56e8e90e4bb7c346c"
|
||||
dependencies = [
|
||||
"libbz2-rs-sys",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "cbc"
|
||||
version = "0.1.2"
|
||||
@@ -163,6 +184,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5252b3d2648e5eedbc1a6f501e3c795e07025c1e93bbf8bbdd6eef7f447a6d54"
|
||||
dependencies = [
|
||||
"find-msvc-tools",
|
||||
"jobserver",
|
||||
"libc",
|
||||
"shlex",
|
||||
]
|
||||
|
||||
@@ -373,6 +396,18 @@ dependencies = [
|
||||
"wasi",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "getrandom"
|
||||
version = "0.3.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "899def5c37c4fd7b2664648c28120ecec138e4d395b459e5ca34f9cce2dd77fd"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"libc",
|
||||
"r-efi",
|
||||
"wasip2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "heck"
|
||||
version = "0.5.0"
|
||||
@@ -401,6 +436,25 @@ version = "1.70.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7943c866cc5cd64cbc25b2e01621d07fa8eb2a1a23160ee81ce38704e97b8ecf"
|
||||
|
||||
[[package]]
|
||||
name = "itertools"
|
||||
version = "0.14.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2b192c782037fadd9cfa75548310488aabdbf3d2da73885b31bd0abd03351285"
|
||||
dependencies = [
|
||||
"either",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "jobserver"
|
||||
version = "0.1.34"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9afb3de4395d6b3e67a780b6de64b51c978ecf11cb9a462c66be7d4ca9039d33"
|
||||
dependencies = [
|
||||
"getrandom 0.3.4",
|
||||
"libc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "lazy_static"
|
||||
version = "1.5.0"
|
||||
@@ -410,12 +464,38 @@ dependencies = [
|
||||
"spin",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "libbz2-rs-sys"
|
||||
version = "0.2.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2c4a545a15244c7d945065b5d392b2d2d7f21526fba56ce51467b06ed445e8f7"
|
||||
|
||||
[[package]]
|
||||
name = "libc"
|
||||
version = "0.2.175"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6a82ae493e598baaea5209805c49bbf2ea7de956d50d7da0da1164f9c6d28543"
|
||||
|
||||
[[package]]
|
||||
name = "liblzma"
|
||||
version = "0.4.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "73c36d08cad03a3fbe2c4e7bb3a9e84c57e4ee4135ed0b065cade3d98480c648"
|
||||
dependencies = [
|
||||
"liblzma-sys",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "liblzma-sys"
|
||||
version = "0.4.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "01b9596486f6d60c3bbe644c0e1be1aa6ccc472ad630fe8927b456973d7cb736"
|
||||
dependencies = [
|
||||
"cc",
|
||||
"libc",
|
||||
"pkg-config",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "libm"
|
||||
version = "0.2.15"
|
||||
@@ -582,6 +662,12 @@ dependencies = [
|
||||
"spki",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "pkg-config"
|
||||
version = "0.3.32"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7edddbd0b52d732b21ad9a5fab5c704c14cd949e5e9a1ec5929a24fded1b904c"
|
||||
|
||||
[[package]]
|
||||
name = "ppv-lite86"
|
||||
version = "0.2.21"
|
||||
@@ -600,6 +686,38 @@ dependencies = [
|
||||
"unicode-ident",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "prost"
|
||||
version = "0.14.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7231bd9b3d3d33c86b58adbac74b5ec0ad9f496b19d22801d773636feaa95f3d"
|
||||
dependencies = [
|
||||
"bytes",
|
||||
"prost-derive",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "prost-derive"
|
||||
version = "0.14.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9120690fafc389a67ba3803df527d0ec9cbbc9cc45e4cc20b332996dfb672425"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"itertools",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "prost-types"
|
||||
version = "0.14.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b9b4db3d6da204ed77bb26ba83b6122a73aeb2e87e25fbf7ad2e84c4ccbf8f72"
|
||||
dependencies = [
|
||||
"prost",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "quote"
|
||||
version = "1.0.40"
|
||||
@@ -609,6 +727,12 @@ dependencies = [
|
||||
"proc-macro2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "r-efi"
|
||||
version = "5.3.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "69cdb34c158ceb288df11e18b4bd39de994f6657d83847bdffdbd7f346754b0f"
|
||||
|
||||
[[package]]
|
||||
name = "rand"
|
||||
version = "0.8.5"
|
||||
@@ -635,7 +759,7 @@ version = "0.6.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c"
|
||||
dependencies = [
|
||||
"getrandom",
|
||||
"getrandom 0.2.16",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -787,15 +911,19 @@ version = "0.1.0"
|
||||
dependencies = [
|
||||
"aes",
|
||||
"binrw",
|
||||
"bzip2",
|
||||
"cbc",
|
||||
"clap",
|
||||
"ecb",
|
||||
"flate2",
|
||||
"hex",
|
||||
"liblzma",
|
||||
"lz4",
|
||||
"lzma-rs",
|
||||
"md5",
|
||||
"minilzo-rs",
|
||||
"prost",
|
||||
"prost-types",
|
||||
"rsa",
|
||||
"sha1",
|
||||
"simd-adler32",
|
||||
@@ -820,6 +948,15 @@ version = "0.11.1+wasi-snapshot-preview1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ccf3ec651a847eb01de73ccad15eb7d99f80485de043efb2f370cd654f4ea44b"
|
||||
|
||||
[[package]]
|
||||
name = "wasip2"
|
||||
version = "1.0.1+wasi-0.2.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0562428422c63773dad2c345a1882263bbf4d65cf3f42e90921f787ef5ad58e7"
|
||||
dependencies = [
|
||||
"wit-bindgen",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows-link"
|
||||
version = "0.1.3"
|
||||
@@ -900,6 +1037,12 @@ version = "0.53.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "271414315aff87387382ec3d271b52d7ae78726f5d44ac98b4f4030c91880486"
|
||||
|
||||
[[package]]
|
||||
name = "wit-bindgen"
|
||||
version = "0.46.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f17a85883d4e6d00e8a97c586de764dabcc06133f7f1d55dce5cdc070ad7fe59"
|
||||
|
||||
[[package]]
|
||||
name = "xattr"
|
||||
version = "1.6.1"
|
||||
|
||||
+5
-1
@@ -18,4 +18,8 @@ ecb = "0.1.2"
|
||||
tar = "0.4.44"
|
||||
binrw = "0.15"
|
||||
simd-adler32 = "*"
|
||||
minilzo-rs = "0.6.1"
|
||||
minilzo-rs = "0.6.1"
|
||||
prost = "0.14.1"
|
||||
prost-types = "0.14.1"
|
||||
bzip2 = "0.6.1"
|
||||
liblzma = "0.4.5"
|
||||
+26
@@ -0,0 +1,26 @@
|
||||
| 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 |
|
||||
| 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 | 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 |
|
||||
| Mediatek upgrade_loader | Older Mediatek-based TVs | All files should be supported providing they are not encrypted | - |
|
||||
| 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 |
|
||||
@@ -12,6 +12,7 @@ pub mod sony_bdp;
|
||||
pub mod rvp;
|
||||
pub mod funai_upg;
|
||||
pub mod pana_dvd;
|
||||
pub mod android_ota_payload;
|
||||
|
||||
pub mod pup;
|
||||
|
||||
|
||||
@@ -0,0 +1,89 @@
|
||||
use std::fs::{self, File, OpenOptions};
|
||||
use std::path::{Path};
|
||||
use std::io::{Write};
|
||||
use binrw::{BinRead, BinReaderExt};
|
||||
use prost::Message;
|
||||
|
||||
use crate::utils::common;
|
||||
use crate::utils::android_ota_update_metadata::{DeltaArchiveManifest, install_operation};
|
||||
use crate::utils::compression::{decompress_bzip, decompress_xz};
|
||||
|
||||
#[derive(BinRead)]
|
||||
struct Header {
|
||||
#[br(count = 4)] _magic_bytes: Vec<u8>, //CrAU
|
||||
file_format_version: u64,
|
||||
manifest_size: u64,
|
||||
metadata_signature_size: u32,
|
||||
}
|
||||
|
||||
pub fn is_android_ota_payload_file(file: &File) -> bool {
|
||||
let header = common::read_file(&file, 0, 4).expect("Failed to read from file.");
|
||||
if header == b"CrAU" {
|
||||
true
|
||||
} else {
|
||||
false
|
||||
}
|
||||
}
|
||||
|
||||
pub fn extract_android_ota_payload(mut file: &File, output_folder: &str) -> Result<(), Box<dyn std::error::Error>> {
|
||||
let header: Header = file.read_be()?;
|
||||
println!("File info:\nFormat version: {}\nManifest size: {}", header.file_format_version, header.manifest_size);
|
||||
|
||||
if header.file_format_version != 2 {
|
||||
println!("\nSorry, this version of the file is not supported!");
|
||||
return Ok(())
|
||||
}
|
||||
|
||||
let base_offset = 24 /* size of header */ + header.manifest_size + header.metadata_signature_size as u64;
|
||||
|
||||
let read_manifest = common::read_exact(&mut file, header.manifest_size as usize)?;
|
||||
let manifest = DeltaArchiveManifest::decode(&*read_manifest)?;
|
||||
|
||||
for (i, partition) in manifest.partitions.into_iter().enumerate() {
|
||||
let operation_count = partition.operations.len();
|
||||
println!("\n#{} - {}, Size: {}, Operations: {}",
|
||||
i + 1, partition.partition_name, partition.new_partition_info.unwrap().size.unwrap(), operation_count);
|
||||
|
||||
for (i, operation) in partition.operations.into_iter().enumerate() {
|
||||
let operation_name_str = match install_operation::Type::try_from(operation.r#type) {
|
||||
Ok(t) => t.as_str_name(),
|
||||
Err(_) => "UNKNOWN",
|
||||
};
|
||||
|
||||
let offset = base_offset + operation.data_offset.unwrap();
|
||||
let size = operation.data_length.unwrap();
|
||||
|
||||
//because the amount of operations can reach up to the thousands, i think its best to update the current line
|
||||
//to not clog up the terminal and so you know what the program is actually doing
|
||||
print!("\r- ({}/{}) - {}({}), Offset: {}, Size: {}",
|
||||
i + 1, operation_count, operation_name_str, operation.r#type, offset, size);
|
||||
std::io::stdout().flush()?;
|
||||
|
||||
let data = common::read_file(&file, offset, size as usize)?;
|
||||
|
||||
let out_data;
|
||||
if operation.r#type == 0 { //REPLACE - just write the stored data
|
||||
out_data = data;
|
||||
}
|
||||
else if operation.r#type == 1 { //REPLACE_BZ - decompress with bzip and write
|
||||
out_data = decompress_bzip(&data)?;
|
||||
}
|
||||
else if operation.r#type == 8 { //REPLACE_XZ - decompress with xz and write
|
||||
out_data = decompress_xz(&data)?;
|
||||
} else {
|
||||
println!("-- Unsupported operation!");
|
||||
break
|
||||
}
|
||||
|
||||
fs::create_dir_all(&output_folder)?;
|
||||
let output_path = Path::new(&output_folder).join(format!("{}.bin", partition.partition_name));
|
||||
let mut out_file = OpenOptions::new().append(true).create(true).open(output_path)?;
|
||||
out_file.write_all(&out_data)?;
|
||||
}
|
||||
println!("\n-- Saved!");
|
||||
}
|
||||
|
||||
println!("\nExtraction finished!");
|
||||
|
||||
Ok(())
|
||||
}
|
||||
+5
-1
@@ -69,7 +69,11 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {
|
||||
else if formats::nvt_timg::is_nvt_timg_file(&file) {
|
||||
println!("Novatek TIMG file detected!");
|
||||
formats::nvt_timg::extract_nvt_timg(&file, &output_path)?;
|
||||
}
|
||||
}
|
||||
if formats::android_ota_payload::is_android_ota_payload_file(&file) {
|
||||
println!("Android OTA payload file detected!");
|
||||
formats::android_ota_payload::extract_android_ota_payload(&file, &output_path)?;
|
||||
}
|
||||
else if formats::novatek::is_novatek_file(&file) {
|
||||
println!("Novatek file detected!");
|
||||
formats::novatek::extract_novatek(&file, &output_path)?;
|
||||
|
||||
+2
-1
@@ -4,4 +4,5 @@ pub mod pana_dvd_crypto;
|
||||
pub mod lzss;
|
||||
pub mod lzop;
|
||||
pub mod sparse;
|
||||
pub mod compression;
|
||||
pub mod compression;
|
||||
pub mod android_ota_update_metadata;
|
||||
@@ -0,0 +1,471 @@
|
||||
// This file is @generated by prost-build.
|
||||
/// Data is packed into blocks on disk, always starting from the beginning
|
||||
/// of the block. If a file's data is too large for one block, it overflows
|
||||
/// into another block, which may or may not be the following block on the
|
||||
/// physical partition. An ordered list of extents is another
|
||||
/// representation of an ordered list of blocks. For example, a file stored
|
||||
/// in blocks 9, 10, 11, 2, 18, 12 (in that order) would be stored in
|
||||
/// extents { {9, 3}, {2, 1}, {18, 1}, {12, 1} } (in that order).
|
||||
/// In general, files are stored sequentially on disk, so it's more efficient
|
||||
/// to use extents to encode the block lists (this is effectively
|
||||
/// run-length encoding).
|
||||
/// A sentinel value (kuint64max) as the start block denotes a sparse-hole
|
||||
/// in a file whose block-length is specified by num_blocks.
|
||||
#[derive(Clone, Copy, PartialEq, ::prost::Message)]
|
||||
pub struct Extent {
|
||||
#[prost(uint64, optional, tag = "1")]
|
||||
pub start_block: ::core::option::Option<u64>,
|
||||
#[prost(uint64, optional, tag = "2")]
|
||||
pub num_blocks: ::core::option::Option<u64>,
|
||||
}
|
||||
/// Signatures: Updates may be signed by the OS vendor. The client verifies
|
||||
/// an update's signature by hashing the entire download. The section of the
|
||||
/// download that contains the signature is at the end of the file, so when
|
||||
/// signing a file, only the part up to the signature part is signed.
|
||||
/// Then, the client looks inside the download's Signatures message for a
|
||||
/// Signature message that it knows how to handle. Generally, a client will
|
||||
/// only know how to handle one type of signature, but an update may contain
|
||||
/// many signatures to support many different types of client. Then client
|
||||
/// selects a Signature message and uses that, along with a known public key,
|
||||
/// to verify the download. The public key is expected to be part of the
|
||||
/// client.
|
||||
// -- Added by me , struct Signatures is unused --
|
||||
//#[derive(Clone, PartialEq, ::prost::Message)]
|
||||
//pub struct Signatures {
|
||||
// #[prost(message, repeated, tag = "1")]
|
||||
// pub signatures: ::prost::alloc::vec::Vec<signatures::Signature>,
|
||||
//}
|
||||
/// Nested message and enum types in `Signatures`.
|
||||
pub mod signatures {
|
||||
#[derive(Clone, PartialEq, ::prost::Message)]
|
||||
pub struct Signature {
|
||||
#[deprecated]
|
||||
#[prost(uint32, optional, tag = "1")]
|
||||
pub version: ::core::option::Option<u32>,
|
||||
#[prost(bytes = "vec", optional, tag = "2")]
|
||||
pub data: ::core::option::Option<::prost::alloc::vec::Vec<u8>>,
|
||||
/// The DER encoded signature size of EC keys is nondeterministic for
|
||||
/// different input of sha256 hash. However, we need the size of the
|
||||
/// serialized signatures protobuf string to be fixed before signing;
|
||||
/// because this size is part of the content to be signed. Therefore, we
|
||||
/// always pad the signature data to the maximum possible signature size of
|
||||
/// a given key. And the payload verifier will truncate the signature to
|
||||
/// its correct size based on the value of |unpadded_signature_size|.
|
||||
#[prost(fixed32, optional, tag = "3")]
|
||||
pub unpadded_signature_size: ::core::option::Option<u32>,
|
||||
}
|
||||
}
|
||||
#[derive(Clone, PartialEq, ::prost::Message)]
|
||||
pub struct PartitionInfo {
|
||||
#[prost(uint64, optional, tag = "1")]
|
||||
pub size: ::core::option::Option<u64>,
|
||||
#[prost(bytes = "vec", optional, tag = "2")]
|
||||
pub hash: ::core::option::Option<::prost::alloc::vec::Vec<u8>>,
|
||||
}
|
||||
#[derive(Clone, PartialEq, ::prost::Message)]
|
||||
pub struct InstallOperation {
|
||||
#[prost(enumeration = "install_operation::Type", required, tag = "1")]
|
||||
pub r#type: i32,
|
||||
/// Only minor version 6 or newer support 64 bits |data_offset| and
|
||||
/// |data_length|, older client will read them as uint32.
|
||||
/// The offset into the delta file (after the protobuf)
|
||||
/// where the data (if any) is stored
|
||||
#[prost(uint64, optional, tag = "2")]
|
||||
pub data_offset: ::core::option::Option<u64>,
|
||||
/// The length of the data in the delta file
|
||||
#[prost(uint64, optional, tag = "3")]
|
||||
pub data_length: ::core::option::Option<u64>,
|
||||
/// Ordered list of extents that are read from (if any) and written to.
|
||||
#[prost(message, repeated, tag = "4")]
|
||||
pub src_extents: ::prost::alloc::vec::Vec<Extent>,
|
||||
/// Byte length of src, equal to the number of blocks in src_extents *
|
||||
/// block_size. It is used for BSDIFF and SOURCE_BSDIFF, because we need to
|
||||
/// pass that external program the number of bytes to read from the blocks we
|
||||
/// pass it. This is not used in any other operation.
|
||||
#[prost(uint64, optional, tag = "5")]
|
||||
pub src_length: ::core::option::Option<u64>,
|
||||
#[prost(message, repeated, tag = "6")]
|
||||
pub dst_extents: ::prost::alloc::vec::Vec<Extent>,
|
||||
/// Byte length of dst, equal to the number of blocks in dst_extents *
|
||||
/// block_size. Used for BSDIFF and SOURCE_BSDIFF, but not in any other
|
||||
/// operation.
|
||||
#[prost(uint64, optional, tag = "7")]
|
||||
pub dst_length: ::core::option::Option<u64>,
|
||||
/// Optional SHA 256 hash of the blob associated with this operation.
|
||||
/// This is used as a primary validation for http-based downloads and
|
||||
/// as a defense-in-depth validation for https-based downloads. If
|
||||
/// the operation doesn't refer to any blob, this field will have
|
||||
/// zero bytes.
|
||||
#[prost(bytes = "vec", optional, tag = "8")]
|
||||
pub data_sha256_hash: ::core::option::Option<::prost::alloc::vec::Vec<u8>>,
|
||||
/// Indicates the SHA 256 hash of the source data referenced in src_extents at
|
||||
/// the time of applying the operation. If present, the update_engine daemon
|
||||
/// MUST read and verify the source data before applying the operation.
|
||||
#[prost(bytes = "vec", optional, tag = "9")]
|
||||
pub src_sha256_hash: ::core::option::Option<::prost::alloc::vec::Vec<u8>>,
|
||||
}
|
||||
/// Nested message and enum types in `InstallOperation`.
|
||||
pub mod install_operation {
|
||||
#[derive(
|
||||
Clone,
|
||||
Copy,
|
||||
Debug,
|
||||
PartialEq,
|
||||
Eq,
|
||||
Hash,
|
||||
PartialOrd,
|
||||
Ord,
|
||||
::prost::Enumeration
|
||||
)]
|
||||
#[repr(i32)]
|
||||
pub enum Type {
|
||||
/// Replace destination extents w/ attached data.
|
||||
Replace = 0,
|
||||
/// Replace destination extents w/ attached bzipped data.
|
||||
ReplaceBz = 1,
|
||||
/// Move source extents to target extents.
|
||||
Move = 2,
|
||||
/// The data is a bsdiff binary diff.
|
||||
Bsdiff = 3,
|
||||
/// On minor version 2 or newer, these operations are supported:
|
||||
///
|
||||
/// Copy from source to target partition
|
||||
SourceCopy = 4,
|
||||
/// Like BSDIFF, but read from source partition
|
||||
SourceBsdiff = 5,
|
||||
/// On minor version 3 or newer and on major version 2 or newer, these
|
||||
/// operations are supported:
|
||||
///
|
||||
/// Replace destination extents w/ attached xz data.
|
||||
ReplaceXz = 8,
|
||||
/// On minor version 4 or newer, these operations are supported:
|
||||
///
|
||||
/// Write zeros in the destination.
|
||||
Zero = 6,
|
||||
/// Discard the destination blocks, reading as undefined.
|
||||
Discard = 7,
|
||||
/// Like SOURCE_BSDIFF, but compressed with brotli.
|
||||
BrotliBsdiff = 10,
|
||||
/// On minor version 5 or newer, these operations are supported:
|
||||
///
|
||||
/// The data is in puffdiff format.
|
||||
Puffdiff = 9,
|
||||
/// On minor version 8 or newer, these operations are supported:
|
||||
Zucchini = 11,
|
||||
/// On minor version 9 or newer, these operations are supported:
|
||||
Lz4diffBsdiff = 12,
|
||||
Lz4diffPuffdiff = 13,
|
||||
/// This is not part of the original spec, but is currently in use for some
|
||||
/// types of payloads.
|
||||
///
|
||||
/// Replace destination extents w/ attached zstd data.
|
||||
ReplaceZstd = 14,
|
||||
}
|
||||
impl Type {
|
||||
/// String value of the enum field names used in the ProtoBuf definition.
|
||||
///
|
||||
/// The values are not transformed in any way and thus are considered stable
|
||||
/// (if the ProtoBuf definition does not change) and safe for programmatic use.
|
||||
pub fn as_str_name(&self) -> &'static str {
|
||||
match self {
|
||||
Self::Replace => "REPLACE",
|
||||
Self::ReplaceBz => "REPLACE_BZ",
|
||||
Self::Move => "MOVE",
|
||||
Self::Bsdiff => "BSDIFF",
|
||||
Self::SourceCopy => "SOURCE_COPY",
|
||||
Self::SourceBsdiff => "SOURCE_BSDIFF",
|
||||
Self::ReplaceXz => "REPLACE_XZ",
|
||||
Self::Zero => "ZERO",
|
||||
Self::Discard => "DISCARD",
|
||||
Self::BrotliBsdiff => "BROTLI_BSDIFF",
|
||||
Self::Puffdiff => "PUFFDIFF",
|
||||
Self::Zucchini => "ZUCCHINI",
|
||||
Self::Lz4diffBsdiff => "LZ4DIFF_BSDIFF",
|
||||
Self::Lz4diffPuffdiff => "LZ4DIFF_PUFFDIFF",
|
||||
Self::ReplaceZstd => "REPLACE_ZSTD",
|
||||
}
|
||||
}
|
||||
/// Creates an enum from field names used in the ProtoBuf definition.
|
||||
pub fn from_str_name(value: &str) -> ::core::option::Option<Self> {
|
||||
match value {
|
||||
"REPLACE" => Some(Self::Replace),
|
||||
"REPLACE_BZ" => Some(Self::ReplaceBz),
|
||||
"MOVE" => Some(Self::Move),
|
||||
"BSDIFF" => Some(Self::Bsdiff),
|
||||
"SOURCE_COPY" => Some(Self::SourceCopy),
|
||||
"SOURCE_BSDIFF" => Some(Self::SourceBsdiff),
|
||||
"REPLACE_XZ" => Some(Self::ReplaceXz),
|
||||
"ZERO" => Some(Self::Zero),
|
||||
"DISCARD" => Some(Self::Discard),
|
||||
"BROTLI_BSDIFF" => Some(Self::BrotliBsdiff),
|
||||
"PUFFDIFF" => Some(Self::Puffdiff),
|
||||
"ZUCCHINI" => Some(Self::Zucchini),
|
||||
"LZ4DIFF_BSDIFF" => Some(Self::Lz4diffBsdiff),
|
||||
"LZ4DIFF_PUFFDIFF" => Some(Self::Lz4diffPuffdiff),
|
||||
"REPLACE_ZSTD" => Some(Self::ReplaceZstd),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
/// Hints to VAB snapshot to skip writing some blocks if these blocks are
|
||||
/// identical to the ones on the source image. The src & dst extents for each
|
||||
/// CowMergeOperation should be contiguous, and they're a subset of an OTA
|
||||
/// InstallOperation.
|
||||
/// During merge time, we need to follow the pre-computed sequence to avoid
|
||||
/// read after write, similar to the inplace update schema.
|
||||
#[derive(Clone, Copy, PartialEq, ::prost::Message)]
|
||||
pub struct CowMergeOperation {
|
||||
#[prost(enumeration = "cow_merge_operation::Type", optional, tag = "1")]
|
||||
pub r#type: ::core::option::Option<i32>,
|
||||
#[prost(message, optional, tag = "2")]
|
||||
pub src_extent: ::core::option::Option<Extent>,
|
||||
#[prost(message, optional, tag = "3")]
|
||||
pub dst_extent: ::core::option::Option<Extent>,
|
||||
/// For COW_XOR, source location might be unaligned, so this field is in range
|
||||
/// [0, block_size), representing how much should the src_extent shift toward
|
||||
/// larger block number. If this field is non-zero, then src_extent will
|
||||
/// include 1 extra block in the end, as the merge op actually references the
|
||||
/// first |src_offset| bytes of that extra block. For example, if |dst_extent|
|
||||
/// is \[10, 15\], |src_offset| is 500, then src_extent might look like \[25, 31\].
|
||||
/// Note that |src_extent| contains 1 extra block than the |dst_extent|.
|
||||
#[prost(uint32, optional, tag = "4")]
|
||||
pub src_offset: ::core::option::Option<u32>,
|
||||
}
|
||||
/// Nested message and enum types in `CowMergeOperation`.
|
||||
pub mod cow_merge_operation {
|
||||
#[derive(
|
||||
Clone,
|
||||
Copy,
|
||||
Debug,
|
||||
PartialEq,
|
||||
Eq,
|
||||
Hash,
|
||||
PartialOrd,
|
||||
Ord,
|
||||
::prost::Enumeration
|
||||
)]
|
||||
#[repr(i32)]
|
||||
pub enum Type {
|
||||
/// identical blocks
|
||||
CowCopy = 0,
|
||||
/// used when src/dst blocks are highly similar
|
||||
CowXor = 1,
|
||||
/// Raw replace operation
|
||||
CowReplace = 2,
|
||||
}
|
||||
impl Type {
|
||||
/// String value of the enum field names used in the ProtoBuf definition.
|
||||
///
|
||||
/// The values are not transformed in any way and thus are considered stable
|
||||
/// (if the ProtoBuf definition does not change) and safe for programmatic use.
|
||||
pub fn as_str_name(&self) -> &'static str {
|
||||
match self {
|
||||
Self::CowCopy => "COW_COPY",
|
||||
Self::CowXor => "COW_XOR",
|
||||
Self::CowReplace => "COW_REPLACE",
|
||||
}
|
||||
}
|
||||
/// Creates an enum from field names used in the ProtoBuf definition.
|
||||
pub fn from_str_name(value: &str) -> ::core::option::Option<Self> {
|
||||
match value {
|
||||
"COW_COPY" => Some(Self::CowCopy),
|
||||
"COW_XOR" => Some(Self::CowXor),
|
||||
"COW_REPLACE" => Some(Self::CowReplace),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
/// Describes the update to apply to a single partition.
|
||||
#[derive(Clone, PartialEq, ::prost::Message)]
|
||||
pub struct PartitionUpdate {
|
||||
/// A platform-specific name to identify the partition set being updated. For
|
||||
/// example, in Chrome OS this could be "ROOT" or "KERNEL".
|
||||
#[prost(string, required, tag = "1")]
|
||||
pub partition_name: ::prost::alloc::string::String,
|
||||
/// Whether this partition carries a filesystem with post-install program that
|
||||
/// must be run to finalize the update process. See also |postinstall_path| and
|
||||
/// |filesystem_type|.
|
||||
#[prost(bool, optional, tag = "2")]
|
||||
pub run_postinstall: ::core::option::Option<bool>,
|
||||
/// The path of the executable program to run during the post-install step,
|
||||
/// relative to the root of this filesystem. If not set, the default "postinst"
|
||||
/// will be used. This setting is only used when |run_postinstall| is set and
|
||||
/// true.
|
||||
#[prost(string, optional, tag = "3")]
|
||||
pub postinstall_path: ::core::option::Option<::prost::alloc::string::String>,
|
||||
/// The filesystem type as passed to the mount(2) syscall when mounting the new
|
||||
/// filesystem to run the post-install program. If not set, a fixed list of
|
||||
/// filesystems will be attempted. This setting is only used if
|
||||
/// |run_postinstall| is set and true.
|
||||
#[prost(string, optional, tag = "4")]
|
||||
pub filesystem_type: ::core::option::Option<::prost::alloc::string::String>,
|
||||
/// If present, a list of signatures of the new_partition_info.hash signed with
|
||||
/// different keys. If the update_engine daemon requires vendor-signed images
|
||||
/// and has its public key installed, one of the signatures should be valid
|
||||
/// for /postinstall to run.
|
||||
#[prost(message, repeated, tag = "5")]
|
||||
pub new_partition_signature: ::prost::alloc::vec::Vec<signatures::Signature>,
|
||||
#[prost(message, optional, tag = "6")]
|
||||
pub old_partition_info: ::core::option::Option<PartitionInfo>,
|
||||
#[prost(message, optional, tag = "7")]
|
||||
pub new_partition_info: ::core::option::Option<PartitionInfo>,
|
||||
/// The list of operations to be performed to apply this PartitionUpdate. The
|
||||
/// associated operation blobs (in operations\[i\].data_offset, data_length)
|
||||
/// should be stored contiguously and in the same order.
|
||||
#[prost(message, repeated, tag = "8")]
|
||||
pub operations: ::prost::alloc::vec::Vec<InstallOperation>,
|
||||
/// Whether a failure in the postinstall step for this partition should be
|
||||
/// ignored.
|
||||
#[prost(bool, optional, tag = "9")]
|
||||
pub postinstall_optional: ::core::option::Option<bool>,
|
||||
/// On minor version 6 or newer, these fields are supported:
|
||||
/// The extent for data covered by verity hash tree.
|
||||
#[prost(message, optional, tag = "10")]
|
||||
pub hash_tree_data_extent: ::core::option::Option<Extent>,
|
||||
/// The extent to store verity hash tree.
|
||||
#[prost(message, optional, tag = "11")]
|
||||
pub hash_tree_extent: ::core::option::Option<Extent>,
|
||||
/// The hash algorithm used in verity hash tree.
|
||||
#[prost(string, optional, tag = "12")]
|
||||
pub hash_tree_algorithm: ::core::option::Option<::prost::alloc::string::String>,
|
||||
/// The salt used for verity hash tree.
|
||||
#[prost(bytes = "vec", optional, tag = "13")]
|
||||
pub hash_tree_salt: ::core::option::Option<::prost::alloc::vec::Vec<u8>>,
|
||||
/// The extent for data covered by FEC.
|
||||
#[prost(message, optional, tag = "14")]
|
||||
pub fec_data_extent: ::core::option::Option<Extent>,
|
||||
/// The extent to store FEC.
|
||||
#[prost(message, optional, tag = "15")]
|
||||
pub fec_extent: ::core::option::Option<Extent>,
|
||||
/// The number of FEC roots.
|
||||
#[prost(uint32, optional, tag = "16", default = "2")]
|
||||
pub fec_roots: ::core::option::Option<u32>,
|
||||
/// Per-partition version used for downgrade detection, added
|
||||
/// as an effort to support partial updates. For most partitions,
|
||||
/// this is the build timestamp.
|
||||
#[prost(string, optional, tag = "17")]
|
||||
pub version: ::core::option::Option<::prost::alloc::string::String>,
|
||||
/// A sorted list of CowMergeOperation. When writing cow, we can choose to
|
||||
/// skip writing the raw bytes for these extents. During snapshot merge, the
|
||||
/// bytes will read from the source partitions instead.
|
||||
#[prost(message, repeated, tag = "18")]
|
||||
pub merge_operations: ::prost::alloc::vec::Vec<CowMergeOperation>,
|
||||
/// Estimated size for COW image. This is used by libsnapshot
|
||||
/// as a hint. If set to 0, libsnapshot should use alternative
|
||||
/// methods for estimating size.
|
||||
#[prost(uint64, optional, tag = "19")]
|
||||
pub estimate_cow_size: ::core::option::Option<u64>,
|
||||
}
|
||||
#[derive(Clone, PartialEq, ::prost::Message)]
|
||||
pub struct DynamicPartitionGroup {
|
||||
/// Name of the group.
|
||||
#[prost(string, required, tag = "1")]
|
||||
pub name: ::prost::alloc::string::String,
|
||||
/// Maximum size of the group. The sum of sizes of all partitions in the group
|
||||
/// must not exceed the maximum size of the group.
|
||||
#[prost(uint64, optional, tag = "2")]
|
||||
pub size: ::core::option::Option<u64>,
|
||||
/// A list of partitions that belong to the group.
|
||||
#[prost(string, repeated, tag = "3")]
|
||||
pub partition_names: ::prost::alloc::vec::Vec<::prost::alloc::string::String>,
|
||||
}
|
||||
#[derive(Clone, Copy, PartialEq, ::prost::Message)]
|
||||
pub struct VabcFeatureSet {
|
||||
#[prost(bool, optional, tag = "1")]
|
||||
pub threaded: ::core::option::Option<bool>,
|
||||
#[prost(bool, optional, tag = "2")]
|
||||
pub batch_writes: ::core::option::Option<bool>,
|
||||
}
|
||||
/// Metadata related to all dynamic partitions.
|
||||
#[derive(Clone, PartialEq, ::prost::Message)]
|
||||
pub struct DynamicPartitionMetadata {
|
||||
/// All updatable groups present in |partitions| of this DeltaArchiveManifest.
|
||||
/// - If an updatable group is on the device but not in the manifest, it is
|
||||
/// not updated. Hence, the group will not be resized, and partitions cannot
|
||||
/// be added to or removed from the group.
|
||||
/// - If an updatable group is in the manifest but not on the device, the group
|
||||
/// is added to the device.
|
||||
#[prost(message, repeated, tag = "1")]
|
||||
pub groups: ::prost::alloc::vec::Vec<DynamicPartitionGroup>,
|
||||
/// Whether dynamic partitions have snapshots during the update. If this is
|
||||
/// set to true, the update_engine daemon creates snapshots for all dynamic
|
||||
/// partitions if possible. If this is unset, the update_engine daemon MUST
|
||||
/// NOT create snapshots for dynamic partitions.
|
||||
#[prost(bool, optional, tag = "2")]
|
||||
pub snapshot_enabled: ::core::option::Option<bool>,
|
||||
/// If this is set to false, update_engine should not use VABC regardless. If
|
||||
/// this is set to true, update_engine may choose to use VABC if device
|
||||
/// supports it, but not guaranteed.
|
||||
/// VABC stands for Virtual AB Compression
|
||||
#[prost(bool, optional, tag = "3")]
|
||||
pub vabc_enabled: ::core::option::Option<bool>,
|
||||
/// The compression algorithm used by VABC. Available ones are "gz", "brotli".
|
||||
/// See system/core/fs_mgr/libsnapshot/cow_writer.cpp for available options,
|
||||
/// as this parameter is ultimated forwarded to libsnapshot's CowWriter
|
||||
#[prost(string, optional, tag = "4")]
|
||||
pub vabc_compression_param: ::core::option::Option<::prost::alloc::string::String>,
|
||||
/// COW version used by VABC. The represents the major version in the COW
|
||||
/// header
|
||||
#[prost(uint32, optional, tag = "5")]
|
||||
pub cow_version: ::core::option::Option<u32>,
|
||||
/// A collection of knobs to tune Virtual AB Compression
|
||||
#[prost(message, optional, tag = "6")]
|
||||
pub vabc_feature_set: ::core::option::Option<VabcFeatureSet>,
|
||||
}
|
||||
/// Definition has been duplicated from
|
||||
/// $ANDROID_BUILD_TOP/build/tools/releasetools/ota_metadata.proto. Keep in sync.
|
||||
#[derive(Clone, PartialEq, ::prost::Message)]
|
||||
pub struct ApexInfo {
|
||||
#[prost(string, optional, tag = "1")]
|
||||
pub package_name: ::core::option::Option<::prost::alloc::string::String>,
|
||||
#[prost(int64, optional, tag = "2")]
|
||||
pub version: ::core::option::Option<i64>,
|
||||
#[prost(bool, optional, tag = "3")]
|
||||
pub is_compressed: ::core::option::Option<bool>,
|
||||
#[prost(int64, optional, tag = "4")]
|
||||
pub decompressed_size: ::core::option::Option<i64>,
|
||||
}
|
||||
/// Definition has been duplicated from
|
||||
/// $ANDROID_BUILD_TOP/build/tools/releasetools/ota_metadata.proto. Keep in sync.
|
||||
// -- Added by me , struct ApexMetadata is unused --
|
||||
//#[derive(Clone, PartialEq, ::prost::Message)]
|
||||
//pub struct ApexMetadata {
|
||||
// #[prost(message, repeated, tag = "1")]
|
||||
// pub apex_info: ::prost::alloc::vec::Vec<ApexInfo>,
|
||||
//}
|
||||
#[derive(Clone, PartialEq, ::prost::Message)]
|
||||
pub struct DeltaArchiveManifest {
|
||||
/// (At time of writing) usually 4096
|
||||
#[prost(uint32, optional, tag = "3", default = "4096")]
|
||||
pub block_size: ::core::option::Option<u32>,
|
||||
/// If signatures are present, the offset into the blobs, generally
|
||||
/// tacked onto the end of the file, and the length. We use an offset
|
||||
/// rather than a bool to allow for more flexibility in future file formats.
|
||||
/// If either is absent, it means signatures aren't supported in this
|
||||
/// file.
|
||||
#[prost(uint64, optional, tag = "4")]
|
||||
pub signatures_offset: ::core::option::Option<u64>,
|
||||
#[prost(uint64, optional, tag = "5")]
|
||||
pub signatures_size: ::core::option::Option<u64>,
|
||||
/// The minor version, also referred as "delta version", of the payload.
|
||||
/// Minor version 0 is full payload, everything else is delta payload.
|
||||
#[prost(uint32, optional, tag = "12", default = "0")]
|
||||
pub minor_version: ::core::option::Option<u32>,
|
||||
/// Only present in major version >= 2. List of partitions that will be
|
||||
/// updated, in the order they will be updated. This field replaces the
|
||||
/// |install_operations|, |kernel_install_operations| and the
|
||||
/// |{old,new}_{kernel,rootfs}_info| fields used in major version = 1. This
|
||||
/// array can have more than two partitions if needed, and they are identified
|
||||
/// by the partition name.
|
||||
#[prost(message, repeated, tag = "13")]
|
||||
pub partitions: ::prost::alloc::vec::Vec<PartitionUpdate>,
|
||||
/// The maximum timestamp of the OS allowed to apply this payload.
|
||||
/// Can be used to prevent downgrading the OS.
|
||||
#[prost(int64, optional, tag = "14")]
|
||||
pub max_timestamp: ::core::option::Option<i64>,
|
||||
/// Metadata related to all dynamic partitions.
|
||||
#[prost(message, optional, tag = "15")]
|
||||
pub dynamic_partition_metadata: ::core::option::Option<DynamicPartitionMetadata>,
|
||||
}
|
||||
@@ -4,6 +4,8 @@ use flate2::read::ZlibDecoder;
|
||||
use flate2::read::GzDecoder;
|
||||
use lzma_rs::lzma_decompress;
|
||||
use lz4::block::decompress;
|
||||
use bzip2::read::BzDecoder;
|
||||
use liblzma::read::XzDecoder;
|
||||
|
||||
pub fn decompress_zlib(data: &[u8]) -> io::Result<Vec<u8>> {
|
||||
let mut decoder = ZlibDecoder::new(data);
|
||||
@@ -33,4 +35,18 @@ pub fn decompress_lz4(compressed_data: &[u8], original_size: i32) -> Result<Vec<
|
||||
Ok(decompressed) => Ok(decompressed),
|
||||
Err(e) => Err(std::io::Error::new(std::io::ErrorKind::InvalidData, e)),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn decompress_bzip(compressed: &[u8]) -> std::io::Result<Vec<u8>> {
|
||||
let mut decoder = BzDecoder::new(compressed);
|
||||
let mut decompressed = Vec::new();
|
||||
decoder.read_to_end(&mut decompressed)?;
|
||||
Ok(decompressed)
|
||||
}
|
||||
|
||||
pub fn decompress_xz(compressed: &[u8]) -> std::io::Result<Vec<u8>> {
|
||||
let mut decoder = XzDecoder::new(compressed);
|
||||
let mut decompressed = Vec::new();
|
||||
decoder.read_to_end(&mut decompressed)?;
|
||||
Ok(decompressed)
|
||||
}
|
||||
@@ -1,25 +0,0 @@
|
||||
| Format name | Used by | Notes | Thanks to |
|
||||
| ----------------------------- | --------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------- | ----------------------------------------------------- |
|
||||
| EPK v1 | LG TVs before ~2010 | All files should be supported (expect epkv1(new)) | https://github.com/openlgtv/epk2extract |
|
||||
| EPK v2 | LG TVs since ~2010 | Most files are supported (**depends on keys**) | https://github.com/openlgtv/epk2extract |
|
||||
| EPK v3 | LG webOS TVs | Only some files are supported (**depends on keys**) | 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 | Only some files are supported (**depends on keys**) | https://github.com/bugficks/msddecrypt |
|
||||
| MSD v1.1 | Samsung TVs 2016+ | Only some files are supported (**depends on keys**) | 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 | Many Mediatek-based TVs (Hisense, Sony, Panasonic, Philips...) | Only files with 144 byte header and using 4xVendor magic as enc key are supported | https://github.com/openlgtv/epk2extract |
|
||||
| Mediatek upgrade_loader | Older Mediatek-based TVs | All files should be supported providing they are not encrypted | - |
|
||||
| Novatek pkg | 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 | Only some files are supported (**depends on keys**) | - |
|
||||
| Philips UPG | Philips pre-TPVision TVS 2008-2013 | Only some files are supported (**depends on keys**) | 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 | Only BD-P1600 is supported (**depends on keys**) | - |
|
||||
| RVP/MVP | Sharp Blu-Ray players/recorders | Only supports older files (XOR encrypted) | - |
|
||||
| Samsung | Old Samsung TV firmwares pre 2013 | Only some files are supported (**depends on keys**) | 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 |
|
||||
Reference in New Issue
Block a user