#!/usr/bin/env python3 # # Copyright (C) 2021 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. # """Command-line tool for converting OTA payloads to VABC style COW images.""" import os import sys import tempfile import zipfile import subprocess def IsSparseImage(filepath): """Determine if an image is a sparse image Args: filepath: str, a path to an .img file Returns: return true iff the filepath is a sparse image. """ with open(filepath, 'rb') as fp: # Magic for android sparse image format # https://source.android.com/devices/bootloader/images return fp.read(4) == b'\x3A\xFF\x26\xED' def ConvertCOW(ota_path, target_file_path, tmp_dir, output_dir): """Convert ota payload to COW IMAGE Args: ota_path: str, path to ota.zip target_file_path: str, path to target_file.zip, must be the target build for OTA. tmp_dir: A temp dir as scratch space output_dir: A directory where all converted COW images will be written. """ with zipfile.ZipFile(ota_path) as ota_zip: payload_path = ota_zip.extract("payload.bin", output_dir) with zipfile.ZipFile(target_file_path) as zfp: for fileinfo in zfp.infolist(): img_name = os.path.basename(fileinfo.filename) if not fileinfo.filename.endswith(".img"): continue if fileinfo.filename.startswith("IMAGES/") or \ fileinfo.filename.startswith("RADIO/"): img_path = zfp.extract(fileinfo, tmp_dir) target_img_path = os.path.join(output_dir, img_name) if IsSparseImage(img_path): subprocess.check_call(["simg2img", img_path, target_img_path]) else: os.rename(img_path, target_img_path) print("Extracted", fileinfo.filename, "size:", fileinfo.file_size) subprocess.call(["cow_converter", payload_path, output_dir]) def main(): if len(sys.argv) != 4: print( "Usage:", sys.argv[0], " ") return 1 ota_path = sys.argv[1] target_file_path = sys.argv[2] output_dir = sys.argv[3] os.makedirs(output_dir, exist_ok=True) with tempfile.TemporaryDirectory() as tmp_dir: ConvertCOW(ota_path, target_file_path, tmp_dir, output_dir) return 0 if __name__ == '__main__': sys.exit(main())