blob: 0c4c8595db910505aa6b593b2ce6639085b17ea6 [file] [log] [blame]
Doug Zongkereef39442009-04-02 12:14:19 -07001#!/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"""
18Given a target-files zipfile, produces an image zipfile suitable for
19use with 'fastboot update'.
20
21Usage: img_from_target_files [flags] input_target_files output_image_zip
22
23 -b (--board_config) <file>
Doug Zongkerfdd8e692009-08-03 17:27:48 -070024 Deprecated.
Doug Zongkereef39442009-04-02 12:14:19 -070025
Ying Wang065521b2010-08-23 11:34:40 -070026 -f (--fs_type) <value>
27 The file system type of the user image files to be created.
28 It can be ext fs variants, such as ext2, ext3, ext4, etc.
29 efault is yaffs.
30
Doug Zongkereef39442009-04-02 12:14:19 -070031"""
32
33import sys
34
35if sys.hexversion < 0x02040000:
36 print >> sys.stderr, "Python 2.4 or newer is required."
37 sys.exit(1)
38
Mike Rittere44fade2009-09-15 11:18:31 -070039import errno
Doug Zongkereef39442009-04-02 12:14:19 -070040import os
41import re
42import shutil
43import subprocess
44import tempfile
45import zipfile
46
47# missing in Python 2.4 and before
48if not hasattr(os, "SEEK_SET"):
49 os.SEEK_SET = 0
50
51import common
52
53OPTIONS = common.OPTIONS
54
Ying Wang065521b2010-08-23 11:34:40 -070055class UserImageOptions(object): pass
56USERIMAGE_OPTIONS = UserImageOptions()
57USERIMAGE_OPTIONS.fs_type = None
Doug Zongkereef39442009-04-02 12:14:19 -070058
59def AddUserdata(output_zip):
60 """Create an empty userdata image and store it in output_zip."""
61
62 print "creating userdata.img..."
63
64 # The name of the directory it is making an image out of matters to
65 # mkyaffs2image. So we create a temp dir, and within it we create an
66 # empty dir named "data", and build the image from that.
67 temp_dir = tempfile.mkdtemp()
68 user_dir = os.path.join(temp_dir, "data")
69 os.mkdir(user_dir)
70 img = tempfile.NamedTemporaryFile()
71
Ying Wang065521b2010-08-23 11:34:40 -070072 build_command = []
73 if USERIMAGE_OPTIONS.fs_type is not None and USERIMAGE_OPTIONS.fs_type.startswith("ext"):
74 build_command = ["mkuserimg.sh",
75 user_dir, img.name, USERIMAGE_OPTIONS.fs_type, "userdata"]
76 if "userdata.img" in OPTIONS.max_image_size:
77 build_command.append(str(OPTIONS.max_image_size["userdata.img"]))
78 else:
Ying Wangd421f572010-08-25 20:39:41 -070079 build_command = ["mkyaffs2image", "-f"]
80 if OPTIONS.mkyaffs2_extra_flags is not None:
81 build_command.append(OPTIONS.mkyaffs2_extra_flags);
82 build_command.append(user_dir)
83 build_command.append(img.name)
Ying Wang065521b2010-08-23 11:34:40 -070084
85 p = common.Run(build_command)
Doug Zongkereef39442009-04-02 12:14:19 -070086 p.communicate()
Ying Wang065521b2010-08-23 11:34:40 -070087 assert p.returncode == 0, "build userdata.img image failed"
Doug Zongkereef39442009-04-02 12:14:19 -070088
Ying Wangee4bad52010-08-24 11:18:07 -070089 if USERIMAGE_OPTIONS.fs_type is None or not USERIMAGE_OPTIONS.fs_type.startswith("ext"):
90 common.CheckSize(img.name, "userdata.img")
Doug Zongkereef39442009-04-02 12:14:19 -070091 output_zip.write(img.name, "userdata.img")
92 img.close()
93 os.rmdir(user_dir)
94 os.rmdir(temp_dir)
95
96
97def AddSystem(output_zip):
98 """Turn the contents of SYSTEM into a system image and store it in
99 output_zip."""
100
101 print "creating system.img..."
102
103 img = tempfile.NamedTemporaryFile()
104
105 # The name of the directory it is making an image out of matters to
106 # mkyaffs2image. It wants "system" but we have a directory named
107 # "SYSTEM", so create a symlink.
Mike Rittere44fade2009-09-15 11:18:31 -0700108 try:
109 os.symlink(os.path.join(OPTIONS.input_tmp, "SYSTEM"),
110 os.path.join(OPTIONS.input_tmp, "system"))
111 except OSError, e:
112 # bogus error on my mac version?
113 # File "./build/tools/releasetools/img_from_target_files", line 86, in AddSystem
114 # os.path.join(OPTIONS.input_tmp, "system"))
115 # OSError: [Errno 17] File exists
116 if (e.errno == errno.EEXIST):
117 pass
Doug Zongkereef39442009-04-02 12:14:19 -0700118
Ying Wang065521b2010-08-23 11:34:40 -0700119 build_command = []
120 if USERIMAGE_OPTIONS.fs_type is not None and USERIMAGE_OPTIONS.fs_type.startswith("ext"):
121 build_command = ["mkuserimg.sh",
122 os.path.join(OPTIONS.input_tmp, "system"), img.name,
123 USERIMAGE_OPTIONS.fs_type, "system"]
124 if "system.img" in OPTIONS.max_image_size:
125 build_command.append(str(OPTIONS.max_image_size["system.img"]))
126 else:
Ying Wangd421f572010-08-25 20:39:41 -0700127 build_command = ["mkyaffs2image", "-f"]
128 if OPTIONS.mkyaffs2_extra_flags is not None:
129 build_command.append(OPTIONS.mkyaffs2_extra_flags);
130 build_command.append(os.path.join(OPTIONS.input_tmp, "system"))
131 build_command.append(img.name)
Ying Wang065521b2010-08-23 11:34:40 -0700132
Ying Wangaa6dbe22010-08-26 14:01:50 -0700133 # p = common.Run(build_command)
134 # p.communicate()
135 # assert p.returncode == 0, "build system.img image failed"
136
137 # TODO: Why the above common.Run() generate different system.img for crespo?
138 str_command = "mkyaffs2image -f ";
139 if OPTIONS.mkyaffs2_extra_flags is not None:
140 str_command = str_command + OPTIONS.mkyaffs2_extra_flags
141 str_command = str_command + " " + os.path.join(OPTIONS.input_tmp, "system") + " " + img.name
142
143 print "running " + str_command
144 exit_code = os.system(str_command)
145 assert exit_code == 0, "build system.img image failed"
Doug Zongkereef39442009-04-02 12:14:19 -0700146
147 img.seek(os.SEEK_SET, 0)
148 data = img.read()
149 img.close()
150
Ying Wangee4bad52010-08-24 11:18:07 -0700151 if USERIMAGE_OPTIONS.fs_type is None or not USERIMAGE_OPTIONS.fs_type.startswith("ext"):
152 common.CheckSize(data, "system.img")
Doug Zongker048e7ca2009-06-15 14:31:53 -0700153 common.ZipWriteStr(output_zip, "system.img", data)
Doug Zongkereef39442009-04-02 12:14:19 -0700154
155
156def CopyInfo(output_zip):
157 """Copy the android-info.txt file from the input to the output."""
158 output_zip.write(os.path.join(OPTIONS.input_tmp, "OTA", "android-info.txt"),
159 "android-info.txt")
160
161
162def main(argv):
163
164 def option_handler(o, a):
165 if o in ("-b", "--board_config"):
Doug Zongkerfdd8e692009-08-03 17:27:48 -0700166 pass # deprecated
Ying Wang065521b2010-08-23 11:34:40 -0700167 elif o in ("-f", "--fs_type"):
168 USERIMAGE_OPTIONS.fs_type = a
Doug Zongkereef39442009-04-02 12:14:19 -0700169 else:
170 return False
Doug Zongkerfdd8e692009-08-03 17:27:48 -0700171 return True
Doug Zongkereef39442009-04-02 12:14:19 -0700172
173 args = common.ParseOptions(argv, __doc__,
Ying Wang065521b2010-08-23 11:34:40 -0700174 extra_opts="b:f:",
175 extra_long_opts=["board_config=", "fs_type="],
Doug Zongkereef39442009-04-02 12:14:19 -0700176 extra_option_handler=option_handler)
177
178 if len(args) != 2:
179 common.Usage(__doc__)
180 sys.exit(1)
181
Doug Zongkerfdd8e692009-08-03 17:27:48 -0700182 OPTIONS.input_tmp = common.UnzipTemp(args[0])
183
184 common.LoadMaxSizes()
Doug Zongkereef39442009-04-02 12:14:19 -0700185 if not OPTIONS.max_image_size:
186 print
Doug Zongkerfdd8e692009-08-03 17:27:48 -0700187 print " WARNING: Failed to load max image sizes; will not enforce"
188 print " image size limits."
Doug Zongkereef39442009-04-02 12:14:19 -0700189 print
190
Ying Wangd421f572010-08-25 20:39:41 -0700191 common.LoadMkyaffs2ExtraFlags()
192
Doug Zongkereef39442009-04-02 12:14:19 -0700193 output_zip = zipfile.ZipFile(args[1], "w", compression=zipfile.ZIP_DEFLATED)
194
195 common.AddBoot(output_zip)
196 common.AddRecovery(output_zip)
197 AddSystem(output_zip)
198 AddUserdata(output_zip)
199 CopyInfo(output_zip)
200
201 print "cleaning up..."
202 output_zip.close()
203 shutil.rmtree(OPTIONS.input_tmp)
204
205 print "done."
206
207
208if __name__ == '__main__':
209 try:
210 main(sys.argv[1:])
211 except common.ExternalError, e:
212 print
213 print " ERROR: %s" % (e,)
214 print
215 sys.exit(1)