build_image.py revision 69e9b4d6d1e9647c3f9c011bad0f22138911a413
1#!/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 24import os.path 25import subprocess 26import sys 27 28def 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 40 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", "") 54 run_fsck = False 55 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"]) 59 run_fsck = True 60 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"]) 64 if "selinux_fc" in prop_dict: 65 build_command.append(prop_dict["selinux_fc"]) 66 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) 72 if "selinux_fc" in prop_dict: 73 build_command.append(prop_dict["selinux_fc"]) 74 build_command.append(prop_dict["mount_point"]) 75 76 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 97 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 = {} 107 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 112 common_props = ( 113 "extfs_sparse_flag", 114 "mkyaffs2_extra_flags", 115 "selinux_fc", 116 ) 117 for p in common_props: 118 copy_prop(p, p) 119 120 d["mount_point"] = mount_point 121 if mount_point == "system": 122 copy_prop("fs_type", "fs_type") 123 copy_prop("system_size", "partition_size") 124 elif mount_point == "data": 125 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") 130 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" 164 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) 169 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:]) 178