mirror of
				https://github.com/torvalds/linux.git
				synced 2025-11-04 10:40:15 +02: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…
	
		Reference in a new issue