-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
crypto: ccp - Add a sample python script for Dynamic Boost Control
Dynamic Boost Control commands are triggered by userspace with an IOCTL interface that userspace will prepare proper buffers for a request. To allow prototyping and testing this interface, add a python3 command line script that loads the dbc_library.so for utilizing the IOCTLs. The signature to use and UID are passed as arguments to this script. Acked-by: Tom Lendacky <thomas.lendacky@amd.com> Signed-off-by: Mario Limonciello <mario.limonciello@amd.com> Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
- Loading branch information
Mario Limonciello
authored and
Herbert Xu
committed
Jul 20, 2023
1 parent
febe3ed
commit f40d42f
Showing
3 changed files
with
199 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
__pycache__ |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,64 @@ | ||
#!/usr/bin/python3 | ||
# SPDX-License-Identifier: GPL-2.0 | ||
|
||
import ctypes | ||
import os | ||
|
||
DBC_UID_SIZE = 16 | ||
DBC_NONCE_SIZE = 16 | ||
DBC_SIG_SIZE = 32 | ||
|
||
PARAM_GET_FMAX_CAP = (0x3,) | ||
PARAM_SET_FMAX_CAP = (0x4,) | ||
PARAM_GET_PWR_CAP = (0x5,) | ||
PARAM_SET_PWR_CAP = (0x6,) | ||
PARAM_GET_GFX_MODE = (0x7,) | ||
PARAM_SET_GFX_MODE = (0x8,) | ||
PARAM_GET_CURR_TEMP = (0x9,) | ||
PARAM_GET_FMAX_MAX = (0xA,) | ||
PARAM_GET_FMAX_MIN = (0xB,) | ||
PARAM_GET_SOC_PWR_MAX = (0xC,) | ||
PARAM_GET_SOC_PWR_MIN = (0xD,) | ||
PARAM_GET_SOC_PWR_CUR = (0xE,) | ||
|
||
DEVICE_NODE = "/dev/dbc" | ||
|
||
lib = ctypes.CDLL("./dbc_library.so", mode=ctypes.RTLD_GLOBAL) | ||
|
||
|
||
def handle_error(code): | ||
val = code * -1 | ||
raise OSError(val, os.strerror(val)) | ||
|
||
|
||
def get_nonce(device, signature): | ||
if not device: | ||
raise ValueError("Device required") | ||
buf = ctypes.create_string_buffer(DBC_NONCE_SIZE) | ||
ret = lib.get_nonce(device.fileno(), ctypes.byref(buf), signature) | ||
if ret: | ||
handle_error(ret) | ||
return buf.value | ||
|
||
|
||
def set_uid(device, new_uid, signature): | ||
if not signature: | ||
raise ValueError("Signature required") | ||
if not new_uid: | ||
raise ValueError("UID required") | ||
ret = lib.set_uid(device.fileno(), new_uid, signature) | ||
if ret: | ||
handle_error(ret) | ||
return True | ||
|
||
|
||
def process_param(device, message, signature, data=None): | ||
if not signature: | ||
raise ValueError("Signature required") | ||
if type(message) != tuple: | ||
raise ValueError("Expected message tuple") | ||
arg = ctypes.c_int(data if data else 0) | ||
ret = lib.process_param(device.fileno(), message[0], signature, ctypes.pointer(arg)) | ||
if ret: | ||
handle_error(ret) | ||
return arg, signature |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,134 @@ | ||
#!/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) |