| #!/usr/bin/python3 |
| # SPDX-License-Identifier: GPL-2.0 |
| import argparse |
| import binascii |
| import os |
| import errno |
| from dbc import * |
| |
| ERRORS = { |
| errno.EACCES: "Access is denied", |
| errno.E2BIG: "Excess data provided", |
| errno.EINVAL: "Bad parameters", |
| errno.EAGAIN: "Bad state", |
| errno.ENOENT: "Not implemented or message failure", |
| errno.EBUSY: "Busy", |
| errno.ENFILE: "Overflow", |
| errno.EPERM: "Signature invalid", |
| } |
| |
| messages = { |
| "get-fmax-cap": PARAM_GET_FMAX_CAP, |
| "set-fmax-cap": PARAM_SET_FMAX_CAP, |
| "get-power-cap": PARAM_GET_PWR_CAP, |
| "set-power-cap": PARAM_SET_PWR_CAP, |
| "get-graphics-mode": PARAM_GET_GFX_MODE, |
| "set-graphics-mode": PARAM_SET_GFX_MODE, |
| "get-current-temp": PARAM_GET_CURR_TEMP, |
| "get-fmax-max": PARAM_GET_FMAX_MAX, |
| "get-fmax-min": PARAM_GET_FMAX_MIN, |
| "get-soc-power-max": PARAM_GET_SOC_PWR_MAX, |
| "get-soc-power-min": PARAM_GET_SOC_PWR_MIN, |
| "get-soc-power-cur": PARAM_GET_SOC_PWR_CUR, |
| } |
| |
| |
| def _pretty_buffer(ba): |
| return str(binascii.hexlify(ba, " ")) |
| |
| |
| def parse_args(): |
| parser = argparse.ArgumentParser( |
| description="Dynamic Boost control command line interface" |
| ) |
| parser.add_argument( |
| "command", |
| choices=["get-nonce", "get-param", "set-param", "set-uid"], |
| help="Command to send", |
| ) |
| parser.add_argument("--device", default="/dev/dbc", help="Device to operate") |
| parser.add_argument("--signature", help="File containing signature for command") |
| parser.add_argument("--message", choices=messages.keys(), help="Message index") |
| parser.add_argument("--data", help="Argument to pass to message") |
| parser.add_argument("--uid", help="File containing UID to pass") |
| return parser.parse_args() |
| |
| |
| def pretty_error(code): |
| if code in ERRORS: |
| print(ERRORS[code]) |
| else: |
| print("failed with return code %d" % code) |
| |
| |
| if __name__ == "__main__": |
| args = parse_args() |
| data = 0 |
| sig = None |
| uid = None |
| if not os.path.exists(args.device): |
| raise IOError("Missing device {device}".format(device=args.device)) |
| if args.signature: |
| if not os.path.exists(args.signature): |
| raise ValueError("Invalid signature file %s" % args.signature) |
| with open(args.signature, "rb") as f: |
| sig = f.read() |
| if len(sig) != DBC_SIG_SIZE: |
| raise ValueError( |
| "Invalid signature length %d (expected %d)" % (len(sig), DBC_SIG_SIZE) |
| ) |
| if args.uid: |
| if not os.path.exists(args.uid): |
| raise ValueError("Invalid uid file %s" % args.uid) |
| with open(args.uid, "rb") as f: |
| uid = f.read() |
| if len(uid) != DBC_UID_SIZE: |
| raise ValueError( |
| "Invalid UID length %d (expected %d)" % (len(uid), DBC_UID_SIZE) |
| ) |
| if args.data: |
| try: |
| data = int(args.data, 10) |
| except ValueError: |
| data = int(args.data, 16) |
| |
| with open(args.device) as d: |
| if args.command == "get-nonce": |
| try: |
| nonce = get_nonce(d, sig) |
| print("Nonce: %s" % _pretty_buffer(bytes(nonce))) |
| except OSError as e: |
| pretty_error(e.errno) |
| elif args.command == "set-uid": |
| try: |
| result = set_uid(d, uid, sig) |
| if result: |
| print("Set UID") |
| except OSError as e: |
| pretty_error(e.errno) |
| elif args.command == "get-param": |
| if not args.message or args.message.startswith("set"): |
| raise ValueError("Invalid message %s" % args.message) |
| try: |
| param, signature = process_param(d, messages[args.message], sig) |
| print( |
| "Parameter: {par}, response signature {sig}".format( |
| par=param, |
| sig=_pretty_buffer(bytes(signature)), |
| ) |
| ) |
| except OSError as e: |
| pretty_error(e.errno) |
| elif args.command == "set-param": |
| if not args.message or args.message.startswith("get"): |
| raise ValueError("Invalid message %s" % args.message) |
| try: |
| param, signature = process_param(d, messages[args.message], sig, data) |
| print( |
| "Parameter: {par}, response signature {sig}".format( |
| par=param, |
| sig=_pretty_buffer(bytes(signature)), |
| ) |
| ) |
| except OSError as e: |
| pretty_error(e.errno) |