| Doug Zongker | eef3944 | 2009-04-02 12:14:19 -0700 | [diff] [blame] | 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 | -b  (--board_config)  <file> | 
| Doug Zongker | fdd8e69 | 2009-08-03 17:27:48 -0700 | [diff] [blame] | 24 | Deprecated. | 
| Doug Zongker | eef3944 | 2009-04-02 12:14:19 -0700 | [diff] [blame] | 25 |  | 
|  | 26 | """ | 
|  | 27 |  | 
|  | 28 | import sys | 
|  | 29 |  | 
|  | 30 | if sys.hexversion < 0x02040000: | 
|  | 31 | print >> sys.stderr, "Python 2.4 or newer is required." | 
|  | 32 | sys.exit(1) | 
|  | 33 |  | 
| Mike Ritter | e44fade | 2009-09-15 11:18:31 -0700 | [diff] [blame] | 34 | import errno | 
| Doug Zongker | eef3944 | 2009-04-02 12:14:19 -0700 | [diff] [blame] | 35 | import os | 
|  | 36 | import re | 
|  | 37 | import shutil | 
|  | 38 | import subprocess | 
|  | 39 | import tempfile | 
|  | 40 | import zipfile | 
|  | 41 |  | 
|  | 42 | # missing in Python 2.4 and before | 
|  | 43 | if not hasattr(os, "SEEK_SET"): | 
|  | 44 | os.SEEK_SET = 0 | 
|  | 45 |  | 
|  | 46 | import common | 
|  | 47 |  | 
|  | 48 | OPTIONS = common.OPTIONS | 
|  | 49 |  | 
| Doug Zongker | eef3944 | 2009-04-02 12:14:19 -0700 | [diff] [blame] | 50 | def AddUserdata(output_zip): | 
|  | 51 | """Create an empty userdata image and store it in output_zip.""" | 
|  | 52 |  | 
|  | 53 | print "creating userdata.img..." | 
|  | 54 |  | 
|  | 55 | # The name of the directory it is making an image out of matters to | 
|  | 56 | # mkyaffs2image.  So we create a temp dir, and within it we create an | 
|  | 57 | # empty dir named "data", and build the image from that. | 
|  | 58 | temp_dir = tempfile.mkdtemp() | 
|  | 59 | user_dir = os.path.join(temp_dir, "data") | 
|  | 60 | os.mkdir(user_dir) | 
|  | 61 | img = tempfile.NamedTemporaryFile() | 
|  | 62 |  | 
| Ying Wang | 933abf1 | 2010-06-16 14:31:34 -0700 | [diff] [blame] | 63 | build_command = [] | 
| Doug Zongker | 33a4b08 | 2010-09-21 16:12:55 -0700 | [diff] [blame] | 64 | fstab = OPTIONS.info_dict["fstab"] | 
|  | 65 | if fstab and fstab["/data"].fs_type.startswith("ext"): | 
| Ying Wang | c5a07ce | 2010-11-17 17:45:36 -0800 | [diff] [blame] | 66 | build_command = ["mkuserimg.sh"] | 
|  | 67 | if "extfs_sparse_flag" in OPTIONS.info_dict: | 
|  | 68 | build_command.append(OPTIONS.info_dict["extfs_sparse_flag"]) | 
|  | 69 | build_command.extend([user_dir, img.name, | 
|  | 70 | fstab["/data"].fs_type, "data"]) | 
| Doug Zongker | 1684d9c | 2010-09-17 07:44:38 -0700 | [diff] [blame] | 71 | if "userdata_size" in OPTIONS.info_dict: | 
|  | 72 | build_command.append(str(OPTIONS.info_dict["userdata_size"])) | 
| Ying Wang | 933abf1 | 2010-06-16 14:31:34 -0700 | [diff] [blame] | 73 | else: | 
| Ying Wang | d421f57 | 2010-08-25 20:39:41 -0700 | [diff] [blame] | 74 | build_command = ["mkyaffs2image", "-f"] | 
| Doug Zongker | 3797473 | 2010-09-16 17:44:38 -0700 | [diff] [blame] | 75 | extra = OPTIONS.info_dict.get("mkyaffs2_extra_flags", None) | 
|  | 76 | if extra: | 
|  | 77 | build_command.extend(extra.split()) | 
| Ying Wang | d421f57 | 2010-08-25 20:39:41 -0700 | [diff] [blame] | 78 | build_command.append(user_dir) | 
|  | 79 | build_command.append(img.name) | 
| Ying Wang | 933abf1 | 2010-06-16 14:31:34 -0700 | [diff] [blame] | 80 |  | 
|  | 81 | p = common.Run(build_command); | 
| Doug Zongker | eef3944 | 2009-04-02 12:14:19 -0700 | [diff] [blame] | 82 | p.communicate() | 
| Ying Wang | 933abf1 | 2010-06-16 14:31:34 -0700 | [diff] [blame] | 83 | assert p.returncode == 0, "build userdata.img image failed" | 
| Doug Zongker | eef3944 | 2009-04-02 12:14:19 -0700 | [diff] [blame] | 84 |  | 
| Doug Zongker | 3797473 | 2010-09-16 17:44:38 -0700 | [diff] [blame] | 85 | common.CheckSize(img.name, "userdata.img", OPTIONS.info_dict) | 
| Doug Zongker | eef3944 | 2009-04-02 12:14:19 -0700 | [diff] [blame] | 86 | output_zip.write(img.name, "userdata.img") | 
|  | 87 | img.close() | 
|  | 88 | os.rmdir(user_dir) | 
|  | 89 | os.rmdir(temp_dir) | 
|  | 90 |  | 
|  | 91 |  | 
|  | 92 | def AddSystem(output_zip): | 
|  | 93 | """Turn the contents of SYSTEM into a system image and store it in | 
|  | 94 | output_zip.""" | 
|  | 95 |  | 
|  | 96 | print "creating system.img..." | 
|  | 97 |  | 
|  | 98 | img = tempfile.NamedTemporaryFile() | 
|  | 99 |  | 
|  | 100 | # The name of the directory it is making an image out of matters to | 
|  | 101 | # mkyaffs2image.  It wants "system" but we have a directory named | 
|  | 102 | # "SYSTEM", so create a symlink. | 
| Mike Ritter | e44fade | 2009-09-15 11:18:31 -0700 | [diff] [blame] | 103 | try: | 
|  | 104 | os.symlink(os.path.join(OPTIONS.input_tmp, "SYSTEM"), | 
|  | 105 | os.path.join(OPTIONS.input_tmp, "system")) | 
|  | 106 | except OSError, e: | 
|  | 107 | # bogus error on my mac version? | 
|  | 108 | #   File "./build/tools/releasetools/img_from_target_files", line 86, in AddSystem | 
|  | 109 | #     os.path.join(OPTIONS.input_tmp, "system")) | 
|  | 110 | # OSError: [Errno 17] File exists | 
|  | 111 | if (e.errno == errno.EEXIST): | 
|  | 112 | pass | 
| Doug Zongker | eef3944 | 2009-04-02 12:14:19 -0700 | [diff] [blame] | 113 |  | 
| Ying Wang | 933abf1 | 2010-06-16 14:31:34 -0700 | [diff] [blame] | 114 | build_command = [] | 
| Doug Zongker | 33a4b08 | 2010-09-21 16:12:55 -0700 | [diff] [blame] | 115 | fstab = OPTIONS.info_dict["fstab"] | 
|  | 116 | if fstab and fstab["/system"].fs_type.startswith("ext"): | 
| Ying Wang | c5a07ce | 2010-11-17 17:45:36 -0800 | [diff] [blame] | 117 |  | 
|  | 118 | build_command = ["mkuserimg.sh"] | 
|  | 119 | if "extfs_sparse_flag" in OPTIONS.info_dict: | 
|  | 120 | build_command.append(OPTIONS.info_dict["extfs_sparse_flag"]) | 
|  | 121 | build_command.extend([os.path.join(OPTIONS.input_tmp, "system"), img.name, | 
|  | 122 | fstab["/system"].fs_type, "system"]) | 
| Doug Zongker | ad80698 | 2010-09-21 17:22:14 -0700 | [diff] [blame] | 123 | if "system_size" in OPTIONS.info_dict: | 
| Doug Zongker | 1684d9c | 2010-09-17 07:44:38 -0700 | [diff] [blame] | 124 | build_command.append(str(OPTIONS.info_dict["system_size"])) | 
| Ying Wang | 933abf1 | 2010-06-16 14:31:34 -0700 | [diff] [blame] | 125 | else: | 
| Ying Wang | d421f57 | 2010-08-25 20:39:41 -0700 | [diff] [blame] | 126 | build_command = ["mkyaffs2image", "-f"] | 
| Doug Zongker | 3797473 | 2010-09-16 17:44:38 -0700 | [diff] [blame] | 127 | extra = OPTIONS.info_dict.get("mkyaffs2_extra_flags", None) | 
|  | 128 | if extra: | 
|  | 129 | build_command.extend(extra.split()) | 
| Ying Wang | d421f57 | 2010-08-25 20:39:41 -0700 | [diff] [blame] | 130 | build_command.append(os.path.join(OPTIONS.input_tmp, "system")) | 
|  | 131 | build_command.append(img.name) | 
| Ying Wang | 933abf1 | 2010-06-16 14:31:34 -0700 | [diff] [blame] | 132 |  | 
| Doug Zongker | 39a9845 | 2010-09-03 14:15:34 -0700 | [diff] [blame] | 133 | p = common.Run(build_command) | 
|  | 134 | p.communicate() | 
|  | 135 | assert p.returncode == 0, "build system.img image failed" | 
| Doug Zongker | eef3944 | 2009-04-02 12:14:19 -0700 | [diff] [blame] | 136 |  | 
|  | 137 | img.seek(os.SEEK_SET, 0) | 
|  | 138 | data = img.read() | 
|  | 139 | img.close() | 
|  | 140 |  | 
| Doug Zongker | 3797473 | 2010-09-16 17:44:38 -0700 | [diff] [blame] | 141 | common.CheckSize(data, "system.img", OPTIONS.info_dict) | 
| Doug Zongker | 048e7ca | 2009-06-15 14:31:53 -0700 | [diff] [blame] | 142 | common.ZipWriteStr(output_zip, "system.img", data) | 
| Doug Zongker | eef3944 | 2009-04-02 12:14:19 -0700 | [diff] [blame] | 143 |  | 
|  | 144 |  | 
|  | 145 | def CopyInfo(output_zip): | 
|  | 146 | """Copy the android-info.txt file from the input to the output.""" | 
|  | 147 | output_zip.write(os.path.join(OPTIONS.input_tmp, "OTA", "android-info.txt"), | 
|  | 148 | "android-info.txt") | 
|  | 149 |  | 
|  | 150 |  | 
|  | 151 | def main(argv): | 
|  | 152 |  | 
|  | 153 | def option_handler(o, a): | 
|  | 154 | if o in ("-b", "--board_config"): | 
| Doug Zongker | fdd8e69 | 2009-08-03 17:27:48 -0700 | [diff] [blame] | 155 | pass       # deprecated | 
| Doug Zongker | eef3944 | 2009-04-02 12:14:19 -0700 | [diff] [blame] | 156 | else: | 
|  | 157 | return False | 
| Doug Zongker | fdd8e69 | 2009-08-03 17:27:48 -0700 | [diff] [blame] | 158 | return True | 
| Doug Zongker | eef3944 | 2009-04-02 12:14:19 -0700 | [diff] [blame] | 159 |  | 
|  | 160 | args = common.ParseOptions(argv, __doc__, | 
| Doug Zongker | c77a9ad | 2010-09-16 11:28:43 -0700 | [diff] [blame] | 161 | extra_opts="b:", | 
|  | 162 | extra_long_opts=["board_config="], | 
| Doug Zongker | eef3944 | 2009-04-02 12:14:19 -0700 | [diff] [blame] | 163 | extra_option_handler=option_handler) | 
|  | 164 |  | 
|  | 165 | if len(args) != 2: | 
|  | 166 | common.Usage(__doc__) | 
|  | 167 | sys.exit(1) | 
|  | 168 |  | 
| Doug Zongker | fdd8e69 | 2009-08-03 17:27:48 -0700 | [diff] [blame] | 169 | OPTIONS.input_tmp = common.UnzipTemp(args[0]) | 
|  | 170 |  | 
| Doug Zongker | 3797473 | 2010-09-16 17:44:38 -0700 | [diff] [blame] | 171 | input_zip = zipfile.ZipFile(args[0], "r") | 
|  | 172 | OPTIONS.info_dict = common.LoadInfoDict(input_zip) | 
| Ying Wang | d421f57 | 2010-08-25 20:39:41 -0700 | [diff] [blame] | 173 |  | 
| Doug Zongker | eef3944 | 2009-04-02 12:14:19 -0700 | [diff] [blame] | 174 | output_zip = zipfile.ZipFile(args[1], "w", compression=zipfile.ZIP_DEFLATED) | 
|  | 175 |  | 
| Doug Zongker | 3797473 | 2010-09-16 17:44:38 -0700 | [diff] [blame] | 176 | common.AddBoot(output_zip, OPTIONS.info_dict) | 
|  | 177 | common.AddRecovery(output_zip, OPTIONS.info_dict) | 
| Doug Zongker | eef3944 | 2009-04-02 12:14:19 -0700 | [diff] [blame] | 178 | AddSystem(output_zip) | 
|  | 179 | AddUserdata(output_zip) | 
|  | 180 | CopyInfo(output_zip) | 
|  | 181 |  | 
|  | 182 | print "cleaning up..." | 
|  | 183 | output_zip.close() | 
|  | 184 | shutil.rmtree(OPTIONS.input_tmp) | 
|  | 185 |  | 
|  | 186 | print "done." | 
|  | 187 |  | 
|  | 188 |  | 
|  | 189 | if __name__ == '__main__': | 
|  | 190 | try: | 
|  | 191 | main(sys.argv[1:]) | 
|  | 192 | except common.ExternalError, e: | 
|  | 193 | print | 
|  | 194 | print "   ERROR: %s" % (e,) | 
|  | 195 | print | 
|  | 196 | sys.exit(1) |