diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index e7d670e..dda989a 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -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 diff --git a/Cargo.lock b/Cargo.lock index 4622c8d..1a85011 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -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" diff --git a/README.md b/README.md index e29d67f..0b1016f 100644 --- a/README.md +++ b/README.md @@ -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: diff --git a/README.ru.md b/README.ru.md index 83f474e..5318207 100644 --- a/README.ru.md +++ b/README.ru.md @@ -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, выполните: diff --git a/avbroot/Cargo.toml b/avbroot/Cargo.toml index 376024f..46d0872 100644 --- a/avbroot/Cargo.toml +++ b/avbroot/Cargo.toml @@ -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 diff --git a/avbroot/src/format/compression.rs b/avbroot/src/format/compression.rs index 0fe0a81..3d63b24 100644 --- a/avbroot/src/format/compression.rs +++ b/avbroot/src/format/compression.rs @@ -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 = std::result::Result; @@ -114,14 +110,14 @@ pub enum CompressedFormat { Xz, } -pub enum CompressedReader { +pub enum CompressedReader<'reader, R: Read> { None(R), Gzip(GzDecoder), Lz4(FrameDecoder), - Xz(XzDecoder), + Xz(XZReader<'reader, R>), } -impl CompressedReader { +impl<'reader, R: Read + Seek + 'reader> CompressedReader<'reader, R> { pub fn new(mut reader: R, raw_if_unknown: bool) -> Result { let magic = reader.read_array_exact::<6>().map_err(Error::AutoDetect)?; @@ -132,7 +128,7 @@ impl CompressedReader { } 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 CompressedReader { } } -impl Read for CompressedReader { +impl<'reader, R: Read + 'reader> Read for CompressedReader<'reader, R> { fn read(&mut self, buf: &mut [u8]) -> io::Result { match self { Self::None(r) => r.read(buf), @@ -170,14 +166,15 @@ impl Read for CompressedReader { } } -pub enum CompressedWriter { +#[allow(clippy::large_enum_variant)] +pub enum CompressedWriter<'writer, W: Write> { None(W), Gzip(GzEncoder), Lz4Legacy(Lz4LegacyEncoder), - Xz(XzEncoder), + Xz(XZWriter<'writer, W>), } -impl CompressedWriter { +impl<'writer, W: Write + 'writer> CompressedWriter<'writer, W> { pub fn new(writer: W, format: CompressedFormat) -> Result { match format { CompressedFormat::None => Ok(Self::None(writer)), @@ -190,8 +187,11 @@ impl CompressedWriter { } 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 CompressedWriter { } } -impl Write for CompressedWriter { +impl<'writer, W: Write + 'writer> Write for CompressedWriter<'writer, W> { fn write(&mut self, buf: &[u8]) -> io::Result { match self { Self::None(w) => w.write(buf), diff --git a/avbroot/src/format/payload.rs b/avbroot/src/format/payload.rs index 70b1bbc..b836879 100644 --- a/avbroot/src/format/payload.rs +++ b/avbroot/src/format/payload.rs @@ -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, #[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> { - 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()) diff --git a/avbroot/src/stream.rs b/avbroot/src/stream.rs index c88b20b..f950951 100644 --- a/avbroot/src/stream.rs +++ b/avbroot/src/stream.rs @@ -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 { 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 { + 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); diff --git a/e2e/Cargo.toml b/e2e/Cargo.toml index fe092f6..6f19597 100644 --- a/e2e/Cargo.toml +++ b/e2e/Cargo.toml @@ -32,8 +32,5 @@ git = "https://github.com/chenxiaolong/zip2" rev = "59685f4dadbfee8cb3ea74c8fbb402b60d8137e8" default-features = false -[features] -static = ["avbroot/static"] - [lints] workspace = true diff --git a/e2e/e2e.toml b/e2e/e2e.toml index 9ae1fc6..096c993 100644 --- a/e2e/e2e.toml +++ b/e2e/e2e.toml @@ -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"