1*9e94795aSAndroid Build Coastguard Worker#!/usr/bin/env python 2*9e94795aSAndroid Build Coastguard Worker# 3*9e94795aSAndroid Build Coastguard Worker# Copyright (C) 2018 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"); 6*9e94795aSAndroid Build Coastguard Worker# you may not use this file except in compliance with the License. 7*9e94795aSAndroid Build Coastguard Worker# You may obtain a copy of 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, 13*9e94795aSAndroid Build Coastguard Worker# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14*9e94795aSAndroid Build Coastguard Worker# See the License for the specific language governing permissions and 15*9e94795aSAndroid Build Coastguard Worker# limitations under the License. 16*9e94795aSAndroid Build Coastguard Worker 17*9e94795aSAndroid Build Coastguard Worker""" 18*9e94795aSAndroid Build Coastguard WorkerSigns a given image using avbtool 19*9e94795aSAndroid Build Coastguard Worker 20*9e94795aSAndroid Build Coastguard WorkerUsage: verity_utils properties_file output_image 21*9e94795aSAndroid Build Coastguard Worker""" 22*9e94795aSAndroid Build Coastguard Worker 23*9e94795aSAndroid Build Coastguard Workerfrom __future__ import print_function 24*9e94795aSAndroid Build Coastguard Worker 25*9e94795aSAndroid Build Coastguard Workerimport logging 26*9e94795aSAndroid Build Coastguard Workerimport os.path 27*9e94795aSAndroid Build Coastguard Workerimport shlex 28*9e94795aSAndroid Build Coastguard Workerimport struct 29*9e94795aSAndroid Build Coastguard Workerimport sys 30*9e94795aSAndroid Build Coastguard Worker 31*9e94795aSAndroid Build Coastguard Workerimport common 32*9e94795aSAndroid Build Coastguard Workerimport sparse_img 33*9e94795aSAndroid Build Coastguard Workerfrom rangelib import RangeSet 34*9e94795aSAndroid Build Coastguard Workerfrom hashlib import sha256 35*9e94795aSAndroid Build Coastguard Worker 36*9e94795aSAndroid Build Coastguard Workerlogger = logging.getLogger(__name__) 37*9e94795aSAndroid Build Coastguard Worker 38*9e94795aSAndroid Build Coastguard WorkerOPTIONS = common.OPTIONS 39*9e94795aSAndroid Build Coastguard WorkerBLOCK_SIZE = common.BLOCK_SIZE 40*9e94795aSAndroid Build Coastguard WorkerFIXED_SALT = "aee087a5be3b982978c923f566a94613496b417f2af592639bc80d141e34dfe7" 41*9e94795aSAndroid Build Coastguard Worker 42*9e94795aSAndroid Build Coastguard Worker# From external/avb/avbtool.py 43*9e94795aSAndroid Build Coastguard WorkerMAX_VBMETA_SIZE = 64 * 1024 44*9e94795aSAndroid Build Coastguard WorkerMAX_FOOTER_SIZE = 4096 45*9e94795aSAndroid Build Coastguard Worker 46*9e94795aSAndroid Build Coastguard Worker 47*9e94795aSAndroid Build Coastguard Workerclass BuildVerityImageError(Exception): 48*9e94795aSAndroid Build Coastguard Worker """An Exception raised during verity image building.""" 49*9e94795aSAndroid Build Coastguard Worker 50*9e94795aSAndroid Build Coastguard Worker def __init__(self, message): 51*9e94795aSAndroid Build Coastguard Worker Exception.__init__(self, message) 52*9e94795aSAndroid Build Coastguard Worker 53*9e94795aSAndroid Build Coastguard Worker 54*9e94795aSAndroid Build Coastguard Workerdef CreateVerityImageBuilder(prop_dict): 55*9e94795aSAndroid Build Coastguard Worker """Returns a verity image builder based on the given build properties. 56*9e94795aSAndroid Build Coastguard Worker 57*9e94795aSAndroid Build Coastguard Worker Args: 58*9e94795aSAndroid Build Coastguard Worker prop_dict: A dict that contains the build properties. In particular, it will 59*9e94795aSAndroid Build Coastguard Worker look for verity-related property values. 60*9e94795aSAndroid Build Coastguard Worker 61*9e94795aSAndroid Build Coastguard Worker Returns: 62*9e94795aSAndroid Build Coastguard Worker A VerityImageBuilder instance for Verified Boot 1.0 or Verified Boot 2.0; or 63*9e94795aSAndroid Build Coastguard Worker None if the given build doesn't support Verified Boot. 64*9e94795aSAndroid Build Coastguard Worker """ 65*9e94795aSAndroid Build Coastguard Worker partition_size = prop_dict.get("partition_size") 66*9e94795aSAndroid Build Coastguard Worker # partition_size could be None at this point, if using dynamic partitions. 67*9e94795aSAndroid Build Coastguard Worker if partition_size: 68*9e94795aSAndroid Build Coastguard Worker partition_size = int(partition_size) 69*9e94795aSAndroid Build Coastguard Worker # Set up the salt (based on fingerprint) that will be used when adding AVB 70*9e94795aSAndroid Build Coastguard Worker # hash / hashtree footers. 71*9e94795aSAndroid Build Coastguard Worker salt = prop_dict.get("avb_salt") 72*9e94795aSAndroid Build Coastguard Worker if salt is None: 73*9e94795aSAndroid Build Coastguard Worker salt = sha256(prop_dict.get("fingerprint", "").encode()).hexdigest() 74*9e94795aSAndroid Build Coastguard Worker 75*9e94795aSAndroid Build Coastguard Worker # Verified Boot 2.0 76*9e94795aSAndroid Build Coastguard Worker if (prop_dict.get("avb_hash_enable") == "true" or 77*9e94795aSAndroid Build Coastguard Worker prop_dict.get("avb_hashtree_enable") == "true"): 78*9e94795aSAndroid Build Coastguard Worker # key_path and algorithm are only available when chain partition is used. 79*9e94795aSAndroid Build Coastguard Worker key_path = prop_dict.get("avb_key_path") 80*9e94795aSAndroid Build Coastguard Worker algorithm = prop_dict.get("avb_algorithm") 81*9e94795aSAndroid Build Coastguard Worker 82*9e94795aSAndroid Build Coastguard Worker # Image uses hash footer. 83*9e94795aSAndroid Build Coastguard Worker if prop_dict.get("avb_hash_enable") == "true": 84*9e94795aSAndroid Build Coastguard Worker return VerifiedBootVersion2VerityImageBuilder( 85*9e94795aSAndroid Build Coastguard Worker prop_dict["partition_name"], 86*9e94795aSAndroid Build Coastguard Worker partition_size, 87*9e94795aSAndroid Build Coastguard Worker VerifiedBootVersion2VerityImageBuilder.AVB_HASH_FOOTER, 88*9e94795aSAndroid Build Coastguard Worker prop_dict["avb_avbtool"], 89*9e94795aSAndroid Build Coastguard Worker key_path, 90*9e94795aSAndroid Build Coastguard Worker algorithm, 91*9e94795aSAndroid Build Coastguard Worker salt, 92*9e94795aSAndroid Build Coastguard Worker prop_dict["avb_add_hash_footer_args"]) 93*9e94795aSAndroid Build Coastguard Worker 94*9e94795aSAndroid Build Coastguard Worker # Image uses hashtree footer. 95*9e94795aSAndroid Build Coastguard Worker return VerifiedBootVersion2VerityImageBuilder( 96*9e94795aSAndroid Build Coastguard Worker prop_dict["partition_name"], 97*9e94795aSAndroid Build Coastguard Worker partition_size, 98*9e94795aSAndroid Build Coastguard Worker VerifiedBootVersion2VerityImageBuilder.AVB_HASHTREE_FOOTER, 99*9e94795aSAndroid Build Coastguard Worker prop_dict["avb_avbtool"], 100*9e94795aSAndroid Build Coastguard Worker key_path, 101*9e94795aSAndroid Build Coastguard Worker algorithm, 102*9e94795aSAndroid Build Coastguard Worker salt, 103*9e94795aSAndroid Build Coastguard Worker prop_dict["avb_add_hashtree_footer_args"]) 104*9e94795aSAndroid Build Coastguard Worker 105*9e94795aSAndroid Build Coastguard Worker return None 106*9e94795aSAndroid Build Coastguard Worker 107*9e94795aSAndroid Build Coastguard Worker 108*9e94795aSAndroid Build Coastguard Workerclass VerityImageBuilder(object): 109*9e94795aSAndroid Build Coastguard Worker """A builder that generates an image with verity metadata for Verified Boot. 110*9e94795aSAndroid Build Coastguard Worker 111*9e94795aSAndroid Build Coastguard Worker A VerityImageBuilder instance handles the works for building an image with 112*9e94795aSAndroid Build Coastguard Worker verity metadata for supporting Android Verified Boot. This class defines the 113*9e94795aSAndroid Build Coastguard Worker common interface between Verified Boot 1.0 and Verified Boot 2.0. A matching 114*9e94795aSAndroid Build Coastguard Worker builder will be returned based on the given build properties. 115*9e94795aSAndroid Build Coastguard Worker 116*9e94795aSAndroid Build Coastguard Worker More info on the verity image generation can be found at the following link. 117*9e94795aSAndroid Build Coastguard Worker https://source.android.com/security/verifiedboot/dm-verity#implementation 118*9e94795aSAndroid Build Coastguard Worker """ 119*9e94795aSAndroid Build Coastguard Worker 120*9e94795aSAndroid Build Coastguard Worker def CalculateMaxImageSize(self, partition_size): 121*9e94795aSAndroid Build Coastguard Worker """Calculates the filesystem image size for the given partition size.""" 122*9e94795aSAndroid Build Coastguard Worker raise NotImplementedError 123*9e94795aSAndroid Build Coastguard Worker 124*9e94795aSAndroid Build Coastguard Worker def CalculateDynamicPartitionSize(self, image_size): 125*9e94795aSAndroid Build Coastguard Worker """Calculates and sets the partition size for a dynamic partition.""" 126*9e94795aSAndroid Build Coastguard Worker raise NotImplementedError 127*9e94795aSAndroid Build Coastguard Worker 128*9e94795aSAndroid Build Coastguard Worker def PadSparseImage(self, out_file): 129*9e94795aSAndroid Build Coastguard Worker """Adds padding to the generated sparse image.""" 130*9e94795aSAndroid Build Coastguard Worker raise NotImplementedError 131*9e94795aSAndroid Build Coastguard Worker 132*9e94795aSAndroid Build Coastguard Worker def Build(self, out_file): 133*9e94795aSAndroid Build Coastguard Worker """Builds the verity image and writes it to the given file.""" 134*9e94795aSAndroid Build Coastguard Worker raise NotImplementedError 135*9e94795aSAndroid Build Coastguard Worker 136*9e94795aSAndroid Build Coastguard Worker 137*9e94795aSAndroid Build Coastguard Workerclass VerifiedBootVersion2VerityImageBuilder(VerityImageBuilder): 138*9e94795aSAndroid Build Coastguard Worker """A VerityImageBuilder for Verified Boot 2.0.""" 139*9e94795aSAndroid Build Coastguard Worker 140*9e94795aSAndroid Build Coastguard Worker AVB_HASH_FOOTER = 1 141*9e94795aSAndroid Build Coastguard Worker AVB_HASHTREE_FOOTER = 2 142*9e94795aSAndroid Build Coastguard Worker 143*9e94795aSAndroid Build Coastguard Worker def __init__(self, partition_name, partition_size, footer_type, avbtool, 144*9e94795aSAndroid Build Coastguard Worker key_path, algorithm, salt, signing_args): 145*9e94795aSAndroid Build Coastguard Worker self.version = 2 146*9e94795aSAndroid Build Coastguard Worker self.partition_name = partition_name 147*9e94795aSAndroid Build Coastguard Worker self.partition_size = partition_size 148*9e94795aSAndroid Build Coastguard Worker self.footer_type = footer_type 149*9e94795aSAndroid Build Coastguard Worker self.avbtool = avbtool 150*9e94795aSAndroid Build Coastguard Worker self.algorithm = algorithm 151*9e94795aSAndroid Build Coastguard Worker self.key_path = common.ResolveAVBSigningPathArgs(key_path) 152*9e94795aSAndroid Build Coastguard Worker 153*9e94795aSAndroid Build Coastguard Worker self.salt = salt 154*9e94795aSAndroid Build Coastguard Worker self.signing_args = signing_args 155*9e94795aSAndroid Build Coastguard Worker self.image_size = None 156*9e94795aSAndroid Build Coastguard Worker 157*9e94795aSAndroid Build Coastguard Worker def CalculateMinPartitionSize(self, image_size, size_calculator=None): 158*9e94795aSAndroid Build Coastguard Worker """Calculates min partition size for a given image size. 159*9e94795aSAndroid Build Coastguard Worker 160*9e94795aSAndroid Build Coastguard Worker This is used when determining the partition size for a dynamic partition, 161*9e94795aSAndroid Build Coastguard Worker which should be cover the given image size (for filesystem files) as well as 162*9e94795aSAndroid Build Coastguard Worker the verity metadata size. 163*9e94795aSAndroid Build Coastguard Worker 164*9e94795aSAndroid Build Coastguard Worker Args: 165*9e94795aSAndroid Build Coastguard Worker image_size: The size of the image in question. 166*9e94795aSAndroid Build Coastguard Worker size_calculator: The function to calculate max image size 167*9e94795aSAndroid Build Coastguard Worker for a given partition size. 168*9e94795aSAndroid Build Coastguard Worker 169*9e94795aSAndroid Build Coastguard Worker Returns: 170*9e94795aSAndroid Build Coastguard Worker The minimum partition size required to accommodate the image size. 171*9e94795aSAndroid Build Coastguard Worker """ 172*9e94795aSAndroid Build Coastguard Worker if size_calculator is None: 173*9e94795aSAndroid Build Coastguard Worker size_calculator = self.CalculateMaxImageSize 174*9e94795aSAndroid Build Coastguard Worker 175*9e94795aSAndroid Build Coastguard Worker # Use image size as partition size to approximate final partition size. 176*9e94795aSAndroid Build Coastguard Worker image_ratio = size_calculator(image_size) / float(image_size) 177*9e94795aSAndroid Build Coastguard Worker 178*9e94795aSAndroid Build Coastguard Worker # Prepare a binary search for the optimal partition size. 179*9e94795aSAndroid Build Coastguard Worker lo = int(image_size / image_ratio) // BLOCK_SIZE * BLOCK_SIZE - BLOCK_SIZE 180*9e94795aSAndroid Build Coastguard Worker 181*9e94795aSAndroid Build Coastguard Worker # Ensure lo is small enough: max_image_size should <= image_size. 182*9e94795aSAndroid Build Coastguard Worker delta = BLOCK_SIZE 183*9e94795aSAndroid Build Coastguard Worker max_image_size = size_calculator(lo) 184*9e94795aSAndroid Build Coastguard Worker while max_image_size > image_size: 185*9e94795aSAndroid Build Coastguard Worker image_ratio = max_image_size / float(lo) 186*9e94795aSAndroid Build Coastguard Worker lo = int(image_size / image_ratio) // BLOCK_SIZE * BLOCK_SIZE - delta 187*9e94795aSAndroid Build Coastguard Worker delta *= 2 188*9e94795aSAndroid Build Coastguard Worker max_image_size = size_calculator(lo) 189*9e94795aSAndroid Build Coastguard Worker 190*9e94795aSAndroid Build Coastguard Worker hi = lo + BLOCK_SIZE 191*9e94795aSAndroid Build Coastguard Worker 192*9e94795aSAndroid Build Coastguard Worker # Ensure hi is large enough: max_image_size should >= image_size. 193*9e94795aSAndroid Build Coastguard Worker delta = BLOCK_SIZE 194*9e94795aSAndroid Build Coastguard Worker max_image_size = size_calculator(hi) 195*9e94795aSAndroid Build Coastguard Worker while max_image_size < image_size: 196*9e94795aSAndroid Build Coastguard Worker image_ratio = max_image_size / float(hi) 197*9e94795aSAndroid Build Coastguard Worker hi = int(image_size / image_ratio) // BLOCK_SIZE * BLOCK_SIZE + delta 198*9e94795aSAndroid Build Coastguard Worker delta *= 2 199*9e94795aSAndroid Build Coastguard Worker max_image_size = size_calculator(hi) 200*9e94795aSAndroid Build Coastguard Worker 201*9e94795aSAndroid Build Coastguard Worker partition_size = hi 202*9e94795aSAndroid Build Coastguard Worker 203*9e94795aSAndroid Build Coastguard Worker # Start to binary search. 204*9e94795aSAndroid Build Coastguard Worker while lo < hi: 205*9e94795aSAndroid Build Coastguard Worker mid = ((lo + hi) // (2 * BLOCK_SIZE)) * BLOCK_SIZE 206*9e94795aSAndroid Build Coastguard Worker max_image_size = size_calculator(mid) 207*9e94795aSAndroid Build Coastguard Worker if max_image_size >= image_size: # if mid can accommodate image_size 208*9e94795aSAndroid Build Coastguard Worker if mid < partition_size: # if a smaller partition size is found 209*9e94795aSAndroid Build Coastguard Worker partition_size = mid 210*9e94795aSAndroid Build Coastguard Worker hi = mid 211*9e94795aSAndroid Build Coastguard Worker else: 212*9e94795aSAndroid Build Coastguard Worker lo = mid + BLOCK_SIZE 213*9e94795aSAndroid Build Coastguard Worker 214*9e94795aSAndroid Build Coastguard Worker logger.info( 215*9e94795aSAndroid Build Coastguard Worker "CalculateMinPartitionSize(%d): partition_size %d.", image_size, 216*9e94795aSAndroid Build Coastguard Worker partition_size) 217*9e94795aSAndroid Build Coastguard Worker 218*9e94795aSAndroid Build Coastguard Worker return partition_size 219*9e94795aSAndroid Build Coastguard Worker 220*9e94795aSAndroid Build Coastguard Worker def CalculateDynamicPartitionSize(self, image_size): 221*9e94795aSAndroid Build Coastguard Worker self.partition_size = self.CalculateMinPartitionSize(image_size) 222*9e94795aSAndroid Build Coastguard Worker return self.partition_size 223*9e94795aSAndroid Build Coastguard Worker 224*9e94795aSAndroid Build Coastguard Worker def CalculateMaxImageSize(self, partition_size=None): 225*9e94795aSAndroid Build Coastguard Worker """Calculates max image size for a given partition size. 226*9e94795aSAndroid Build Coastguard Worker 227*9e94795aSAndroid Build Coastguard Worker Args: 228*9e94795aSAndroid Build Coastguard Worker partition_size: The partition size, which defaults to self.partition_size 229*9e94795aSAndroid Build Coastguard Worker if unspecified. 230*9e94795aSAndroid Build Coastguard Worker 231*9e94795aSAndroid Build Coastguard Worker Returns: 232*9e94795aSAndroid Build Coastguard Worker The maximum image size. 233*9e94795aSAndroid Build Coastguard Worker 234*9e94795aSAndroid Build Coastguard Worker Raises: 235*9e94795aSAndroid Build Coastguard Worker BuildVerityImageError: On error or getting invalid image size. 236*9e94795aSAndroid Build Coastguard Worker """ 237*9e94795aSAndroid Build Coastguard Worker if partition_size is None: 238*9e94795aSAndroid Build Coastguard Worker partition_size = self.partition_size 239*9e94795aSAndroid Build Coastguard Worker assert partition_size > 0, \ 240*9e94795aSAndroid Build Coastguard Worker "Invalid partition size: {}".format(partition_size) 241*9e94795aSAndroid Build Coastguard Worker 242*9e94795aSAndroid Build Coastguard Worker add_footer = ("add_hash_footer" if self.footer_type == self.AVB_HASH_FOOTER 243*9e94795aSAndroid Build Coastguard Worker else "add_hashtree_footer") 244*9e94795aSAndroid Build Coastguard Worker cmd = [self.avbtool, add_footer, "--partition_size", 245*9e94795aSAndroid Build Coastguard Worker str(partition_size), "--calc_max_image_size"] 246*9e94795aSAndroid Build Coastguard Worker cmd.extend(shlex.split(self.signing_args)) 247*9e94795aSAndroid Build Coastguard Worker 248*9e94795aSAndroid Build Coastguard Worker proc = common.Run(cmd) 249*9e94795aSAndroid Build Coastguard Worker output, _ = proc.communicate() 250*9e94795aSAndroid Build Coastguard Worker if proc.returncode != 0: 251*9e94795aSAndroid Build Coastguard Worker raise BuildVerityImageError( 252*9e94795aSAndroid Build Coastguard Worker "Failed to calculate max image size:\n{}".format(output)) 253*9e94795aSAndroid Build Coastguard Worker image_size = int(output) 254*9e94795aSAndroid Build Coastguard Worker if image_size <= 0: 255*9e94795aSAndroid Build Coastguard Worker raise BuildVerityImageError( 256*9e94795aSAndroid Build Coastguard Worker "Invalid max image size: {}".format(output)) 257*9e94795aSAndroid Build Coastguard Worker self.image_size = image_size 258*9e94795aSAndroid Build Coastguard Worker return image_size 259*9e94795aSAndroid Build Coastguard Worker 260*9e94795aSAndroid Build Coastguard Worker def PadSparseImage(self, out_file): 261*9e94795aSAndroid Build Coastguard Worker # No-op as the padding is taken care of by avbtool. 262*9e94795aSAndroid Build Coastguard Worker pass 263*9e94795aSAndroid Build Coastguard Worker 264*9e94795aSAndroid Build Coastguard Worker def Build(self, out_file): 265*9e94795aSAndroid Build Coastguard Worker """Adds dm-verity hashtree and AVB metadata to an image. 266*9e94795aSAndroid Build Coastguard Worker 267*9e94795aSAndroid Build Coastguard Worker Args: 268*9e94795aSAndroid Build Coastguard Worker out_file: Path to image to modify. 269*9e94795aSAndroid Build Coastguard Worker """ 270*9e94795aSAndroid Build Coastguard Worker add_footer = ("add_hash_footer" if self.footer_type == self.AVB_HASH_FOOTER 271*9e94795aSAndroid Build Coastguard Worker else "add_hashtree_footer") 272*9e94795aSAndroid Build Coastguard Worker cmd = [self.avbtool, add_footer, 273*9e94795aSAndroid Build Coastguard Worker "--partition_size", str(self.partition_size), 274*9e94795aSAndroid Build Coastguard Worker "--partition_name", self.partition_name, 275*9e94795aSAndroid Build Coastguard Worker "--image", out_file] 276*9e94795aSAndroid Build Coastguard Worker if self.key_path and self.algorithm: 277*9e94795aSAndroid Build Coastguard Worker cmd.extend(["--key", self.key_path, "--algorithm", self.algorithm]) 278*9e94795aSAndroid Build Coastguard Worker if self.salt: 279*9e94795aSAndroid Build Coastguard Worker cmd.extend(["--salt", self.salt]) 280*9e94795aSAndroid Build Coastguard Worker cmd.extend(shlex.split(self.signing_args)) 281*9e94795aSAndroid Build Coastguard Worker 282*9e94795aSAndroid Build Coastguard Worker proc = common.Run(cmd) 283*9e94795aSAndroid Build Coastguard Worker output, _ = proc.communicate() 284*9e94795aSAndroid Build Coastguard Worker if proc.returncode != 0: 285*9e94795aSAndroid Build Coastguard Worker raise BuildVerityImageError("Failed to add AVB footer: {}".format(output)) 286*9e94795aSAndroid Build Coastguard Worker 287*9e94795aSAndroid Build Coastguard Worker 288*9e94795aSAndroid Build Coastguard Workerdef CreateCustomImageBuilder(info_dict, partition_name, partition_size, 289*9e94795aSAndroid Build Coastguard Worker key_path, algorithm, signing_args): 290*9e94795aSAndroid Build Coastguard Worker builder = None 291*9e94795aSAndroid Build Coastguard Worker if info_dict.get("avb_enable") == "true": 292*9e94795aSAndroid Build Coastguard Worker builder = VerifiedBootVersion2VerityImageBuilder( 293*9e94795aSAndroid Build Coastguard Worker partition_name, 294*9e94795aSAndroid Build Coastguard Worker partition_size, 295*9e94795aSAndroid Build Coastguard Worker VerifiedBootVersion2VerityImageBuilder.AVB_HASHTREE_FOOTER, 296*9e94795aSAndroid Build Coastguard Worker info_dict.get("avb_avbtool"), 297*9e94795aSAndroid Build Coastguard Worker key_path, 298*9e94795aSAndroid Build Coastguard Worker algorithm, 299*9e94795aSAndroid Build Coastguard Worker # Salt is None because custom images have no fingerprint property to be 300*9e94795aSAndroid Build Coastguard Worker # used as the salt. 301*9e94795aSAndroid Build Coastguard Worker None, 302*9e94795aSAndroid Build Coastguard Worker signing_args) 303*9e94795aSAndroid Build Coastguard Worker 304*9e94795aSAndroid Build Coastguard Worker return builder 305*9e94795aSAndroid Build Coastguard Worker 306*9e94795aSAndroid Build Coastguard Worker 307*9e94795aSAndroid Build Coastguard Workerdef GetDiskUsage(path): 308*9e94795aSAndroid Build Coastguard Worker """Returns the number of bytes that "path" occupies on host. 309*9e94795aSAndroid Build Coastguard Worker 310*9e94795aSAndroid Build Coastguard Worker Args: 311*9e94795aSAndroid Build Coastguard Worker path: The directory or file to calculate size on. 312*9e94795aSAndroid Build Coastguard Worker 313*9e94795aSAndroid Build Coastguard Worker Returns: 314*9e94795aSAndroid Build Coastguard Worker The number of bytes based on a 1K block_size. 315*9e94795aSAndroid Build Coastguard Worker """ 316*9e94795aSAndroid Build Coastguard Worker cmd = ["du", "-b", "-k", "-s", path] 317*9e94795aSAndroid Build Coastguard Worker output = common.RunAndCheckOutput(cmd, verbose=False) 318*9e94795aSAndroid Build Coastguard Worker return int(output.split()[0]) * 1024 319*9e94795aSAndroid Build Coastguard Worker 320*9e94795aSAndroid Build Coastguard Worker 321*9e94795aSAndroid Build Coastguard Workerdef CalculateVbmetaDigest(extracted_dir, avbtool): 322*9e94795aSAndroid Build Coastguard Worker """Calculates the vbmeta digest of the images in the extracted target_file""" 323*9e94795aSAndroid Build Coastguard Worker 324*9e94795aSAndroid Build Coastguard Worker images_dir = common.MakeTempDir() 325*9e94795aSAndroid Build Coastguard Worker for name in ("PREBUILT_IMAGES", "RADIO", "IMAGES"): 326*9e94795aSAndroid Build Coastguard Worker path = os.path.join(extracted_dir, name) 327*9e94795aSAndroid Build Coastguard Worker if not os.path.exists(path): 328*9e94795aSAndroid Build Coastguard Worker continue 329*9e94795aSAndroid Build Coastguard Worker 330*9e94795aSAndroid Build Coastguard Worker # Create symlink for image files under PREBUILT_IMAGES, RADIO and IMAGES, 331*9e94795aSAndroid Build Coastguard Worker # and put them into one directory. 332*9e94795aSAndroid Build Coastguard Worker for filename in os.listdir(path): 333*9e94795aSAndroid Build Coastguard Worker if not filename.endswith(".img"): 334*9e94795aSAndroid Build Coastguard Worker continue 335*9e94795aSAndroid Build Coastguard Worker symlink_path = os.path.join(images_dir, filename) 336*9e94795aSAndroid Build Coastguard Worker # The files in latter directory overwrite the existing links 337*9e94795aSAndroid Build Coastguard Worker common.RunAndCheckOutput( 338*9e94795aSAndroid Build Coastguard Worker ['ln', '-sf', os.path.join(path, filename), symlink_path]) 339*9e94795aSAndroid Build Coastguard Worker 340*9e94795aSAndroid Build Coastguard Worker cmd = [avbtool, "calculate_vbmeta_digest", "--image", 341*9e94795aSAndroid Build Coastguard Worker os.path.join(images_dir, 'vbmeta.img')] 342*9e94795aSAndroid Build Coastguard Worker return common.RunAndCheckOutput(cmd) 343*9e94795aSAndroid Build Coastguard Worker 344*9e94795aSAndroid Build Coastguard Worker 345*9e94795aSAndroid Build Coastguard Workerdef main(argv): 346*9e94795aSAndroid Build Coastguard Worker if len(argv) != 2: 347*9e94795aSAndroid Build Coastguard Worker print(__doc__) 348*9e94795aSAndroid Build Coastguard Worker sys.exit(1) 349*9e94795aSAndroid Build Coastguard Worker 350*9e94795aSAndroid Build Coastguard Worker common.InitLogging() 351*9e94795aSAndroid Build Coastguard Worker 352*9e94795aSAndroid Build Coastguard Worker dict_file = argv[0] 353*9e94795aSAndroid Build Coastguard Worker out_file = argv[1] 354*9e94795aSAndroid Build Coastguard Worker 355*9e94795aSAndroid Build Coastguard Worker prop_dict = {} 356*9e94795aSAndroid Build Coastguard Worker with open(dict_file, 'r') as f: 357*9e94795aSAndroid Build Coastguard Worker for line in f: 358*9e94795aSAndroid Build Coastguard Worker line = line.strip() 359*9e94795aSAndroid Build Coastguard Worker if not line or line.startswith("#"): 360*9e94795aSAndroid Build Coastguard Worker continue 361*9e94795aSAndroid Build Coastguard Worker k, v = line.split("=", 1) 362*9e94795aSAndroid Build Coastguard Worker prop_dict[k] = v 363*9e94795aSAndroid Build Coastguard Worker 364*9e94795aSAndroid Build Coastguard Worker builder = CreateVerityImageBuilder(prop_dict) 365*9e94795aSAndroid Build Coastguard Worker 366*9e94795aSAndroid Build Coastguard Worker if "partition_size" not in prop_dict: 367*9e94795aSAndroid Build Coastguard Worker image_size = GetDiskUsage(out_file) 368*9e94795aSAndroid Build Coastguard Worker # make sure that the image is big enough to hold vbmeta and footer 369*9e94795aSAndroid Build Coastguard Worker image_size = image_size + (MAX_VBMETA_SIZE + MAX_FOOTER_SIZE) 370*9e94795aSAndroid Build Coastguard Worker size = builder.CalculateDynamicPartitionSize(image_size) 371*9e94795aSAndroid Build Coastguard Worker prop_dict["partition_size"] = size 372*9e94795aSAndroid Build Coastguard Worker 373*9e94795aSAndroid Build Coastguard Worker builder.Build(out_file) 374*9e94795aSAndroid Build Coastguard Worker 375*9e94795aSAndroid Build Coastguard Worker 376*9e94795aSAndroid Build Coastguard Workerif __name__ == '__main__': 377*9e94795aSAndroid Build Coastguard Worker try: 378*9e94795aSAndroid Build Coastguard Worker main(sys.argv[1:]) 379*9e94795aSAndroid Build Coastguard Worker finally: 380*9e94795aSAndroid Build Coastguard Worker common.Cleanup() 381