aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndroid Build Coastguard Worker <android-build-coastguard-worker@google.com>2023-12-14 16:40:03 +0000
committerAndroid Build Coastguard Worker <android-build-coastguard-worker@google.com>2023-12-14 16:40:03 +0000
commite920e5900ba4117e43e6f16c571b879bd3696ae3 (patch)
tree59f57869a7bcdaecd6059343276ef820f0c1645a
parent197e2599b86357a9d707053508d8f063ac04ba7c (diff)
parentf5dd1b90061ef92623974b839af9b4dc12376d2b (diff)
downloadupdate_engine-aml_tz4_332714010.tar.gz
Snap for 11219529 from f5dd1b90061ef92623974b839af9b4dc12376d2b to mainline-tzdata4-releaseaml_tz4_332714070aml_tz4_332714050aml_tz4_332714010aml_tz4_332714010
Change-Id: I57a14fd8e5cf3f7e6133bf998f639193358d75b8
-rw-r--r--Android.bp8
-rw-r--r--scripts/Android.bp79
-rwxr-xr-xscripts/brillo_update_payload6
-rwxr-xr-x[-rw-r--r--]scripts/simulate_ota.py26
-rw-r--r--scripts/trim_ota_package.py2
-rwxr-xr-xscripts/update_device.py72
-rw-r--r--scripts/update_metadata_pb2.py (renamed from scripts/update_payload/update_metadata_pb2.py)281
-rw-r--r--scripts/update_payload/applier.py621
-rw-r--r--scripts/update_payload/checker.py2
-rwxr-xr-xscripts/update_payload/checker_unittest.py2
-rw-r--r--scripts/update_payload/common.py2
-rw-r--r--scripts/update_payload/payload.py70
-rw-r--r--scripts/update_payload/test_utils.py2
-rw-r--r--update_metadata.proto12
14 files changed, 336 insertions, 849 deletions
diff --git a/Android.bp b/Android.bp
index cace5b61..cdb492f5 100644
--- a/Android.bp
+++ b/Android.bp
@@ -1170,3 +1170,11 @@ cc_binary_host {
"update_metadata-protos",
],
}
+
+python_library_host {
+ name: "update_metadata-protos-python",
+ srcs: ["update_metadata.proto"],
+ proto: {
+ canonical_path_from_root: false,
+ },
+}
diff --git a/scripts/Android.bp b/scripts/Android.bp
new file mode 100644
index 00000000..e86a9f20
--- /dev/null
+++ b/scripts/Android.bp
@@ -0,0 +1,79 @@
+// Copyright (C) 2022 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+//
+// Module-specific defaults.
+//
+// For module X, if we need to build it both as a library and an executable:
+// - A default rule `releasetools_X_defaults` is created, which lists `srcs`, `libs` and
+// `required` properties.
+// - `python_library_host` and `python_binary_host` are created by listing
+// `releasetools_X_defaults` in their defaults.
+//
+
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "system_update_engine_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["system_update_engine_license"],
+}
+
+filegroup {
+ name: "update_device_script",
+ srcs: [
+ "**/*.py",
+ ],
+ path: ".",
+}
+
+python_library_host {
+ name: "update_payload",
+
+ srcs: [
+ "update_payload/__init__.py",
+ "update_payload/payload.py",
+ "update_payload/checker.py",
+ "update_payload/common.py",
+ "update_payload/error.py",
+ "update_payload/histogram.py",
+ "update_payload/format_utils.py",
+ ],
+ proto: {
+ canonical_path_from_root: false,
+ },
+ libs: [
+ "update_metadata-protos-python",
+ ],
+}
+
+python_binary_host {
+ name: "update_device",
+ srcs: [
+ "update_device.py",
+ ],
+ main: "update_device.py",
+ libs: [
+ "update_payload",
+ ],
+ version: {
+ py2: {
+ enabled: false,
+ },
+ py3: {
+ enabled: true,
+ },
+ },
+}
diff --git a/scripts/brillo_update_payload b/scripts/brillo_update_payload
index b2d60801..6652b387 100755
--- a/scripts/brillo_update_payload
+++ b/scripts/brillo_update_payload
@@ -220,6 +220,8 @@ a subset of partitions on device."
"Required if --enabled_lz4diff true is passed. Path to liblz4.so. delta_generator will use this copy of liblz4.so for compression. It is important that this copy of liblz4.so is the same as the one on source build."
DEFINE_string erofs_compression_param "" \
"Compression parameter passed to mkfs.erofs's -z option."
+ DEFINE_string security_patch_level "" \
+ "Optional: security patch level of this OTA"
fi
if [[ "${COMMAND}" == "hash" || "${COMMAND}" == "sign" ]]; then
DEFINE_string unsigned_payload "" "Path to the input unsigned payload."
@@ -776,6 +778,10 @@ cmd_generate() {
GENERATOR_ARGS+=( --max_timestamp="${FLAGS_max_timestamp}" )
fi
+ if [[ -n "${FLAGS_security_patch_level}" ]]; then
+ GENERATOR_ARGS+=( --security_patch_level="${FLAGS_security_patch_level}" )
+ fi
+
if [[ -n "${FLAGS_partition_timestamps}" ]]; then
GENERATOR_ARGS+=( --partition_timestamps="${FLAGS_partition_timestamps}" )
fi
diff --git a/scripts/simulate_ota.py b/scripts/simulate_ota.py
index bf1fc984..0e5a21ba 100644..100755
--- a/scripts/simulate_ota.py
+++ b/scripts/simulate_ota.py
@@ -1,3 +1,4 @@
+#!/usr/bin/env python3
#
# Copyright (C) 2020 The Android Open Source Project
#
@@ -17,8 +18,6 @@
"""Tools for running host side simulation of an OTA update."""
-from __future__ import print_function
-
import argparse
import filecmp
import os
@@ -49,7 +48,8 @@ def is_sparse_image(filepath):
return fp.read(4) == b'\x3A\xFF\x26\xED'
-def extract_img(zip_archive: zipfile.ZipFile, img_name, output_path):
+def extract_img(zip_archive: zipfile.ZipFile, img_name, output_path, is_source):
+ """ Extract and unsparse partition image from zip archive """
entry_name = "IMAGES/" + img_name + ".img"
try:
extract_file(zip_archive, entry_name, output_path)
@@ -61,6 +61,22 @@ def extract_img(zip_archive: zipfile.ZipFile, img_name, output_path):
subprocess.check_output(["simg2img", output_path, raw_img_path])
os.rename(raw_img_path, output_path)
+ # delta_generator only supports images multiple of 4 KiB. For target images
+ # we pad the data with zeros if needed, but for source images we truncate
+ # down the data since the last block of the old image could be padded on
+ # disk with unknown data.
+ file_size = os.path.getsize(output_path)
+ if file_size % 4096 != 0:
+ if is_source:
+ print("Rounding DOWN partition {} to a multiple of 4 KiB."
+ .format(output_path))
+ file_size = file_size & -4096
+ else:
+ print("Rounding UP partition {} to a multiple of 4 KiB."
+ .format(output_path))
+ file_size = (file_size + 4095) & -4096
+ with open(output_path, 'a') as f:
+ f.truncate(file_size)
def run_ota(source, target, payload_path, tempdir, output_dir):
"""Run an OTA on host side"""
@@ -87,10 +103,10 @@ def run_ota(source, target, payload_path, tempdir, output_dir):
"source target file must point to a valid zipfile or directory " + \
source
print("Extracting source image for", name)
- extract_img(source, name, old_image)
+ extract_img(source, name, old_image, True)
if target_exist:
print("Extracting target image for", name)
- extract_img(target, name, new_image)
+ extract_img(target, name, new_image, False)
old_partitions.append(old_image)
scratch_image_name = new_image + ".actual"
diff --git a/scripts/trim_ota_package.py b/scripts/trim_ota_package.py
index df7f1703..8bf2182b 100644
--- a/scripts/trim_ota_package.py
+++ b/scripts/trim_ota_package.py
@@ -27,7 +27,7 @@ def main(argv):
outfile = argv[2]
with zipfile.ZipFile(infile, "r") as inzfp, zipfile.ZipFile(outfile, "w") as outzfp:
for entry in inzfp.infolist():
- if entry.filename.startswith("META") or entry.filename.endswith(".map"):
+ if entry.filename.startswith("META") or entry.filename.endswith(".map") or entry.filename.endswith(".prop"):
outzfp.writestr(entry, inzfp.read(entry))
elif entry.filename == "payload.bin":
outzfp.writestr(entry, readPayloadMetadata(inzfp, entry))
diff --git a/scripts/update_device.py b/scripts/update_device.py
index 72cee494..f94774b1 100755
--- a/scripts/update_device.py
+++ b/scripts/update_device.py
@@ -25,6 +25,7 @@ import binascii
import hashlib
import logging
import os
+import re
import socket
import subprocess
import sys
@@ -50,7 +51,7 @@ PAYLOAD_KEY_PATH = '/etc/update_engine/update-payload-key.pub.pem'
DEVICE_PORT = 1234
-def CopyFileObjLength(fsrc, fdst, buffer_size=128 * 1024, copy_length=None):
+def CopyFileObjLength(fsrc, fdst, buffer_size=128 * 1024, copy_length=None, speed_limit=None):
"""Copy from a file object to another.
This function is similar to shutil.copyfileobj except that it allows to copy
@@ -61,10 +62,18 @@ def CopyFileObjLength(fsrc, fdst, buffer_size=128 * 1024, copy_length=None):
fdst: destination file object where to write to.
buffer_size: size of the copy buffer in memory.
copy_length: maximum number of bytes to copy, or None to copy everything.
+ speed_limit: upper limit for copying speed, in bytes per second.
Returns:
the number of bytes copied.
"""
+ # If buffer size significantly bigger than speed limit
+ # traffic would seem extremely spiky to the client.
+ if speed_limit:
+ print(f"Applying speed limit: {speed_limit}")
+ buffer_size = min(speed_limit//32, buffer_size)
+
+ start_time = time.time()
copied = 0
while True:
chunk_size = buffer_size
@@ -75,6 +84,11 @@ def CopyFileObjLength(fsrc, fdst, buffer_size=128 * 1024, copy_length=None):
buf = fsrc.read(chunk_size)
if not buf:
break
+ if speed_limit:
+ expected_duration = copied/speed_limit
+ actual_duration = time.time() - start_time
+ if actual_duration < expected_duration:
+ time.sleep(expected_duration-actual_duration)
fdst.write(buf)
copied += len(buf)
return copied
@@ -211,7 +225,8 @@ class UpdateHandler(BaseHTTPServer.BaseHTTPRequestHandler):
self.end_headers()
f.seek(serving_start + start_range)
- CopyFileObjLength(f, self.wfile, copy_length=end_range - start_range)
+ CopyFileObjLength(f, self.wfile, copy_length=end_range -
+ start_range, speed_limit=self.speed_limit)
def do_POST(self): # pylint: disable=invalid-name
"""Reply with the omaha response xml."""
@@ -291,12 +306,13 @@ class UpdateHandler(BaseHTTPServer.BaseHTTPRequestHandler):
class ServerThread(threading.Thread):
"""A thread for serving HTTP requests."""
- def __init__(self, ota_filename, serving_range):
+ def __init__(self, ota_filename, serving_range, speed_limit):
threading.Thread.__init__(self)
# serving_payload and serving_range are class attributes and the
# UpdateHandler class is instantiated with every request.
UpdateHandler.serving_payload = ota_filename
UpdateHandler.serving_range = serving_range
+ UpdateHandler.speed_limit = speed_limit
self._httpd = BaseHTTPServer.HTTPServer(('127.0.0.1', 0), UpdateHandler)
self.port = self._httpd.server_port
@@ -312,8 +328,8 @@ class ServerThread(threading.Thread):
self._httpd.socket.close()
-def StartServer(ota_filename, serving_range):
- t = ServerThread(ota_filename, serving_range)
+def StartServer(ota_filename, serving_range, speed_limit):
+ t = ServerThread(ota_filename, serving_range, speed_limit)
t.start()
return t
@@ -408,6 +424,27 @@ def PushMetadata(dut, otafile, metadata_path):
]) == 0
+def ParseSpeedLimit(arg: str) -> int:
+ arg = arg.strip().upper()
+ if not re.match(r"\d+[KkMmGgTt]?", arg):
+ raise argparse.ArgumentError(
+ "Wrong speed limit format, expected format is number followed by unit, such as 10K, 5m, 3G (case insensitive)")
+ unit = 1
+ if arg[-1].isalpha():
+ if arg[-1] == "K":
+ unit = 1024
+ elif arg[-1] == "M":
+ unit = 1024 * 1024
+ elif arg[-1] == "G":
+ unit = 1024 * 1024 * 1024
+ elif arg[-1] == "T":
+ unit = 1024 * 1024 * 1024 * 1024
+ else:
+ raise argparse.ArgumentError(
+ f"Unsupported unit for download speed: {arg[-1]}, supported units are K,M,G,T (case insensitive)")
+ return int(float(arg[:-1]) * unit)
+
+
def main():
parser = argparse.ArgumentParser(description='Android A/B OTA helper.')
parser.add_argument('otafile', metavar='PAYLOAD', type=str,
@@ -444,7 +481,22 @@ def main():
help='Perform reset slot switch for this OTA package')
parser.add_argument('--wipe-user-data', action='store_true',
help='Wipe userdata after installing OTA')
+ parser.add_argument('--vabc-none', action='store_true',
+ help='Set Virtual AB Compression algorithm to none, but still use Android COW format')
+ parser.add_argument('--disable-vabc', action='store_true',
+ help='Option to enable or disable vabc. If set to false, will fall back on A/B')
+ parser.add_argument('--enable-threading', action='store_true',
+ help='Enable multi-threaded compression for VABC')
+ parser.add_argument('--batched-writes', action='store_true',
+ help='Enable batched writes for VABC')
+ parser.add_argument('--speed-limit', type=str,
+ help='Speed limit for serving payloads over HTTP. For '
+ 'example: 10K, 5m, 1G, input is case insensitive')
+
args = parser.parse_args()
+ if args.speed_limit:
+ args.speed_limit = ParseSpeedLimit(args.speed_limit)
+
logging.basicConfig(
level=logging.WARNING if args.no_verbose else logging.INFO)
@@ -497,6 +549,14 @@ def main():
args.extra_headers += "\nRUN_POST_INSTALL=0"
if args.wipe_user_data:
args.extra_headers += "\nPOWERWASH=1"
+ if args.vabc_none:
+ args.extra_headers += "\nVABC_NONE=1"
+ if args.disable_vabc:
+ args.extra_headers += "\nDISABLE_VABC=1"
+ if args.enable_threading:
+ args.extra_headers += "\nENABLE_THREADING=1"
+ if args.batched_writes:
+ args.extra_headers += "\nBATCHED_WRITES=1"
with zipfile.ZipFile(args.otafile) as zfp:
CARE_MAP_ENTRY_NAME = "care_map.pb"
@@ -531,7 +591,7 @@ def main():
serving_range = (ota.offset, ota.size)
else:
serving_range = (0, os.stat(args.otafile).st_size)
- server_thread = StartServer(args.otafile, serving_range)
+ server_thread = StartServer(args.otafile, serving_range, args.speed_limit)
cmds.append(
['reverse', 'tcp:%d' % DEVICE_PORT, 'tcp:%d' % server_thread.port])
finalize_cmds.append(['reverse', '--remove', 'tcp:%d' % DEVICE_PORT])
diff --git a/scripts/update_payload/update_metadata_pb2.py b/scripts/update_metadata_pb2.py
index b62a67a1..cb6c39c7 100644
--- a/scripts/update_payload/update_metadata_pb2.py
+++ b/scripts/update_metadata_pb2.py
@@ -20,7 +20,7 @@ DESCRIPTOR = _descriptor.FileDescriptor(
package='chromeos_update_engine',
syntax='proto2',
serialized_options=_b('H\003'),
- serialized_pb=_b('\n\x15update_metadata.proto\x12\x16\x63hromeos_update_engine\"1\n\x06\x45xtent\x12\x13\n\x0bstart_block\x18\x01 \x01(\x04\x12\x12\n\nnum_blocks\x18\x02 \x01(\x04\"\x9f\x01\n\nSignatures\x12@\n\nsignatures\x18\x01 \x03(\x0b\x32,.chromeos_update_engine.Signatures.Signature\x1aO\n\tSignature\x12\x13\n\x07version\x18\x01 \x01(\rB\x02\x18\x01\x12\x0c\n\x04\x64\x61ta\x18\x02 \x01(\x0c\x12\x1f\n\x17unpadded_signature_size\x18\x03 \x01(\x07\"+\n\rPartitionInfo\x12\x0c\n\x04size\x18\x01 \x01(\x04\x12\x0c\n\x04hash\x18\x02 \x01(\x0c\"\x8f\x01\n\tImageInfo\x12\x11\n\x05\x62oard\x18\x01 \x01(\tB\x02\x18\x01\x12\x0f\n\x03key\x18\x02 \x01(\tB\x02\x18\x01\x12\x13\n\x07\x63hannel\x18\x03 \x01(\tB\x02\x18\x01\x12\x13\n\x07version\x18\x04 \x01(\tB\x02\x18\x01\x12\x19\n\rbuild_channel\x18\x05 \x01(\tB\x02\x18\x01\x12\x19\n\rbuild_version\x18\x06 \x01(\tB\x02\x18\x01\"\xfc\x03\n\x10InstallOperation\x12;\n\x04type\x18\x01 \x02(\x0e\x32-.chromeos_update_engine.InstallOperation.Type\x12\x13\n\x0b\x64\x61ta_offset\x18\x02 \x01(\x04\x12\x13\n\x0b\x64\x61ta_length\x18\x03 \x01(\x04\x12\x33\n\x0bsrc_extents\x18\x04 \x03(\x0b\x32\x1e.chromeos_update_engine.Extent\x12\x12\n\nsrc_length\x18\x05 \x01(\x04\x12\x33\n\x0b\x64st_extents\x18\x06 \x03(\x0b\x32\x1e.chromeos_update_engine.Extent\x12\x12\n\ndst_length\x18\x07 \x01(\x04\x12\x18\n\x10\x64\x61ta_sha256_hash\x18\x08 \x01(\x0c\x12\x17\n\x0fsrc_sha256_hash\x18\t \x01(\x0c\"\xbb\x01\n\x04Type\x12\x0b\n\x07REPLACE\x10\x00\x12\x0e\n\nREPLACE_BZ\x10\x01\x12\x0c\n\x04MOVE\x10\x02\x1a\x02\x08\x01\x12\x0e\n\x06\x42SDIFF\x10\x03\x1a\x02\x08\x01\x12\x0f\n\x0bSOURCE_COPY\x10\x04\x12\x11\n\rSOURCE_BSDIFF\x10\x05\x12\x0e\n\nREPLACE_XZ\x10\x08\x12\x08\n\x04ZERO\x10\x06\x12\x0b\n\x07\x44ISCARD\x10\x07\x12\x11\n\rBROTLI_BSDIFF\x10\n\x12\x0c\n\x08PUFFDIFF\x10\t\x12\x0c\n\x08ZUCCHINI\x10\x0b\"\x81\x02\n\x11\x43owMergeOperation\x12<\n\x04type\x18\x01 \x01(\x0e\x32..chromeos_update_engine.CowMergeOperation.Type\x12\x32\n\nsrc_extent\x18\x02 \x01(\x0b\x32\x1e.chromeos_update_engine.Extent\x12\x32\n\ndst_extent\x18\x03 \x01(\x0b\x32\x1e.chromeos_update_engine.Extent\x12\x12\n\nsrc_offset\x18\x04 \x01(\r\"2\n\x04Type\x12\x0c\n\x08\x43OW_COPY\x10\x00\x12\x0b\n\x07\x43OW_XOR\x10\x01\x12\x0f\n\x0b\x43OW_REPLACE\x10\x02\"\xc8\x06\n\x0fPartitionUpdate\x12\x16\n\x0epartition_name\x18\x01 \x02(\t\x12\x17\n\x0frun_postinstall\x18\x02 \x01(\x08\x12\x18\n\x10postinstall_path\x18\x03 \x01(\t\x12\x17\n\x0f\x66ilesystem_type\x18\x04 \x01(\t\x12M\n\x17new_partition_signature\x18\x05 \x03(\x0b\x32,.chromeos_update_engine.Signatures.Signature\x12\x41\n\x12old_partition_info\x18\x06 \x01(\x0b\x32%.chromeos_update_engine.PartitionInfo\x12\x41\n\x12new_partition_info\x18\x07 \x01(\x0b\x32%.chromeos_update_engine.PartitionInfo\x12<\n\noperations\x18\x08 \x03(\x0b\x32(.chromeos_update_engine.InstallOperation\x12\x1c\n\x14postinstall_optional\x18\t \x01(\x08\x12=\n\x15hash_tree_data_extent\x18\n \x01(\x0b\x32\x1e.chromeos_update_engine.Extent\x12\x38\n\x10hash_tree_extent\x18\x0b \x01(\x0b\x32\x1e.chromeos_update_engine.Extent\x12\x1b\n\x13hash_tree_algorithm\x18\x0c \x01(\t\x12\x16\n\x0ehash_tree_salt\x18\r \x01(\x0c\x12\x37\n\x0f\x66\x65\x63_data_extent\x18\x0e \x01(\x0b\x32\x1e.chromeos_update_engine.Extent\x12\x32\n\nfec_extent\x18\x0f \x01(\x0b\x32\x1e.chromeos_update_engine.Extent\x12\x14\n\tfec_roots\x18\x10 \x01(\r:\x01\x32\x12\x0f\n\x07version\x18\x11 \x01(\t\x12\x43\n\x10merge_operations\x18\x12 \x03(\x0b\x32).chromeos_update_engine.CowMergeOperation\x12\x19\n\x11\x65stimate_cow_size\x18\x13 \x01(\x04\"L\n\x15\x44ynamicPartitionGroup\x12\x0c\n\x04name\x18\x01 \x02(\t\x12\x0c\n\x04size\x18\x02 \x01(\x04\x12\x17\n\x0fpartition_names\x18\x03 \x03(\t\"\xbe\x01\n\x18\x44ynamicPartitionMetadata\x12=\n\x06groups\x18\x01 \x03(\x0b\x32-.chromeos_update_engine.DynamicPartitionGroup\x12\x18\n\x10snapshot_enabled\x18\x02 \x01(\x08\x12\x14\n\x0cvabc_enabled\x18\x03 \x01(\x08\x12\x1e\n\x16vabc_compression_param\x18\x04 \x01(\t\x12\x13\n\x0b\x63ow_version\x18\x05 \x01(\r\"c\n\x08\x41pexInfo\x12\x14\n\x0cpackage_name\x18\x01 \x01(\t\x12\x0f\n\x07version\x18\x02 \x01(\x03\x12\x15\n\ris_compressed\x18\x03 \x01(\x08\x12\x19\n\x11\x64\x65\x63ompressed_size\x18\x04 \x01(\x03\"C\n\x0c\x41pexMetadata\x12\x33\n\tapex_info\x18\x01 \x03(\x0b\x32 .chromeos_update_engine.ApexInfo\"\x9e\x07\n\x14\x44\x65ltaArchiveManifest\x12H\n\x12install_operations\x18\x01 \x03(\x0b\x32(.chromeos_update_engine.InstallOperationB\x02\x18\x01\x12O\n\x19kernel_install_operations\x18\x02 \x03(\x0b\x32(.chromeos_update_engine.InstallOperationB\x02\x18\x01\x12\x18\n\nblock_size\x18\x03 \x01(\r:\x04\x34\x30\x39\x36\x12\x19\n\x11signatures_offset\x18\x04 \x01(\x04\x12\x17\n\x0fsignatures_size\x18\x05 \x01(\x04\x12\x42\n\x0fold_kernel_info\x18\x06 \x01(\x0b\x32%.chromeos_update_engine.PartitionInfoB\x02\x18\x01\x12\x42\n\x0fnew_kernel_info\x18\x07 \x01(\x0b\x32%.chromeos_update_engine.PartitionInfoB\x02\x18\x01\x12\x42\n\x0fold_rootfs_info\x18\x08 \x01(\x0b\x32%.chromeos_update_engine.PartitionInfoB\x02\x18\x01\x12\x42\n\x0fnew_rootfs_info\x18\t \x01(\x0b\x32%.chromeos_update_engine.PartitionInfoB\x02\x18\x01\x12=\n\x0eold_image_info\x18\n \x01(\x0b\x32!.chromeos_update_engine.ImageInfoB\x02\x18\x01\x12=\n\x0enew_image_info\x18\x0b \x01(\x0b\x32!.chromeos_update_engine.ImageInfoB\x02\x18\x01\x12\x18\n\rminor_version\x18\x0c \x01(\r:\x01\x30\x12;\n\npartitions\x18\r \x03(\x0b\x32\'.chromeos_update_engine.PartitionUpdate\x12\x15\n\rmax_timestamp\x18\x0e \x01(\x03\x12T\n\x1a\x64ynamic_partition_metadata\x18\x0f \x01(\x0b\x32\x30.chromeos_update_engine.DynamicPartitionMetadata\x12\x16\n\x0epartial_update\x18\x10 \x01(\x08\x12\x33\n\tapex_info\x18\x11 \x03(\x0b\x32 .chromeos_update_engine.ApexInfoB\x02H\x03')
+ serialized_pb=_b('\n\x15update_metadata.proto\x12\x16\x63hromeos_update_engine\"1\n\x06\x45xtent\x12\x13\n\x0bstart_block\x18\x01 \x01(\x04\x12\x12\n\nnum_blocks\x18\x02 \x01(\x04\"\x9f\x01\n\nSignatures\x12@\n\nsignatures\x18\x01 \x03(\x0b\x32,.chromeos_update_engine.Signatures.Signature\x1aO\n\tSignature\x12\x13\n\x07version\x18\x01 \x01(\rB\x02\x18\x01\x12\x0c\n\x04\x64\x61ta\x18\x02 \x01(\x0c\x12\x1f\n\x17unpadded_signature_size\x18\x03 \x01(\x07\"+\n\rPartitionInfo\x12\x0c\n\x04size\x18\x01 \x01(\x04\x12\x0c\n\x04hash\x18\x02 \x01(\x0c\"\xa6\x04\n\x10InstallOperation\x12;\n\x04type\x18\x01 \x02(\x0e\x32-.chromeos_update_engine.InstallOperation.Type\x12\x13\n\x0b\x64\x61ta_offset\x18\x02 \x01(\x04\x12\x13\n\x0b\x64\x61ta_length\x18\x03 \x01(\x04\x12\x33\n\x0bsrc_extents\x18\x04 \x03(\x0b\x32\x1e.chromeos_update_engine.Extent\x12\x12\n\nsrc_length\x18\x05 \x01(\x04\x12\x33\n\x0b\x64st_extents\x18\x06 \x03(\x0b\x32\x1e.chromeos_update_engine.Extent\x12\x12\n\ndst_length\x18\x07 \x01(\x04\x12\x18\n\x10\x64\x61ta_sha256_hash\x18\x08 \x01(\x0c\x12\x17\n\x0fsrc_sha256_hash\x18\t \x01(\x0c\"\xe5\x01\n\x04Type\x12\x0b\n\x07REPLACE\x10\x00\x12\x0e\n\nREPLACE_BZ\x10\x01\x12\x0c\n\x04MOVE\x10\x02\x1a\x02\x08\x01\x12\x0e\n\x06\x42SDIFF\x10\x03\x1a\x02\x08\x01\x12\x0f\n\x0bSOURCE_COPY\x10\x04\x12\x11\n\rSOURCE_BSDIFF\x10\x05\x12\x0e\n\nREPLACE_XZ\x10\x08\x12\x08\n\x04ZERO\x10\x06\x12\x0b\n\x07\x44ISCARD\x10\x07\x12\x11\n\rBROTLI_BSDIFF\x10\n\x12\x0c\n\x08PUFFDIFF\x10\t\x12\x0c\n\x08ZUCCHINI\x10\x0b\x12\x12\n\x0eLZ4DIFF_BSDIFF\x10\x0c\x12\x14\n\x10LZ4DIFF_PUFFDIFF\x10\r\"\x81\x02\n\x11\x43owMergeOperation\x12<\n\x04type\x18\x01 \x01(\x0e\x32..chromeos_update_engine.CowMergeOperation.Type\x12\x32\n\nsrc_extent\x18\x02 \x01(\x0b\x32\x1e.chromeos_update_engine.Extent\x12\x32\n\ndst_extent\x18\x03 \x01(\x0b\x32\x1e.chromeos_update_engine.Extent\x12\x12\n\nsrc_offset\x18\x04 \x01(\r\"2\n\x04Type\x12\x0c\n\x08\x43OW_COPY\x10\x00\x12\x0b\n\x07\x43OW_XOR\x10\x01\x12\x0f\n\x0b\x43OW_REPLACE\x10\x02\"\xc8\x06\n\x0fPartitionUpdate\x12\x16\n\x0epartition_name\x18\x01 \x02(\t\x12\x17\n\x0frun_postinstall\x18\x02 \x01(\x08\x12\x18\n\x10postinstall_path\x18\x03 \x01(\t\x12\x17\n\x0f\x66ilesystem_type\x18\x04 \x01(\t\x12M\n\x17new_partition_signature\x18\x05 \x03(\x0b\x32,.chromeos_update_engine.Signatures.Signature\x12\x41\n\x12old_partition_info\x18\x06 \x01(\x0b\x32%.chromeos_update_engine.PartitionInfo\x12\x41\n\x12new_partition_info\x18\x07 \x01(\x0b\x32%.chromeos_update_engine.PartitionInfo\x12<\n\noperations\x18\x08 \x03(\x0b\x32(.chromeos_update_engine.InstallOperation\x12\x1c\n\x14postinstall_optional\x18\t \x01(\x08\x12=\n\x15hash_tree_data_extent\x18\n \x01(\x0b\x32\x1e.chromeos_update_engine.Extent\x12\x38\n\x10hash_tree_extent\x18\x0b \x01(\x0b\x32\x1e.chromeos_update_engine.Extent\x12\x1b\n\x13hash_tree_algorithm\x18\x0c \x01(\t\x12\x16\n\x0ehash_tree_salt\x18\r \x01(\x0c\x12\x37\n\x0f\x66\x65\x63_data_extent\x18\x0e \x01(\x0b\x32\x1e.chromeos_update_engine.Extent\x12\x32\n\nfec_extent\x18\x0f \x01(\x0b\x32\x1e.chromeos_update_engine.Extent\x12\x14\n\tfec_roots\x18\x10 \x01(\r:\x01\x32\x12\x0f\n\x07version\x18\x11 \x01(\t\x12\x43\n\x10merge_operations\x18\x12 \x03(\x0b\x32).chromeos_update_engine.CowMergeOperation\x12\x19\n\x11\x65stimate_cow_size\x18\x13 \x01(\x04\"L\n\x15\x44ynamicPartitionGroup\x12\x0c\n\x04name\x18\x01 \x02(\t\x12\x0c\n\x04size\x18\x02 \x01(\x04\x12\x17\n\x0fpartition_names\x18\x03 \x03(\t\"8\n\x0eVABCFeatureSet\x12\x10\n\x08threaded\x18\x01 \x01(\x08\x12\x14\n\x0c\x62\x61tch_writes\x18\x02 \x01(\x08\"\x80\x02\n\x18\x44ynamicPartitionMetadata\x12=\n\x06groups\x18\x01 \x03(\x0b\x32-.chromeos_update_engine.DynamicPartitionGroup\x12\x18\n\x10snapshot_enabled\x18\x02 \x01(\x08\x12\x14\n\x0cvabc_enabled\x18\x03 \x01(\x08\x12\x1e\n\x16vabc_compression_param\x18\x04 \x01(\t\x12\x13\n\x0b\x63ow_version\x18\x05 \x01(\r\x12@\n\x10vabc_feature_set\x18\x06 \x01(\x0b\x32&.chromeos_update_engine.VABCFeatureSet\"c\n\x08\x41pexInfo\x12\x14\n\x0cpackage_name\x18\x01 \x01(\t\x12\x0f\n\x07version\x18\x02 \x01(\x03\x12\x15\n\ris_compressed\x18\x03 \x01(\x08\x12\x19\n\x11\x64\x65\x63ompressed_size\x18\x04 \x01(\x03\"C\n\x0c\x41pexMetadata\x12\x33\n\tapex_info\x18\x01 \x03(\x0b\x32 .chromeos_update_engine.ApexInfo\"\xc3\x03\n\x14\x44\x65ltaArchiveManifest\x12\x18\n\nblock_size\x18\x03 \x01(\r:\x04\x34\x30\x39\x36\x12\x19\n\x11signatures_offset\x18\x04 \x01(\x04\x12\x17\n\x0fsignatures_size\x18\x05 \x01(\x04\x12\x18\n\rminor_version\x18\x0c \x01(\r:\x01\x30\x12;\n\npartitions\x18\r \x03(\x0b\x32\'.chromeos_update_engine.PartitionUpdate\x12\x15\n\rmax_timestamp\x18\x0e \x01(\x03\x12T\n\x1a\x64ynamic_partition_metadata\x18\x0f \x01(\x0b\x32\x30.chromeos_update_engine.DynamicPartitionMetadata\x12\x16\n\x0epartial_update\x18\x10 \x01(\x08\x12\x33\n\tapex_info\x18\x11 \x03(\x0b\x32 .chromeos_update_engine.ApexInfo\x12\x1c\n\x14security_patch_level\x18\x12 \x01(\tJ\x04\x08\x01\x10\x02J\x04\x08\x02\x10\x03J\x04\x08\x06\x10\x07J\x04\x08\x07\x10\x08J\x04\x08\x08\x10\tJ\x04\x08\t\x10\nJ\x04\x08\n\x10\x0bJ\x04\x08\x0b\x10\x0c\x42\x02H\x03')
)
@@ -79,11 +79,19 @@ _INSTALLOPERATION_TYPE = _descriptor.EnumDescriptor(
name='ZUCCHINI', index=11, number=11,
serialized_options=None,
type=None),
+ _descriptor.EnumValueDescriptor(
+ name='LZ4DIFF_BSDIFF', index=12, number=12,
+ serialized_options=None,
+ type=None),
+ _descriptor.EnumValueDescriptor(
+ name='LZ4DIFF_PUFFDIFF', index=13, number=13,
+ serialized_options=None,
+ type=None),
],
containing_type=None,
serialized_options=None,
- serialized_start=775,
- serialized_end=962,
+ serialized_start=629,
+ serialized_end=858,
)
_sym_db.RegisterEnumDescriptor(_INSTALLOPERATION_TYPE)
@@ -108,8 +116,8 @@ _COWMERGEOPERATION_TYPE = _descriptor.EnumDescriptor(
],
containing_type=None,
serialized_options=None,
- serialized_start=1172,
- serialized_end=1222,
+ serialized_start=1068,
+ serialized_end=1118,
)
_sym_db.RegisterEnumDescriptor(_COWMERGEOPERATION_TYPE)
@@ -265,72 +273,6 @@ _PARTITIONINFO = _descriptor.Descriptor(
)
-_IMAGEINFO = _descriptor.Descriptor(
- name='ImageInfo',
- full_name='chromeos_update_engine.ImageInfo',
- filename=None,
- file=DESCRIPTOR,
- containing_type=None,
- fields=[
- _descriptor.FieldDescriptor(
- name='board', full_name='chromeos_update_engine.ImageInfo.board', index=0,
- number=1, type=9, cpp_type=9, label=1,
- has_default_value=False, default_value=_b("").decode('utf-8'),
- message_type=None, enum_type=None, containing_type=None,
- is_extension=False, extension_scope=None,
- serialized_options=_b('\030\001'), file=DESCRIPTOR),
- _descriptor.FieldDescriptor(
- name='key', full_name='chromeos_update_engine.ImageInfo.key', index=1,
- number=2, type=9, cpp_type=9, label=1,
- has_default_value=False, default_value=_b("").decode('utf-8'),
- message_type=None, enum_type=None, containing_type=None,
- is_extension=False, extension_scope=None,
- serialized_options=_b('\030\001'), file=DESCRIPTOR),
- _descriptor.FieldDescriptor(
- name='channel', full_name='chromeos_update_engine.ImageInfo.channel', index=2,
- number=3, type=9, cpp_type=9, label=1,
- has_default_value=False, default_value=_b("").decode('utf-8'),
- message_type=None, enum_type=None, containing_type=None,
- is_extension=False, extension_scope=None,
- serialized_options=_b('\030\001'), file=DESCRIPTOR),
- _descriptor.FieldDescriptor(
- name='version', full_name='chromeos_update_engine.ImageInfo.version', index=3,
- number=4, type=9, cpp_type=9, label=1,
- has_default_value=False, default_value=_b("").decode('utf-8'),
- message_type=None, enum_type=None, containing_type=None,
- is_extension=False, extension_scope=None,
- serialized_options=_b('\030\001'), file=DESCRIPTOR),
- _descriptor.FieldDescriptor(
- name='build_channel', full_name='chromeos_update_engine.ImageInfo.build_channel', index=4,
- number=5, type=9, cpp_type=9, label=1,
- has_default_value=False, default_value=_b("").decode('utf-8'),
- message_type=None, enum_type=None, containing_type=None,
- is_extension=False, extension_scope=None,
- serialized_options=_b('\030\001'), file=DESCRIPTOR),
- _descriptor.FieldDescriptor(
- name='build_version', full_name='chromeos_update_engine.ImageInfo.build_version', index=5,
- number=6, type=9, cpp_type=9, label=1,
- has_default_value=False, default_value=_b("").decode('utf-8'),
- message_type=None, enum_type=None, containing_type=None,
- is_extension=False, extension_scope=None,
- serialized_options=_b('\030\001'), file=DESCRIPTOR),
- ],
- extensions=[
- ],
- nested_types=[],
- enum_types=[
- ],
- serialized_options=None,
- is_extendable=False,
- syntax='proto2',
- extension_ranges=[],
- oneofs=[
- ],
- serialized_start=308,
- serialized_end=451,
-)
-
-
_INSTALLOPERATION = _descriptor.Descriptor(
name='InstallOperation',
full_name='chromeos_update_engine.InstallOperation',
@@ -414,8 +356,8 @@ _INSTALLOPERATION = _descriptor.Descriptor(
extension_ranges=[],
oneofs=[
],
- serialized_start=454,
- serialized_end=962,
+ serialized_start=308,
+ serialized_end=858,
)
@@ -467,8 +409,8 @@ _COWMERGEOPERATION = _descriptor.Descriptor(
extension_ranges=[],
oneofs=[
],
- serialized_start=965,
- serialized_end=1222,
+ serialized_start=861,
+ serialized_end=1118,
)
@@ -624,8 +566,8 @@ _PARTITIONUPDATE = _descriptor.Descriptor(
extension_ranges=[],
oneofs=[
],
- serialized_start=1225,
- serialized_end=2065,
+ serialized_start=1121,
+ serialized_end=1961,
)
@@ -669,8 +611,46 @@ _DYNAMICPARTITIONGROUP = _descriptor.Descriptor(
extension_ranges=[],
oneofs=[
],
- serialized_start=2067,
- serialized_end=2143,
+ serialized_start=1963,
+ serialized_end=2039,
+)
+
+
+_VABCFEATURESET = _descriptor.Descriptor(
+ name='VABCFeatureSet',
+ full_name='chromeos_update_engine.VABCFeatureSet',
+ filename=None,
+ file=DESCRIPTOR,
+ containing_type=None,
+ fields=[
+ _descriptor.FieldDescriptor(
+ name='threaded', full_name='chromeos_update_engine.VABCFeatureSet.threaded', index=0,
+ number=1, type=8, cpp_type=7, label=1,
+ has_default_value=False, default_value=False,
+ message_type=None, enum_type=None, containing_type=None,
+ is_extension=False, extension_scope=None,
+ serialized_options=None, file=DESCRIPTOR),
+ _descriptor.FieldDescriptor(
+ name='batch_writes', full_name='chromeos_update_engine.VABCFeatureSet.batch_writes', index=1,
+ number=2, type=8, cpp_type=7, label=1,
+ has_default_value=False, default_value=False,
+ message_type=None, enum_type=None, containing_type=None,
+ is_extension=False, extension_scope=None,
+ serialized_options=None, file=DESCRIPTOR),
+ ],
+ extensions=[
+ ],
+ nested_types=[],
+ enum_types=[
+ ],
+ serialized_options=None,
+ is_extendable=False,
+ syntax='proto2',
+ extension_ranges=[],
+ oneofs=[
+ ],
+ serialized_start=2041,
+ serialized_end=2097,
)
@@ -716,6 +696,13 @@ _DYNAMICPARTITIONMETADATA = _descriptor.Descriptor(
message_type=None, enum_type=None, containing_type=None,
is_extension=False, extension_scope=None,
serialized_options=None, file=DESCRIPTOR),
+ _descriptor.FieldDescriptor(
+ name='vabc_feature_set', full_name='chromeos_update_engine.DynamicPartitionMetadata.vabc_feature_set', index=5,
+ number=6, type=11, cpp_type=10, label=1,
+ has_default_value=False, default_value=None,
+ message_type=None, enum_type=None, containing_type=None,
+ is_extension=False, extension_scope=None,
+ serialized_options=None, file=DESCRIPTOR),
],
extensions=[
],
@@ -728,8 +715,8 @@ _DYNAMICPARTITIONMETADATA = _descriptor.Descriptor(
extension_ranges=[],
oneofs=[
],
- serialized_start=2146,
- serialized_end=2336,
+ serialized_start=2100,
+ serialized_end=2356,
)
@@ -780,8 +767,8 @@ _APEXINFO = _descriptor.Descriptor(
extension_ranges=[],
oneofs=[
],
- serialized_start=2338,
- serialized_end=2437,
+ serialized_start=2358,
+ serialized_end=2457,
)
@@ -811,8 +798,8 @@ _APEXMETADATA = _descriptor.Descriptor(
extension_ranges=[],
oneofs=[
],
- serialized_start=2439,
- serialized_end=2506,
+ serialized_start=2459,
+ serialized_end=2526,
)
@@ -824,124 +811,75 @@ _DELTAARCHIVEMANIFEST = _descriptor.Descriptor(
containing_type=None,
fields=[
_descriptor.FieldDescriptor(
- name='install_operations', full_name='chromeos_update_engine.DeltaArchiveManifest.install_operations', index=0,
- number=1, type=11, cpp_type=10, label=3,
- has_default_value=False, default_value=[],
- message_type=None, enum_type=None, containing_type=None,
- is_extension=False, extension_scope=None,
- serialized_options=_b('\030\001'), file=DESCRIPTOR),
- _descriptor.FieldDescriptor(
- name='kernel_install_operations', full_name='chromeos_update_engine.DeltaArchiveManifest.kernel_install_operations', index=1,
- number=2, type=11, cpp_type=10, label=3,
- has_default_value=False, default_value=[],
- message_type=None, enum_type=None, containing_type=None,
- is_extension=False, extension_scope=None,
- serialized_options=_b('\030\001'), file=DESCRIPTOR),
- _descriptor.FieldDescriptor(
- name='block_size', full_name='chromeos_update_engine.DeltaArchiveManifest.block_size', index=2,
+ name='block_size', full_name='chromeos_update_engine.DeltaArchiveManifest.block_size', index=0,
number=3, type=13, cpp_type=3, label=1,
has_default_value=True, default_value=4096,
message_type=None, enum_type=None, containing_type=None,
is_extension=False, extension_scope=None,
serialized_options=None, file=DESCRIPTOR),
_descriptor.FieldDescriptor(
- name='signatures_offset', full_name='chromeos_update_engine.DeltaArchiveManifest.signatures_offset', index=3,
+ name='signatures_offset', full_name='chromeos_update_engine.DeltaArchiveManifest.signatures_offset', index=1,
number=4, type=4, cpp_type=4, label=1,
has_default_value=False, default_value=0,
message_type=None, enum_type=None, containing_type=None,
is_extension=False, extension_scope=None,
serialized_options=None, file=DESCRIPTOR),
_descriptor.FieldDescriptor(
- name='signatures_size', full_name='chromeos_update_engine.DeltaArchiveManifest.signatures_size', index=4,
+ name='signatures_size', full_name='chromeos_update_engine.DeltaArchiveManifest.signatures_size', index=2,
number=5, type=4, cpp_type=4, label=1,
has_default_value=False, default_value=0,
message_type=None, enum_type=None, containing_type=None,
is_extension=False, extension_scope=None,
serialized_options=None, file=DESCRIPTOR),
_descriptor.FieldDescriptor(
- name='old_kernel_info', full_name='chromeos_update_engine.DeltaArchiveManifest.old_kernel_info', index=5,
- number=6, type=11, cpp_type=10, label=1,
- has_default_value=False, default_value=None,
- message_type=None, enum_type=None, containing_type=None,
- is_extension=False, extension_scope=None,
- serialized_options=_b('\030\001'), file=DESCRIPTOR),
- _descriptor.FieldDescriptor(
- name='new_kernel_info', full_name='chromeos_update_engine.DeltaArchiveManifest.new_kernel_info', index=6,
- number=7, type=11, cpp_type=10, label=1,
- has_default_value=False, default_value=None,
- message_type=None, enum_type=None, containing_type=None,
- is_extension=False, extension_scope=None,
- serialized_options=_b('\030\001'), file=DESCRIPTOR),
- _descriptor.FieldDescriptor(
- name='old_rootfs_info', full_name='chromeos_update_engine.DeltaArchiveManifest.old_rootfs_info', index=7,
- number=8, type=11, cpp_type=10, label=1,
- has_default_value=False, default_value=None,
- message_type=None, enum_type=None, containing_type=None,
- is_extension=False, extension_scope=None,
- serialized_options=_b('\030\001'), file=DESCRIPTOR),
- _descriptor.FieldDescriptor(
- name='new_rootfs_info', full_name='chromeos_update_engine.DeltaArchiveManifest.new_rootfs_info', index=8,
- number=9, type=11, cpp_type=10, label=1,
- has_default_value=False, default_value=None,
- message_type=None, enum_type=None, containing_type=None,
- is_extension=False, extension_scope=None,
- serialized_options=_b('\030\001'), file=DESCRIPTOR),
- _descriptor.FieldDescriptor(
- name='old_image_info', full_name='chromeos_update_engine.DeltaArchiveManifest.old_image_info', index=9,
- number=10, type=11, cpp_type=10, label=1,
- has_default_value=False, default_value=None,
- message_type=None, enum_type=None, containing_type=None,
- is_extension=False, extension_scope=None,
- serialized_options=_b('\030\001'), file=DESCRIPTOR),
- _descriptor.FieldDescriptor(
- name='new_image_info', full_name='chromeos_update_engine.DeltaArchiveManifest.new_image_info', index=10,
- number=11, type=11, cpp_type=10, label=1,
- has_default_value=False, default_value=None,
- message_type=None, enum_type=None, containing_type=None,
- is_extension=False, extension_scope=None,
- serialized_options=_b('\030\001'), file=DESCRIPTOR),
- _descriptor.FieldDescriptor(
- name='minor_version', full_name='chromeos_update_engine.DeltaArchiveManifest.minor_version', index=11,
+ name='minor_version', full_name='chromeos_update_engine.DeltaArchiveManifest.minor_version', index=3,
number=12, type=13, cpp_type=3, label=1,
has_default_value=True, default_value=0,
message_type=None, enum_type=None, containing_type=None,
is_extension=False, extension_scope=None,
serialized_options=None, file=DESCRIPTOR),
_descriptor.FieldDescriptor(
- name='partitions', full_name='chromeos_update_engine.DeltaArchiveManifest.partitions', index=12,
+ name='partitions', full_name='chromeos_update_engine.DeltaArchiveManifest.partitions', index=4,
number=13, type=11, cpp_type=10, label=3,
has_default_value=False, default_value=[],
message_type=None, enum_type=None, containing_type=None,
is_extension=False, extension_scope=None,
serialized_options=None, file=DESCRIPTOR),
_descriptor.FieldDescriptor(
- name='max_timestamp', full_name='chromeos_update_engine.DeltaArchiveManifest.max_timestamp', index=13,
+ name='max_timestamp', full_name='chromeos_update_engine.DeltaArchiveManifest.max_timestamp', index=5,
number=14, type=3, cpp_type=2, label=1,
has_default_value=False, default_value=0,
message_type=None, enum_type=None, containing_type=None,
is_extension=False, extension_scope=None,
serialized_options=None, file=DESCRIPTOR),
_descriptor.FieldDescriptor(
- name='dynamic_partition_metadata', full_name='chromeos_update_engine.DeltaArchiveManifest.dynamic_partition_metadata', index=14,
+ name='dynamic_partition_metadata', full_name='chromeos_update_engine.DeltaArchiveManifest.dynamic_partition_metadata', index=6,
number=15, type=11, cpp_type=10, label=1,
has_default_value=False, default_value=None,
message_type=None, enum_type=None, containing_type=None,
is_extension=False, extension_scope=None,
serialized_options=None, file=DESCRIPTOR),
_descriptor.FieldDescriptor(
- name='partial_update', full_name='chromeos_update_engine.DeltaArchiveManifest.partial_update', index=15,
+ name='partial_update', full_name='chromeos_update_engine.DeltaArchiveManifest.partial_update', index=7,
number=16, type=8, cpp_type=7, label=1,
has_default_value=False, default_value=False,
message_type=None, enum_type=None, containing_type=None,
is_extension=False, extension_scope=None,
serialized_options=None, file=DESCRIPTOR),
_descriptor.FieldDescriptor(
- name='apex_info', full_name='chromeos_update_engine.DeltaArchiveManifest.apex_info', index=16,
+ name='apex_info', full_name='chromeos_update_engine.DeltaArchiveManifest.apex_info', index=8,
number=17, type=11, cpp_type=10, label=3,
has_default_value=False, default_value=[],
message_type=None, enum_type=None, containing_type=None,
is_extension=False, extension_scope=None,
serialized_options=None, file=DESCRIPTOR),
+ _descriptor.FieldDescriptor(
+ name='security_patch_level', full_name='chromeos_update_engine.DeltaArchiveManifest.security_patch_level', index=9,
+ number=18, type=9, cpp_type=9, label=1,
+ has_default_value=False, default_value=_b("").decode('utf-8'),
+ message_type=None, enum_type=None, containing_type=None,
+ is_extension=False, extension_scope=None,
+ serialized_options=None, file=DESCRIPTOR),
],
extensions=[
],
@@ -954,8 +892,8 @@ _DELTAARCHIVEMANIFEST = _descriptor.Descriptor(
extension_ranges=[],
oneofs=[
],
- serialized_start=2509,
- serialized_end=3435,
+ serialized_start=2529,
+ serialized_end=2980,
)
_SIGNATURES_SIGNATURE.containing_type = _SIGNATURES
@@ -978,26 +916,19 @@ _PARTITIONUPDATE.fields_by_name['fec_data_extent'].message_type = _EXTENT
_PARTITIONUPDATE.fields_by_name['fec_extent'].message_type = _EXTENT
_PARTITIONUPDATE.fields_by_name['merge_operations'].message_type = _COWMERGEOPERATION
_DYNAMICPARTITIONMETADATA.fields_by_name['groups'].message_type = _DYNAMICPARTITIONGROUP
+_DYNAMICPARTITIONMETADATA.fields_by_name['vabc_feature_set'].message_type = _VABCFEATURESET
_APEXMETADATA.fields_by_name['apex_info'].message_type = _APEXINFO
-_DELTAARCHIVEMANIFEST.fields_by_name['install_operations'].message_type = _INSTALLOPERATION
-_DELTAARCHIVEMANIFEST.fields_by_name['kernel_install_operations'].message_type = _INSTALLOPERATION
-_DELTAARCHIVEMANIFEST.fields_by_name['old_kernel_info'].message_type = _PARTITIONINFO
-_DELTAARCHIVEMANIFEST.fields_by_name['new_kernel_info'].message_type = _PARTITIONINFO
-_DELTAARCHIVEMANIFEST.fields_by_name['old_rootfs_info'].message_type = _PARTITIONINFO
-_DELTAARCHIVEMANIFEST.fields_by_name['new_rootfs_info'].message_type = _PARTITIONINFO
-_DELTAARCHIVEMANIFEST.fields_by_name['old_image_info'].message_type = _IMAGEINFO
-_DELTAARCHIVEMANIFEST.fields_by_name['new_image_info'].message_type = _IMAGEINFO
_DELTAARCHIVEMANIFEST.fields_by_name['partitions'].message_type = _PARTITIONUPDATE
_DELTAARCHIVEMANIFEST.fields_by_name['dynamic_partition_metadata'].message_type = _DYNAMICPARTITIONMETADATA
_DELTAARCHIVEMANIFEST.fields_by_name['apex_info'].message_type = _APEXINFO
DESCRIPTOR.message_types_by_name['Extent'] = _EXTENT
DESCRIPTOR.message_types_by_name['Signatures'] = _SIGNATURES
DESCRIPTOR.message_types_by_name['PartitionInfo'] = _PARTITIONINFO
-DESCRIPTOR.message_types_by_name['ImageInfo'] = _IMAGEINFO
DESCRIPTOR.message_types_by_name['InstallOperation'] = _INSTALLOPERATION
DESCRIPTOR.message_types_by_name['CowMergeOperation'] = _COWMERGEOPERATION
DESCRIPTOR.message_types_by_name['PartitionUpdate'] = _PARTITIONUPDATE
DESCRIPTOR.message_types_by_name['DynamicPartitionGroup'] = _DYNAMICPARTITIONGROUP
+DESCRIPTOR.message_types_by_name['VABCFeatureSet'] = _VABCFEATURESET
DESCRIPTOR.message_types_by_name['DynamicPartitionMetadata'] = _DYNAMICPARTITIONMETADATA
DESCRIPTOR.message_types_by_name['ApexInfo'] = _APEXINFO
DESCRIPTOR.message_types_by_name['ApexMetadata'] = _APEXMETADATA
@@ -1033,13 +964,6 @@ PartitionInfo = _reflection.GeneratedProtocolMessageType('PartitionInfo', (_mess
})
_sym_db.RegisterMessage(PartitionInfo)
-ImageInfo = _reflection.GeneratedProtocolMessageType('ImageInfo', (_message.Message,), {
- 'DESCRIPTOR' : _IMAGEINFO,
- '__module__' : 'update_metadata_pb2'
- # @@protoc_insertion_point(class_scope:chromeos_update_engine.ImageInfo)
- })
-_sym_db.RegisterMessage(ImageInfo)
-
InstallOperation = _reflection.GeneratedProtocolMessageType('InstallOperation', (_message.Message,), {
'DESCRIPTOR' : _INSTALLOPERATION,
'__module__' : 'update_metadata_pb2'
@@ -1068,6 +992,13 @@ DynamicPartitionGroup = _reflection.GeneratedProtocolMessageType('DynamicPartiti
})
_sym_db.RegisterMessage(DynamicPartitionGroup)
+VABCFeatureSet = _reflection.GeneratedProtocolMessageType('VABCFeatureSet', (_message.Message,), {
+ 'DESCRIPTOR' : _VABCFEATURESET,
+ '__module__' : 'update_metadata_pb2'
+ # @@protoc_insertion_point(class_scope:chromeos_update_engine.VABCFeatureSet)
+ })
+_sym_db.RegisterMessage(VABCFeatureSet)
+
DynamicPartitionMetadata = _reflection.GeneratedProtocolMessageType('DynamicPartitionMetadata', (_message.Message,), {
'DESCRIPTOR' : _DYNAMICPARTITIONMETADATA,
'__module__' : 'update_metadata_pb2'
@@ -1099,20 +1030,6 @@ _sym_db.RegisterMessage(DeltaArchiveManifest)
DESCRIPTOR._options = None
_SIGNATURES_SIGNATURE.fields_by_name['version']._options = None
-_IMAGEINFO.fields_by_name['board']._options = None
-_IMAGEINFO.fields_by_name['key']._options = None
-_IMAGEINFO.fields_by_name['channel']._options = None
-_IMAGEINFO.fields_by_name['version']._options = None
-_IMAGEINFO.fields_by_name['build_channel']._options = None
-_IMAGEINFO.fields_by_name['build_version']._options = None
_INSTALLOPERATION_TYPE.values_by_name["MOVE"]._options = None
_INSTALLOPERATION_TYPE.values_by_name["BSDIFF"]._options = None
-_DELTAARCHIVEMANIFEST.fields_by_name['install_operations']._options = None
-_DELTAARCHIVEMANIFEST.fields_by_name['kernel_install_operations']._options = None
-_DELTAARCHIVEMANIFEST.fields_by_name['old_kernel_info']._options = None
-_DELTAARCHIVEMANIFEST.fields_by_name['new_kernel_info']._options = None
-_DELTAARCHIVEMANIFEST.fields_by_name['old_rootfs_info']._options = None
-_DELTAARCHIVEMANIFEST.fields_by_name['new_rootfs_info']._options = None
-_DELTAARCHIVEMANIFEST.fields_by_name['old_image_info']._options = None
-_DELTAARCHIVEMANIFEST.fields_by_name['new_image_info']._options = None
# @@protoc_insertion_point(module_scope)
diff --git a/scripts/update_payload/applier.py b/scripts/update_payload/applier.py
deleted file mode 100644
index 29ccb8e5..00000000
--- a/scripts/update_payload/applier.py
+++ /dev/null
@@ -1,621 +0,0 @@
-#
-# Copyright (C) 2013 The Android Open Source Project
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-#
-
-"""Applying a Chrome OS update payload.
-
-This module is used internally by the main Payload class for applying an update
-payload. The interface for invoking the applier is as follows:
-
- applier = PayloadApplier(payload)
- applier.Run(...)
-
-"""
-
-from __future__ import absolute_import
-from __future__ import print_function
-
-import array
-import bz2
-import hashlib
-# Not everywhere we can have the lzma library so we ignore it if we didn't have
-# it because it is not going to be used. For example, 'cros flash' uses
-# devserver code which eventually loads this file, but the lzma library is not
-# included in the client test devices, and it is not necessary to do so. But
-# lzma is not used in 'cros flash' so it should be fine. Python 3.x include
-# lzma, but for backward compatibility with Python 2.7, backports-lzma is
-# needed.
-try:
- import lzma
-except ImportError:
- try:
- from backports import lzma
- except ImportError:
- pass
-import os
-import subprocess
-import sys
-import tempfile
-
-from update_payload import common
-from update_payload.error import PayloadError
-
-#
-# Helper functions.
-#
-def _VerifySha256(file_obj, expected_hash, name, length=-1):
- """Verifies the SHA256 hash of a file.
-
- Args:
- file_obj: file object to read
- expected_hash: the hash digest we expect to be getting
- name: name string of this hash, for error reporting
- length: precise length of data to verify (optional)
-
- Raises:
- PayloadError if computed hash doesn't match expected one, or if fails to
- read the specified length of data.
- """
- hasher = hashlib.sha256()
- block_length = 1024 * 1024
- max_length = length if length >= 0 else sys.maxsize
-
- while max_length > 0:
- read_length = min(max_length, block_length)
- data = file_obj.read(read_length)
- if not data:
- break
- max_length -= len(data)
- hasher.update(data)
-
- if length >= 0 and max_length > 0:
- raise PayloadError(
- 'insufficient data (%d instead of %d) when verifying %s' %
- (length - max_length, length, name))
-
- actual_hash = hasher.digest()
- if actual_hash != expected_hash:
- raise PayloadError('%s hash (%s) not as expected (%s)' %
- (name, common.FormatSha256(actual_hash),
- common.FormatSha256(expected_hash)))
-
-
-def _ReadExtents(file_obj, extents, block_size, max_length=-1):
- """Reads data from file as defined by extent sequence.
-
- This tries to be efficient by not copying data as it is read in chunks.
-
- Args:
- file_obj: file object
- extents: sequence of block extents (offset and length)
- block_size: size of each block
- max_length: maximum length to read (optional)
-
- Returns:
- A character array containing the concatenated read data.
- """
- data = array.array('B')
- if max_length < 0:
- max_length = sys.maxsize
- for ex in extents:
- if max_length == 0:
- break
- read_length = min(max_length, ex.num_blocks * block_size)
-
- file_obj.seek(ex.start_block * block_size)
- data.fromfile(file_obj, read_length)
-
- max_length -= read_length
-
- return data
-
-
-def _WriteExtents(file_obj, data, extents, block_size, base_name):
- """Writes data to file as defined by extent sequence.
-
- This tries to be efficient by not copy data as it is written in chunks.
-
- Args:
- file_obj: file object
- data: data to write
- extents: sequence of block extents (offset and length)
- block_size: size of each block
- base_name: name string of extent sequence for error reporting
-
- Raises:
- PayloadError when things don't add up.
- """
- data_offset = 0
- data_length = len(data)
- for ex, ex_name in common.ExtentIter(extents, base_name):
- if not data_length:
- raise PayloadError('%s: more write extents than data' % ex_name)
- write_length = min(data_length, ex.num_blocks * block_size)
- file_obj.seek(ex.start_block * block_size)
- file_obj.write(data[data_offset:(data_offset + write_length)])
-
- data_offset += write_length
- data_length -= write_length
-
- if data_length:
- raise PayloadError('%s: more data than write extents' % base_name)
-
-
-def _ExtentsToBspatchArg(extents, block_size, base_name, data_length=-1):
- """Translates an extent sequence into a bspatch-compatible string argument.
-
- Args:
- extents: sequence of block extents (offset and length)
- block_size: size of each block
- base_name: name string of extent sequence for error reporting
- data_length: the actual total length of the data in bytes (optional)
-
- Returns:
- A tuple consisting of (i) a string of the form
- "off_1:len_1,...,off_n:len_n", (ii) an offset where zero padding is needed
- for filling the last extent, (iii) the length of the padding (zero means no
- padding is needed and the extents cover the full length of data).
-
- Raises:
- PayloadError if data_length is too short or too long.
- """
- arg = ''
- pad_off = pad_len = 0
- if data_length < 0:
- data_length = sys.maxsize
- for ex, ex_name in common.ExtentIter(extents, base_name):
- if not data_length:
- raise PayloadError('%s: more extents than total data length' % ex_name)
-
- start_byte = ex.start_block * block_size
- num_bytes = ex.num_blocks * block_size
- if data_length < num_bytes:
- # We're only padding a real extent.
- pad_off = start_byte + data_length
- pad_len = num_bytes - data_length
- num_bytes = data_length
-
- arg += '%s%d:%d' % (arg and ',', start_byte, num_bytes)
- data_length -= num_bytes
-
- if data_length:
- raise PayloadError('%s: extents not covering full data length' % base_name)
-
- return arg, pad_off, pad_len
-
-
-#
-# Payload application.
-#
-class PayloadApplier(object):
- """Applying an update payload.
-
- This is a short-lived object whose purpose is to isolate the logic used for
- applying an update payload.
- """
-
- def __init__(self, payload, bsdiff_in_place=True, bspatch_path=None,
- puffpatch_path=None, truncate_to_expected_size=True):
- """Initialize the applier.
-
- Args:
- payload: the payload object to check
- bsdiff_in_place: whether to perform BSDIFF operation in-place (optional)
- bspatch_path: path to the bspatch binary (optional)
- puffpatch_path: path to the puffpatch binary (optional)
- truncate_to_expected_size: whether to truncate the resulting partitions
- to their expected sizes, as specified in the
- payload (optional)
- """
- assert payload.is_init, 'uninitialized update payload'
- self.payload = payload
- self.block_size = payload.manifest.block_size
- self.minor_version = payload.manifest.minor_version
- self.bsdiff_in_place = bsdiff_in_place
- self.bspatch_path = bspatch_path or 'bspatch'
- self.puffpatch_path = puffpatch_path or 'puffin'
- self.truncate_to_expected_size = truncate_to_expected_size
-
- def _ApplyReplaceOperation(self, op, op_name, out_data, part_file, part_size):
- """Applies a REPLACE{,_BZ,_XZ} operation.
-
- Args:
- op: the operation object
- op_name: name string for error reporting
- out_data: the data to be written
- part_file: the partition file object
- part_size: the size of the partition
-
- Raises:
- PayloadError if something goes wrong.
- """
- block_size = self.block_size
- data_length = len(out_data)
-
- # Decompress data if needed.
- if op.type == common.OpType.REPLACE_BZ:
- out_data = bz2.decompress(out_data)
- data_length = len(out_data)
- elif op.type == common.OpType.REPLACE_XZ:
- # pylint: disable=no-member
- out_data = lzma.decompress(out_data)
- data_length = len(out_data)
-
- # Write data to blocks specified in dst extents.
- data_start = 0
- for ex, ex_name in common.ExtentIter(op.dst_extents,
- '%s.dst_extents' % op_name):
- start_block = ex.start_block
- num_blocks = ex.num_blocks
- count = num_blocks * block_size
-
- data_end = data_start + count
-
- # Make sure we're not running past partition boundary.
- if (start_block + num_blocks) * block_size > part_size:
- raise PayloadError(
- '%s: extent (%s) exceeds partition size (%d)' %
- (ex_name, common.FormatExtent(ex, block_size),
- part_size))
-
- # Make sure that we have enough data to write.
- if data_end >= data_length + block_size:
- raise PayloadError(
- '%s: more dst blocks than data (even with padding)')
-
- # Pad with zeros if necessary.
- if data_end > data_length:
- padding = data_end - data_length
- out_data += b'\0' * padding
-
- self.payload.payload_file.seek(start_block * block_size)
- part_file.seek(start_block * block_size)
- part_file.write(out_data[data_start:data_end])
-
- data_start += count
-
- # Make sure we wrote all data.
- if data_start < data_length:
- raise PayloadError('%s: wrote fewer bytes (%d) than expected (%d)' %
- (op_name, data_start, data_length))
-
- def _ApplyZeroOperation(self, op, op_name, part_file):
- """Applies a ZERO operation.
-
- Args:
- op: the operation object
- op_name: name string for error reporting
- part_file: the partition file object
-
- Raises:
- PayloadError if something goes wrong.
- """
- block_size = self.block_size
- base_name = '%s.dst_extents' % op_name
-
- # Iterate over the extents and write zero.
- # pylint: disable=unused-variable
- for ex, ex_name in common.ExtentIter(op.dst_extents, base_name):
- part_file.seek(ex.start_block * block_size)
- part_file.write(b'\0' * (ex.num_blocks * block_size))
-
- def _ApplySourceCopyOperation(self, op, op_name, old_part_file,
- new_part_file):
- """Applies a SOURCE_COPY operation.
-
- Args:
- op: the operation object
- op_name: name string for error reporting
- old_part_file: the old partition file object
- new_part_file: the new partition file object
-
- Raises:
- PayloadError if something goes wrong.
- """
- if not old_part_file:
- raise PayloadError(
- '%s: no source partition file provided for operation type (%d)' %
- (op_name, op.type))
-
- block_size = self.block_size
-
- # Gather input raw data from src extents.
- in_data = _ReadExtents(old_part_file, op.src_extents, block_size)
-
- # Dump extracted data to dst extents.
- _WriteExtents(new_part_file, in_data, op.dst_extents, block_size,
- '%s.dst_extents' % op_name)
-
- def _BytesInExtents(self, extents, base_name):
- """Counts the length of extents in bytes.
-
- Args:
- extents: The list of Extents.
- base_name: For error reporting.
-
- Returns:
- The number of bytes in extents.
- """
-
- length = 0
- # pylint: disable=unused-variable
- for ex, ex_name in common.ExtentIter(extents, base_name):
- length += ex.num_blocks * self.block_size
- return length
-
- def _ApplyDiffOperation(self, op, op_name, patch_data, old_part_file,
- new_part_file):
- """Applies a SOURCE_BSDIFF, BROTLI_BSDIFF or PUFFDIFF operation.
-
- Args:
- op: the operation object
- op_name: name string for error reporting
- patch_data: the binary patch content
- old_part_file: the source partition file object
- new_part_file: the target partition file object
-
- Raises:
- PayloadError if something goes wrong.
- """
- if not old_part_file:
- raise PayloadError(
- '%s: no source partition file provided for operation type (%d)' %
- (op_name, op.type))
-
- block_size = self.block_size
-
- # Dump patch data to file.
- with tempfile.NamedTemporaryFile(delete=False) as patch_file:
- patch_file_name = patch_file.name
- patch_file.write(patch_data)
-
- if (hasattr(new_part_file, 'fileno') and
- ((not old_part_file) or hasattr(old_part_file, 'fileno'))):
- # Construct input and output extents argument for bspatch.
-
- in_extents_arg, _, _ = _ExtentsToBspatchArg(
- op.src_extents, block_size, '%s.src_extents' % op_name,
- data_length=op.src_length if op.src_length else
- self._BytesInExtents(op.src_extents, "%s.src_extents"))
- out_extents_arg, pad_off, pad_len = _ExtentsToBspatchArg(
- op.dst_extents, block_size, '%s.dst_extents' % op_name,
- data_length=op.dst_length if op.dst_length else
- self._BytesInExtents(op.dst_extents, "%s.dst_extents"))
-
- new_file_name = '/dev/fd/%d' % new_part_file.fileno()
- # Diff from source partition.
- old_file_name = '/dev/fd/%d' % old_part_file.fileno()
-
- # In python3, file descriptors(fd) are not passed to child processes by
- # default. To pass the fds to the child processes, we need to set the flag
- # 'inheritable' in the fds and make the subprocess calls with the argument
- # close_fds set to False.
- if sys.version_info.major >= 3:
- os.set_inheritable(new_part_file.fileno(), True)
- os.set_inheritable(old_part_file.fileno(), True)
-
- if op.type in (common.OpType.SOURCE_BSDIFF, common.OpType.BROTLI_BSDIFF):
- # Invoke bspatch on partition file with extents args.
- bspatch_cmd = [self.bspatch_path, old_file_name, new_file_name,
- patch_file_name, in_extents_arg, out_extents_arg]
- subprocess.check_call(bspatch_cmd, close_fds=False)
- elif op.type == common.OpType.PUFFDIFF:
- # Invoke puffpatch on partition file with extents args.
- puffpatch_cmd = [self.puffpatch_path,
- "--operation=puffpatch",
- "--src_file=%s" % old_file_name,
- "--dst_file=%s" % new_file_name,
- "--patch_file=%s" % patch_file_name,
- "--src_extents=%s" % in_extents_arg,
- "--dst_extents=%s" % out_extents_arg]
- subprocess.check_call(puffpatch_cmd, close_fds=False)
- else:
- raise PayloadError("Unknown operation %s" % op.type)
-
- # Pad with zeros past the total output length.
- if pad_len:
- new_part_file.seek(pad_off)
- new_part_file.write(b'\0' * pad_len)
- else:
- # Gather input raw data and write to a temp file.
- input_part_file = old_part_file if old_part_file else new_part_file
- in_data = _ReadExtents(input_part_file, op.src_extents, block_size,
- max_length=op.src_length if op.src_length else
- self._BytesInExtents(op.src_extents,
- "%s.src_extents"))
- with tempfile.NamedTemporaryFile(delete=False) as in_file:
- in_file_name = in_file.name
- in_file.write(in_data)
-
- # Allocate temporary output file.
- with tempfile.NamedTemporaryFile(delete=False) as out_file:
- out_file_name = out_file.name
-
- if op.type in (common.OpType.SOURCE_BSDIFF, common.OpType.BROTLI_BSDIFF):
- # Invoke bspatch.
- bspatch_cmd = [self.bspatch_path, in_file_name, out_file_name,
- patch_file_name]
- subprocess.check_call(bspatch_cmd)
- elif op.type == common.OpType.PUFFDIFF:
- # Invoke puffpatch.
- puffpatch_cmd = [self.puffpatch_path,
- "--operation=puffpatch",
- "--src_file=%s" % in_file_name,
- "--dst_file=%s" % out_file_name,
- "--patch_file=%s" % patch_file_name]
- subprocess.check_call(puffpatch_cmd)
- else:
- raise PayloadError("Unknown operation %s" % op.type)
-
- # Read output.
- with open(out_file_name, 'rb') as out_file:
- out_data = out_file.read()
- if len(out_data) != op.dst_length:
- raise PayloadError(
- '%s: actual patched data length (%d) not as expected (%d)' %
- (op_name, len(out_data), op.dst_length))
-
- # Write output back to partition, with padding.
- unaligned_out_len = len(out_data) % block_size
- if unaligned_out_len:
- out_data += b'\0' * (block_size - unaligned_out_len)
- _WriteExtents(new_part_file, out_data, op.dst_extents, block_size,
- '%s.dst_extents' % op_name)
-
- # Delete input/output files.
- os.remove(in_file_name)
- os.remove(out_file_name)
-
- # Delete patch file.
- os.remove(patch_file_name)
-
- def _ApplyOperations(self, operations, base_name, old_part_file,
- new_part_file, part_size):
- """Applies a sequence of update operations to a partition.
-
- Args:
- operations: the sequence of operations
- base_name: the name of the operation sequence
- old_part_file: the old partition file object, open for reading/writing
- new_part_file: the new partition file object, open for reading/writing
- part_size: the partition size
-
- Raises:
- PayloadError if anything goes wrong while processing the payload.
- """
- for op, op_name in common.OperationIter(operations, base_name):
- # Read data blob.
- data = self.payload.ReadDataBlob(op.data_offset, op.data_length)
-
- if op.type in (common.OpType.REPLACE, common.OpType.REPLACE_BZ,
- common.OpType.REPLACE_XZ):
- self._ApplyReplaceOperation(op, op_name, data, new_part_file, part_size)
- elif op.type == common.OpType.ZERO:
- self._ApplyZeroOperation(op, op_name, new_part_file)
- elif op.type == common.OpType.SOURCE_COPY:
- self._ApplySourceCopyOperation(op, op_name, old_part_file,
- new_part_file)
- elif op.type in (common.OpType.SOURCE_BSDIFF, common.OpType.PUFFDIFF,
- common.OpType.BROTLI_BSDIFF):
- self._ApplyDiffOperation(op, op_name, data, old_part_file,
- new_part_file)
- else:
- raise PayloadError('%s: unknown operation type (%d)' %
- (op_name, op.type))
-
- def _ApplyToPartition(self, operations, part_name, base_name,
- new_part_file_name, new_part_info,
- old_part_file_name=None, old_part_info=None):
- """Applies an update to a partition.
-
- Args:
- operations: the sequence of update operations to apply
- part_name: the name of the partition, for error reporting
- base_name: the name of the operation sequence
- new_part_file_name: file name to write partition data to
- new_part_info: size and expected hash of dest partition
- old_part_file_name: file name of source partition (optional)
- old_part_info: size and expected hash of source partition (optional)
-
- Raises:
- PayloadError if anything goes wrong with the update.
- """
- # Do we have a source partition?
- if old_part_file_name:
- # Verify the source partition.
- with open(old_part_file_name, 'rb') as old_part_file:
- _VerifySha256(old_part_file, old_part_info.hash,
- 'old ' + part_name, length=old_part_info.size)
- new_part_file_mode = 'r+b'
- open(new_part_file_name, 'w').close()
-
- else:
- # We need to create/truncate the dst partition file.
- new_part_file_mode = 'w+b'
-
- # Apply operations.
- with open(new_part_file_name, new_part_file_mode) as new_part_file:
- old_part_file = (open(old_part_file_name, 'r+b')
- if old_part_file_name else None)
- try:
- self._ApplyOperations(operations, base_name, old_part_file,
- new_part_file, new_part_info.size)
- finally:
- if old_part_file:
- old_part_file.close()
-
- # Truncate the result, if so instructed.
- if self.truncate_to_expected_size:
- new_part_file.seek(0, 2)
- if new_part_file.tell() > new_part_info.size:
- new_part_file.seek(new_part_info.size)
- new_part_file.truncate()
-
- # Verify the resulting partition.
- with open(new_part_file_name, 'rb') as new_part_file:
- _VerifySha256(new_part_file, new_part_info.hash,
- 'new ' + part_name, length=new_part_info.size)
-
- def Run(self, new_parts, old_parts=None):
- """Applier entry point, invoking all update operations.
-
- Args:
- new_parts: map of partition name to dest partition file
- old_parts: map of partition name to source partition file (optional)
-
- Raises:
- PayloadError if payload application failed.
- """
- if old_parts is None:
- old_parts = {}
-
- self.payload.ResetFile()
-
- new_part_info = {}
- old_part_info = {}
- install_operations = []
-
- manifest = self.payload.manifest
- for part in manifest.partitions:
- name = part.partition_name
- new_part_info[name] = part.new_partition_info
- old_part_info[name] = part.old_partition_info
- install_operations.append((name, part.operations))
-
- part_names = set(new_part_info.keys()) # Equivalently, old_part_info.keys()
-
- # Make sure the arguments are sane and match the payload.
- new_part_names = set(new_parts.keys())
- if new_part_names != part_names:
- raise PayloadError('missing dst partition(s) %s' %
- ', '.join(part_names - new_part_names))
-
- old_part_names = set(old_parts.keys())
- if part_names - old_part_names:
- if self.payload.IsDelta():
- raise PayloadError('trying to apply a delta update without src '
- 'partition(s) %s' %
- ', '.join(part_names - old_part_names))
- elif old_part_names == part_names:
- if self.payload.IsFull():
- raise PayloadError('trying to apply a full update onto src partitions')
- else:
- raise PayloadError('not all src partitions provided')
-
- for name, operations in install_operations:
- # Apply update to partition.
- self._ApplyToPartition(
- operations, name, '%s_install_operations' % name, new_parts[name],
- new_part_info[name], old_parts.get(name, None), old_part_info[name])
diff --git a/scripts/update_payload/checker.py b/scripts/update_payload/checker.py
index 56a93708..44b68115 100644
--- a/scripts/update_payload/checker.py
+++ b/scripts/update_payload/checker.py
@@ -42,7 +42,7 @@ from update_payload import common
from update_payload import error
from update_payload import format_utils
from update_payload import histogram
-from update_payload import update_metadata_pb2
+import update_metadata_pb2
#
# Constants.
diff --git a/scripts/update_payload/checker_unittest.py b/scripts/update_payload/checker_unittest.py
index 993b785c..cf813fda 100755
--- a/scripts/update_payload/checker_unittest.py
+++ b/scripts/update_payload/checker_unittest.py
@@ -37,7 +37,7 @@ import mock # pylint: disable=import-error
from update_payload import checker
from update_payload import common
from update_payload import test_utils
-from update_payload import update_metadata_pb2
+import update_metadata_pb2
from update_payload.error import PayloadError
from update_payload.payload import Payload # Avoid name conflicts later.
diff --git a/scripts/update_payload/common.py b/scripts/update_payload/common.py
index 7c6ec8fe..7139f6f0 100644
--- a/scripts/update_payload/common.py
+++ b/scripts/update_payload/common.py
@@ -21,7 +21,7 @@ from __future__ import print_function
import base64
-from update_payload import update_metadata_pb2
+import update_metadata_pb2
from update_payload.error import PayloadError
diff --git a/scripts/update_payload/payload.py b/scripts/update_payload/payload.py
index 86caef7d..4abd63e6 100644
--- a/scripts/update_payload/payload.py
+++ b/scripts/update_payload/payload.py
@@ -18,6 +18,7 @@
from __future__ import absolute_import
from __future__ import print_function
+import binascii
import hashlib
import io
@@ -25,10 +26,10 @@ import mmap
import struct
import zipfile
-from update_payload import applier
+import update_metadata_pb2
+
from update_payload import checker
from update_payload import common
-from update_payload import update_metadata_pb2
from update_payload.error import PayloadError
@@ -123,15 +124,22 @@ class Payload(object):
payload_file_offset: the offset of the actual payload
"""
if zipfile.is_zipfile(payload_file):
+ self.name = payload_file
with zipfile.ZipFile(payload_file) as zfp:
+ if "payload.bin" not in zfp.namelist():
+ raise ValueError(f"payload.bin missing in archive {payload_file}")
self.payload_file = zfp.open("payload.bin", "r")
elif isinstance(payload_file, str):
+ self.name = payload_file
payload_fp = open(payload_file, "rb")
payload_bytes = mmap.mmap(
payload_fp.fileno(), 0, access=mmap.ACCESS_READ)
self.payload_file = io.BytesIO(payload_bytes)
else:
+ self.name = payload_file.name
self.payload_file = payload_file
+ self.payload_file_size = self.payload_file.seek(0, io.SEEK_END)
+ self.payload_file.seek(0, io.SEEK_SET)
self.payload_file_offset = payload_file_offset
self.manifest_hasher = None
self.is_init = False
@@ -141,6 +149,7 @@ class Payload(object):
self.metadata_signature = None
self.payload_signature = None
self.metadata_size = None
+ self.Init()
@property
def is_incremental(self):
@@ -150,6 +159,20 @@ class Payload(object):
def is_partial(self):
return self.manifest.partial_update
+ @property
+ def total_data_length(self):
+ """Return the total data length of this payload, excluding payload
+ signature at the very end.
+ """
+ # Operations are sorted in ascending data_offset order, so iterating
+ # backwards and find the first one with non zero data_offset will tell
+ # us total data length
+ for partition in reversed(self.manifest.partitions):
+ for op in reversed(partition.operations):
+ if op.data_length > 0:
+ return op.data_offset + op.data_length
+ return 0
+
def _ReadHeader(self):
"""Reads and returns the payload header.
@@ -223,7 +246,7 @@ class Payload(object):
correctly.
"""
if self.is_init:
- raise PayloadError('payload object already initialized')
+ return
self.manifest_hasher = hashlib.sha256()
@@ -245,7 +268,7 @@ class Payload(object):
self.metadata_size = self.header.size + self.header.manifest_len
self.data_offset = self.metadata_size + self.header.metadata_signature_len
- if self.manifest.signatures_offset and self.manifest.signatures_size:
+ if self.manifest.signatures_offset and self.manifest.signatures_size and self.manifest.signatures_offset + self.manifest.signatures_size <= self.payload_file_size:
payload_signature_blob = self.ReadDataBlob(
self.manifest.signatures_offset, self.manifest.signatures_size)
payload_signature = update_metadata_pb2.Signatures()
@@ -305,29 +328,16 @@ class Payload(object):
part_sizes=part_sizes,
report_out_file=report_out_file)
- def Apply(self, new_parts, old_parts=None, bsdiff_in_place=True,
- bspatch_path=None, puffpatch_path=None,
- truncate_to_expected_size=True):
- """Applies the update payload.
-
- Args:
- new_parts: map of partition name to dest partition file
- old_parts: map of partition name to partition file (optional)
- bsdiff_in_place: whether to perform BSDIFF operations in-place (optional)
- bspatch_path: path to the bspatch binary (optional)
- puffpatch_path: path to the puffpatch binary (optional)
- truncate_to_expected_size: whether to truncate the resulting partitions
- to their expected sizes, as specified in the
- payload (optional)
-
- Raises:
- PayloadError if payload application failed.
- """
- self._AssertInit()
-
- # Create a short-lived payload applier object and run it.
- helper = applier.PayloadApplier(
- self, bsdiff_in_place=bsdiff_in_place, bspatch_path=bspatch_path,
- puffpatch_path=puffpatch_path,
- truncate_to_expected_size=truncate_to_expected_size)
- helper.Run(new_parts, old_parts=old_parts)
+ def CheckDataHash(self):
+ for part in self.manifest.partitions:
+ for op in part.operations:
+ if op.data_length == 0:
+ continue
+ if not op.data_sha256_hash:
+ raise PayloadError(
+ f"Operation {op} in partition {part.partition_name} missing data_sha256_hash")
+ blob = self.ReadDataBlob(op.data_offset, op.data_length)
+ blob_hash = hashlib.sha256(blob)
+ if blob_hash.digest() != op.data_sha256_hash:
+ raise PayloadError(
+ f"Operation {op} in partition {part.partition_name} has unexpected hash, expected: {binascii.hexlify(op.data_sha256_hash)}, actual: {blob_hash.hexdigest()}")
diff --git a/scripts/update_payload/test_utils.py b/scripts/update_payload/test_utils.py
index e153669e..70058270 100644
--- a/scripts/update_payload/test_utils.py
+++ b/scripts/update_payload/test_utils.py
@@ -27,7 +27,7 @@ import subprocess
from update_payload import common
from update_payload import payload
-from update_payload import update_metadata_pb2
+import update_metadata_pb2
class TestError(Exception):
diff --git a/update_metadata.proto b/update_metadata.proto
index 3f454add..96e04f20 100644
--- a/update_metadata.proto
+++ b/update_metadata.proto
@@ -331,6 +331,11 @@ message DynamicPartitionGroup {
repeated string partition_names = 3;
}
+message VABCFeatureSet {
+ optional bool threaded = 1;
+ optional bool batch_writes = 2;
+}
+
// Metadata related to all dynamic partitions.
message DynamicPartitionMetadata {
// All updatable groups present in |partitions| of this DeltaArchiveManifest.
@@ -361,6 +366,9 @@ message DynamicPartitionMetadata {
// COW version used by VABC. The represents the major version in the COW
// header
optional uint32 cow_version = 5;
+
+ // A collection of knobs to tune Virtual AB Compression
+ optional VABCFeatureSet vabc_feature_set = 6;
}
// Definition has been duplicated from
@@ -423,4 +431,8 @@ message DeltaArchiveManifest {
// Information on compressed APEX to figure out how much space is required for
// their decompression
repeated ApexInfo apex_info = 17;
+
+ // Security patch level of the device, usually in the format of
+ // yyyy-mm-dd
+ optional string security_patch_level = 18;
}