1#!/usr/bin/python3 2# SPDX-License-Identifier: GPL-2.0 3import argparse 4import binascii 5import os 6import errno 7from dbc import * 8 9ERRORS = { 10 errno.EACCES: "Access is denied", 11 errno.E2BIG: "Excess data provided", 12 errno.EINVAL: "Bad parameters", 13 errno.EAGAIN: "Bad state", 14 errno.ENOENT: "Not implemented or message failure", 15 errno.EBUSY: "Busy", 16 errno.ENFILE: "Overflow", 17 errno.EPERM: "Signature invalid", 18} 19 20messages = { 21 "get-fmax-cap": PARAM_GET_FMAX_CAP, 22 "set-fmax-cap": PARAM_SET_FMAX_CAP, 23 "get-power-cap": PARAM_GET_PWR_CAP, 24 "set-power-cap": PARAM_SET_PWR_CAP, 25 "get-graphics-mode": PARAM_GET_GFX_MODE, 26 "set-graphics-mode": PARAM_SET_GFX_MODE, 27 "get-current-temp": PARAM_GET_CURR_TEMP, 28 "get-fmax-max": PARAM_GET_FMAX_MAX, 29 "get-fmax-min": PARAM_GET_FMAX_MIN, 30 "get-soc-power-max": PARAM_GET_SOC_PWR_MAX, 31 "get-soc-power-min": PARAM_GET_SOC_PWR_MIN, 32 "get-soc-power-cur": PARAM_GET_SOC_PWR_CUR, 33} 34 35 36def _pretty_buffer(ba): 37 return str(binascii.hexlify(ba, " ")) 38 39 40def parse_args(): 41 parser = argparse.ArgumentParser( 42 description="Dynamic Boost control command line interface" 43 ) 44 parser.add_argument( 45 "command", 46 choices=["get-nonce", "get-param", "set-param", "set-uid"], 47 help="Command to send", 48 ) 49 parser.add_argument("--device", default="/dev/dbc", help="Device to operate") 50 parser.add_argument("--signature", help="File containing signature for command") 51 parser.add_argument("--message", choices=messages.keys(), help="Message index") 52 parser.add_argument("--data", help="Argument to pass to message") 53 parser.add_argument("--uid", help="File containing UID to pass") 54 return parser.parse_args() 55 56 57def pretty_error(code): 58 if code in ERRORS: 59 print(ERRORS[code]) 60 else: 61 print("failed with return code %d" % code) 62 63 64if __name__ == "__main__": 65 args = parse_args() 66 data = 0 67 sig = None 68 uid = None 69 if not os.path.exists(args.device): 70 raise IOError("Missing device {device}".format(device=args.device)) 71 if args.signature: 72 if not os.path.exists(args.signature): 73 raise ValueError("Invalid signature file %s" % args.signature) 74 with open(args.signature, "rb") as f: 75 sig = f.read() 76 if len(sig) != DBC_SIG_SIZE: 77 raise ValueError( 78 "Invalid signature length %d (expected %d)" % (len(sig), DBC_SIG_SIZE) 79 ) 80 if args.uid: 81 if not os.path.exists(args.uid): 82 raise ValueError("Invalid uid file %s" % args.uid) 83 with open(args.uid, "rb") as f: 84 uid = f.read() 85 if len(uid) != DBC_UID_SIZE: 86 raise ValueError( 87 "Invalid UID length %d (expected %d)" % (len(uid), DBC_UID_SIZE) 88 ) 89 if args.data: 90 try: 91 data = int(args.data, 10) 92 except ValueError: 93 data = int(args.data, 16) 94 95 with open(args.device) as d: 96 if args.command == "get-nonce": 97 try: 98 nonce = get_nonce(d, sig) 99 print("Nonce: %s" % _pretty_buffer(bytes(nonce))) 100 except OSError as e: 101 pretty_error(e.errno) 102 elif args.command == "set-uid": 103 try: 104 result = set_uid(d, uid, sig) 105 if result: 106 print("Set UID") 107 except OSError as e: 108 pretty_error(e.errno) 109 elif args.command == "get-param": 110 if not args.message or args.message.startswith("set"): 111 raise ValueError("Invalid message %s" % args.message) 112 try: 113 param, signature = process_param(d, messages[args.message], sig) 114 print( 115 "Parameter: {par}, response signature {sig}".format( 116 par=param, 117 sig=_pretty_buffer(bytes(signature)), 118 ) 119 ) 120 except OSError as e: 121 pretty_error(e.errno) 122 elif args.command == "set-param": 123 if not args.message or args.message.startswith("get"): 124 raise ValueError("Invalid message %s" % args.message) 125 try: 126 param, signature = process_param(d, messages[args.message], sig, data) 127 print( 128 "Parameter: {par}, response signature {sig}".format( 129 par=param, 130 sig=_pretty_buffer(bytes(signature)), 131 ) 132 ) 133 except OSError as e: 134 pretty_error(e.errno) 135