Switch to rust-lzma2 for XZ compression/decompression

The performance, both in CPU time and compression ratios, is very
comparable to liblzma. This lets us drop the last remaining
compression-related dependency written in C.

Signed-off-by: Andrew Gunnerson <accounts+github@chiller3.com>
This commit is contained in:
Andrew Gunnerson
2025-08-08 21:17:03 -04:00
parent 2bac85f080
commit ac95660e23
11 changed files with 115 additions and 138 deletions
+4 -4
View File
@@ -92,7 +92,7 @@ jobs:
run: |
for target in ${TARGETS}; do
cargo android \
clippy --release --workspace --features static \
clippy --release --workspace \
--target "${target}"
done
@@ -101,7 +101,7 @@ jobs:
run: |
for target in ${TARGETS}; do
cargo android \
build --release --workspace --features static \
build --release --workspace \
--target "${target}"
done
@@ -110,7 +110,7 @@ jobs:
run: |
for target in ${TARGETS}; do
cargo android \
test --release --workspace --features static \
test --release --workspace \
--target "${target}"
done
@@ -119,7 +119,7 @@ jobs:
run: |
for target in ${TARGETS}; do
cargo android \
run --release -p e2e --features static \
run --release -p e2e \
--target "${target}" \
-- test -a -c e2e/e2e.toml
done
Generated
+26 -39
View File
@@ -135,8 +135,8 @@ dependencies = [
"gf256",
"hex",
"libc",
"liblzma",
"lz4_flex",
"lzma-rust2",
"memchr",
"num-bigint-dig",
"num-traits",
@@ -308,8 +308,6 @@ version = "1.2.31"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c3a42d84bb6b69d3a8b3eaacf0d88f179e1929695e1ad012b6cf64d9caaa5fd2"
dependencies = [
"jobserver",
"libc",
"shlex",
]
@@ -423,6 +421,21 @@ dependencies = [
"libc",
]
[[package]]
name = "crc"
version = "3.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9710d3b3739c2e349eb44fe848ad0b7c8cb1e42bd87ee49371df2f7acaf3e675"
dependencies = [
"crc-catalog",
]
[[package]]
name = "crc-catalog"
version = "2.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "19d374276b40fb8bbdee95aef7c7fa6b5316ec764510eb64b8dd0e2ed0d7e7f5"
[[package]]
name = "crc32fast"
version = "1.5.0"
@@ -830,16 +843,6 @@ dependencies = [
"either",
]
[[package]]
name = "jobserver"
version = "0.1.33"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "38f262f097c174adebe41eb73d66ae9c06b2844fb0da69969647bbddd9b0538a"
dependencies = [
"getrandom 0.3.3",
"libc",
]
[[package]]
name = "js-sys"
version = "0.3.77"
@@ -871,26 +874,6 @@ version = "0.2.174"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1171693293099992e19cddea4e8b849964e9846f4acee11b3948bcc337be8776"
[[package]]
name = "liblzma"
version = "0.4.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0791ab7e08ccc8e0ce893f6906eb2703ed8739d8e89b57c0714e71bad09024c8"
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"
@@ -961,6 +944,16 @@ dependencies = [
"twox-hash",
]
[[package]]
name = "lzma-rust2"
version = "0.8.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a82192ab5b40bc95fff6e8a61e099e421f07055778b2f5261297c102137b6081"
dependencies = [
"crc",
"sha2",
]
[[package]]
name = "maybe-owned"
version = "0.3.4"
@@ -1232,12 +1225,6 @@ 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"
-2
View File
@@ -588,8 +588,6 @@ The output binary is written to `target/release/avbroot`.
Debug builds work too, but they will run significantly slower (in the sha256 computations) due to compiler optimizations being turned off.
By default, the executable links to the system's bzip2 and liblzma libraries, which are the only external libraries avbroot depends on. To compile and statically link these two libraries, pass in `--features static`.
### Android cross-compilation
To cross-compile for Android, install [cargo-android](https://github.com/chenxiaolong/cargo-android) and use the `cargo android` wrapper. To make a release build for aarch64, run:
+10 -12
View File
@@ -391,17 +391,17 @@ avbroot можно использовать для простого перепо
Если вы используете аргумент `--skip-recovery-ota-cert`, потому что уже добавили сертификат OTA в загрузочный образ вручную, рекомендуетcя [проверить пропатченный OTA](#проверка-ota), дабы удостовериться, что замена произведена корректно. Процесс верификации проверяет только копию сертификатов OTA в загрузочном образе, не проверяя копию в образе системы.
### Пропуск всех патчей
Чтобы внести самый минимум изменений, укажите аргументы:
* `--skip-system-ota-cert`
* `--skip-recovery-ota-cert`
* `--rootless`
* не используйте аргумент `--dsu`.
Так, пользовательскими ключами будут переподписаны лишь образ `vbmeta` и OTA, остальные разделы останутся нетронутыми.
**Это следует использовать только для устранения неполадок.** Без патчей сертификатов, поверх полученного OTA не получится установить никакие обновления.
**Это следует использовать только для устранения неполадок.** Без патчей сертификатов, поверх полученного OTA не получится установить никакие обновления.
### Подмена образов
@@ -422,15 +422,15 @@ Verified boot is disabled by vbmeta's header flags: 0x3
Чтобы принудительно включить AVB (очистив флаги), укажите аргумент `--clear-vbmeta-flags`.
### Изменение алгоритма CoW сжатия для вирутального A/B
Алгоритм CoW (copy-on-write) сжатия для виртуального A/B можно изменить, используя аргумент `--vabc-algo <алгоритм>`, указав `gz` или `lz4`. Как правило, по умолчанию OTA использует алгоритм, который совместим с изначальной версией Android, на которой поставлялось устройство.
* Девайсы, поставляемые с Android 12, поддерживают `gz` и `brotli` (последний не поддерживается avbroot)
* Девайсы, поставляемые с Android 14, поддерживают `lz4`
* Девайсы, поставляемые с Android 15, поддерживают `zstd` (не поддерживается avbroot)
Выбор быстрого алгоритма, такого как lz4, может значительно ускорить установку OTA из-под системы (при использованием стороннего приложения для OTA-обновлений). Однако, при установке OTA в режиме Recovery, разницы в скорости не будет.
Обратите внимание, что текущая используемая версия Android должна поддерживать выбранный алгоритм сжатия. В противном случае установка завершится ошибкой. Например, попытка установить OTA-обновление с Android 14, использующее алгоритм lz4, приведет к ошибке, если установка производится из-под Android 13.
### Использование в неинтерактивном режиме
@@ -515,7 +515,7 @@ avbroot поддерживает делегирование всех опера
На современных устройствах с Android 16 и выше, в настройках для разработчиков может появиться опция переключения на ядро с размером страницы 16 КБ. Однако, эта функция не будет работать в системе, пропатченной с помощью avbroot, поскольку переключение данной настройки осуществляется путём установки инкрементальной OTA:
* `/vendor/boot_otas/boot_ota_16k.zip` — используется для переключения на ядро с размером страницы 16 КБ (в разделе `boot` уже должно быть прошито ядро с размером страницы 4K)
* `/vendor/boot_otas/boot_ota_16k.zip` — используется для переключения на ядро с размером страницы 16 КБ (в разделе `boot` уже должно быть прошито ядро с размером страницы 4K)
* `/vendor/boot_otas/boot_ota_4k.zip` — используется для переключения на ядро с размером страницы 4 КБ (в разделе `boot` уже должно быть прошито ядро с размером страницы 16K)
Эти файлы (в `boot_otas`) невозможно прошить на системе, пропатченной avbroot, потому что `payload.bin` внутри них подписан ключом производителя. Кроме того, это неполноценные OTA-файлы: у них нет метаданных, характерных для OTA, а сам zip-файл не подписан. Это просто обычный архив, который содержит подписанный `payload.bin`.
@@ -570,8 +570,6 @@ cargo build --release
Дебаг-сборки тоже работают, но они будут работать значительно медленнее (в вычислениях sha256), потому что оптимизации компилятора отключены.
По умолчанию исполняемый файл ссылается на системные библиотеки bzip2 и liblzma, от которых зависит avbroot. Чтобы скомпилировать и статически связать эти две библиотеки, укажите аргумент `--features static`.
### Кросс-компиляция на Android
Чтобы использовать кросс-компиляцию на Android, установите [cargo-android](https://github.com/chenxiaolong/cargo-android) и воспользуйтесь оболочкой `cargo android`. Чтобы создать релизную сборку для aarch64, выполните:
+1 -4
View File
@@ -28,8 +28,8 @@ dlv-list = "0.6.0"
flate2 = { version = "1.0.29", features = ["zlib-rs"] }
gf256 = { version = "0.3.0", features = ["rs"] }
hex = { version = "0.4.3", features = ["serde"] }
liblzma = "0.4.1"
lz4_flex = "0.11.1"
lzma-rust2 = "0.8.0"
memchr = "2.6.0"
num-bigint-dig = "0.8.4"
num-traits = "0.2.16"
@@ -81,8 +81,5 @@ protox = "0.9.0"
[dev-dependencies]
assert_matches = "1.5.0"
[features]
static = ["liblzma/static"]
[lints]
workspace = true
+18 -18
View File
@@ -1,15 +1,11 @@
// SPDX-FileCopyrightText: 2023-2024 Andrew Gunnerson
// SPDX-FileCopyrightText: 2023-2025 Andrew Gunnerson
// SPDX-License-Identifier: GPL-3.0-only
use std::io::{self, Read, Seek, Write};
use flate2::{Compression, read::GzDecoder, write::GzEncoder};
use liblzma::{
read::XzDecoder,
stream::{Check, Stream},
write::XzEncoder,
};
use lz4_flex::frame::FrameDecoder;
use lzma_rust2::{CheckType, XZOptions, XZReader, XZWriter};
use serde::{Deserialize, Serialize};
use thiserror::Error;
@@ -28,7 +24,7 @@ pub enum Error {
#[error("Failed to initialize legacy LZ4 encoder")]
Lz4Init(#[source] io::Error),
#[error("Failed to initialize XZ encoder")]
XzInit(#[source] liblzma::stream::Error),
XzInit(#[source] io::Error),
}
type Result<T> = std::result::Result<T, Error>;
@@ -114,14 +110,14 @@ pub enum CompressedFormat {
Xz,
}
pub enum CompressedReader<R: Read> {
pub enum CompressedReader<'reader, R: Read> {
None(R),
Gzip(GzDecoder<R>),
Lz4(FrameDecoder<R>),
Xz(XzDecoder<R>),
Xz(XZReader<'reader, R>),
}
impl<R: Read + Seek> CompressedReader<R> {
impl<'reader, R: Read + Seek + 'reader> CompressedReader<'reader, R> {
pub fn new(mut reader: R, raw_if_unknown: bool) -> Result<Self> {
let magic = reader.read_array_exact::<6>().map_err(Error::AutoDetect)?;
@@ -132,7 +128,7 @@ impl<R: Read + Seek> CompressedReader<R> {
} else if &magic[0..4] == LZ4_LEGACY_MAGIC {
Ok(Self::Lz4(FrameDecoder::new(reader)))
} else if &magic == XZ_MAGIC {
Ok(Self::Xz(XzDecoder::new(reader)))
Ok(Self::Xz(XZReader::new(reader, false)))
} else if raw_if_unknown {
Ok(Self::None(reader))
} else {
@@ -159,7 +155,7 @@ impl<R: Read + Seek> CompressedReader<R> {
}
}
impl<R: Read> Read for CompressedReader<R> {
impl<'reader, R: Read + 'reader> Read for CompressedReader<'reader, R> {
fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
match self {
Self::None(r) => r.read(buf),
@@ -170,14 +166,15 @@ impl<R: Read> Read for CompressedReader<R> {
}
}
pub enum CompressedWriter<W: Write> {
#[allow(clippy::large_enum_variant)]
pub enum CompressedWriter<'writer, W: Write> {
None(W),
Gzip(GzEncoder<W>),
Lz4Legacy(Lz4LegacyEncoder<W>),
Xz(XzEncoder<W>),
Xz(XZWriter<'writer, W>),
}
impl<W: Write> CompressedWriter<W> {
impl<'writer, W: Write + 'writer> CompressedWriter<'writer, W> {
pub fn new(writer: W, format: CompressedFormat) -> Result<Self> {
match format {
CompressedFormat::None => Ok(Self::None(writer)),
@@ -190,8 +187,11 @@ impl<W: Write> CompressedWriter<W> {
}
CompressedFormat::Xz => {
// Some kernels are compiled without support for the default CRC64.
let stream = Stream::new_easy_encoder(6, Check::Crc32).map_err(Error::XzInit)?;
Ok(Self::Xz(XzEncoder::new_stream(writer, stream)))
let mut options = XZOptions::with_preset(6);
options.set_check_sum_type(CheckType::Crc32);
let xz_writer = XZWriter::new(writer, options).map_err(Error::XzInit)?;
Ok(Self::Xz(xz_writer))
}
}
}
@@ -215,7 +215,7 @@ impl<W: Write> CompressedWriter<W> {
}
}
impl<W: Write> Write for CompressedWriter<W> {
impl<'writer, W: Write + 'writer> Write for CompressedWriter<'writer, W> {
fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
match self {
Self::None(w) => w.write(buf),
+15 -20
View File
@@ -15,11 +15,7 @@ use base64::Engine;
use base64::engine::general_purpose::STANDARD;
use bzip2::write::BzDecoder;
use flate2::{Compression, write::GzEncoder};
use liblzma::{
stream::{Check, Stream},
write::XzDecoder,
write::XzEncoder,
};
use lzma_rust2::{CheckType, XZOptions, XZReader, XZWriter};
use num_traits::CheckedAdd;
use prost::Message;
use rayon::{
@@ -40,8 +36,8 @@ use crate::{
install_operation::Type, signatures::Signature,
},
stream::{
self, CountingReader, FromReader, HashingWriter, ReadDiscardExt, ReadFixedSizeExt,
ReadSeekReopen, WriteSeek, WriteSeekReopen,
self, CountingReader, FromReader, HashingReader, HashingWriter, ReadDiscardExt,
ReadFixedSizeExt, ReadSeekReopen, WriteSeek, WriteSeekReopen,
},
util::{self, OutOfBoundsError},
};
@@ -139,7 +135,7 @@ pub enum Error {
#[error("Failed to GZ compress partition image chunk")]
GzCompress(#[source] io::Error),
#[error("Failed to initialize XZ encoder")]
XzInit(#[source] liblzma::stream::Error),
XzInit(#[source] io::Error),
#[error("Failed to XZ compress partition image chunk")]
XzCompress(#[source] io::Error),
#[error("Failed to read uncompressed input partition image chunk")]
@@ -818,16 +814,14 @@ pub fn apply_operation(
.map_err(error_fn)?;
}
Type::ReplaceXz => {
let mut decoder = XzDecoder::new(&mut writer);
stream::copy_n_inspect(
&mut reader,
&mut decoder,
data_length,
|data| hasher.update(data),
cancel_signal,
)
.and_then(|()| decoder.finish())
.map_err(error_fn)?;
// lzma_rust2 does not have a Write API, so we limit the
// reader and read till EOF.
let limited_reader = (&mut reader).take(data_length);
let hashing_reader = HashingReader::new(limited_reader, hasher);
let mut decoder = XZReader::new(hashing_reader, false);
stream::copy(&mut decoder, &mut writer, cancel_signal).map_err(error_fn)?;
(_, hasher) = decoder.into_inner().finish();
}
_ => return Err(Error::UnsupportedOperation(op.r#type())),
}
@@ -947,8 +941,9 @@ fn compress_chunk(raw_data: &[u8], cancel_signal: &AtomicBool) -> Result<(Vec<u8
// decompression. Also, we intentionally pick the lowest compression level
// since we primarily care about squishing zeros. The non-zero portions of
// boot images are usually already-compressed kernels and ramdisks.
let stream = Stream::new_easy_encoder(0, Check::None).map_err(Error::XzInit)?;
let mut xz_writer = XzEncoder::new_stream(hashing_writer, stream);
let mut options = XZOptions::with_preset(0);
options.set_check_sum_type(CheckType::None);
let mut xz_writer = XZWriter::new(hashing_writer, options).map_err(Error::XzInit)?;
stream::copy_n(reader, &mut xz_writer, raw_data.len() as u64, cancel_signal)
.map_err(Error::XzCompress)?;
+7 -8
View File
@@ -1,4 +1,4 @@
// SPDX-FileCopyrightText: 2022-2024 Andrew Gunnerson
// SPDX-FileCopyrightText: 2022-2025 Andrew Gunnerson
// SPDX-License-Identifier: GPL-3.0-only
use std::{
@@ -15,10 +15,7 @@ use std::{
};
use bstr::ByteSlice;
use liblzma::{
stream::{Check, Stream},
write::XzEncoder,
};
use lzma_rust2::{CheckType, XZOptions, XZWriter};
use rayon::iter::{IntoParallelRefIterator, IntoParallelRefMutIterator, ParallelIterator};
use regex::bytes::Regex;
use ring::digest::Context;
@@ -83,7 +80,7 @@ pub enum Error {
#[error("Failed to generate replacement otacerts zip")]
OtaCertZip(#[source] otacert::Error),
#[error("Failed to initialize XZ encoder")]
XzInit(#[source] liblzma::stream::Error),
XzInit(#[source] io::Error),
#[error("Failed to XZ compress entry: {:?}", .0.as_bstr())]
XzCompress(Vec<u8>, #[source] io::Error),
#[error("Failed to open zip file: {0:?}")]
@@ -288,9 +285,11 @@ impl MagiskRootPatcher {
}
fn xz_compress(name: &[u8], reader: impl Read, cancel_signal: &AtomicBool) -> Result<Vec<u8>> {
let stream = Stream::new_easy_encoder(9, Check::Crc32).map_err(Error::XzInit)?;
let mut options = XZOptions::with_preset(9);
options.set_check_sum_type(CheckType::None);
let raw_writer = Cursor::new(Vec::new());
let mut writer = XzEncoder::new_stream(raw_writer, stream);
let mut writer = XZWriter::new(raw_writer, options).map_err(Error::XzInit)?;
let raw_writer = stream::copy(reader, &mut writer, cancel_signal)
.and_then(|_| writer.finish())
+18 -12
View File
@@ -1,4 +1,4 @@
// SPDX-FileCopyrightText: 2023 Andrew Gunnerson
// SPDX-FileCopyrightText: 2023-2025 Andrew Gunnerson
// SPDX-License-Identifier: GPL-3.0-only
use std::{
@@ -603,12 +603,14 @@ pub fn copy_n(
copy_n_inspect(reader, writer, size, |_| {}, cancel_signal)
}
/// Copy data from `reader` to `writer` until `reader` reaches EOF. If `writer`
/// reaches EOF before `reader` does, an error is returned. The operation is
/// cancelled on the next loop iteration if `cancel_signal` is set to `true`.
pub fn copy(
/// Copy data from `reader` to `writer` until `reader` reaches EOF, invoking
/// `inspect` after every buffer read iteration. If `writer` reaches EOF before
/// `reader` does, an error is returned. The operation is cancelled on the next
/// loop iteration if `cancel_signal` is set to `true`.
pub fn copy_inspect(
mut reader: impl Read,
mut writer: impl Write,
mut inspect: impl FnMut(&[u8]),
cancel_signal: &AtomicBool,
) -> io::Result<u64> {
let mut buf = [0u8; 16384];
@@ -622,6 +624,8 @@ pub fn copy(
break;
}
inspect(&buf[..n]);
writer.write_all(&buf[..n])?;
copied += n as u64;
@@ -630,6 +634,11 @@ pub fn copy(
Ok(copied)
}
/// Copy data from `reader` to `writer` until `reader` reaches EOF.
pub fn copy(reader: impl Read, writer: impl Write, cancel_signal: &AtomicBool) -> io::Result<u64> {
copy_inspect(reader, writer, |_| {}, cancel_signal)
}
#[cfg(test)]
mod tests {
use std::{
@@ -822,21 +831,19 @@ mod tests {
let mut reader = Cursor::new(b"foobar");
let mut writer = Cursor::new([0u8; 6]);
super::copy_n_inspect(&mut reader, &mut writer, 6, |_| {}, &cancel_signal).unwrap();
super::copy_n(&mut reader, &mut writer, 6, &cancel_signal).unwrap();
assert_eq!(writer.get_ref(), b"foobar");
// Reader early EOF.
reader.seek(SeekFrom::Start(3)).unwrap();
writer.rewind().unwrap();
let err =
super::copy_n_inspect(&mut reader, &mut writer, 6, |_| {}, &cancel_signal).unwrap_err();
let err = super::copy_n(&mut reader, &mut writer, 6, &cancel_signal).unwrap_err();
assert_eq!(err.kind(), io::ErrorKind::UnexpectedEof);
// Writer early EOF.
reader.rewind().unwrap();
writer.seek(SeekFrom::Start(3)).unwrap();
let err =
super::copy_n_inspect(&mut reader, &mut writer, 6, |_| {}, &cancel_signal).unwrap_err();
let err = super::copy_n(&mut reader, &mut writer, 6, &cancel_signal).unwrap_err();
assert_eq!(err.kind(), io::ErrorKind::WriteZero);
reader.rewind().unwrap();
@@ -860,8 +867,7 @@ mod tests {
reader.rewind().unwrap();
writer.rewind().unwrap();
cancel_signal.store(true, Ordering::SeqCst);
let err =
super::copy_n_inspect(&mut reader, &mut writer, 6, |_| {}, &cancel_signal).unwrap_err();
let err = super::copy_n(&mut reader, &mut writer, 6, &cancel_signal).unwrap_err();
assert_eq!(err.kind(), io::ErrorKind::Interrupted);
let err = super::copy(&mut reader, &mut writer, &cancel_signal).unwrap_err();
assert_eq!(err.kind(), io::ErrorKind::Interrupted);
-3
View File
@@ -32,8 +32,5 @@ git = "https://github.com/chenxiaolong/zip2"
rev = "59685f4dadbfee8cb3ea74c8fbb402b60d8137e8"
default-features = false
[features]
static = ["avbroot/static"]
[lints]
workspace = true
+16 -16
View File
@@ -51,12 +51,12 @@ data.version = "vendor_v4"
data.ramdisks = [["otacerts", "first_stage", "dsu_key_dir"]]
[profile.pixel_v4_gki.hashes_streaming]
original = "ef6261cd9ebea90f036e52a46160a400c5b8f6ef24ed2469c4a1e9689987aa06"
patched = "37fd353a766a7b9a339fbf51fa79c703e94640dc6a2c6310d79357aaefcc7ca1"
original = "4e283ad1e3450795a32f46445bf626f6af983f52bd0a3484b49f8740c1029653"
patched = "837861bf64e9387380e02d740b21c94e60c41bba4161d85ab44fc5ce86f19631"
[profile.pixel_v4_gki.hashes_seekable]
original = "8a2c717607c10dfa5483d6f9a9f37b3d978acaf8d2ea18e36544af267943e750"
patched = "2c4734c9e1d028ee6aaf02bb416e5e173857faffd2ca067366790655147b3afa"
original = "0ab2403a2634f00063c44f9a477a672205922ede189442e18850dd8efceb5d6f"
patched = "2d94841c3be6cc1739f4c7ad5d9db048301b3f93f8ccd510e2c825bf13ecff90"
# Google Pixel 6a
# What's unique: boot (boot v4, no ramdisk) + vendor_boot (vendor v4, 2 ramdisks)
@@ -93,12 +93,12 @@ data.version = "vendor_v4"
data.ramdisks = [["init", "otacerts", "first_stage", "dsu_key_dir"], ["dlkm"]]
[profile.pixel_v4_non_gki.hashes_streaming]
original = "630220ef813a2b4743d1941179cc9705da86ad4805f1c52341dcb38fbce3d29e"
patched = "b725e91751fe58aed20495aecbf9b4bdc14d2799cd88dcbd58f3a3b02b3af15b"
original = "c3a978b7225632875d3b1e87e852494b1a69019f5ba4099cf3981503623facca"
patched = "cf0ef7429c4657875018d10d7302aaca371b21c5968af234aabd941304f0035b"
[profile.pixel_v4_non_gki.hashes_seekable]
original = "1afbe6867ded345d941098ee7c7fcf94a3df52c50ff96ab8f3a67b2ab957259a"
patched = "4357b977249006b101002c961916f962787315a80b8608494c6a1f0cf09cecd1"
original = "cc11ee5a5be66bf34dcb6834a9a635016fa9f82dd0d9a2fb1029aa4f218d1d2e"
patched = "e2fb7d3ce2c697372fb342ae5cd7bb606cd764f06a2aa8a2d6d7bd2c88456780"
# Google Pixel 4a 5G
# What's unique: boot (boot v3) + vendor_boot (vendor v3)
@@ -136,12 +136,12 @@ data.version = "vendor_v3"
data.ramdisks = [["otacerts", "first_stage", "dsu_key_dir"]]
[profile.pixel_v3.hashes_streaming]
original = "9b65037343d45211e0f9706929cba34643a9c54274d1b39740c43f45974984e0"
patched = "fb23ab9616968b38b96d1e5e6a503154f89aebc1741e89a9e9dfd2c4d9946b05"
original = "d12d92c051bcc832cc9ceef1d46c415af80a09808a984db4c42a88d65d644a8b"
patched = "408496eb2cca51c0563eceaa3a9def95a5c42acff938850a8577aaa047331284"
[profile.pixel_v3.hashes_seekable]
original = "e581934887dd93b8a9d9c3aa5dec1d48aa7e01bf01ac507e8c5fb256b59cbe7d"
patched = "669a826abc6d67e7e0b1def724aa7b470461087255c65663d195df1426a355f0"
original = "63505cfd7c2c9d948a5ee150cf53f448f11c83cdce3919fd43231640bf002812"
patched = "b246497de1588d41b919ba002b37dff13cb565682aa3e086e543b25ead7d7aaf"
# Google Pixel 4a
# What's unique: boot (boot v2)
@@ -169,9 +169,9 @@ data.type = "vbmeta"
data.deps = ["system"]
[profile.pixel_v2.hashes_streaming]
original = "f10ee15c900a474cc6bbefa705f272cef42636ea096e75563d2d78f6c4327fd1"
patched = "6929f65909037f5550a53982b71e96bdf69ab876bc5e86702c469ed601be8a9a"
original = "c303728f4ee9c42ef990bb576bd0688635b263a67127d2a986caf574c9eedd63"
patched = "e907db408767f81223e3ae53dd8a44c6f59f4702a016093cd6983499c9391ff0"
[profile.pixel_v2.hashes_seekable]
original = "4e863d251b9ff6eaa1511f9c03e9bdb8919650b2e0eaf23e33892a639edafcaf"
patched = "9a103222e73df70a097281525546d25c850df2ae7a2ba715aa5dfbbba3f7972b"
original = "951b1f70bef7736b9e06f3215357fcebf8a4925872cd31691198fdda9d7c04ce"
patched = "2b1bfe46f41942be88e09b40000745c68ed133900d7970f57d15019683a1ba87"