|  | #!/usr/bin/env python3 | 
|  |  | 
|  | # Copyright (C) 2020 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. | 
|  |  | 
|  | """ | 
|  | Generate payload.bin from a single image. | 
|  | """ | 
|  |  | 
|  | import argparse | 
|  | import logging | 
|  | import os | 
|  | import re | 
|  | import shutil | 
|  | import sys | 
|  | from zipfile import ZipFile | 
|  |  | 
|  | import common | 
|  | from ota_from_target_files import (Payload, PayloadSigner) | 
|  |  | 
|  | logger = logging.getLogger(__name__) | 
|  | OPTIONS = common.OPTIONS | 
|  |  | 
|  |  | 
|  | def _ParseArgs(): | 
|  | parser = argparse.ArgumentParser(description=__doc__) | 
|  | parser.add_argument("--tools", metavar="PATH", type=str, nargs="*", | 
|  | help="A list of real paths of tools that this script depends on.") | 
|  | parser.add_argument("--key", type=str, | 
|  | help="Key to use to sign the package. If unspecified, script does not sign " | 
|  | "the package and payload_properties.txt is not generated.") | 
|  | parser.add_argument("--out", type=str, required=True, | 
|  | help="Required output directory to payload.bin and payload_properties.txt") | 
|  | parser.add_argument("input", metavar="NAME:IMAGE", nargs="+", | 
|  | help="Name of the image and path to the image, e.g. boot:path/to/boot.img") | 
|  | args = parser.parse_args() | 
|  |  | 
|  | return args | 
|  |  | 
|  |  | 
|  | def _PrepareEnvironment(args): | 
|  | common.InitLogging() | 
|  | if not args.tools: | 
|  | return | 
|  | for path in args.tools: | 
|  | name = os.path.basename(path) | 
|  | # Use absolute path because GetBootImageTimestamp changes cwd when running some tools. | 
|  | common.SetHostToolLocation(name, os.path.abspath(path)) | 
|  | # brillo_update_payload is a shell script that depends on this environment variable. | 
|  | if name == "delta_generator": | 
|  | os.environ["GENERATOR"] = path | 
|  |  | 
|  |  | 
|  | def CreateOtaFromRawImages(args): | 
|  | _PrepareEnvironment(args) | 
|  |  | 
|  | tf = common.MakeTempFile("target_files", ".zip") | 
|  | payload_additional_args = ["--is_partial_update", "true"] | 
|  | with ZipFile(tf, "w") as zip: | 
|  | names = [] | 
|  | for pair_str in args.input: | 
|  | pair = pair_str.split(":") | 
|  | assert len(pair) == 2, "Incorrect format: " + pair_str | 
|  | name, img_path = tuple(pair) | 
|  | zip.write(img_path, arcname=os.path.join("IMAGES", name + ".img")) | 
|  | names.append(name) | 
|  | if name == "boot": | 
|  | timestamp = common.GetBootImageTimestamp(img_path) | 
|  | assert timestamp is not None, "Cannot extract timestamp from boot image" | 
|  | payload_additional_args += ["--partition_timestamps", | 
|  | "boot:" + str(timestamp)] | 
|  |  | 
|  | zip.writestr("META/ab_partitions.txt", "\n".join(names) + "\n") | 
|  | zip.writestr("META/dynamic_partitions_info.txt", """ | 
|  | virtual_ab=true | 
|  | super_partition_groups= | 
|  | """) | 
|  |  | 
|  | payload = Payload() | 
|  | payload.Generate(tf, None, payload_additional_args) | 
|  |  | 
|  | if args.key: | 
|  | OPTIONS.package_key = args.key | 
|  | OPTIONS.key_passwords = common.GetKeyPasswords([OPTIONS.package_key]) | 
|  | payload_signer = PayloadSigner() | 
|  | payload.Sign(payload_signer) | 
|  |  | 
|  | shutil.copy(payload.payload_file, os.path.join(args.out, "payload.bin")) | 
|  | if payload.payload_properties: | 
|  | shutil.copy(payload.payload_properties, os.path.join(args.out, "payload_properties.txt")) | 
|  |  | 
|  |  | 
|  | if __name__ == "__main__": | 
|  | try: | 
|  | common.CloseInheritedPipes() | 
|  | args = _ParseArgs() | 
|  | CreateOtaFromRawImages(args) | 
|  | except common.ExternalError: | 
|  | logger.exception("\n   ERROR:\n") | 
|  | sys.exit(1) | 
|  | finally: | 
|  | common.Cleanup() |