blob: 94a9fda6dc139eda8e75209821896d167e16174d [file] [log] [blame]
Ying Wangbd93d422011-10-28 17:02:30 -07001#!/usr/bin/env python
2#
3# Copyright (C) 2011 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"""
18Build image output_image_file from input_directory and properties_file.
19
20Usage: build_image input_directory properties_file output_image_file
21
22"""
23import os
Ying Wang6a6c1122012-11-26 18:10:23 -080024import os.path
Ying Wangbd93d422011-10-28 17:02:30 -070025import subprocess
26import sys
27
Ying Wang6a6c1122012-11-26 18:10:23 -080028def RunCommand(cmd):
29 """ Echo and run the given command
30
31 Args:
32 cmd: the command represented as a list of strings.
33 Returns:
34 The exit code.
35 """
36 print "Running: ", " ".join(cmd)
37 p = subprocess.Popen(cmd)
38 p.communicate()
39 return p.returncode
Ying Wangbd93d422011-10-28 17:02:30 -070040
41def BuildImage(in_dir, prop_dict, out_file):
42 """Build an image to out_file from in_dir with property prop_dict.
43
44 Args:
45 in_dir: path of input directory.
46 prop_dict: property dictionary.
47 out_file: path of the output image file.
48
49 Returns:
50 True iff the image is built successfully.
51 """
52 build_command = []
53 fs_type = prop_dict.get("fs_type", "")
Ying Wang6a6c1122012-11-26 18:10:23 -080054 run_fsck = False
Ying Wangbd93d422011-10-28 17:02:30 -070055 if fs_type.startswith("ext"):
56 build_command = ["mkuserimg.sh"]
57 if "extfs_sparse_flag" in prop_dict:
58 build_command.append(prop_dict["extfs_sparse_flag"])
Ying Wang6a6c1122012-11-26 18:10:23 -080059 run_fsck = True
Ying Wangbd93d422011-10-28 17:02:30 -070060 build_command.extend([in_dir, out_file, fs_type,
61 prop_dict["mount_point"]])
62 if "partition_size" in prop_dict:
63 build_command.append(prop_dict["partition_size"])
Kenny Rootf32dc712012-04-08 10:42:34 -070064 if "selinux_fc" in prop_dict:
65 build_command.append(prop_dict["selinux_fc"])
Ying Wangbd93d422011-10-28 17:02:30 -070066 else:
67 build_command = ["mkyaffs2image", "-f"]
68 if prop_dict.get("mkyaffs2_extra_flags", None):
69 build_command.extend(prop_dict["mkyaffs2_extra_flags"].split())
70 build_command.append(in_dir)
71 build_command.append(out_file)
Kenny Rootf32dc712012-04-08 10:42:34 -070072 if "selinux_fc" in prop_dict:
73 build_command.append(prop_dict["selinux_fc"])
74 build_command.append(prop_dict["mount_point"])
Ying Wangbd93d422011-10-28 17:02:30 -070075
Ying Wang6a6c1122012-11-26 18:10:23 -080076 exit_code = RunCommand(build_command)
77 if exit_code != 0:
78 return False
79
80 if run_fsck:
81 # Inflate the sparse image
82 unsparse_image = os.path.join(
83 os.path.dirname(out_file), "unsparse_" + os.path.basename(out_file))
84 inflate_command = ["simg2img", out_file, unsparse_image]
85 exit_code = RunCommand(inflate_command)
86 if exit_code != 0:
87 os.remove(unsparse_image)
88 return False
89
90 # Run e2fsck on the inflated image file
91 e2fsck_command = ["e2fsck", "-f", "-n", unsparse_image]
92 exit_code = RunCommand(e2fsck_command)
93
94 os.remove(unsparse_image)
95
96 return exit_code == 0
Ying Wangbd93d422011-10-28 17:02:30 -070097
98
99def ImagePropFromGlobalDict(glob_dict, mount_point):
100 """Build an image property dictionary from the global dictionary.
101
102 Args:
103 glob_dict: the global dictionary from the build system.
104 mount_point: such as "system", "data" etc.
105 """
106 d = {}
Ying Wang9f8e8db2011-11-04 11:37:01 -0700107
108 def copy_prop(src_p, dest_p):
109 if src_p in glob_dict:
110 d[dest_p] = str(glob_dict[src_p])
111
Ying Wangbd93d422011-10-28 17:02:30 -0700112 common_props = (
Ying Wangbd93d422011-10-28 17:02:30 -0700113 "extfs_sparse_flag",
114 "mkyaffs2_extra_flags",
Kenny Rootf32dc712012-04-08 10:42:34 -0700115 "selinux_fc",
Ying Wangbd93d422011-10-28 17:02:30 -0700116 )
117 for p in common_props:
Ying Wang9f8e8db2011-11-04 11:37:01 -0700118 copy_prop(p, p)
Ying Wangbd93d422011-10-28 17:02:30 -0700119
120 d["mount_point"] = mount_point
121 if mount_point == "system":
Ying Wang9f8e8db2011-11-04 11:37:01 -0700122 copy_prop("fs_type", "fs_type")
123 copy_prop("system_size", "partition_size")
Ying Wangbd93d422011-10-28 17:02:30 -0700124 elif mount_point == "data":
Ying Wang9f8e8db2011-11-04 11:37:01 -0700125 copy_prop("fs_type", "fs_type")
126 copy_prop("userdata_size", "partition_size")
127 elif mount_point == "cache":
128 copy_prop("cache_fs_type", "fs_type")
129 copy_prop("cache_size", "partition_size")
Ying Wangbd93d422011-10-28 17:02:30 -0700130
131 return d
132
133
134def LoadGlobalDict(filename):
135 """Load "name=value" pairs from filename"""
136 d = {}
137 f = open(filename)
138 for line in f:
139 line = line.strip()
140 if not line or line.startswith("#"):
141 continue
142 k, v = line.split("=", 1)
143 d[k] = v
144 f.close()
145 return d
146
147
148def main(argv):
149 if len(argv) != 3:
150 print __doc__
151 sys.exit(1)
152
153 in_dir = argv[0]
154 glob_dict_file = argv[1]
155 out_file = argv[2]
156
157 glob_dict = LoadGlobalDict(glob_dict_file)
158 image_filename = os.path.basename(out_file)
159 mount_point = ""
160 if image_filename == "system.img":
161 mount_point = "system"
162 elif image_filename == "userdata.img":
163 mount_point = "data"
Ying Wang9f8e8db2011-11-04 11:37:01 -0700164 elif image_filename == "cache.img":
165 mount_point = "cache"
166 else:
167 print >> sys.stderr, "error: unknown image file name ", image_filename
168 exit(1)
Ying Wangbd93d422011-10-28 17:02:30 -0700169
170 image_properties = ImagePropFromGlobalDict(glob_dict, mount_point)
171 if not BuildImage(in_dir, image_properties, out_file):
172 print >> sys.stderr, "error: failed to build %s from %s" % (out_file, in_dir)
173 exit(1)
174
175
176if __name__ == '__main__':
177 main(sys.argv[1:])