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