mirror of
git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2025-05-23 01:32:25 +00:00
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>
This commit is contained in:
parent
febe3ed322
commit
f40d42f116
3 changed files with 199 additions and 0 deletions
1
tools/crypto/ccp/.gitignore
vendored
Normal file
1
tools/crypto/ccp/.gitignore
vendored
Normal file
|
@ -0,0 +1 @@
|
||||||
|
__pycache__
|
64
tools/crypto/ccp/dbc.py
Normal file
64
tools/crypto/ccp/dbc.py
Normal file
|
@ -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
|
134
tools/crypto/ccp/dbc_cli.py
Executable file
134
tools/crypto/ccp/dbc_cli.py
Executable file
|
@ -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)
|
Loading…
Add table
Reference in a new issue