#!/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. # """Script to extract payload.bin from an OTA update.""" import argparse import os import tempfile import zipfile import update_payload from update_payload import applier def extract_ota(payload_path, list_partitions, output_dir, partitions): """Extract OTA payload""" payload = update_payload.Payload(payload_path) payload.Init() new_parts = {} new_part_info = {} install_operations = [] for part in payload.manifest.partitions: name = part.partition_name if list_partitions: print(name) if partitions and name not in partitions: continue new_image = os.path.join(output_dir, name + ".img") new_parts[name] = new_image new_part_info[name] = part.new_partition_info install_operations.append((name, part.operations)) if not list_partitions: for name, operations in install_operations: applier.PayloadApplier(payload)._ApplyToPartition( operations, name, '%s_install_operations' % name, new_parts[name], new_part_info[name]) def main(): parser = argparse.ArgumentParser( description="Extract payload.bin from OTA package") parser.add_argument( "payload", help="payload.bin for the OTA package, or a zip of OTA package itself", nargs=1 ) parser.add_argument( "-l", dest="list_partitions", help="List partitions, without extracting", action='store_true') parser.add_argument( "-o", dest="output_dir", help="Output directory to put all images, current directory by default" ) parser.add_argument( "-p", dest="partitions", help="List of partitions to extract, all by default", nargs="*" ) args = parser.parse_args() # pylint: disable=no-member with tempfile.TemporaryDirectory() as tempdir: payload_path = args.payload[0] if zipfile.is_zipfile(payload_path): with zipfile.ZipFile(payload_path, "r") as zfp: payload_entry_name = 'payload.bin' zfp.extract(payload_entry_name, tempdir) payload_path = os.path.join(tempdir, payload_entry_name) if args.output_dir is None: args.output_dir = "." if not os.path.exists(args.output_dir): os.makedirs(args.output_dir, exist_ok=True) assert os.path.isdir(args.output_dir) extract_ota(payload_path, args.list_partitions, args.output_dir, args.partitions) if __name__ == '__main__': main()