1 #!/usr/bin/env python 2 # 3 # Copyright (C) 2008 The Android Open Source Project 4 # 5 # Licensed under the Apache License, Version 2.0 (the "License"); 6 # you may not use this file except in compliance with the License. 7 # You may obtain a copy of the License at 8 # 9 # http://www.apache.org/licenses/LICENSE-2.0 10 # 11 # Unless required by applicable law or agreed to in writing, software 12 # distributed under the License is distributed on an "AS IS" BASIS, 13 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 # See the License for the specific language governing permissions and 15 # limitations under the License. 16 17 """ 18 Given a target-files zipfile, produces an image zipfile suitable for 19 use with 'fastboot update'. 20 21 Usage: img_from_target_files [flags] input_target_files output_image_zip 22 23 -z (--bootable_zip) 24 Include only the bootable images (eg 'boot' and 'recovery') in 25 the output. 26 27 """ 28 29 import sys 30 31 if sys.hexversion < 0x02070000: 32 print >> sys.stderr, "Python 2.7 or newer is required." 33 sys.exit(1) 34 35 import errno 36 import os 37 import re 38 import shutil 39 import subprocess 40 import tempfile 41 import zipfile 42 43 # missing in Python 2.4 and before 44 if not hasattr(os, "SEEK_SET"): 45 os.SEEK_SET = 0 46 47 import common 48 49 OPTIONS = common.OPTIONS 50 51 52 def CopyInfo(output_zip): 53 """Copy the android-info.txt file from the input to the output.""" 54 output_zip.write(os.path.join(OPTIONS.input_tmp, "OTA", "android-info.txt"), 55 "android-info.txt") 56 57 58 def main(argv): 59 bootable_only = [False] 60 61 def option_handler(o, a): 62 if o in ("-z", "--bootable_zip"): 63 bootable_only[0] = True 64 else: 65 return False 66 return True 67 68 args = common.ParseOptions(argv, __doc__, 69 extra_opts="z", 70 extra_long_opts=["bootable_zip"], 71 extra_option_handler=option_handler) 72 73 bootable_only = bootable_only[0] 74 75 if len(args) != 2: 76 common.Usage(__doc__) 77 sys.exit(1) 78 79 OPTIONS.input_tmp, input_zip = common.UnzipTemp(args[0]) 80 output_zip = zipfile.ZipFile(args[1], "w", compression=zipfile.ZIP_DEFLATED) 81 CopyInfo(output_zip) 82 83 try: 84 done = False 85 images_path = os.path.join(OPTIONS.input_tmp, "IMAGES") 86 if os.path.exists(images_path): 87 # If this is a new target-files, it already contains the images, 88 # and all we have to do is copy them to the output zip. 89 images = os.listdir(images_path) 90 if images: 91 for i in images: 92 if bootable_only and i not in ("boot.img", "recovery.img"): continue 93 if not i.endswith(".img"): continue 94 with open(os.path.join(images_path, i), "r") as f: 95 common.ZipWriteStr(output_zip, i, f.read()) 96 done = True 97 98 if not done: 99 # We have an old target-files that doesn't already contain the 100 # images, so build them. 101 import add_img_to_target_files 102 103 OPTIONS.info_dict = common.LoadInfoDict(input_zip) 104 105 # If this image was originally labelled with SELinux contexts, 106 # make sure we also apply the labels in our new image. During 107 # building, the "file_contexts" is in the out/ directory tree, 108 # but for repacking from target-files.zip it's in the root 109 # directory of the ramdisk. 110 if "selinux_fc" in OPTIONS.info_dict: 111 OPTIONS.info_dict["selinux_fc"] = os.path.join( 112 OPTIONS.input_tmp, "BOOT", "RAMDISK", "file_contexts") 113 114 boot_image = common.GetBootableImage( 115 "boot.img", "boot.img", OPTIONS.input_tmp, "BOOT") 116 if boot_image: 117 boot_image.AddToZip(output_zip) 118 recovery_image = common.GetBootableImage( 119 "recovery.img", "recovery.img", OPTIONS.input_tmp, "RECOVERY") 120 if recovery_image: 121 recovery_image.AddToZip(output_zip) 122 123 def banner(s): 124 print "\n\n++++ " + s + " ++++\n\n" 125 126 if not bootable_only: 127 banner("AddSystem") 128 add_img_to_target_files.AddSystem(output_zip, prefix="") 129 try: 130 input_zip.getinfo("VENDOR/") 131 banner("AddVendor") 132 add_img_to_target_files.AddVendor(output_zip, prefix="") 133 except KeyError: 134 pass # no vendor partition for this device 135 banner("AddUserdata") 136 add_img_to_target_files.AddUserdata(output_zip, prefix="") 137 banner("AddCache") 138 add_img_to_target_files.AddCache(output_zip, prefix="") 139 140 finally: 141 print "cleaning up..." 142 output_zip.close() 143 shutil.rmtree(OPTIONS.input_tmp) 144 145 print "done." 146 147 148 if __name__ == '__main__': 149 try: 150 common.CloseInheritedPipes() 151 main(sys.argv[1:]) 152 except common.ExternalError, e: 153 print 154 print " ERROR: %s" % (e,) 155 print 156 sys.exit(1) 157