blob: 5db269d2a0d2213a2f183ae945815a7b1a92ef0b [file] [log] [blame]
/*
* SPDX-License-Identifier: BSD-3-Clause
* SPDX-FileCopyrightText: Copyright TF-RMM Contributors.
*/
#include <assert.h>
#include <debug.h>
#include <psci.h>
#include <rsi-logger.h>
#include <smc-rsi.h>
#include <string.h>
#include <utils_def.h>
/* RMI handler uses 29 chars for function name */
#define MAX_NAME_LEN 29UL
/* Max 10 64-bit parameters separated by space */
#define PARAMS_STR_LEN (10UL * sizeof("0123456789ABCDEF"))
#define MAX_STATUS_LEN sizeof("{RSI_ERROR_INPUT}")
#define BUFFER_SIZE (MAX_NAME_LEN + PARAMS_STR_LEN + \
sizeof(" > ") - 1UL + MAX_STATUS_LEN)
struct rsi_handler {
const char *fn_name; /* function name */
unsigned int num_args; /* number of arguments */
unsigned int num_vals; /* number of output values */
};
#define RSI_HANDLER_ID(_id) SMC64_FID_OFFSET_FROM_RANGE_MIN(RSI, SMC_RSI_##_id)
#define RSI_FUNCTION(_id, _in, _out)[RSI_HANDLER_ID(_id)] = { \
.fn_name = (#_id), \
.num_args = (_in), \
.num_vals = (_out) \
}
static const struct rsi_handler rsi_logger[] = {
RSI_FUNCTION(ABI_VERSION, 1U, 1U), /* 0xC4000190 */
RSI_FUNCTION(FEATURES, 1U, 1U), /* 0xC4000191 */
RSI_FUNCTION(MEASUREMENT_READ, 1U, 8U), /* 0xC4000192 */
RSI_FUNCTION(MEASUREMENT_EXTEND, 10U, 0U), /* 0xC4000193 */
RSI_FUNCTION(ATTEST_TOKEN_INIT, 9U, 0U), /* 0xC4000194 */
RSI_FUNCTION(ATTEST_TOKEN_CONTINUE, 1U, 1U), /* 0xC4000195 */
RSI_FUNCTION(REALM_CONFIG, 1U, 0U), /* 0xC4000196 */
RSI_FUNCTION(IPA_STATE_SET, 4U, 2U), /* 0xC4000197 */
RSI_FUNCTION(IPA_STATE_GET, 1U, 1U), /* 0xC4000198 */
RSI_FUNCTION(HOST_CALL, 1U, 0U) /* 0xC4000199 */
};
#define RSI_STATUS_STRING(_id)[RSI_##_id] = #_id
static const char * const rsi_status_string[] = {
RSI_STATUS_STRING(SUCCESS),
RSI_STATUS_STRING(ERROR_INPUT),
RSI_STATUS_STRING(ERROR_STATE),
RSI_STATUS_STRING(INCOMPLETE)
};
COMPILER_ASSERT(ARRAY_LEN(rsi_status_string) == RSI_ERROR_COUNT);
static const struct rsi_handler *fid_to_rsi_logger(unsigned int id)
{
return &rsi_logger[id - SMC_RSI_ABI_VERSION];
}
static size_t print_entry(unsigned int id, unsigned long args[],
char *buf, size_t len)
{
unsigned int num = 7U; /* up to seven arguments */
int cnt;
switch (id) {
case SMC_RSI_ABI_VERSION ... SMC_RSI_HOST_CALL: {
const struct rsi_handler *logger = fid_to_rsi_logger(id);
num = logger->num_args;
cnt = snprintf(buf, MAX_NAME_LEN + 1UL,
"%s%s", "SMC_RSI_", logger->fn_name);
break;
}
/* SMC32 PSCI calls */
case SMC32_PSCI_FID_MIN ... SMC32_PSCI_FID_MAX:
FALLTHROUGH;
case SMC64_PSCI_FID_MIN ... SMC64_PSCI_FID_MAX:
cnt = snprintf(buf, MAX_NAME_LEN + 1UL, "%s%08x", "PSCI_", id);
break;
/* Other SMC calls */
default:
cnt = snprintf(buf, MAX_NAME_LEN + 1UL, "%s%08x", "SMC_", id);
break;
}
assert((cnt > 0) && ((unsigned int)cnt < (MAX_NAME_LEN + 1U)));
(void)memset((void *)((uintptr_t)buf + (unsigned int)cnt), ' ',
MAX_NAME_LEN - (size_t)cnt);
buf = (char *)((uintptr_t)buf + MAX_NAME_LEN);
len -= MAX_NAME_LEN;
/* Arguments */
for (unsigned int i = 0U; i < num; i++) {
cnt = snprintf(buf, len, " %lx", args[i]);
assert((cnt > 0) && (cnt < (int)len));
buf = (char *)((uintptr_t)buf + (unsigned int)cnt);
len -= (size_t)cnt;
}
return len;
}
static int print_status(char *buf, size_t len, unsigned long res)
{
return_code_t rc = unpack_return_code(res);
if ((unsigned long)rc.status >= RSI_ERROR_COUNT) {
return snprintf(buf, len, " > %lx", res);
}
return snprintf(buf, len, " > RSI_%s",
rsi_status_string[rc.status]);
}
static int print_code(char *buf, size_t len, unsigned long res)
{
return snprintf(buf, len, " > %lx", res);
}
void rsi_log_on_exit(unsigned int function_id, unsigned long args[],
unsigned long regs[])
{
char buffer[BUFFER_SIZE];
size_t len = print_entry(function_id, args, buffer, sizeof(buffer));
char *buf = (char *)((uintptr_t)buffer + sizeof(buffer) - len);
unsigned int num = 3U; /* results in X1-X3 */
int cnt;
switch (function_id) {
case SMC_RSI_ABI_VERSION ... SMC_RSI_HOST_CALL: {
const struct rsi_handler *logger =
fid_to_rsi_logger(function_id);
/* Print status */
cnt = print_status(buf, len, regs[0]);
num = logger->num_vals;
break;
}
default:
/* Print result code */
cnt = print_code(buf, len, regs[0]);
}
assert((cnt > 0) && (cnt < (int)len));
/* Print output values */
for (unsigned int i = 1U; i <= num; i++) {
buf = (char *)((uintptr_t)buf + (unsigned int)cnt);
len -= (size_t)cnt;
cnt = snprintf(buf, len, " %lx", regs[i]);
assert((cnt > 0) && (cnt < (int)len));
}
rmm_log("%s\n", buffer);
}