1*9e94795aSAndroid Build Coastguard Worker#!/usr/bin/env python 2*9e94795aSAndroid Build Coastguard Worker# 3*9e94795aSAndroid Build Coastguard Worker# Copyright (C) 2019 The Android Open Source Project 4*9e94795aSAndroid Build Coastguard Worker# 5*9e94795aSAndroid Build Coastguard Worker# Licensed under the Apache License, Version 2.0 (the "License"); you may not 6*9e94795aSAndroid Build Coastguard Worker# use this file except in compliance with the License. You may obtain a copy of 7*9e94795aSAndroid Build Coastguard Worker# the License at 8*9e94795aSAndroid Build Coastguard Worker# 9*9e94795aSAndroid Build Coastguard Worker# http://www.apache.org/licenses/LICENSE-2.0 10*9e94795aSAndroid Build Coastguard Worker# 11*9e94795aSAndroid Build Coastguard Worker# Unless required by applicable law or agreed to in writing, software 12*9e94795aSAndroid Build Coastguard Worker# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 13*9e94795aSAndroid Build Coastguard Worker# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 14*9e94795aSAndroid Build Coastguard Worker# License for the specific language governing permissions and limitations under 15*9e94795aSAndroid Build Coastguard Worker# the License. 16*9e94795aSAndroid Build Coastguard Worker# 17*9e94795aSAndroid Build Coastguard Worker"""Merges two non-dist partial builds together. 18*9e94795aSAndroid Build Coastguard Worker 19*9e94795aSAndroid Build Coastguard WorkerGiven two partial builds, a framework build and a vendor build, merge the builds 20*9e94795aSAndroid Build Coastguard Workertogether so that the images can be flashed using 'fastboot flashall'. 21*9e94795aSAndroid Build Coastguard Worker 22*9e94795aSAndroid Build Coastguard WorkerTo support both DAP and non-DAP vendor builds with a single framework partial 23*9e94795aSAndroid Build Coastguard Workerbuild, the framework partial build should always be built with DAP enabled. The 24*9e94795aSAndroid Build Coastguard Workervendor partial build determines whether the merged result supports DAP. 25*9e94795aSAndroid Build Coastguard Worker 26*9e94795aSAndroid Build Coastguard WorkerThis script does not require builds to be built with 'make dist'. 27*9e94795aSAndroid Build Coastguard WorkerThis script regenerates super_empty.img and vbmeta.img if necessary. Other 28*9e94795aSAndroid Build Coastguard Workerimages are assumed to not require regeneration. 29*9e94795aSAndroid Build Coastguard Worker 30*9e94795aSAndroid Build Coastguard WorkerUsage: merge_builds.py [args] 31*9e94795aSAndroid Build Coastguard Worker 32*9e94795aSAndroid Build Coastguard Worker --framework_images comma_separated_image_list 33*9e94795aSAndroid Build Coastguard Worker Comma-separated list of image names that should come from the framework 34*9e94795aSAndroid Build Coastguard Worker build. 35*9e94795aSAndroid Build Coastguard Worker 36*9e94795aSAndroid Build Coastguard Worker --product_out_framework product_out_framework_path 37*9e94795aSAndroid Build Coastguard Worker Path to out/target/product/<framework build>. 38*9e94795aSAndroid Build Coastguard Worker 39*9e94795aSAndroid Build Coastguard Worker --product_out_vendor product_out_vendor_path 40*9e94795aSAndroid Build Coastguard Worker Path to out/target/product/<vendor build>. 41*9e94795aSAndroid Build Coastguard Worker 42*9e94795aSAndroid Build Coastguard Worker --build_vbmeta 43*9e94795aSAndroid Build Coastguard Worker If provided, vbmeta.img will be regenerated in out/target/product/<vendor 44*9e94795aSAndroid Build Coastguard Worker build>. 45*9e94795aSAndroid Build Coastguard Worker 46*9e94795aSAndroid Build Coastguard Worker --framework_misc_info_keys 47*9e94795aSAndroid Build Coastguard Worker The optional path to a newline-separated config file containing keys to 48*9e94795aSAndroid Build Coastguard Worker obtain from the framework instance of misc_info.txt, used for creating 49*9e94795aSAndroid Build Coastguard Worker vbmeta.img. The remaining keys come from the vendor instance. 50*9e94795aSAndroid Build Coastguard Worker 51*9e94795aSAndroid Build Coastguard Worker --avb_resolve_rollback_index_location_conflict 52*9e94795aSAndroid Build Coastguard Worker If provided, resolve the conflict AVB rollback index location when 53*9e94795aSAndroid Build Coastguard Worker necessary. 54*9e94795aSAndroid Build Coastguard Worker""" 55*9e94795aSAndroid Build Coastguard Workerfrom __future__ import print_function 56*9e94795aSAndroid Build Coastguard Worker 57*9e94795aSAndroid Build Coastguard Workerimport logging 58*9e94795aSAndroid Build Coastguard Workerimport os 59*9e94795aSAndroid Build Coastguard Workerimport sys 60*9e94795aSAndroid Build Coastguard Worker 61*9e94795aSAndroid Build Coastguard Workerimport build_super_image 62*9e94795aSAndroid Build Coastguard Workerimport common 63*9e94795aSAndroid Build Coastguard Worker 64*9e94795aSAndroid Build Coastguard Workerlogger = logging.getLogger(__name__) 65*9e94795aSAndroid Build Coastguard Worker 66*9e94795aSAndroid Build Coastguard WorkerOPTIONS = common.OPTIONS 67*9e94795aSAndroid Build Coastguard WorkerOPTIONS.framework_images = ("system",) 68*9e94795aSAndroid Build Coastguard WorkerOPTIONS.product_out_framework = None 69*9e94795aSAndroid Build Coastguard WorkerOPTIONS.product_out_vendor = None 70*9e94795aSAndroid Build Coastguard WorkerOPTIONS.build_vbmeta = False 71*9e94795aSAndroid Build Coastguard WorkerOPTIONS.framework_misc_info_keys = None 72*9e94795aSAndroid Build Coastguard WorkerOPTIONS.avb_resolve_rollback_index_location_conflict = False 73*9e94795aSAndroid Build Coastguard Worker 74*9e94795aSAndroid Build Coastguard Worker 75*9e94795aSAndroid Build Coastguard Workerdef CreateImageSymlinks(): 76*9e94795aSAndroid Build Coastguard Worker for image in OPTIONS.framework_images: 77*9e94795aSAndroid Build Coastguard Worker image_path = os.path.join(OPTIONS.product_out_framework, "%s.img" % image) 78*9e94795aSAndroid Build Coastguard Worker symlink_path = os.path.join(OPTIONS.product_out_vendor, "%s.img" % image) 79*9e94795aSAndroid Build Coastguard Worker if os.path.exists(symlink_path): 80*9e94795aSAndroid Build Coastguard Worker if os.path.islink(symlink_path): 81*9e94795aSAndroid Build Coastguard Worker os.remove(symlink_path) 82*9e94795aSAndroid Build Coastguard Worker else: 83*9e94795aSAndroid Build Coastguard Worker raise ValueError("Attempting to overwrite built image: %s" % 84*9e94795aSAndroid Build Coastguard Worker symlink_path) 85*9e94795aSAndroid Build Coastguard Worker os.symlink(image_path, symlink_path) 86*9e94795aSAndroid Build Coastguard Worker 87*9e94795aSAndroid Build Coastguard Worker 88*9e94795aSAndroid Build Coastguard Workerdef BuildSuperEmpty(): 89*9e94795aSAndroid Build Coastguard Worker framework_dict = common.LoadDictionaryFromFile( 90*9e94795aSAndroid Build Coastguard Worker os.path.join(OPTIONS.product_out_framework, "misc_info.txt")) 91*9e94795aSAndroid Build Coastguard Worker vendor_dict = common.LoadDictionaryFromFile( 92*9e94795aSAndroid Build Coastguard Worker os.path.join(OPTIONS.product_out_vendor, "misc_info.txt")) 93*9e94795aSAndroid Build Coastguard Worker # Regenerate super_empty.img if both partial builds enable DAP. If only the 94*9e94795aSAndroid Build Coastguard Worker # the vendor build enables DAP, the vendor build's existing super_empty.img 95*9e94795aSAndroid Build Coastguard Worker # will be reused. If only the framework build should enable DAP, super_empty 96*9e94795aSAndroid Build Coastguard Worker # should be included in the --framework_images flag to copy the existing 97*9e94795aSAndroid Build Coastguard Worker # super_empty.img from the framework build. 98*9e94795aSAndroid Build Coastguard Worker if (framework_dict.get("use_dynamic_partitions") == "true") and ( 99*9e94795aSAndroid Build Coastguard Worker vendor_dict.get("use_dynamic_partitions") == "true"): 100*9e94795aSAndroid Build Coastguard Worker logger.info("Building super_empty.img.") 101*9e94795aSAndroid Build Coastguard Worker merged_dict = dict(vendor_dict) 102*9e94795aSAndroid Build Coastguard Worker merged_dict.update( 103*9e94795aSAndroid Build Coastguard Worker common.MergeDynamicPartitionInfoDicts( 104*9e94795aSAndroid Build Coastguard Worker framework_dict=framework_dict, vendor_dict=vendor_dict)) 105*9e94795aSAndroid Build Coastguard Worker output_super_empty_path = os.path.join(OPTIONS.product_out_vendor, 106*9e94795aSAndroid Build Coastguard Worker "super_empty.img") 107*9e94795aSAndroid Build Coastguard Worker build_super_image.BuildSuperImage(merged_dict, output_super_empty_path) 108*9e94795aSAndroid Build Coastguard Worker 109*9e94795aSAndroid Build Coastguard Worker 110*9e94795aSAndroid Build Coastguard Workerdef BuildVBMeta(): 111*9e94795aSAndroid Build Coastguard Worker logger.info("Building vbmeta.img.") 112*9e94795aSAndroid Build Coastguard Worker 113*9e94795aSAndroid Build Coastguard Worker framework_dict = common.LoadDictionaryFromFile( 114*9e94795aSAndroid Build Coastguard Worker os.path.join(OPTIONS.product_out_framework, "misc_info.txt")) 115*9e94795aSAndroid Build Coastguard Worker vendor_dict = common.LoadDictionaryFromFile( 116*9e94795aSAndroid Build Coastguard Worker os.path.join(OPTIONS.product_out_vendor, "misc_info.txt")) 117*9e94795aSAndroid Build Coastguard Worker merged_dict = dict(vendor_dict) 118*9e94795aSAndroid Build Coastguard Worker if OPTIONS.framework_misc_info_keys: 119*9e94795aSAndroid Build Coastguard Worker for key in common.LoadListFromFile(OPTIONS.framework_misc_info_keys): 120*9e94795aSAndroid Build Coastguard Worker merged_dict[key] = framework_dict[key] 121*9e94795aSAndroid Build Coastguard Worker 122*9e94795aSAndroid Build Coastguard Worker # Build vbmeta.img using partitions in product_out_vendor. 123*9e94795aSAndroid Build Coastguard Worker partitions = {} 124*9e94795aSAndroid Build Coastguard Worker for partition in common.AVB_PARTITIONS: 125*9e94795aSAndroid Build Coastguard Worker partition_path = os.path.join(OPTIONS.product_out_vendor, 126*9e94795aSAndroid Build Coastguard Worker "%s.img" % partition) 127*9e94795aSAndroid Build Coastguard Worker if os.path.exists(partition_path): 128*9e94795aSAndroid Build Coastguard Worker partitions[partition] = partition_path 129*9e94795aSAndroid Build Coastguard Worker 130*9e94795aSAndroid Build Coastguard Worker # vbmeta_partitions includes the partitions that should be included into 131*9e94795aSAndroid Build Coastguard Worker # top-level vbmeta.img, which are the ones that are not included in any 132*9e94795aSAndroid Build Coastguard Worker # chained VBMeta image plus the chained VBMeta images themselves. 133*9e94795aSAndroid Build Coastguard Worker vbmeta_partitions = common.AVB_PARTITIONS[:] 134*9e94795aSAndroid Build Coastguard Worker for partition in common.AVB_VBMETA_PARTITIONS: 135*9e94795aSAndroid Build Coastguard Worker chained_partitions = merged_dict.get("avb_%s" % partition, "").strip() 136*9e94795aSAndroid Build Coastguard Worker if chained_partitions: 137*9e94795aSAndroid Build Coastguard Worker partitions[partition] = os.path.join(OPTIONS.product_out_vendor, 138*9e94795aSAndroid Build Coastguard Worker "%s.img" % partition) 139*9e94795aSAndroid Build Coastguard Worker vbmeta_partitions = [ 140*9e94795aSAndroid Build Coastguard Worker item for item in vbmeta_partitions 141*9e94795aSAndroid Build Coastguard Worker if item not in chained_partitions.split() 142*9e94795aSAndroid Build Coastguard Worker ] 143*9e94795aSAndroid Build Coastguard Worker vbmeta_partitions.append(partition) 144*9e94795aSAndroid Build Coastguard Worker 145*9e94795aSAndroid Build Coastguard Worker output_vbmeta_path = os.path.join(OPTIONS.product_out_vendor, "vbmeta.img") 146*9e94795aSAndroid Build Coastguard Worker OPTIONS.info_dict = merged_dict 147*9e94795aSAndroid Build Coastguard Worker common.BuildVBMeta(output_vbmeta_path, partitions, "vbmeta", 148*9e94795aSAndroid Build Coastguard Worker vbmeta_partitions, 149*9e94795aSAndroid Build Coastguard Worker OPTIONS.avb_resolve_rollback_index_location_conflict) 150*9e94795aSAndroid Build Coastguard Worker 151*9e94795aSAndroid Build Coastguard Worker 152*9e94795aSAndroid Build Coastguard Workerdef MergeBuilds(): 153*9e94795aSAndroid Build Coastguard Worker CreateImageSymlinks() 154*9e94795aSAndroid Build Coastguard Worker BuildSuperEmpty() 155*9e94795aSAndroid Build Coastguard Worker if OPTIONS.build_vbmeta: 156*9e94795aSAndroid Build Coastguard Worker BuildVBMeta() 157*9e94795aSAndroid Build Coastguard Worker 158*9e94795aSAndroid Build Coastguard Worker 159*9e94795aSAndroid Build Coastguard Workerdef main(): 160*9e94795aSAndroid Build Coastguard Worker common.InitLogging() 161*9e94795aSAndroid Build Coastguard Worker 162*9e94795aSAndroid Build Coastguard Worker def option_handler(o, a): 163*9e94795aSAndroid Build Coastguard Worker if o == "--framework_images": 164*9e94795aSAndroid Build Coastguard Worker OPTIONS.framework_images = [i.strip() for i in a.split(",")] 165*9e94795aSAndroid Build Coastguard Worker elif o == "--product_out_framework": 166*9e94795aSAndroid Build Coastguard Worker OPTIONS.product_out_framework = a 167*9e94795aSAndroid Build Coastguard Worker elif o == "--product_out_vendor": 168*9e94795aSAndroid Build Coastguard Worker OPTIONS.product_out_vendor = a 169*9e94795aSAndroid Build Coastguard Worker elif o == "--build_vbmeta": 170*9e94795aSAndroid Build Coastguard Worker OPTIONS.build_vbmeta = True 171*9e94795aSAndroid Build Coastguard Worker elif o == "--framework_misc_info_keys": 172*9e94795aSAndroid Build Coastguard Worker OPTIONS.framework_misc_info_keys = a 173*9e94795aSAndroid Build Coastguard Worker elif o == "--avb_resolve_rollback_index_location_conflict": 174*9e94795aSAndroid Build Coastguard Worker OPTIONS.avb_resolve_rollback_index_location_conflict = True 175*9e94795aSAndroid Build Coastguard Worker else: 176*9e94795aSAndroid Build Coastguard Worker return False 177*9e94795aSAndroid Build Coastguard Worker return True 178*9e94795aSAndroid Build Coastguard Worker 179*9e94795aSAndroid Build Coastguard Worker args = common.ParseOptions( 180*9e94795aSAndroid Build Coastguard Worker sys.argv[1:], 181*9e94795aSAndroid Build Coastguard Worker __doc__, 182*9e94795aSAndroid Build Coastguard Worker extra_long_opts=[ 183*9e94795aSAndroid Build Coastguard Worker "framework_images=", 184*9e94795aSAndroid Build Coastguard Worker "product_out_framework=", 185*9e94795aSAndroid Build Coastguard Worker "product_out_vendor=", 186*9e94795aSAndroid Build Coastguard Worker "build_vbmeta", 187*9e94795aSAndroid Build Coastguard Worker "framework_misc_info_keys=", 188*9e94795aSAndroid Build Coastguard Worker "avb_resolve_rollback_index_location_conflict" 189*9e94795aSAndroid Build Coastguard Worker ], 190*9e94795aSAndroid Build Coastguard Worker extra_option_handler=option_handler) 191*9e94795aSAndroid Build Coastguard Worker 192*9e94795aSAndroid Build Coastguard Worker if (args or OPTIONS.product_out_framework is None or 193*9e94795aSAndroid Build Coastguard Worker OPTIONS.product_out_vendor is None): 194*9e94795aSAndroid Build Coastguard Worker common.Usage(__doc__) 195*9e94795aSAndroid Build Coastguard Worker sys.exit(1) 196*9e94795aSAndroid Build Coastguard Worker 197*9e94795aSAndroid Build Coastguard Worker MergeBuilds() 198*9e94795aSAndroid Build Coastguard Worker 199*9e94795aSAndroid Build Coastguard Worker 200*9e94795aSAndroid Build Coastguard Workerif __name__ == "__main__": 201*9e94795aSAndroid Build Coastguard Worker main() 202