blob: acd0697acb204283dcc092cbb641608d5329e0c3 [file] [log] [blame]
#!/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()