Resguardo inicial

This commit is contained in:
lastdragon
2026-09-06 12:53:21 -06:00
parent 662efe3c2a
commit ad2088d178
94853 changed files with 43200404 additions and 0 deletions
+1
View File
@@ -0,0 +1 @@
__pycache__
+13
View File
@@ -0,0 +1,13 @@
# SPDX-License-Identifier: GPL-2.0-only
CFLAGS += -D__EXPORTED_HEADERS__ -I../../../include/uapi -I../../../include
TARGET = dbc_library.so
all: $(TARGET)
dbc_library.so: dbc.c
$(CC) $(CFLAGS) $(LDFLAGS) -shared -o $@ $<
chmod -x $@
clean:
$(RM) $(TARGET)
+72
View File
@@ -0,0 +1,72 @@
// SPDX-License-Identifier: GPL-2.0-only
/*
* AMD Secure Processor Dynamic Boost Control sample library
*
* Copyright (C) 2023 Advanced Micro Devices, Inc.
*
* Author: Mario Limonciello <mario.limonciello@amd.com>
*/
#include <assert.h>
#include <errno.h>
#include <string.h>
#include <sys/ioctl.h>
/* if uapi header isn't installed, this might not yet exist */
#ifndef __packed
#define __packed __attribute__((packed))
#endif
#include <linux/psp-dbc.h>
int get_nonce(int fd, void *nonce_out, void *signature)
{
struct dbc_user_nonce tmp = {
.auth_needed = !!signature,
};
assert(nonce_out);
if (signature)
memcpy(tmp.signature, signature, sizeof(tmp.signature));
if (ioctl(fd, DBCIOCNONCE, &tmp))
return errno;
memcpy(nonce_out, tmp.nonce, sizeof(tmp.nonce));
return 0;
}
int set_uid(int fd, __u8 *uid, __u8 *signature)
{
struct dbc_user_setuid tmp;
assert(uid);
assert(signature);
memcpy(tmp.uid, uid, sizeof(tmp.uid));
memcpy(tmp.signature, signature, sizeof(tmp.signature));
if (ioctl(fd, DBCIOCUID, &tmp))
return errno;
return 0;
}
int process_param(int fd, int msg_index, __u8 *signature, int *data)
{
struct dbc_user_param tmp = {
.msg_index = msg_index,
.param = *data,
};
assert(signature);
assert(data);
memcpy(tmp.signature, signature, sizeof(tmp.signature));
if (ioctl(fd, DBCIOCPARAM, &tmp))
return errno;
*data = tmp.param;
memcpy(signature, tmp.signature, sizeof(tmp.signature));
return 0;
}
+64
View 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):
raise OSError(code, os.strerror(code))
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)
sig = ctypes.create_string_buffer(signature, len(signature))
ret = lib.process_param(device.fileno(), message[0], ctypes.pointer(sig), ctypes.pointer(arg))
if ret:
handle_error(ret)
return arg.value, sig.value
+134
View 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)
+277
View File
@@ -0,0 +1,277 @@
#!/usr/bin/python3
# SPDX-License-Identifier: GPL-2.0
import unittest
import os
import time
import glob
import fcntl
try:
import ioctl_opt as ioctl
except ImportError:
ioctl = None
pass
from dbc import *
# Artificial delay between set commands
SET_DELAY = 0.5
class invalid_param(ctypes.Structure):
_fields_ = [
("data", ctypes.c_uint8),
]
def system_is_secured() -> bool:
fused_part = glob.glob("/sys/bus/pci/drivers/ccp/**/fused_part")[0]
if os.path.exists(fused_part):
with open(fused_part, "r") as r:
return int(r.read()) == 1
return True
class DynamicBoostControlTest(unittest.TestCase):
def __init__(self, data) -> None:
self.d = None
self.signature = b"FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF"
self.uid = b"1111111111111111"
super().__init__(data)
def setUp(self) -> None:
self.d = open(DEVICE_NODE)
return super().setUp()
def tearDown(self) -> None:
if self.d:
self.d.close()
return super().tearDown()
class TestUnsupportedSystem(DynamicBoostControlTest):
def setUp(self) -> None:
if os.path.exists(DEVICE_NODE):
self.skipTest("system is supported")
with self.assertRaises(FileNotFoundError) as error:
super().setUp()
self.assertEqual(error.exception.errno, 2)
def test_unauthenticated_nonce(self) -> None:
"""fetch unauthenticated nonce"""
with self.assertRaises(ValueError) as error:
get_nonce(self.d, None)
class TestInvalidIoctls(DynamicBoostControlTest):
def __init__(self, data) -> None:
self.data = invalid_param()
self.data.data = 1
super().__init__(data)
def setUp(self) -> None:
if not os.path.exists(DEVICE_NODE):
self.skipTest("system is unsupported")
if not ioctl:
self.skipTest("unable to test IOCTLs without ioctl_opt")
return super().setUp()
def test_invalid_nonce_ioctl(self) -> None:
"""tries to call get_nonce ioctl with invalid data structures"""
# 0x1 (get nonce), and invalid data
INVALID1 = ioctl.IOWR(ord("D"), 0x01, invalid_param)
with self.assertRaises(OSError) as error:
fcntl.ioctl(self.d, INVALID1, self.data, True)
self.assertEqual(error.exception.errno, 22)
def test_invalid_setuid_ioctl(self) -> None:
"""tries to call set_uid ioctl with invalid data structures"""
# 0x2 (set uid), and invalid data
INVALID2 = ioctl.IOW(ord("D"), 0x02, invalid_param)
with self.assertRaises(OSError) as error:
fcntl.ioctl(self.d, INVALID2, self.data, True)
self.assertEqual(error.exception.errno, 22)
def test_invalid_setuid_rw_ioctl(self) -> None:
"""tries to call set_uid ioctl with invalid data structures"""
# 0x2 as RW (set uid), and invalid data
INVALID3 = ioctl.IOWR(ord("D"), 0x02, invalid_param)
with self.assertRaises(OSError) as error:
fcntl.ioctl(self.d, INVALID3, self.data, True)
self.assertEqual(error.exception.errno, 22)
def test_invalid_param_ioctl(self) -> None:
"""tries to call param ioctl with invalid data structures"""
# 0x3 (param), and invalid data
INVALID4 = ioctl.IOWR(ord("D"), 0x03, invalid_param)
with self.assertRaises(OSError) as error:
fcntl.ioctl(self.d, INVALID4, self.data, True)
self.assertEqual(error.exception.errno, 22)
def test_invalid_call_ioctl(self) -> None:
"""tries to call the DBC ioctl with invalid data structures"""
# 0x4, and invalid data
INVALID5 = ioctl.IOWR(ord("D"), 0x04, invalid_param)
with self.assertRaises(OSError) as error:
fcntl.ioctl(self.d, INVALID5, self.data, True)
self.assertEqual(error.exception.errno, 22)
class TestInvalidSignature(DynamicBoostControlTest):
def setUp(self) -> None:
if not os.path.exists(DEVICE_NODE):
self.skipTest("system is unsupported")
if not system_is_secured():
self.skipTest("system is unfused")
return super().setUp()
def test_unauthenticated_nonce(self) -> None:
"""fetch unauthenticated nonce"""
get_nonce(self.d, None)
def test_multiple_unauthenticated_nonce(self) -> None:
"""ensure state machine always returns nonce"""
for count in range(0, 2):
get_nonce(self.d, None)
def test_authenticated_nonce(self) -> None:
"""fetch authenticated nonce"""
get_nonce(self.d, None)
with self.assertRaises(OSError) as error:
get_nonce(self.d, self.signature)
self.assertEqual(error.exception.errno, 22)
def test_set_uid(self) -> None:
"""set uid"""
get_nonce(self.d, None)
with self.assertRaises(OSError) as error:
set_uid(self.d, self.uid, self.signature)
self.assertEqual(error.exception.errno, 1)
def test_get_param(self) -> None:
"""fetch a parameter"""
with self.assertRaises(OSError) as error:
process_param(self.d, PARAM_GET_SOC_PWR_CUR, self.signature)
self.assertEqual(error.exception.errno, 11)
def test_set_param(self) -> None:
"""set a parameter"""
with self.assertRaises(OSError) as error:
process_param(self.d, PARAM_SET_PWR_CAP, self.signature, 1000)
self.assertEqual(error.exception.errno, 11)
class TestUnFusedSystem(DynamicBoostControlTest):
def setup_identity(self) -> None:
"""sets up the identity of the caller"""
# if already authenticated these may fail
try:
get_nonce(self.d, None)
except PermissionError:
pass
try:
set_uid(self.d, self.uid, self.signature)
except BlockingIOError:
pass
try:
get_nonce(self.d, self.signature)
except PermissionError:
pass
def setUp(self) -> None:
if not os.path.exists(DEVICE_NODE):
self.skipTest("system is unsupported")
if system_is_secured():
self.skipTest("system is fused")
super().setUp()
self.setup_identity()
time.sleep(SET_DELAY)
def test_get_valid_param(self) -> None:
"""fetch all possible parameters"""
# SOC power
soc_power_max = process_param(self.d, PARAM_GET_SOC_PWR_MAX, self.signature)
soc_power_min = process_param(self.d, PARAM_GET_SOC_PWR_MIN, self.signature)
self.assertGreater(soc_power_max[0], soc_power_min[0])
# fmax
fmax_max = process_param(self.d, PARAM_GET_FMAX_MAX, self.signature)
fmax_min = process_param(self.d, PARAM_GET_FMAX_MIN, self.signature)
self.assertGreater(fmax_max[0], fmax_min[0])
# cap values
keys = {
"fmax-cap": PARAM_GET_FMAX_CAP,
"power-cap": PARAM_GET_PWR_CAP,
"current-temp": PARAM_GET_CURR_TEMP,
"soc-power-cur": PARAM_GET_SOC_PWR_CUR,
}
for k in keys:
result = process_param(self.d, keys[k], self.signature)
self.assertGreater(result[0], 0)
def test_get_invalid_param(self) -> None:
"""fetch an invalid parameter"""
try:
set_uid(self.d, self.uid, self.signature)
except OSError:
pass
with self.assertRaises(OSError) as error:
process_param(self.d, (0xF,), self.signature)
self.assertEqual(error.exception.errno, 22)
def test_set_fmax(self) -> None:
"""get/set fmax limit"""
# fetch current
original = process_param(self.d, PARAM_GET_FMAX_CAP, self.signature)
# set the fmax
target = original[0] - 100
process_param(self.d, PARAM_SET_FMAX_CAP, self.signature, target)
time.sleep(SET_DELAY)
new = process_param(self.d, PARAM_GET_FMAX_CAP, self.signature)
self.assertEqual(new[0], target)
# revert back to current
process_param(self.d, PARAM_SET_FMAX_CAP, self.signature, original[0])
time.sleep(SET_DELAY)
cur = process_param(self.d, PARAM_GET_FMAX_CAP, self.signature)
self.assertEqual(cur[0], original[0])
def test_set_power_cap(self) -> None:
"""get/set power cap limit"""
# fetch current
original = process_param(self.d, PARAM_GET_PWR_CAP, self.signature)
# set the fmax
target = original[0] - 10
process_param(self.d, PARAM_SET_PWR_CAP, self.signature, target)
time.sleep(SET_DELAY)
new = process_param(self.d, PARAM_GET_PWR_CAP, self.signature)
self.assertEqual(new[0], target)
# revert back to current
process_param(self.d, PARAM_SET_PWR_CAP, self.signature, original[0])
time.sleep(SET_DELAY)
cur = process_param(self.d, PARAM_GET_PWR_CAP, self.signature)
self.assertEqual(cur[0], original[0])
def test_set_3d_graphics_mode(self) -> None:
"""set/get 3d graphics mode"""
# these aren't currently implemented but may be some day
# they are *expected* to fail
with self.assertRaises(OSError) as error:
process_param(self.d, PARAM_GET_GFX_MODE, self.signature)
self.assertEqual(error.exception.errno, 2)
time.sleep(SET_DELAY)
with self.assertRaises(OSError) as error:
process_param(self.d, PARAM_SET_GFX_MODE, self.signature, 1)
self.assertEqual(error.exception.errno, 2)
if __name__ == "__main__":
unittest.main()
+190
View File
@@ -0,0 +1,190 @@
#!/usr/bin/env python3
# SPDX-License-Identifier: GPL-2.0
#
# Copyright (C) xFusion Digital Technologies Co., Ltd., 2023
#
# Author: Wang Jinchao <wangjinchao@xfusion.com>
#
"""
A tool for comparing tcrypt speed test logs.
Please note that for such a comparison, stability depends
on whether we allow frequency to float or pin the frequency.
Both support tests for operations within one second and
cycles of operation.
For example, use it in the bash script below.
```bash
#!/bin/bash
# log file prefix
seq_num=0
# When sec=0, it will perform cycle tests;
# otherwise, it indicates the duration of a single test
sec=0
num_mb=8
mode=211
# base speed test
lsmod | grep pcrypt && modprobe -r pcrypt
dmesg -C
modprobe tcrypt alg="pcrypt(rfc4106(gcm(aes)))" type=3
modprobe tcrypt mode=${mode} sec=${sec} num_mb=${num_mb}
dmesg > ${seq_num}_base_dmesg.log
# new speed test
lsmod | grep pcrypt && modprobe -r pcrypt
dmesg -C
modprobe tcrypt alg="pcrypt(rfc4106(gcm(aes)))" type=3
modprobe tcrypt mode=${mode} sec=${sec} num_mb=${num_mb}
dmesg > ${seq_num}_new_dmesg.log
lsmod | grep pcrypt && modprobe -r pcrypt
tools/crypto/tcrypt/tcrypt_speed_compare.py \
${seq_num}_base_dmesg.log \
${seq_num}_new_dmesg.log \
>${seq_num}_compare.log
grep 'average' -A2 -B0 --group-separator="" ${seq_num}_compare.log
```
"""
import sys
import re
def parse_title(line):
pattern = r'tcrypt: testing speed of (.*?) (encryption|decryption)'
match = re.search(pattern, line)
if match:
alg = match.group(1)
op = match.group(2)
return alg, op
else:
return "", ""
def parse_item(line):
pattern_operations = r'\((\d+) bit key, (\d+) byte blocks\): (\d+) operations'
pattern_cycles = r'\((\d+) bit key, (\d+) byte blocks\): 1 operation in (\d+) cycles'
match = re.search(pattern_operations, line)
if match:
res = {
"bit_key": int(match.group(1)),
"byte_blocks": int(match.group(2)),
"operations": int(match.group(3)),
}
return res
match = re.search(pattern_cycles, line)
if match:
res = {
"bit_key": int(match.group(1)),
"byte_blocks": int(match.group(2)),
"cycles": int(match.group(3)),
}
return res
return None
def parse(filepath):
result = {}
alg, op = "", ""
with open(filepath, 'r') as file:
for line in file:
if not line:
continue
_alg, _op = parse_title(line)
if _alg:
alg, op = _alg, _op
if alg not in result:
result[alg] = {}
if op not in result[alg]:
result[alg][op] = []
continue
parsed_result = parse_item(line)
if parsed_result:
result[alg][op].append(parsed_result)
return result
def merge(base, new):
merged = {}
for alg in base.keys():
merged[alg] = {}
for op in base[alg].keys():
if op not in merged[alg]:
merged[alg][op] = []
for index in range(len(base[alg][op])):
merged_item = {
"bit_key": base[alg][op][index]["bit_key"],
"byte_blocks": base[alg][op][index]["byte_blocks"],
}
if "operations" in base[alg][op][index].keys():
merged_item["base_ops"] = base[alg][op][index]["operations"]
merged_item["new_ops"] = new[alg][op][index]["operations"]
else:
merged_item["base_cycles"] = base[alg][op][index]["cycles"]
merged_item["new_cycles"] = new[alg][op][index]["cycles"]
merged[alg][op].append(merged_item)
return merged
def format(merged):
for alg in merged.keys():
for op in merged[alg].keys():
base_sum = 0
new_sum = 0
differ_sum = 0
differ_cnt = 0
print()
hlen = 80
print("="*hlen)
print(f"{alg}")
print(f"{' '*(len(alg)//3) + op}")
print("-"*hlen)
key = ""
if "base_ops" in merged[alg][op][0]:
key = "ops"
print(f"bit key | byte blocks | base ops | new ops | differ(%)")
else:
key = "cycles"
print(f"bit key | byte blocks | base cycles | new cycles | differ(%)")
for index in range(len(merged[alg][op])):
item = merged[alg][op][index]
base_cnt = item[f"base_{key}"]
new_cnt = item[f"new_{key}"]
base_sum += base_cnt
new_sum += new_cnt
differ = round((new_cnt - base_cnt)*100/base_cnt, 2)
differ_sum += differ
differ_cnt += 1
bit_key = item["bit_key"]
byte_blocks = item["byte_blocks"]
print(
f"{bit_key:<7} | {byte_blocks:<11} | {base_cnt:<11} | {new_cnt:<11} | {differ:<8}")
average_speed_up = "{:.2f}".format(differ_sum/differ_cnt)
ops_total_speed_up = "{:.2f}".format(
(base_sum - new_sum) * 100 / base_sum)
print('-'*hlen)
print(f"average differ(%s) | total_differ(%)")
print('-'*hlen)
print(f"{average_speed_up:<21} | {ops_total_speed_up:<10}")
print('='*hlen)
def main(base_log, new_log):
base = parse(base_log)
new = parse(new_log)
merged = merge(base, new)
format(merged)
if __name__ == "__main__":
if len(sys.argv) != 3:
print(f"usage: {sys.argv[0]} base_log new_log")
exit(-1)
main(sys.argv[1], sys.argv[2])