1*d289c2baSAndroid Build Coastguard Worker#!/usr/bin/env python 2*d289c2baSAndroid Build Coastguard Worker# 3*d289c2baSAndroid Build Coastguard Worker# Copyright 2018 The Android Open Source Project 4*d289c2baSAndroid Build Coastguard Worker# 5*d289c2baSAndroid Build Coastguard Worker# Licensed under the Apache License, Version 2.0 (the "License"); 6*d289c2baSAndroid Build Coastguard Worker# you may not use this file except in compliance with the License. 7*d289c2baSAndroid Build Coastguard Worker# 8*d289c2baSAndroid Build Coastguard Worker# You may obtain a copy of the License at 9*d289c2baSAndroid Build Coastguard Worker# 10*d289c2baSAndroid Build Coastguard Worker# http://www.apache.org/licenses/LICENSE-2.0 11*d289c2baSAndroid Build Coastguard Worker# 12*d289c2baSAndroid Build Coastguard Worker# Unless required by applicable law or agreed to in writing, software 13*d289c2baSAndroid Build Coastguard Worker# distributed under the License is distributed on an "AS IS" BASIS, 14*d289c2baSAndroid Build Coastguard Worker# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15*d289c2baSAndroid Build Coastguard Worker# See the License for the specific language governing permissions and 16*d289c2baSAndroid Build Coastguard Worker# limitations under the License. 17*d289c2baSAndroid Build Coastguard Worker"""Helper tool for 'oem at-write-persistent-digest' fastboot command. 18*d289c2baSAndroid Build Coastguard Worker 19*d289c2baSAndroid Build Coastguard WorkerThis tool generates and stages the correct input data format, based on the 20*d289c2baSAndroid Build Coastguard Workeruser-provided inputs, for the 'oem at-write-persistent-digest' fastboot command 21*d289c2baSAndroid Build Coastguard Workerfor Android Things devices before running the command itself. 22*d289c2baSAndroid Build Coastguard Worker 23*d289c2baSAndroid Build Coastguard WorkerThe input format is defined elsewhere to be the following: 24*d289c2baSAndroid Build Coastguard Worker 25*d289c2baSAndroid Build Coastguard Worker - Name length: 4 bytes (little-endian) 26*d289c2baSAndroid Build Coastguard Worker - Name: 'name length' bytes 27*d289c2baSAndroid Build Coastguard Worker - Digest length: 4 bytes (little-endian) 28*d289c2baSAndroid Build Coastguard Worker - Digest: 'digest length' bytes 29*d289c2baSAndroid Build Coastguard Worker 30*d289c2baSAndroid Build Coastguard WorkerDigest length can be zero, indicating that any existing digest with the given 31*d289c2baSAndroid Build Coastguard Workername should be deleted. This corresponds to the '--clear_digest' option for this 32*d289c2baSAndroid Build Coastguard Workertool. 33*d289c2baSAndroid Build Coastguard Worker 34*d289c2baSAndroid Build Coastguard WorkerDigest names must be prefixed with 'avb.persistent_digest.', and if the 35*d289c2baSAndroid Build Coastguard Workeruser-provided name does not include that prefix it is added automatically. 36*d289c2baSAndroid Build Coastguard Worker""" 37*d289c2baSAndroid Build Coastguard Worker 38*d289c2baSAndroid Build Coastguard Workerimport sys 39*d289c2baSAndroid Build Coastguard Worker 40*d289c2baSAndroid Build Coastguard Workerver = sys.version_info 41*d289c2baSAndroid Build Coastguard Workerif (ver[0] < 2) or (ver[0] == 2 and ver[1] < 7) or (ver[0] == 3 and ver[1] < 2): 42*d289c2baSAndroid Build Coastguard Worker print('This script requires Python 2.7+ or 3.2+') 43*d289c2baSAndroid Build Coastguard Worker sys.exit(1) 44*d289c2baSAndroid Build Coastguard Worker 45*d289c2baSAndroid Build Coastguard Workerimport argparse 46*d289c2baSAndroid Build Coastguard Workerimport os 47*d289c2baSAndroid Build Coastguard Workerimport shutil 48*d289c2baSAndroid Build Coastguard Workerimport struct 49*d289c2baSAndroid Build Coastguard Workerimport subprocess 50*d289c2baSAndroid Build Coastguard Workerimport tempfile 51*d289c2baSAndroid Build Coastguard Worker 52*d289c2baSAndroid Build Coastguard WorkerHELP_DESCRIPTION = """Helper script for 'fastboot oem 53*d289c2baSAndroid Build Coastguard Workerat-write-persistent-digest' that generates and stages the required input data 54*d289c2baSAndroid Build Coastguard Workerformat.""" 55*d289c2baSAndroid Build Coastguard Worker 56*d289c2baSAndroid Build Coastguard WorkerAVB_PERSISTENT_DIGEST_PREFIX = 'avb.persistent_digest.' 57*d289c2baSAndroid Build Coastguard Worker 58*d289c2baSAndroid Build Coastguard Worker 59*d289c2baSAndroid Build Coastguard Workerdef WritePersistentDigest(name, 60*d289c2baSAndroid Build Coastguard Worker digest=None, 61*d289c2baSAndroid Build Coastguard Worker clear_digest=False, 62*d289c2baSAndroid Build Coastguard Worker serial=None, 63*d289c2baSAndroid Build Coastguard Worker verbose=False): 64*d289c2baSAndroid Build Coastguard Worker if not name.startswith(AVB_PERSISTENT_DIGEST_PREFIX): 65*d289c2baSAndroid Build Coastguard Worker print("Automatically adding '{}' prefix to persistent value name".format( 66*d289c2baSAndroid Build Coastguard Worker AVB_PERSISTENT_DIGEST_PREFIX)) 67*d289c2baSAndroid Build Coastguard Worker name = AVB_PERSISTENT_DIGEST_PREFIX + name 68*d289c2baSAndroid Build Coastguard Worker 69*d289c2baSAndroid Build Coastguard Worker tempdir = tempfile.mkdtemp() 70*d289c2baSAndroid Build Coastguard Worker try: 71*d289c2baSAndroid Build Coastguard Worker digest_data = os.path.join(tempdir, 'digest_data') 72*d289c2baSAndroid Build Coastguard Worker 73*d289c2baSAndroid Build Coastguard Worker with open(digest_data, 'wb') as out: 74*d289c2baSAndroid Build Coastguard Worker out.write(struct.pack('<I', len(name))) 75*d289c2baSAndroid Build Coastguard Worker out.write(name) 76*d289c2baSAndroid Build Coastguard Worker if clear_digest: 77*d289c2baSAndroid Build Coastguard Worker out.write(struct.pack('<I', 0)) 78*d289c2baSAndroid Build Coastguard Worker else: 79*d289c2baSAndroid Build Coastguard Worker digest_bytes = bytearray.fromhex(digest) 80*d289c2baSAndroid Build Coastguard Worker out.write(struct.pack('<I', len(digest_bytes))) 81*d289c2baSAndroid Build Coastguard Worker out.write(digest_bytes) 82*d289c2baSAndroid Build Coastguard Worker 83*d289c2baSAndroid Build Coastguard Worker def fastboot_cmd(args): 84*d289c2baSAndroid Build Coastguard Worker args = ['fastboot'] + (['-s', serial] if serial else []) + args 85*d289c2baSAndroid Build Coastguard Worker if verbose: 86*d289c2baSAndroid Build Coastguard Worker print('$ ' + ' '.join(args)) 87*d289c2baSAndroid Build Coastguard Worker 88*d289c2baSAndroid Build Coastguard Worker try: 89*d289c2baSAndroid Build Coastguard Worker out = subprocess.check_output( 90*d289c2baSAndroid Build Coastguard Worker args, stderr=subprocess.STDOUT).decode('utf-8') 91*d289c2baSAndroid Build Coastguard Worker except subprocess.CalledProcessError as e: 92*d289c2baSAndroid Build Coastguard Worker print(e.output.decode('utf-8')) 93*d289c2baSAndroid Build Coastguard Worker print("Command '{}' returned non-zero exit status {}".format( 94*d289c2baSAndroid Build Coastguard Worker ' '.join(e.cmd), e.returncode)) 95*d289c2baSAndroid Build Coastguard Worker sys.exit(1) 96*d289c2baSAndroid Build Coastguard Worker 97*d289c2baSAndroid Build Coastguard Worker if verbose: 98*d289c2baSAndroid Build Coastguard Worker print(out) 99*d289c2baSAndroid Build Coastguard Worker 100*d289c2baSAndroid Build Coastguard Worker fastboot_cmd(['stage', digest_data]) 101*d289c2baSAndroid Build Coastguard Worker fastboot_cmd(['oem', 'at-write-persistent-digest']) 102*d289c2baSAndroid Build Coastguard Worker 103*d289c2baSAndroid Build Coastguard Worker print("Persistent value '{}' {}".format( 104*d289c2baSAndroid Build Coastguard Worker name, 'cleared' if clear_digest else 'written')) 105*d289c2baSAndroid Build Coastguard Worker 106*d289c2baSAndroid Build Coastguard Worker finally: 107*d289c2baSAndroid Build Coastguard Worker shutil.rmtree(tempdir) 108*d289c2baSAndroid Build Coastguard Worker 109*d289c2baSAndroid Build Coastguard Worker 110*d289c2baSAndroid Build Coastguard Workerif __name__ == '__main__': 111*d289c2baSAndroid Build Coastguard Worker parser = argparse.ArgumentParser(description=HELP_DESCRIPTION) 112*d289c2baSAndroid Build Coastguard Worker 113*d289c2baSAndroid Build Coastguard Worker # Optional arguments 114*d289c2baSAndroid Build Coastguard Worker parser.add_argument( 115*d289c2baSAndroid Build Coastguard Worker '-v', 116*d289c2baSAndroid Build Coastguard Worker '--verbose', 117*d289c2baSAndroid Build Coastguard Worker action='store_true', 118*d289c2baSAndroid Build Coastguard Worker help='verbose; prints fastboot commands and their output') 119*d289c2baSAndroid Build Coastguard Worker parser.add_argument( 120*d289c2baSAndroid Build Coastguard Worker '-s', 121*d289c2baSAndroid Build Coastguard Worker '--serial', 122*d289c2baSAndroid Build Coastguard Worker help= 123*d289c2baSAndroid Build Coastguard Worker "specify device to unlock, either by serial or any other valid value for fastboot's -s arg" 124*d289c2baSAndroid Build Coastguard Worker ) 125*d289c2baSAndroid Build Coastguard Worker 126*d289c2baSAndroid Build Coastguard Worker # Required arguments 127*d289c2baSAndroid Build Coastguard Worker parser.add_argument( 128*d289c2baSAndroid Build Coastguard Worker '--name', 129*d289c2baSAndroid Build Coastguard Worker required=True, 130*d289c2baSAndroid Build Coastguard Worker help= 131*d289c2baSAndroid Build Coastguard Worker "persistent digest name to write, 'avb.persistent_digest.' prefix will be automatically added if not already present" 132*d289c2baSAndroid Build Coastguard Worker ) 133*d289c2baSAndroid Build Coastguard Worker group = parser.add_mutually_exclusive_group(required=True) 134*d289c2baSAndroid Build Coastguard Worker group.add_argument( 135*d289c2baSAndroid Build Coastguard Worker '--clear_digest', 136*d289c2baSAndroid Build Coastguard Worker action='store_true', 137*d289c2baSAndroid Build Coastguard Worker help= 138*d289c2baSAndroid Build Coastguard Worker 'clear any existing persistent digest value, rather than writing a new value' 139*d289c2baSAndroid Build Coastguard Worker ) 140*d289c2baSAndroid Build Coastguard Worker group.add_argument( 141*d289c2baSAndroid Build Coastguard Worker '--digest', 142*d289c2baSAndroid Build Coastguard Worker help='persistent digest value to write, as a hex encoded string') 143*d289c2baSAndroid Build Coastguard Worker 144*d289c2baSAndroid Build Coastguard Worker # Print help if no args given 145*d289c2baSAndroid Build Coastguard Worker args = parser.parse_args(args=None if sys.argv[1:] else ['-h']) 146*d289c2baSAndroid Build Coastguard Worker 147*d289c2baSAndroid Build Coastguard Worker WritePersistentDigest( 148*d289c2baSAndroid Build Coastguard Worker name=args.name, 149*d289c2baSAndroid Build Coastguard Worker clear_digest=args.clear_digest, 150*d289c2baSAndroid Build Coastguard Worker digest=args.digest, 151*d289c2baSAndroid Build Coastguard Worker serial=args.serial, 152*d289c2baSAndroid Build Coastguard Worker verbose=args.verbose) 153