| 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 |  | 
 | 50 |  | 
 | 51 | def AddUserdata(output_zip): | 
 | 52 |   """Create an empty userdata image and store it in output_zip.""" | 
 | 53 |  | 
 | 54 |   print "creating userdata.img..." | 
 | 55 |  | 
 | 56 |   # The name of the directory it is making an image out of matters to | 
 | 57 |   # mkyaffs2image.  So we create a temp dir, and within it we create an | 
 | 58 |   # empty dir named "data", and build the image from that. | 
 | 59 |   temp_dir = tempfile.mkdtemp() | 
 | 60 |   user_dir = os.path.join(temp_dir, "data") | 
 | 61 |   os.mkdir(user_dir) | 
 | 62 |   img = tempfile.NamedTemporaryFile() | 
 | 63 |  | 
 | 64 |   p = common.Run(["mkyaffs2image", "-f", user_dir, img.name]) | 
 | 65 |   p.communicate() | 
 | 66 |   assert p.returncode == 0, "mkyaffs2image of userdata.img image failed" | 
 | 67 |  | 
 | 68 |   common.CheckSize(img.name, "userdata.img") | 
 | 69 |   output_zip.write(img.name, "userdata.img") | 
 | 70 |   img.close() | 
 | 71 |   os.rmdir(user_dir) | 
 | 72 |   os.rmdir(temp_dir) | 
 | 73 |  | 
 | 74 |  | 
 | 75 | def AddSystem(output_zip): | 
 | 76 |   """Turn the contents of SYSTEM into a system image and store it in | 
 | 77 |   output_zip.""" | 
 | 78 |  | 
 | 79 |   print "creating system.img..." | 
 | 80 |  | 
 | 81 |   img = tempfile.NamedTemporaryFile() | 
 | 82 |  | 
 | 83 |   # The name of the directory it is making an image out of matters to | 
 | 84 |   # mkyaffs2image.  It wants "system" but we have a directory named | 
 | 85 |   # "SYSTEM", so create a symlink. | 
| Mike Ritter | e44fade | 2009-09-15 11:18:31 -0700 | [diff] [blame] | 86 |   try: | 
 | 87 |     os.symlink(os.path.join(OPTIONS.input_tmp, "SYSTEM"), | 
 | 88 |                os.path.join(OPTIONS.input_tmp, "system")) | 
 | 89 |   except OSError, e: | 
 | 90 |       # bogus error on my mac version? | 
 | 91 |       #   File "./build/tools/releasetools/img_from_target_files", line 86, in AddSystem | 
 | 92 |       #     os.path.join(OPTIONS.input_tmp, "system")) | 
 | 93 |       # OSError: [Errno 17] File exists | 
 | 94 |     if (e.errno == errno.EEXIST): | 
 | 95 |       pass | 
| Doug Zongker | eef3944 | 2009-04-02 12:14:19 -0700 | [diff] [blame] | 96 |  | 
 | 97 |   p = common.Run(["mkyaffs2image", "-f", | 
 | 98 |                   os.path.join(OPTIONS.input_tmp, "system"), img.name]) | 
 | 99 |   p.communicate() | 
 | 100 |   assert p.returncode == 0, "mkyaffs2image of system.img image failed" | 
 | 101 |  | 
 | 102 |   img.seek(os.SEEK_SET, 0) | 
 | 103 |   data = img.read() | 
 | 104 |   img.close() | 
 | 105 |  | 
 | 106 |   common.CheckSize(data, "system.img") | 
| Doug Zongker | 048e7ca | 2009-06-15 14:31:53 -0700 | [diff] [blame] | 107 |   common.ZipWriteStr(output_zip, "system.img", data) | 
| Doug Zongker | eef3944 | 2009-04-02 12:14:19 -0700 | [diff] [blame] | 108 |  | 
 | 109 |  | 
 | 110 | def CopyInfo(output_zip): | 
 | 111 |   """Copy the android-info.txt file from the input to the output.""" | 
 | 112 |   output_zip.write(os.path.join(OPTIONS.input_tmp, "OTA", "android-info.txt"), | 
 | 113 |                    "android-info.txt") | 
 | 114 |  | 
 | 115 |  | 
 | 116 | def main(argv): | 
 | 117 |  | 
 | 118 |   def option_handler(o, a): | 
 | 119 |     if o in ("-b", "--board_config"): | 
| Doug Zongker | fdd8e69 | 2009-08-03 17:27:48 -0700 | [diff] [blame] | 120 |       pass       # deprecated | 
| Doug Zongker | eef3944 | 2009-04-02 12:14:19 -0700 | [diff] [blame] | 121 |     else: | 
 | 122 |       return False | 
| Doug Zongker | fdd8e69 | 2009-08-03 17:27:48 -0700 | [diff] [blame] | 123 |     return True | 
| Doug Zongker | eef3944 | 2009-04-02 12:14:19 -0700 | [diff] [blame] | 124 |  | 
 | 125 |   args = common.ParseOptions(argv, __doc__, | 
 | 126 |                              extra_opts="b:", | 
 | 127 |                              extra_long_opts=["board_config="], | 
 | 128 |                              extra_option_handler=option_handler) | 
 | 129 |  | 
 | 130 |   if len(args) != 2: | 
 | 131 |     common.Usage(__doc__) | 
 | 132 |     sys.exit(1) | 
 | 133 |  | 
| Doug Zongker | fdd8e69 | 2009-08-03 17:27:48 -0700 | [diff] [blame] | 134 |   OPTIONS.input_tmp = common.UnzipTemp(args[0]) | 
 | 135 |  | 
 | 136 |   common.LoadMaxSizes() | 
| Doug Zongker | eef3944 | 2009-04-02 12:14:19 -0700 | [diff] [blame] | 137 |   if not OPTIONS.max_image_size: | 
 | 138 |     print | 
| Doug Zongker | fdd8e69 | 2009-08-03 17:27:48 -0700 | [diff] [blame] | 139 |     print "  WARNING:  Failed to load max image sizes; will not enforce" | 
 | 140 |     print "  image size limits." | 
| Doug Zongker | eef3944 | 2009-04-02 12:14:19 -0700 | [diff] [blame] | 141 |     print | 
 | 142 |  | 
| Doug Zongker | eef3944 | 2009-04-02 12:14:19 -0700 | [diff] [blame] | 143 |   output_zip = zipfile.ZipFile(args[1], "w", compression=zipfile.ZIP_DEFLATED) | 
 | 144 |  | 
 | 145 |   common.AddBoot(output_zip) | 
 | 146 |   common.AddRecovery(output_zip) | 
 | 147 |   AddSystem(output_zip) | 
 | 148 |   AddUserdata(output_zip) | 
 | 149 |   CopyInfo(output_zip) | 
 | 150 |  | 
 | 151 |   print "cleaning up..." | 
 | 152 |   output_zip.close() | 
 | 153 |   shutil.rmtree(OPTIONS.input_tmp) | 
 | 154 |  | 
 | 155 |   print "done." | 
 | 156 |  | 
 | 157 |  | 
 | 158 | if __name__ == '__main__': | 
 | 159 |   try: | 
 | 160 |     main(sys.argv[1:]) | 
 | 161 |   except common.ExternalError, e: | 
 | 162 |     print | 
 | 163 |     print "   ERROR: %s" % (e,) | 
 | 164 |     print | 
 | 165 |     sys.exit(1) |