Compare commits

..

23 Commits

Author SHA1 Message Date
Andrew Gunnerson 02b172b1c9 Version 3.30.1
Signed-off-by: Andrew Gunnerson <accounts+github@chiller3.com>
2026-06-06 16:44:50 -04:00
Andrew Gunnerson 8cbcb44e23 CHANGELOG.md: Add entry for PR #608
Signed-off-by: Andrew Gunnerson <accounts+github@chiller3.com>
2026-06-06 16:42:45 -04:00
Andrew Gunnerson 144e635257 cli/payload: Skip recow for non-VABC payloads when packing
Setting the CoW size for non-VABC payloads is invalid and results in the
recow process failing with:

    ERROR Partition has CoW estimate, but VABC is disabled: <name>

Fixes: #607

Signed-off-by: Andrew Gunnerson <accounts+github@chiller3.com>
2026-06-06 16:33:19 -04:00
Andrew Gunnerson 0c17db4fc4 Version 3.30.0
Signed-off-by: Andrew Gunnerson <accounts+github@chiller3.com>
2026-06-04 22:58:58 -04:00
Andrew Gunnerson a06b7ade86 CHANGELOG.md: Add entry for PR #606
Signed-off-by: Andrew Gunnerson <accounts+github@chiller3.com>
2026-06-04 22:57:50 -04:00
Andrew Gunnerson 22a0196cae ota: Add subcommand to list all partitions
Closes: #603

Signed-off-by: Andrew Gunnerson <accounts+github@chiller3.com>
2026-06-04 22:34:45 -04:00
Andrew Gunnerson f12e2633ce CHANGELOG.md: Add entry for PR #605
Signed-off-by: Andrew Gunnerson <accounts+github@chiller3.com>
2026-06-04 22:34:29 -04:00
Andrew Gunnerson 4fc694039e Update dependencies
The e2e checksums had to be updated due to bug fixes in the lzma-rust2
encoder:

https://github.com/hasenbanck/lzma-rust2/compare/v0.16.2...v0.16.4

Signed-off-by: Andrew Gunnerson <accounts+github@chiller3.com>
2026-06-04 22:28:40 -04:00
Andrew Gunnerson 1b4789a337 README.md: Document how keys correspond to AOSP keys
Fixes: #604

Signed-off-by: Andrew Gunnerson <accounts+github@chiller3.com>
2026-06-04 21:25:39 -04:00
Ivan 6387b8ae4d README.ru.md: Update translation
* https://github.com/chenxiaolong/avbroot/commit/6f8de8b2c4cde899e30c8d1744f8c19b5a742f6d
* https://github.com/chenxiaolong/avbroot/commit/fce0bfabab05ccea25a90fb9b014b0a4dd3b760b
* https://github.com/chenxiaolong/avbroot/commit/f82db7aafcb3f8a0229df1ef86c91d8631b90e0b

also noticed that I had missed https://github.com/chenxiaolong/avbroot/commit/d7439e15aedb77948e7079fc1e23c2f44e6636ec a while back. added that, too.

Signed-off-by: Ivan <reddxae@proton.me>
2026-05-28 16:50:48 +03:00
Andrew Gunnerson f82db7aafc README.md: Update minimum fastboot version to 35
https://github.com/chenxiaolong/avbroot/pull/316#issuecomment-4526748687

Signed-off-by: Andrew Gunnerson <accounts+github@chiller3.com>
2026-05-26 09:31:57 -04:00
Andrew Gunnerson fce0bfabab README.md: Clarify that license is GPLv3 only
Signed-off-by: Andrew Gunnerson <accounts+github@chiller3.com>
2026-04-25 15:32:19 -04:00
Andrew Gunnerson 07b6901d8e Version 3.29.1
Signed-off-by: Andrew Gunnerson <accounts+github@chiller3.com>
2026-04-23 11:36:35 -04:00
Andrew Gunnerson b2b3d98005 CHANGELOG.md: Add entry for PR #594
Signed-off-by: Andrew Gunnerson <accounts+github@chiller3.com>
2026-04-23 11:26:51 -04:00
Andrew Gunnerson 21c1dc86ce format/payload: Allow manifests up to 16 MiB
The memory limit prevented some larger incremental OTAs from being
loaded.

Fixes: #593

Signed-off-by: Andrew Gunnerson <accounts+github@chiller3.com>
2026-04-23 11:24:57 -04:00
Andrew Gunnerson 462084ac18 Version 3.29.0
Signed-off-by: Andrew Gunnerson <accounts+github@chiller3.com>
2026-03-28 01:15:32 -04:00
Andrew Gunnerson 4c3e1efd99 CHANGELOG.md: Add entry for PR #587
Signed-off-by: Andrew Gunnerson <accounts+github@chiller3.com>
2026-03-28 01:14:41 -04:00
Andrew Gunnerson 9b7f27e384 cli/payload: Add support for unpacking skeleton images
This is useful for getting properly sized (but empty) image files when
unpacking delta payloads.

Discussion: #582

Signed-off-by: Andrew Gunnerson <accounts+github@chiller3.com>
2026-03-28 01:03:37 -04:00
Andrew Gunnerson 2120827755 CHANGELOG.md: Add entry for PR #586
Signed-off-by: Andrew Gunnerson <accounts+github@chiller3.com>
2026-03-28 00:56:58 -04:00
Andrew Gunnerson 8b33645026 cli/zip: Add support for packing/unpacking the payload at the same time
This is more efficient since there's no need to waste space on an extra
copy of payload.bin when we can directly read it from the zip file or
directly write to the zip file.

Discussion: #582

Signed-off-by: Andrew Gunnerson <accounts+github@chiller3.com>
2026-03-28 00:22:02 -04:00
Andrew Gunnerson eafc6ad3b4 Version 3.28.0
Signed-off-by: Andrew Gunnerson <accounts+github@chiller3.com>
2026-03-25 18:48:32 -04:00
Andrew Gunnerson 188d256d03 CHANGELOG.md: Add entry for PR #584
Signed-off-by: Andrew Gunnerson <accounts+github@chiller3.com>
2026-03-25 18:41:08 -04:00
Andrew Gunnerson c1836d01a4 cli/payload: Allow unpacking only metadata from delta payloads
The images are the only parts that can't be extracted. Having the
unpacked metadata is useful because it allows for manually building a
full payload using the metadata from the delta payload.

Discussion: #582

Signed-off-by: Andrew Gunnerson <accounts+github@chiller3.com>
2026-03-25 18:40:07 -04:00
17 changed files with 683 additions and 236 deletions
+2 -2
View File
@@ -47,7 +47,7 @@ jobs:
android_api: '31'
steps:
- name: Check out repository
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3
with:
# For git describe
fetch-depth: 0
@@ -160,7 +160,7 @@ jobs:
run: cp LICENSE README.md target/output/
- name: Archive executable
uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7.0.0
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
with:
name: avbroot-${{ steps.get_version.outputs.version }}-${{ matrix.artifact.name }}
path: |
+2 -2
View File
@@ -10,7 +10,7 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: Check out repository
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3
- name: Run cargo-deny
uses: EmbarkStudios/cargo-deny-action@3fd3802e88374d3fe9159b834c7714ec57d6c979 # v2.0.15
uses: EmbarkStudios/cargo-deny-action@bb137d7af7e4fb67e5f82a49c4fce4fad40782fe # v2.0.20
+2 -2
View File
@@ -24,10 +24,10 @@ jobs:
echo "version=${version}" >> "${GITHUB_OUTPUT}"
- name: Check out repository
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3
- name: Create release
uses: softprops/action-gh-release@153bb8e04406b158c6c84fc1615b65b24149a1fe # v2.6.1
uses: softprops/action-gh-release@b4309332981a82ec1c5618f44dd2e27cc8bfbfda # v3.0.0
with:
tag_name: v${{ steps.get_version.outputs.version }}
name: Version ${{ steps.get_version.outputs.version }}
+33
View File
@@ -7,6 +7,28 @@
to update the actual links at the bottom of the file.
-->
### Version 3.30.1
* Fix `avbroot payload pack` and `avbroot zip pack --payload` for non-VABC devices ([Issue #607], [PR #608])
### Version 3.30.0
* Add `avbroot ota list` subcommand to list all partitions in an OTA ([Issue #603], [PR #606])
* Update dependencies ([PR #605])
### Version 3.29.1
* Increase memory limit for payload manifest size to 16 MiB ([Issue #593], [PR #594])
### Version 3.29.0
* Add support for unpacking/packing payloads at the same time as the OTA in `avbroot zip {unpack,pack}` ([Discussion #582], [PR #586])
* Add new `--skeleton` option to `avbroot payload unpack` ([Discussion #582], [PR #587])
### Version 3.28.0
* Add support for unpacking metadata from delta payloads in `avbroot payload unpack` ([Discussion #582], [PR #584])
### Version 3.27.0
* Add support for LZMA compression for ramdisks ([Issue #578], [PR #580])
@@ -441,6 +463,7 @@ Behind-the-scenes changes:
[Discussion #294]: https://github.com/chenxiaolong/avbroot/discussions/294
[Discussion #417]: https://github.com/chenxiaolong/avbroot/discussions/417
[Discussion #426]: https://github.com/chenxiaolong/avbroot/discussions/426
[Discussion #582]: https://github.com/chenxiaolong/avbroot/discussions/582
[Issue #138]: https://github.com/chenxiaolong/avbroot/issues/138
[Issue #144]: https://github.com/chenxiaolong/avbroot/issues/144
[Issue #145]: https://github.com/chenxiaolong/avbroot/issues/145
@@ -480,6 +503,9 @@ Behind-the-scenes changes:
[Issue #554]: https://github.com/chenxiaolong/avbroot/issues/554
[Issue #569]: https://github.com/chenxiaolong/avbroot/issues/569
[Issue #578]: https://github.com/chenxiaolong/avbroot/issues/578
[Issue #593]: https://github.com/chenxiaolong/avbroot/issues/593
[Issue #603]: https://github.com/chenxiaolong/avbroot/issues/603
[Issue #607]: https://github.com/chenxiaolong/avbroot/issues/607
[PR #130]: https://github.com/chenxiaolong/avbroot/pull/130
[PR #132]: https://github.com/chenxiaolong/avbroot/pull/132
[PR #133]: https://github.com/chenxiaolong/avbroot/pull/133
@@ -707,3 +733,10 @@ Behind-the-scenes changes:
[PR #573]: https://github.com/chenxiaolong/avbroot/pull/573
[PR #579]: https://github.com/chenxiaolong/avbroot/pull/579
[PR #580]: https://github.com/chenxiaolong/avbroot/pull/580
[PR #584]: https://github.com/chenxiaolong/avbroot/pull/584
[PR #586]: https://github.com/chenxiaolong/avbroot/pull/586
[PR #587]: https://github.com/chenxiaolong/avbroot/pull/587
[PR #594]: https://github.com/chenxiaolong/avbroot/pull/594
[PR #605]: https://github.com/chenxiaolong/avbroot/pull/605
[PR #606]: https://github.com/chenxiaolong/avbroot/pull/606
[PR #608]: https://github.com/chenxiaolong/avbroot/pull/608
Generated
+220 -112
View File
@@ -16,7 +16,7 @@ checksum = "b169f7a6d4742236a0a00c541b845991d0ac43e546831af1249753ab4c3aa3a0"
dependencies = [
"cfg-if",
"cipher",
"cpufeatures",
"cpufeatures 0.2.17",
]
[[package]]
@@ -98,13 +98,13 @@ checksum = "9b34d609dfbaf33d6889b2b7106d3ca345eacad44200913df5ba02bfd31d2ba9"
[[package]]
name = "autocfg"
version = "1.5.0"
version = "1.5.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c08606f8c3cbf4ce6ec8e28fb0014a2c086708fe954eaa885384a6165172e7e8"
checksum = "f2032f911046de80f0a198e0901378627c33f59ea0ac00e363d481118bd70a53"
[[package]]
name = "avbroot"
version = "3.27.0"
version = "3.30.1"
dependencies = [
"anyhow",
"assert_matches",
@@ -115,7 +115,7 @@ dependencies = [
"clap",
"clap_complete",
"cms",
"const-oid",
"const-oid 0.9.6",
"constcat",
"crc32fast",
"ctrlc",
@@ -144,7 +144,7 @@ dependencies = [
"rustix",
"serde",
"sha1",
"sha2",
"sha2 0.10.9",
"system-properties",
"tempfile",
"thiserror",
@@ -191,15 +191,15 @@ dependencies = [
"quote",
"regex",
"rustc-hash",
"shlex",
"shlex 1.3.0",
"syn 2.0.117",
]
[[package]]
name = "bitflags"
version = "2.11.0"
version = "2.12.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "843867be96c8daad0d758b57df9392b6d8d271134fce549de6ce169ff98a92af"
checksum = "84d7ced0ae9557296835c32bf1b1e02b44c746701f898460fb000d7eaa84f00a"
dependencies = [
"serde_core",
]
@@ -213,6 +213,15 @@ dependencies = [
"generic-array",
]
[[package]]
name = "block-buffer"
version = "0.12.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cdd35008169921d80bc60d3d0ab416eecb028c4cd653352907921d95084790be"
dependencies = [
"hybrid-array",
]
[[package]]
name = "block-padding"
version = "0.3.3"
@@ -268,12 +277,12 @@ dependencies = [
[[package]]
name = "cc"
version = "1.2.57"
version = "1.2.63"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7a0dd1ca384932ff3641c8718a02769f1698e7563dc6974ffd03346116310423"
checksum = "556e016178bb5662a08681bbe0f00f8e17631781a4dfc8c45e466e4b185ec27f"
dependencies = [
"find-msvc-tools",
"shlex",
"shlex 2.0.1",
]
[[package]]
@@ -303,7 +312,7 @@ version = "0.4.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "773f3b9af64447d2ce9850330c473515014aa235e6a783b02db81ff39e4a3dad"
dependencies = [
"crypto-common",
"crypto-common 0.1.7",
"inout",
]
@@ -320,9 +329,9 @@ dependencies = [
[[package]]
name = "clap"
version = "4.6.0"
version = "4.6.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b193af5b67834b676abd72466a96c1024e6a6ad978a1f484bd90b85c94041351"
checksum = "1ddb117e43bbf7dacf0a4190fef4d345b9bad68dfc649cb349e7d17d28428e51"
dependencies = [
"clap_builder",
"clap_derive",
@@ -342,18 +351,18 @@ dependencies = [
[[package]]
name = "clap_complete"
version = "4.6.0"
version = "4.6.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "19c9f1dde76b736e3681f28cec9d5a61299cbaae0fce80a68e43724ad56031eb"
checksum = "e0a7a9bfdb35811f9e59832f0f05975114d2251b415fb534108e6f34060fd772"
dependencies = [
"clap",
]
[[package]]
name = "clap_derive"
version = "4.6.0"
version = "4.6.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1110bd8a634a1ab8cb04345d8d878267d57c3cf1b38d91b71af6686408bbca6a"
checksum = "f2ce8604710f6733aa641a2b3731eaa1e8b3d9973d5e3565da11800813f997a9"
dependencies = [
"heck",
"proc-macro2",
@@ -373,7 +382,7 @@ version = "0.2.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7b77c319abfd5219629c45c34c89ba945ed3c5e49fcde9d16b6c3885f118a730"
dependencies = [
"const-oid",
"const-oid 0.9.6",
"der",
"spki",
"x509-cert",
@@ -391,6 +400,12 @@ version = "0.9.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c2459377285ad874054d797f3ccebf984978aa39129f6eafde5cdc8315b612f8"
[[package]]
name = "const-oid"
version = "0.10.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a6ef517f0926dd24a1582492c791b6a4818a4d94e789a334894aa15b0d12f55c"
[[package]]
name = "constcat"
version = "0.6.1"
@@ -406,6 +421,15 @@ dependencies = [
"libc",
]
[[package]]
name = "cpufeatures"
version = "0.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8b2a41393f66f16b0823bb79094d54ac5fbd34ab292ddafb9a0456ac9f87d201"
dependencies = [
"libc",
]
[[package]]
name = "crc32fast"
version = "1.5.0"
@@ -450,6 +474,15 @@ dependencies = [
"typenum",
]
[[package]]
name = "crypto-common"
version = "0.2.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ce6e4c961d6cd6c9a86db418387425e8bdeaf05b3c8bc1411e6dca4c252f1453"
dependencies = [
"hybrid-array",
]
[[package]]
name = "ctrlc"
version = "3.5.2"
@@ -502,7 +535,7 @@ version = "0.7.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e7c1832837b905bbfb5101e07cc24c8deddf52f93225eee6ead5f4d63d53ddcb"
dependencies = [
"const-oid",
"const-oid 0.9.6",
"der_derive",
"flagset",
"pem-rfc7468",
@@ -526,12 +559,23 @@ version = "0.10.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292"
dependencies = [
"block-buffer",
"const-oid",
"crypto-common",
"block-buffer 0.10.4",
"const-oid 0.9.6",
"crypto-common 0.1.7",
"subtle",
]
[[package]]
name = "digest"
version = "0.11.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f1dd6dbb5841937940781866fa1281a1ff7bd3bf827091440879f9994983d5c2"
dependencies = [
"block-buffer 0.12.0",
"const-oid 0.10.2",
"crypto-common 0.2.2",
]
[[package]]
name = "dispatch2"
version = "0.3.1"
@@ -552,7 +596,7 @@ checksum = "ecb08c4819242b1ec89b3d0c6affa229005bef46ae4f7eed8b80768187c10087"
[[package]]
name = "e2e"
version = "3.27.0"
version = "3.30.1"
dependencies = [
"anyhow",
"avbroot",
@@ -573,9 +617,9 @@ dependencies = [
[[package]]
name = "either"
version = "1.15.0"
version = "1.16.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "48c757948c5ede0e46177b7add2e67155f70e33c07fea8284df6576da70b3719"
checksum = "91622ff5e7162018101f2fea40d6ebf4a78bbe5a49736a2020649edf9693679e"
[[package]]
name = "equivalent"
@@ -601,9 +645,9 @@ checksum = "cfc25fd417983cc7f203394ebb89eba18e2df1b0ac1be2673091b5aca52b595f"
[[package]]
name = "fastrand"
version = "2.3.0"
version = "2.4.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "37909eebbb50d72f9059c3b6d82c0463f2ff062c9e95845c43a6c9c0355411be"
checksum = "9f1f227452a390804cdb637b74a86990f2a7d7ba4b7d5693aac9b4dd6defd8d6"
[[package]]
name = "find-msvc-tools"
@@ -648,7 +692,7 @@ checksum = "d9c4f5dac5e15c24eb999c26181a6ca40b39fe946cbe4c263c7209467bc83af2"
[[package]]
name = "fuzz"
version = "3.27.0"
version = "3.30.1"
dependencies = [
"avbroot",
"honggfuzz",
@@ -728,9 +772,9 @@ dependencies = [
[[package]]
name = "hashbrown"
version = "0.16.1"
version = "0.17.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "841d1cc9bed7f9236f321df977030373f4a4163ae1a7dbfe1a51a2c1a51d9100"
checksum = "ed5909b6e89a2db4456e54cd5f673791d7eca6732202bbf2a9cc504fe2f9b84a"
[[package]]
name = "heck"
@@ -753,14 +797,14 @@ version = "0.12.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6c49c37c09c17a53d937dfbb742eb3a961d65a994e6bcdcf37e7399d0cc8ab5e"
dependencies = [
"digest",
"digest 0.10.7",
]
[[package]]
name = "honggfuzz"
version = "0.5.59"
version = "0.5.60"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9724607fd5cc535fceca960d7f684a1735c4e96c26b4e43986fe8ce798c2550e"
checksum = "4d6510a410acedd7a7683b3a45dafdc5ccf3c72d6addaa373497005964fc4e23"
dependencies = [
"arbitrary",
"lazy_static",
@@ -769,6 +813,15 @@ dependencies = [
"semver",
]
[[package]]
name = "hybrid-array"
version = "0.4.12"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9155a582abd142abc056962c29e3ce5ff2ad5469f4246b537ed42c5deba857da"
dependencies = [
"typenum",
]
[[package]]
name = "id-arena"
version = "2.3.0"
@@ -783,12 +836,12 @@ checksum = "b9e0384b61958566e926dc50660321d12159025e767c18e043daf26b70104c39"
[[package]]
name = "indexmap"
version = "2.13.0"
version = "2.14.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7714e70437a7dc3ac8eb7e6f8df75fd8eb422675fc7678aff7364301092b1017"
checksum = "d466e9454f08e4a911e14806c24e16fba1b4c121d1ea474396f396069cf949d9"
dependencies = [
"equivalent",
"hashbrown 0.16.1",
"hashbrown 0.17.1",
"serde",
"serde_core",
]
@@ -829,9 +882,9 @@ dependencies = [
[[package]]
name = "itoa"
version = "1.0.17"
version = "1.0.18"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "92ecc6618181def0457392ccd0ee51198e065e016d1d527a7ac1b6dc7c1f09d2"
checksum = "8f42a60cbdf9a97f5d2305f08a87dc4e09308d1276d28c869c684d7777685682"
[[package]]
name = "lazy_static"
@@ -850,15 +903,15 @@ checksum = "09edd9e8b54e49e587e4f6295a7d29c3ea94d469cb40ab8ca70b288248a81db2"
[[package]]
name = "libbz2-rs-sys"
version = "0.2.2"
version = "0.2.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2c4a545a15244c7d945065b5d392b2d2d7f21526fba56ce51467b06ed445e8f7"
checksum = "34b357333733e8260735ba5894eb928c02ecc69c78715f01a8019e7fa7f2db4c"
[[package]]
name = "libc"
version = "0.2.183"
version = "0.2.186"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b5b646652bf6661599e1da8901b3b9522896f01e736bad5f723fe7a3a27f899d"
checksum = "68ab91017fe16c622486840e4c83c9a37afeff978bd239b5293d61ece587de66"
[[package]]
name = "libloading"
@@ -884,9 +937,9 @@ checksum = "32a66949e030da00e8c7d4434b251670a91556f4144941d37452769c25d58a53"
[[package]]
name = "log"
version = "0.4.29"
version = "0.4.32"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5e5032e24019045c762d3c0f28f5b6b8bbf38563a65908389bf7978758920897"
checksum = "953f07c43838f8e6f9758cab68bf5bed85465e7587ebe0b823f1bcd81978ad3a"
[[package]]
name = "logos"
@@ -894,7 +947,16 @@ version = "0.15.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ff472f899b4ec2d99161c51f60ff7075eeb3097069a36050d8037a6325eb8154"
dependencies = [
"logos-derive",
"logos-derive 0.15.1",
]
[[package]]
name = "logos"
version = "0.16.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "eb2c55a318a87600ea870ff8c2012148b44bf18b74fad48d0f835c38c7d07c5f"
dependencies = [
"logos-derive 0.16.1",
]
[[package]]
@@ -913,38 +975,61 @@ dependencies = [
"syn 2.0.117",
]
[[package]]
name = "logos-codegen"
version = "0.16.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "58b3ffaa284e1350d017a57d04ada118c4583cf260c8fb01e0fe28a2e9cf8970"
dependencies = [
"fnv",
"proc-macro2",
"quote",
"regex-automata",
"regex-syntax",
"syn 2.0.117",
]
[[package]]
name = "logos-derive"
version = "0.15.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "605d9697bcd5ef3a42d38efc51541aa3d6a4a25f7ab6d1ed0da5ac632a26b470"
dependencies = [
"logos-codegen",
"logos-codegen 0.15.1",
]
[[package]]
name = "logos-derive"
version = "0.16.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "52d3a9855747c17eaf4383823f135220716ab49bea5fbea7dd42cc9a92f8aa31"
dependencies = [
"logos-codegen 0.16.1",
]
[[package]]
name = "lz4_flex"
version = "0.13.0"
version = "0.13.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "db9a0d582c2874f68138a16ce1867e0ffde6c0bb0a0df85e1f36d04146db488a"
checksum = "7ef0d4ed8669f8f8826eb00dc878084aa8f253506c4fd5e8f58f5bce72ddb97e"
dependencies = [
"twox-hash",
]
[[package]]
name = "lzma-rust2"
version = "0.16.2"
version = "0.16.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "47bb1e988e6fb779cf720ad431242d3f03167c1b3f2b1aae7f1a94b2495b36ae"
checksum = "ce716bf1a316f47a280fc76295f6495b5bea4752bca01c3b3885e101b1c23c02"
dependencies = [
"sha2",
"sha2 0.11.0",
]
[[package]]
name = "memchr"
version = "2.8.0"
version = "2.8.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f8ca58f447f06ed17d5fc4043ce1b10dd205e060fb3ce5b979b8ed8e59ff3f79"
checksum = "6b947ae49db0d222b1dbc6b113ce7248a3fc3a6ca21b696717bfc000ba4484d8"
[[package]]
name = "memmap2"
@@ -1001,9 +1086,9 @@ checksum = "1d87ecb2933e8aeadb3e3a02b828fed80a7528047e68b4f424523a0981a3a084"
[[package]]
name = "nix"
version = "0.31.2"
version = "0.31.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5d6d0705320c1e6ba1d912b5e37cf18071b6c2e9b7fa8215a1e8a7651966f5d3"
checksum = "cf20d2fde8ff38632c426f1165ed7436270b44f199fc55284c38276f9db47c3d"
dependencies = [
"bitflags",
"cfg-if",
@@ -1120,7 +1205,7 @@ version = "0.12.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f8ed6a7761f76e3b9f92dfb0a60a6a6477c61024b775147ff0973a02653abaf2"
dependencies = [
"digest",
"digest 0.10.7",
"hmac",
]
@@ -1215,7 +1300,7 @@ dependencies = [
"der",
"pbkdf2",
"scrypt",
"sha2",
"sha2 0.10.9",
"spki",
]
@@ -1303,11 +1388,11 @@ dependencies = [
[[package]]
name = "prost-reflect"
version = "0.16.3"
version = "0.16.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b89455ef41ed200cafc47c76c552ee7792370ac420497e551f16123a9135f76e"
checksum = "590aa145fee8f7a26b5a6055365e7c5e89a5c1caae9869de76ec0ee73181a2f9"
dependencies = [
"logos",
"logos 0.16.1",
"miette",
"prost",
"prost-types",
@@ -1343,7 +1428,7 @@ version = "0.9.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "072eee358134396a4643dff81cfff1c255c9fbd3fb296be14bdb6a26f9156366"
dependencies = [
"logos",
"logos 0.15.1",
"miette",
"prost-types",
"thiserror",
@@ -1366,9 +1451,9 @@ checksum = "f8dcc9c7d52a811697d2151c701e0d08956f92b0e24136cf4cf27b57a6a0d9bf"
[[package]]
name = "rand"
version = "0.8.5"
version = "0.8.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404"
checksum = "5ca0ecfa931c29007047d1bc58e623ab12e5590e8c7cc53200d5202b69266d8a"
dependencies = [
"libc",
"rand_chacha",
@@ -1402,9 +1487,9 @@ checksum = "9d9575f44c8cf85bc843ad666dcdf20d05a7753772bef56eb2a5140282b32150"
[[package]]
name = "rayon"
version = "1.11.0"
version = "1.12.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "368f01d005bf8fd9b1206fb6fa653e6c4a81ceb1466406b81792d87c5677a58f"
checksum = "fb39b166781f92d482534ef4b4b1b2568f42613b53e5b6c160e24cfbfa30926d"
dependencies = [
"either",
"rayon-core",
@@ -1469,8 +1554,8 @@ version = "0.9.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b8573f03f5883dcaebdfcf4725caa1ecb9c15b2ef50c43a07b816e06799bb12d"
dependencies = [
"const-oid",
"digest",
"const-oid 0.9.6",
"digest 0.10.7",
"num-bigint-dig",
"num-integer",
"num-traits",
@@ -1478,7 +1563,7 @@ dependencies = [
"pkcs8",
"rand_core",
"sha1",
"sha2",
"sha2 0.10.9",
"signature",
"spki",
"subtle",
@@ -1487,9 +1572,9 @@ dependencies = [
[[package]]
name = "rustc-hash"
version = "2.1.1"
version = "2.1.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "357703d41365b4b27c590e3ed91eabb1b663f07c4c084095e60cbed4362dff0d"
checksum = "94300abf3f1ae2e2b8ffb7b58043de3d399c73fa6f4b73826402a5c457614dbe"
[[package]]
name = "rustc_version"
@@ -1530,14 +1615,14 @@ checksum = "0516a385866c09368f0b5bcd1caff3366aace790fcd46e2bb032697bb172fd1f"
dependencies = [
"pbkdf2",
"salsa20",
"sha2",
"sha2 0.10.9",
]
[[package]]
name = "semver"
version = "1.0.27"
version = "1.0.28"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d767eb0aabc880b29956c35734170f26ed551a859dbd361d140cdbeca61ab1e2"
checksum = "8a7852d02fc848982e0c167ef163aaff9cd91dc640ba85e263cb1ce46fae51cd"
[[package]]
name = "serde"
@@ -1571,9 +1656,9 @@ dependencies = [
[[package]]
name = "serde_json"
version = "1.0.149"
version = "1.0.150"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "83fc039473c5595ace860d8c4fafa220ff474b3fc6bfdb4293327f1a37e94d86"
checksum = "e8014e44b4736ed0538adeecded0fce2a272f22dc9578a7eb6b2d9993c74cfb9"
dependencies = [
"itoa",
"memchr",
@@ -1584,9 +1669,9 @@ dependencies = [
[[package]]
name = "serde_spanned"
version = "1.0.4"
version = "1.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f8bbf91e5a4d6315eee45e704372590b30e260ee83af6639d64557f51b067776"
checksum = "6662b5879511e06e8999a8a235d848113e942c9124f211511b16466ee2995f26"
dependencies = [
"serde_core",
]
@@ -1598,8 +1683,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e3bf829a2d51ab4a5ddf1352d8470c140cadc8301b2ae1789db023f01cedd6ba"
dependencies = [
"cfg-if",
"cpufeatures",
"digest",
"cpufeatures 0.2.17",
"digest 0.10.7",
]
[[package]]
@@ -1609,8 +1694,19 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a7507d819769d01a365ab707794a4084392c824f54a7a6a7862f8c3d0892b283"
dependencies = [
"cfg-if",
"cpufeatures",
"digest",
"cpufeatures 0.2.17",
"digest 0.10.7",
]
[[package]]
name = "sha2"
version = "0.11.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "446ba717509524cb3f22f17ecc096f10f4822d76ab5c0b9822c5f9c284e825f4"
dependencies = [
"cfg-if",
"cpufeatures 0.3.0",
"digest 0.11.3",
]
[[package]]
@@ -1628,27 +1724,33 @@ version = "1.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64"
[[package]]
name = "shlex"
version = "2.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f8fadd59c855ef2080decdef8ff161eb6661b86933c9d82e5ba29dc602a55aba"
[[package]]
name = "signature"
version = "2.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "77549399552de45a898a580c1b41d445bf730df867cc44e6c0233bbc4b8329de"
dependencies = [
"digest",
"digest 0.10.7",
"rand_core",
]
[[package]]
name = "simd-adler32"
version = "0.3.8"
version = "0.3.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e320a6c5ad31d271ad523dcf3ad13e2767ad8b1cb8f047f75a8aeaf8da139da2"
checksum = "703d5c7ef118737c72f1af64ad2f6f8c5e1921f818cdcb97b8fe6fc69bf66214"
[[package]]
name = "siphasher"
version = "1.0.2"
version = "1.0.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b2aa850e253778c88a04c3d7323b043aeda9d3e30d5971937c1855769763678e"
checksum = "8ee5873ec9cce0195efcb7a4e9507a04cd49aec9c83d0389df45b1ef7ba2e649"
[[package]]
name = "smallvec"
@@ -1797,9 +1899,9 @@ dependencies = [
[[package]]
name = "toml"
version = "1.0.7+spec-1.1.0"
version = "1.1.2+spec-1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "dd28d57d8a6f6e458bc0b8784f8fdcc4b99a437936056fa122cb234f18656a96"
checksum = "81f3d15e84cbcd896376e6730314d59fb5a87f31e4b038454184435cd57defee"
dependencies = [
"indexmap",
"serde_core",
@@ -1812,18 +1914,18 @@ dependencies = [
[[package]]
name = "toml_datetime"
version = "1.0.1+spec-1.1.0"
version = "1.1.1+spec-1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9b320e741db58cac564e26c607d3cc1fdc4a88fd36c879568c07856ed83ff3e9"
checksum = "3165f65f62e28e0115a00b2ebdd37eb6f3b641855f9d636d3cd4103767159ad7"
dependencies = [
"serde_core",
]
[[package]]
name = "toml_edit"
version = "0.25.5+spec-1.1.0"
version = "0.25.12+spec-1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8ca1a40644a28bce036923f6a431df0b34236949d111cc07cb6dca830c9ef2e1"
checksum = "d2153edc6955a6c354fad8f5efd38b6a8769bdccf9fe50f8e1329f81b0baa5d7"
dependencies = [
"indexmap",
"toml_datetime",
@@ -1834,18 +1936,18 @@ dependencies = [
[[package]]
name = "toml_parser"
version = "1.0.10+spec-1.1.0"
version = "1.1.2+spec-1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7df25b4befd31c4816df190124375d5a20c6b6921e2cad937316de3fccd63420"
checksum = "a2abe9b86193656635d2411dc43050282ca48aa31c2451210f4202550afb7526"
dependencies = [
"winnow",
]
[[package]]
name = "toml_writer"
version = "1.0.7+spec-1.1.0"
version = "1.1.1+spec-1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f17aaa1c6e3dc22b1da4b6bba97d066e354c7945cac2f7852d4e4e7ca7a6b56d"
checksum = "756daf9b1013ebe47a8776667b466417e2d4c5679d441c26230efd9ef78692db"
[[package]]
name = "topological-sort"
@@ -1918,9 +2020,9 @@ checksum = "9ea3136b675547379c4bd395ca6b938e5ad3c3d20fad76e7fe85f9e0d011419c"
[[package]]
name = "typenum"
version = "1.19.0"
version = "1.20.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "562d481066bde0658276a35467c4af00bdc6ee726305698a55b86e61d7ad82bb"
checksum = "b6f5e870be6c3b371b77fe0ee0bafb859fa4964b4404c27de1d380043c4dda20"
[[package]]
name = "unicode-ident"
@@ -1972,11 +2074,11 @@ checksum = "ccf3ec651a847eb01de73ccad15eb7d99f80485de043efb2f370cd654f4ea44b"
[[package]]
name = "wasip2"
version = "1.0.2+wasi-0.2.9"
version = "1.0.3+wasi-0.2.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9517f9239f02c069db75e65f174b3da828fe5f5b945c4dd26bd25d89c03ebcf5"
checksum = "20064672db26d7cdc89c7798c48a0fdfac8213434a1186e5ef29fd560ae223d6"
dependencies = [
"wit-bindgen",
"wit-bindgen 0.57.1",
]
[[package]]
@@ -1985,7 +2087,7 @@ version = "0.4.0+wasi-0.3.0-rc-2026-01-06"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5428f8bf88ea5ddc08faddef2ac4a67e390b88186c703ce6dbd955e1c145aca5"
dependencies = [
"wit-bindgen",
"wit-bindgen 0.51.0",
]
[[package]]
@@ -2112,9 +2214,9 @@ checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec"
[[package]]
name = "winnow"
version = "1.0.0"
version = "1.0.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a90e88e4667264a994d34e6d1ab2d26d398dcdca8b7f52bec8668957517fc7d8"
checksum = "0592e1c9d151f854e6fd382574c3a0855250e1d9b2f99d9281c6e6391af352f1"
dependencies = [
"memchr",
]
@@ -2128,6 +2230,12 @@ dependencies = [
"wit-bindgen-rust-macro",
]
[[package]]
name = "wit-bindgen"
version = "0.57.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1ebf944e87a7c253233ad6766e082e3cd714b5d03812acc24c318f549614536e"
[[package]]
name = "wit-bindgen-core"
version = "0.51.0"
@@ -2213,7 +2321,7 @@ version = "0.2.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1301e935010a701ae5f8655edc0ad17c44bad3ac5ce8c39185f75453b720ae94"
dependencies = [
"const-oid",
"const-oid 0.9.6",
"der",
"sha1",
"signature",
@@ -2223,7 +2331,7 @@ dependencies = [
[[package]]
name = "xtask"
version = "3.27.0"
version = "3.30.1"
dependencies = [
"anyhow",
"clap",
@@ -2233,18 +2341,18 @@ dependencies = [
[[package]]
name = "zerocopy"
version = "0.8.47"
version = "0.8.50"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "efbb2a062be311f2ba113ce66f697a4dc589f85e78a4aea276200804cea0ed87"
checksum = "3b065d4f0e55f82fae73202e189638116a87c55ab6b8e6c2721e13dd9d854ad1"
dependencies = [
"zerocopy-derive",
]
[[package]]
name = "zerocopy-derive"
version = "0.8.47"
version = "0.8.50"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0e8bc7269b54418e7aeeef514aa68f8690b8c0489a06b0136e5f57c4c5ccab89"
checksum = "0b631b19d36a892ab55420c92dbc83ccd79274f25be714855d3074aa71cab639"
dependencies = [
"proc-macro2",
"quote",
+1 -1
View File
@@ -4,7 +4,7 @@ members = ["avbroot", "e2e", "fuzz", "xtask"]
resolver = "2"
[workspace.package]
version = "3.27.0"
version = "3.30.1"
license = "GPL-3.0-only"
edition = "2024"
repository = "https://github.com/chenxiaolong/avbroot"
+7 -3
View File
@@ -340,7 +340,7 @@ avbroot payload unpack -i <input payload>
This subcommand unpacks the payload header information to `payload.toml` and the partition images to the `payload_images` directory.
Only full payload binaries can be unpacked. Delta payload binaries from incremental OTAs are not supported.
Data can only be unpacked from full payload binaries. For delta payloads, either use `--no-output-images` to skip image extraction or use `--skeleton` to create properly sized sparse files with no data.
### Packing a payload binary
@@ -429,19 +429,23 @@ This set of commands is for working with raw OTA zip files. They are intentional
### Unpacking an OTA zip
```bash
avbroot zip unpack -i <input OTA>
avbroot zip unpack -i <input OTA> [--payload]
```
This subcommand unpacks the OTA metadata to `ota.toml` and the OTA files to the `ota_files` directory.
When `--payload` is specified, the payload and OTA zip will be unpacked at the same time, which is significantly more efficient that unpack the payload and OTA zip separately. The payload unpacking process writes to the same `payload.toml` and `payload_images` outputs as `avbroot payload unpack`.
### Packing an OTA zip
```bash
avbroot zip pack -o <output OTA> -k <OTA private key>
avbroot zip pack -o <output OTA> -k <OTA private key> [--payload]
```
This subcommand packs a new OTA zip from the `ota.toml` file and `ota_files` directory. Any files in the `ota_files` directory that don't have a corresponding entry in `ota.toml` are silently ignored.
When `--payload` is specified, the payload and OTA zip will be packed at the same time, which is significantly more efficient than packing the payload and OTA zip separately. The payload packing process reads the same `payload.toml` and `payload_images` inputs as `avbroot payload pack`.
When packing an OTA zip, the `metadata.property_files` field in `ota.toml` may potentially be recomputed. To write a TOML file containing the new values, use `--output-info <output TOML>`. It is safe to overwrite the existing `ota.toml` if desired.
### Repacking an OTA zip
+29 -2
View File
@@ -134,9 +134,26 @@ The commands above are provided for convenience. avbroot is compatible with any
If you lose your AVB or OTA signing key, you will no longer be able to sign new OTA zips. You will have to generate new signing keys and unlock your bootloader again (triggering a data wipe). Follow the [Usage section](#usage) as if doing an initial setup.
### AOSP keys
If you're building Android from source, this is how avbroot's keys correspond to AOSP's keys:
| avbroot | AOSP |
|----------------|-----------------------|
| `avb.key` | `avb.pem` |
| `avb_pkmd.bin` | `avb_pkmd.bin` |
| `ota.key` | `releasekey.pk8` |
| `ota.crt` | `releasekey.x509.pem` |
To use an AOSP `releasekey.pk8` key with avbroot, it must be converted from DER to PEM first:
```bash
openssl pkcs8 -topk8 -scrypt -in releasekey.pk8 -out ota.key -outform PEM
```
## Initial setup
1. Make sure that the version of fastboot is 34 or newer. Older versions have bugs that prevent the `fastboot flashall` command (required later) from working properly.
1. Make sure that the version of fastboot is 35 or newer. Older versions have bugs that prevent the `fastboot flashall` command (required later) from working properly.
```bash
fastboot --version
@@ -503,6 +520,16 @@ By default, this only extracts the images that could potentially be patched by a
This command also supports extracting the embedded OTA certificate and AVB public key using the `--cert-ota` and `--public-key-avb` options. To extract only these components, pass in `--none` to skip extracting partition images.
### Listing partitions in OTA
To list all partitions in an OTA, run:
```bash
avbroot ota list --input ota.zip
```
The output format is one partition per line with no formatting.
### Zip write mode
By default, avbroot uses streaming writes for the output OTA during patching. This means it computes the sha256 digest for the digital signature as the file is being written. This mode causes the zip file to contain data descriptors, which is part of the zip standard and works on the vast majority of devices. However, some devices may have broken zip file parsers and fail to properly read OTA zip files containing data descriptors. If this is the case, pass in `--zip-mode seekable` when patching.
@@ -614,4 +641,4 @@ Contributions are welcome! However, I'm unlikely to accept changes for supportin
## License
avbroot is licensed under GPLv3. Please see [`LICENSE`](./LICENSE) for the full license text.
avbroot is licensed under GPL-3.0-only. Please see [`LICENSE`](./LICENSE) for the full license text.
+12 -2
View File
@@ -134,7 +134,7 @@ avbroot совместим с любым стандартным 4096-битны
## Первоначальная настройка
1. Убедитесь, что вы используете утилиту fastboot версии 34 или новее. Предыдущие версии содержат баги, что не позволяют команде `fastboot flashall` (которая понадобится по ходу инструкции) работать правильно.
1. Убедитесь, что вы используете утилиту fastboot версии 35 или новее. Предыдущие версии содержат баги, что не позволяют команде `fastboot flashall` (которая понадобится по ходу инструкции) работать правильно.
```bash
fastboot --version
@@ -419,6 +419,16 @@ avbroot поддерживает подмену целых образов в OTA
Это не влияет на ход применения пачтей. Например, при использовании Magisk, патч получения root-прав применяется к загрузочному образу одинаково, независимо от того, был ли он получен из оригинального `payload.bin` или это файл, указанный через `--replace`.
### Переподписание разделов
avbroot автоматически переподписывает все разделы в OTA, которые он изменяет. Однако и те разделы, что не были затронуты, также можно переподписать с помощью параметра `--re-sign <имя раздела>`. Это полезно, например, когда OTA содержит разделы, подписанные публичным тестовым ключом AOSP (test key).
### Загрузка подписанных GSI
Функция [динамических обновлений системы (DSU)](https://developer.android.com/topic/dsu?hl=ru) в Android использует корень доверия, отличный от используемого обычной системой. Вместо `avb_custom_key` в загрузчике, она получает доверенные ключи из файлов `first_stage_ramdisk/avb/*.avbpubkey` в ramdisk'е разделов `init_boot` или `vendor_boot`. Эти файлы закодированы в том же двоичном формате, что и файл `avb_pkmd.bin`.
avbroot может добавить пользовательский публичный ключ AVB в эту директорию с помощью параметра `--dsu` при патчинге OTA. Это позволяет запускать [общие образы системы (GSI)](https://developer.android.com/topic/generic-system-image?hl=ru), подписанные пользовательским ключом AVB.
### Очистка флагов vbmeta
Некоторые сборки Android-прошивок могут поставляться с образом `vbmeta`, в котором флаги установлены таким образом, что AVB фактически отключен. Если avbroot сталкивается с такими образом, процесс патчинга завершается ошибкой с сообщением следующего типа:
@@ -598,5 +608,5 @@ cargo android build --release --target aarch64-linux-android
## Лицензия
avbroot распространяется по лицензии GPLv3. Полный текст лицензии см. в [`LICENSE`.](./LICENSE)
avbroot распространяется по лицензии GPL-3.0-only. Полный текст лицензии см. в [`LICENSE`.](./LICENSE)
+59 -2
View File
@@ -1228,11 +1228,11 @@ fn patch_ota_payload(
.with_context(|| format!("Failed to copy from original payload: {name}"))?;
}
let (_, _, properties, metadata_size) = payload_writer
let (_, header, properties) = payload_writer
.finish()
.context("Failed to finalize payload")?;
Ok((properties, metadata_size))
Ok((properties, header.blob_offset))
}
#[allow(clippy::too_many_arguments)]
@@ -2254,11 +2254,58 @@ pub fn verify_subcommand(cli: &VerifyCli, cancel_signal: &AtomicBool) -> Result<
Ok(())
}
pub fn list_subcommand(cli: &ListCli) -> Result<()> {
let raw_reader = File::open(&cli.input)
.with_context(|| format!("Failed to open for reading: {:?}", cli.input))?;
let mut buffer = vec![0u8; RECOMMENDED_BUFFER_SIZE];
let zip = ZipArchive::from_read_at(&raw_reader, &mut buffer)
.with_context(|| format!("Failed to read zip: {:?}", cli.input))?;
let mut entries = zip.entries_safe(&mut buffer);
while let Some((cd_entry, _)) =
entries.next_entry().context("Failed to list zip entries")?
{
let path = cd_entry
.file_path_utf8()
.context("Zip contains non-UTF-8 paths")?;
if path != ota::PATH_PAYLOAD {
continue;
}
let entry_reader = zip
.get_entry(cd_entry.wayfinder())
.and_then(|e| zip::verifying_reader(&e, cd_entry.compression_method()))
.with_context(|| format!("Failed to open zip entry: {path}"))?;
let header = PayloadHeader::from_reader(entry_reader)
.context("Failed to load OTA payload header")?;
for partition in header.manifest.partitions {
let name = &partition.partition_name;
util::path_ensure_single(name)?;
// Ensure the output cannot be misparsed since we use newlines as a
// separator.
if name.contains('\n') {
bail!("Partition name contains newline: {name:?}");
}
println!("{name}");
}
return Ok(());
}
bail!("Zip entry not found: {}", ota::PATH_PAYLOAD);
}
pub fn ota_main(cli: &OtaCli, cancel_signal: &AtomicBool) -> Result<()> {
match &cli.command {
OtaCommand::Patch(c) => patch_subcommand(c, cancel_signal),
OtaCommand::Extract(c) => extract_subcommand(c, cancel_signal),
OtaCommand::Verify(c) => verify_subcommand(c, cancel_signal),
OtaCommand::List(c) => list_subcommand(c),
}
}
@@ -2612,12 +2659,22 @@ pub struct VerifyCli {
fail_if_missing: bool,
}
/// List partitions contained in an OTA.
#[derive(Debug, Parser)]
pub struct ListCli {
/// Path to OTA zip.
#[arg(short, long, value_name = "FILE", value_parser)]
pub input: PathBuf,
}
#[allow(clippy::large_enum_variant)]
#[derive(Debug, Subcommand)]
enum OtaCommand {
Patch(PatchCli),
Extract(ExtractCli),
Verify(VerifyCli),
List(ListCli),
}
/// Patch or extract OTA images.
+144 -60
View File
@@ -1,11 +1,11 @@
// SPDX-FileCopyrightText: 2024-2025 Andrew Gunnerson
// SPDX-FileCopyrightText: 2024-2026 Andrew Gunnerson
// SPDX-License-Identifier: GPL-3.0-only
use std::{
collections::HashMap,
ffi::OsString,
fs::{self, File},
io::{BufReader, BufWriter, Seek, SeekFrom},
io::{BufReader, BufWriter, Seek, SeekFrom, Write},
path::{Path, PathBuf},
sync::{Arc, atomic::AtomicBool},
};
@@ -18,31 +18,34 @@ use crate::{
cli::ota,
crypto::{self, PassphraseSource, RsaSigningKey},
format::payload::{PayloadHeader, PayloadWriter},
stream::{self, FromReader},
stream::{self, FromReader, SectionReader},
util,
};
fn open_reader(path: &Path, allow_delta: bool) -> Result<(BufReader<File>, PayloadHeader)> {
let mut reader = File::open(path)
.map(BufReader::new)
.with_context(|| format!("Failed to open payload for reading: {path:?}"))?;
fn open_raw_reader(path: &Path) -> Result<File> {
File::open(path).with_context(|| format!("Failed to open payload for reading: {path:?}"))
}
fn open_reader(path: &Path) -> Result<(BufReader<File>, PayloadHeader)> {
let mut reader = open_raw_reader(path).map(BufReader::new)?;
let header = PayloadHeader::from_reader(&mut reader)
.with_context(|| format!("Failed to read payload header: {path:?}"))?;
if !allow_delta && !header.is_full_ota() {
bail!("Payload is a delta OTA, not a full OTA");
}
Ok((reader, header))
}
fn open_raw_writer(path: &Path) -> Result<BufWriter<File>> {
File::create(path)
.map(BufWriter::new)
.with_context(|| format!("Failed to open payload for writing: {path:?}"))
}
fn open_writer(
path: &Path,
header: PayloadHeader,
key: RsaSigningKey,
) -> Result<PayloadWriter<BufWriter<File>>> {
let writer = File::create(path)
.map(BufWriter::new)
.with_context(|| format!("Failed to open payload for writing: {path:?}"))?;
let writer = open_raw_writer(path)?;
let payload_writer = PayloadWriter::new(writer, header, key)
.with_context(|| format!("Failed to write payload header: {path:?}"))?;
@@ -67,8 +70,8 @@ fn write_info(path: &Path, manifest: &PayloadHeader) -> Result<()> {
Ok(())
}
fn display_header(cli: &PayloadCli, header: &PayloadHeader) {
if !cli.quiet {
fn display_header(quiet: bool, header: &PayloadHeader) {
if !quiet {
println!("{header:#?}");
}
}
@@ -99,52 +102,105 @@ fn load_key(group: &KeyGroup) -> Result<RsaSigningKey> {
Ok(signing_key)
}
fn unpack_subcommand(
payload_cli: &PayloadCli,
cli: &UnpackCli,
#[allow(clippy::too_many_arguments)]
pub fn unpack_payload(
quiet: bool,
output_info: &Path,
output_images: &Path,
no_output_images: bool,
skeleton: bool,
reader: &File,
payload_offset: u64,
payload_size: u64,
cancel_signal: &AtomicBool,
) -> Result<()> {
let (mut reader, header) = open_reader(&cli.input, false)?;
let payload_size = reader
.seek(SeekFrom::End(0))
.with_context(|| format!("Failed to get file size: {:?}", cli.input))?;
let section_reader = SectionReader::new(reader, payload_offset, payload_size)
.context("Failed to directly open payload section")?;
let header =
PayloadHeader::from_reader(section_reader).context("Failed to read payload header")?;
display_header(payload_cli, &header);
display_header(quiet, &header);
write_info(&cli.output_info, &header)?;
write_info(output_info, &header)?;
if !cli.no_output_images {
fs::create_dir_all(&cli.output_images)
.with_context(|| format!("Failed to create directory: {:?}", cli.output_images))?;
if !no_output_images {
fs::create_dir_all(output_images)
.with_context(|| format!("Failed to create directory: {output_images:?}"))?;
ota::extract_payload(
&reader.into_inner(),
&cli.output_images,
0,
payload_size,
&header,
&header
.manifest
.partitions
.iter()
.map(|p| &p.partition_name)
.cloned()
.collect(),
cancel_signal,
)?;
if skeleton {
for partition in &header.manifest.partitions {
let name = &partition.partition_name;
let path = util::path_join_single(output_images, format!("{name}.img"))?;
let size = partition
.new_partition_info
.as_ref()
.and_then(|info| info.size)
.ok_or_else(|| anyhow!("Size not found for partition: {name}"))?;
let file = File::create(&path)
.with_context(|| format!("Failed to create file: {path:?}"))?;
file.set_len(size)
.with_context(|| format!("Failed to truncate file: {path:?}"))?;
}
} else {
if !header.is_full_ota() {
bail!("Cannot extract images from a delta payload");
}
ota::extract_payload(
reader,
output_images,
payload_offset,
payload_size,
&header,
&header
.manifest
.partitions
.iter()
.map(|p| &p.partition_name)
.cloned()
.collect(),
cancel_signal,
)?;
}
}
Ok(())
}
fn pack_subcommand(
fn unpack_subcommand(
payload_cli: &PayloadCli,
cli: &PackCli,
cli: &UnpackCli,
cancel_signal: &AtomicBool,
) -> Result<()> {
let signing_key = load_key(&cli.key)?;
let mut reader = open_raw_reader(&cli.input)?;
let payload_size = reader
.seek(SeekFrom::End(0))
.with_context(|| format!("Failed to get file size: {:?}", cli.input))?;
let mut header = read_info(&cli.input_info)?;
unpack_payload(
payload_cli.quiet,
&cli.output_info,
&cli.output_images,
cli.no_output_images,
cli.skeleton,
&reader,
0,
payload_size,
cancel_signal,
)
}
pub fn pack_payload(
quiet: bool,
input_info: &Path,
input_images: &Path,
writer: &mut dyn Write,
signing_key: &RsaSigningKey,
cancel_signal: &AtomicBool,
) -> Result<(String, u64)> {
let mut header = read_info(input_info)?;
// Pre-open all of the image files.
let input_files = header
@@ -152,8 +208,7 @@ fn pack_subcommand(
.partitions
.iter()
.map(|p| {
let path =
util::path_join_single(&cli.input_images, format!("{}.img", p.partition_name))?;
let path = util::path_join_single(input_images, format!("{}.img", p.partition_name))?;
let file = File::open(&path)
.map(Arc::new)
.with_context(|| format!("Failed to open file: {path:?}"))?;
@@ -164,8 +219,11 @@ fn pack_subcommand(
for (name, input_file) in &input_files {
let Some(dpm) = &header.manifest.dynamic_partition_metadata else {
continue;
break;
};
if !dpm.vabc_enabled() {
break;
}
if !dpm.groups.iter().any(|g| g.partition_names.contains(name)) {
continue;
@@ -199,7 +257,8 @@ fn pack_subcommand(
// Now we can write the actual payload. With everything precomputed, this is
// mostly just a simple copy.
let mut payload_writer = open_writer(&cli.output, header.clone(), signing_key)?;
let mut payload_writer = PayloadWriter::new(writer, header.clone(), signing_key.clone())
.context("Failed to write payload header")?;
while payload_writer
.begin_next_operation()
@@ -235,14 +294,35 @@ fn pack_subcommand(
.with_context(|| format!("Failed to copy from replacement image: {name}"))?;
}
let (raw_writer, header, properties, _) = payload_writer
let (_, header, properties) = payload_writer
.finish()
.context("Failed to finalize payload")?;
raw_writer.into_inner().context("Failed to flush payload")?;
// Display the header information now that it has been finalized.
display_header(payload_cli, &header);
display_header(quiet, &header);
Ok((properties, header.blob_offset))
}
fn pack_subcommand(
payload_cli: &PayloadCli,
cli: &PackCli,
cancel_signal: &AtomicBool,
) -> Result<()> {
let signing_key = load_key(&cli.key)?;
let mut writer = open_raw_writer(&cli.output)?;
let (properties, _) = pack_payload(
payload_cli.quiet,
&cli.input_info,
&cli.input_images,
&mut writer,
&signing_key,
cancel_signal,
)?;
writer.into_inner().context("Failed to flush payload")?;
// Optionally, write payload_properties.txt.
if let Some(path) = &cli.output_properties {
@@ -260,7 +340,7 @@ fn repack_subcommand(
) -> Result<()> {
let signing_key = load_key(&cli.key)?;
let (mut reader, header) = open_reader(&cli.input, true)?;
let (mut reader, header) = open_reader(&cli.input)?;
info!("Generating new OTA payload");
@@ -299,12 +379,12 @@ fn repack_subcommand(
.with_context(|| format!("Failed to copy from original payload: {name}"))?;
}
let (_, header, properties, _) = payload_writer
let (_, header, properties) = payload_writer
.finish()
.context("Failed to finalize payload")?;
// Display the header information now that it has been finalized.
display_header(payload_cli, &header);
display_header(payload_cli.quiet, &header);
// Optionally, write payload_properties.txt.
if let Some(path) = &cli.output_properties {
@@ -316,9 +396,9 @@ fn repack_subcommand(
}
fn info_subcommand(payload_cli: &PayloadCli, cli: &InfoCli) -> Result<()> {
let (_, header) = open_reader(&cli.input, true)?;
let (_, header) = open_reader(&cli.input)?;
display_header(payload_cli, &header);
display_header(payload_cli.quiet, &header);
Ok(())
}
@@ -391,8 +471,12 @@ struct UnpackCli {
output_images: PathBuf,
/// Do not output images.
#[arg(long, conflicts_with = "output_images")]
#[arg(long, conflicts_with_all = ["output_images", "skeleton"])]
no_output_images: bool,
/// Only create empty sparse files for output images.
#[arg(long)]
skeleton: bool,
}
/// Pack a payload binary.
+151 -29
View File
@@ -5,7 +5,7 @@ use std::{
collections::BTreeMap,
ffi::OsString,
fs::{self, File, OpenOptions},
io::{BufReader, Seek},
io::{BufReader, Seek, Write},
path::{Path, PathBuf},
sync::atomic::AtomicBool,
};
@@ -21,6 +21,7 @@ use tracing::warn;
use x509_cert::Certificate;
use crate::{
cli::payload,
crypto::{self, PassphraseSource, RsaSigningKey},
format::{
ota::{self, SigningWriter, ZipEntry, ZipMode},
@@ -137,8 +138,8 @@ fn write_info(path: &Path, info: &OtaInfo) -> Result<()> {
Ok(())
}
fn display_info(cli: &ZipCli, info: &OtaInfo) {
if !cli.quiet {
fn display_info(quiet: bool, info: &OtaInfo) {
if !quiet {
println!("{info:#?}");
}
}
@@ -285,11 +286,33 @@ fn finalize_ota(
fn unpack_subcommand(zip_cli: &ZipCli, cli: &UnpackCli, cancel_signal: &AtomicBool) -> Result<()> {
let (zip_reader, metadata, input_entries) = open_reader(&cli.input)?;
if !cli.no_output_files {
for (path, input_entry) in &input_entries {
let entry = zip_reader
.get_entry(input_entry.wayfinder)
.with_context(|| format!("Failed to open zip entry: {path}"))?;
for (path, input_entry) in &input_entries {
let entry = zip_reader
.get_entry(input_entry.wayfinder)
.with_context(|| format!("Failed to open zip entry: {path}"))?;
if cli.payload && path == ota::PATH_PAYLOAD {
let (payload_offset, payload_size) = {
let range = entry.compressed_data_range();
(range.0, range.1 - range.0)
};
payload::unpack_payload(
zip_cli.quiet,
&cli.output_payload_info,
&cli.output_payload_images,
cli.no_output_payload_images,
cli.payload_skeleton,
&zip_reader.get_ref().0,
payload_offset,
payload_size,
cancel_signal,
)?;
} else if cli.payload && path == ota::PATH_PROPERTIES {
// We intentionally ignore this since it's recomputed when
// packing with --payload.
} else if !cli.no_output_files {
let mut entry_reader = zip::verifying_reader(&entry, input_entry.compression_method)
.with_context(|| format!("Failed to open zip entry: {path}"))?;
@@ -312,7 +335,7 @@ fn unpack_subcommand(zip_cli: &ZipCli, cli: &UnpackCli, cancel_signal: &AtomicBo
files: input_entries.into_keys().collect(),
};
display_info(zip_cli, &info);
display_info(zip_cli.quiet, &info);
write_info(&cli.output_info, &info)?;
Ok(())
@@ -331,10 +354,15 @@ fn pack_subcommand(zip_cli: &ZipCli, cli: &PackCli, cancel_signal: &AtomicBool)
continue;
}
let input_path = util::path_join(&cli.input_files, path)?;
let input_size = fs::metadata(&input_path)
.map(|m| m.len())
.with_context(|| format!("Failed to get file size: {input_path:?}"))?;
let input_size =
if cli.payload && (path == ota::PATH_PAYLOAD || path == ota::PATH_PROPERTIES) {
0
} else {
let input_path = util::path_join(&cli.input_files, path)?;
fs::metadata(&input_path)
.map(|m| m.len())
.with_context(|| format!("Failed to get file size: {input_path:?}"))?
};
input_entries.insert(path, input_size >= 0xffffffff);
}
@@ -342,28 +370,56 @@ fn pack_subcommand(zip_cli: &ZipCli, cli: &PackCli, cancel_signal: &AtomicBool)
let mut payload_metadata_size = None;
let mut metadata_entries = vec![];
// Only used when packing the zip and payload at the same time.
let mut payload_properties = None;
for (&path, &is_zip64) in &input_entries {
let (offset, mut data_writer) =
start_entry(&mut zip_writer, path, cli.zip_mode.zip_mode, is_zip64)?;
let input_path = util::path_join(&cli.input_files, path)?;
let mut input_file = File::open(&input_path)
.with_context(|| format!("Failed to open for reading: {input_path:?}"))?;
if path == ota::PATH_PAYLOAD && cli.payload {
// Pack the payload directly into the zip.
let (properties, metadata_size) = payload::pack_payload(
zip_cli.quiet,
&cli.input_payload_info,
&cli.input_payload_images,
&mut data_writer,
&signing_key,
cancel_signal,
)?;
if path == ota::PATH_PAYLOAD {
let header = PayloadHeader::from_reader(&mut input_file)
.with_context(|| format!("Failed to read payload header: {input_path:?}"))?;
payload_metadata_size = Some(metadata_size);
payload_properties = Some(properties);
} else if path == ota::PATH_PROPERTIES && cli.payload {
// We process files in order, so this would only happen if the file
// list did not contain the payload.
let properties = payload_properties
.as_ref()
.ok_or_else(|| anyhow!("Payload has not been processed yet"))?;
payload_metadata_size = Some(header.blob_offset);
data_writer
.write_all(properties.as_bytes())
.with_context(|| format!("Failed to write zip entry: {path}"))?;
} else {
let input_path = util::path_join(&cli.input_files, path)?;
let mut input_file = File::open(&input_path)
.with_context(|| format!("Failed to open for reading: {input_path:?}"))?;
input_file
.rewind()
.with_context(|| format!("Failed to seek file: {input_path:?}"))?;
if path == ota::PATH_PAYLOAD {
let header = PayloadHeader::from_reader(&mut input_file)
.with_context(|| format!("Failed to read payload header: {input_path:?}"))?;
payload_metadata_size = Some(header.blob_offset);
input_file
.rewind()
.with_context(|| format!("Failed to seek file: {input_path:?}"))?;
}
stream::copy(&mut input_file, &mut data_writer, cancel_signal)
.with_context(|| format!("Failed to copy zip entry: {path}"))?;
}
stream::copy(&mut input_file, &mut data_writer, cancel_signal)
.with_context(|| format!("Failed to copy zip entry: {path}"))?;
finalize_entry(path, offset, data_writer, &mut metadata_entries)?;
}
@@ -382,7 +438,7 @@ fn pack_subcommand(zip_cli: &ZipCli, cli: &PackCli, cancel_signal: &AtomicBool)
info.files.retain(|p| !is_excluded_path(p));
info.files.sort();
display_info(zip_cli, &info);
display_info(zip_cli.quiet, &info);
if let Some(path) = &cli.output_info {
write_info(path, &info)?;
@@ -446,7 +502,7 @@ fn repack_subcommand(zip_cli: &ZipCli, cli: &RepackCli, cancel_signal: &AtomicBo
files: input_entries.into_keys().collect(),
};
display_info(zip_cli, &info);
display_info(zip_cli.quiet, &info);
Ok(())
}
@@ -458,7 +514,7 @@ fn info_subcommand(zip_cli: &ZipCli, cli: &InfoCli) -> Result<()> {
files: input_entries.into_keys().collect(),
};
display_info(zip_cli, &info);
display_info(zip_cli.quiet, &info);
Ok(())
}
@@ -541,6 +597,45 @@ struct UnpackCli {
/// Do not output files.
#[arg(long, conflicts_with = "output_files")]
no_output_files: bool,
/// Also unpack the payload in the OTA.
///
/// Unpacking the zip and payload at the same time is more efficient than
/// unpacking them separately.
#[arg(long)]
payload: bool,
/// Path to output payload info TOML.
#[arg(
long,
value_name = "FILE",
value_parser,
default_value = "payload.toml",
requires = "payload"
)]
output_payload_info: PathBuf,
/// Path to output payload images directory.
#[arg(
long,
value_name = "DIR",
value_parser,
default_value = "payload_images",
requires = "payload"
)]
output_payload_images: PathBuf,
/// Do not output payload images.
#[arg(
long,
conflicts_with_all = ["output_payload_images", "payload_skeleton"],
requires = "payload"
)]
no_output_payload_images: bool,
/// Only create empty sparse files for output payload images.
#[arg(long, requires = "payload")]
payload_skeleton: bool,
}
/// Pack an OTA zip.
@@ -573,6 +668,33 @@ struct PackCli {
#[arg(long, value_name = "DIR", value_parser, default_value = "ota_files")]
input_files: PathBuf,
/// Also pack the payload in the OTA.
///
/// Packing the zip and payload at the same time is more efficient than
/// packing them separately.
#[arg(long)]
payload: bool,
/// Path to input payload info TOML.
#[arg(
long,
value_name = "FILE",
value_parser,
default_value = "payload.toml",
requires = "payload"
)]
input_payload_info: PathBuf,
/// Path to input payload images directory.
#[arg(
long,
value_name = "DIR",
value_parser,
default_value = "payload_images",
requires = "payload"
)]
input_payload_images: PathBuf,
#[command(flatten)]
key: KeyGroup,
+11 -9
View File
@@ -1,4 +1,4 @@
// SPDX-FileCopyrightText: 2022-2025 Andrew Gunnerson
// SPDX-FileCopyrightText: 2022-2026 Andrew Gunnerson
// SPDX-License-Identifier: GPL-3.0-only
use std::{
@@ -45,7 +45,7 @@ use crate::{
const PAYLOAD_MAGIC: &[u8; 4] = b"CrAU";
const PAYLOAD_VERSION: u64 = 2;
const MANIFEST_MAX_SIZE: usize = 4 * 1024 * 1024;
const MANIFEST_MAX_SIZE: usize = 16 * 1024 * 1024;
/// Size of each extent. This matches what AOSP's delta_generator does. We also
/// require this to be a multiple of the block size and a multiple of the
@@ -436,11 +436,11 @@ impl<W: Write> PayloadWriter<W> {
/// Finalize the payload. If this function is not called, the payload will
/// be left in an incomplete state. Returns the original writer, the final
/// header, the contents that should be written for `payload_properties.txt`
/// and the length of the header + manifest + manifest signature sections
/// (for constructing the `payload_metadata.bin` OTA metadata property files
/// entry).
pub fn finish(mut self) -> Result<(W, PayloadHeader, String, u64)> {
/// header and the data that should be written for `payload_properties.txt`.
/// [`PayloadHeader::blob_offset`] indicates the length of the header +
/// manifest + manifest signature sections (for constructing the
/// `payload_metadata.bin` OTA metadata property files entry).
pub fn finish(mut self) -> Result<(W, PayloadHeader, String)> {
// Append payload signature.
let payload_partial_hash = self.h_partial.clone().finish();
let payload_sig = sign_digest(payload_partial_hash.as_ref(), &self.key)?;
@@ -465,7 +465,9 @@ impl<W: Write> PayloadWriter<W> {
self.metadata_size as u64,
);
Ok((self.inner, self.header, properties, metadata_with_sig_size))
self.header.blob_offset = metadata_with_sig_size;
Ok((self.inner, self.header, properties))
}
/// Prepare for writing the next source data blob corresponding to an
@@ -1457,7 +1459,7 @@ pub fn compress_image(
.collect::<io::Result<Vec<_>>>()
.map_err(Error::ChunkWrite)?;
operations.extend(group_operations.into_iter());
operations.extend(group_operations);
}
let digest_uncompressed = context_uncompressed.finish();
+1 -1
View File
@@ -313,7 +313,7 @@ pub trait ZipArchiveReadAtExt {
impl ZipArchiveReadAtExt for ZipArchive<()> {}
pub struct ReaderAtWrapper<R: ReadAt>(R);
pub struct ReaderAtWrapper<R: ReadAt>(pub R);
impl<R: ReadAt> ReaderAt for ReaderAtWrapper<R> {
fn read_at(&self, buf: &mut [u8], offset: u64) -> io::Result<usize> {
+1 -1
View File
@@ -1415,7 +1415,7 @@ pub fn patch_boot_images<'a>(
// Regroup data so we can parallelize by target.
let mut groups = HashMap::<&str, (BootImageInfo, Vec<&Box<dyn BootImagePatch + Sync>>)>::new();
for (patcher, targets) in patchers.iter().zip(all_targets.into_iter()) {
for (patcher, targets) in patchers.iter().zip(all_targets) {
for target in targets {
groups
.entry(target)
+6 -6
View File
@@ -53,11 +53,11 @@ data.ramdisks = [["otacerts", "first_stage", "dsu_key_dir"]]
[profile.pixel_v4_gki.hashes_streaming]
original = "ea96196191e3a4133db4aff45d47aa3468514e29e0a724faac8081cbf4adf808"
patched = "c073cbb271099aaf338a8c70f3565ec70db47a87b4c9bb3efffd96ccee1a0c27"
patched = "6b88761a7927ea4a3fdd953cbb7ffb78361e51648f5ab7a34b0dffad2bc163d5"
[profile.pixel_v4_gki.hashes_seekable]
original = "f6615ae355eba38689d24aa535981d09175d4832e7c65c04cdd89aa95d21f09d"
patched = "65ce91a95574a308ffc5279696efe7f6f7e4e847795dc9ae43d9ffd012a7ce3f"
patched = "e9c0b85a0f9384d3e022f3c83a4653511cd03bfbfa26e660b35cf52986dec888"
# Google Pixel 6a
# What's unique: boot (boot v4, no ramdisk) + vendor_boot (vendor v4, 2 ramdisks)
@@ -141,11 +141,11 @@ data.ramdisks = [["otacerts", "first_stage", "dsu_key_dir"]]
[profile.pixel_v3.hashes_streaming]
original = "4b864b906a13ec98b1d6c3440a5eca7404ec63d073080e80a3b84afabcbd2fa2"
patched = "da3b9a4d6a58bb5aaadfc63006cb36b7af9c1c5945e81b38587c245bd5ad1f5a"
patched = "cdb9f92e357d8fdf43640704cf7c73917f026e0f759991871ccbab4bfd8c303b"
[profile.pixel_v3.hashes_seekable]
original = "e0e93ee11de56992f3a5f543858c1d11858b4deb76a91a4caf4fb0f3f34be855"
patched = "71682a4f31a5920784a0e2e38a6ee5fe3c65213436c7bf1ce347b121cd01a367"
patched = "bd57432a97feb62c5e4116f0d5bc3b5db61dd46ffa6e436403d197f091a19a55"
# Google Pixel 4a
# What's unique: boot (boot v2)
@@ -174,8 +174,8 @@ data.deps = ["system"]
[profile.pixel_v2.hashes_streaming]
original = "abc0ad7f80020018101437c2494d6564a877df663d208a123267fc100734c175"
patched = "132fb4d90e3c19a7a5ee0da2082767228255228ea5fb66811df1ccd5ff600bb5"
patched = "deea7ebf412d413743f14792fbf5605dea1a2a099114b33b9e05d464d90e1228"
[profile.pixel_v2.hashes_seekable]
original = "57d4ac5ab7d362a593f3c02f3d2044b5400c10db0f732741a2d18e025d4231ec"
patched = "b365eb32f463ac4ba13f7bed4e6535a68483379640dc6e842c591f194db042c2"
patched = "71f49a27c801b837a219927430b41ba37126084d88d141485263a011d2fb9d70"
+2 -2
View File
@@ -704,11 +704,11 @@ fn create_payload(
.with_context(|| format!("Failed to copy from image: {name}"))?;
}
let (_, _, properties, metadata_size) = payload_writer
let (_, header, properties) = payload_writer
.finish()
.context("Failed to finalize payload")?;
Ok((properties, metadata_size))
Ok((properties, header.blob_offset))
}
#[allow(clippy::too_many_arguments)]