Soby Mathew | b4c6df4 | 2022-11-09 11:13:29 +0000 | [diff] [blame] | 1 | /* |
| 2 | * SPDX-License-Identifier: BSD-3-Clause |
| 3 | * SPDX-FileCopyrightText: Copyright TF-RMM Contributors. |
| 4 | */ |
| 5 | |
| 6 | #include <assert.h> |
| 7 | #include <debug.h> |
| 8 | #include <psci.h> |
| 9 | #include <rsi-logger.h> |
| 10 | #include <smc-rsi.h> |
AlexeiFedorov | 6c11969 | 2023-04-21 12:31:15 +0100 | [diff] [blame] | 11 | #include <string.h> |
Soby Mathew | b4c6df4 | 2022-11-09 11:13:29 +0000 | [diff] [blame] | 12 | #include <utils_def.h> |
| 13 | |
| 14 | /* RMI handler uses 29 chars for function name */ |
AlexeiFedorov | 7b3c304 | 2023-06-28 15:41:11 +0100 | [diff] [blame] | 15 | #define MAX_NAME_LEN 29UL |
Soby Mathew | b4c6df4 | 2022-11-09 11:13:29 +0000 | [diff] [blame] | 16 | |
AlexeiFedorov | 6c11969 | 2023-04-21 12:31:15 +0100 | [diff] [blame] | 17 | /* Max 10 64-bit parameters separated by space */ |
| 18 | #define PARAMS_STR_LEN (10UL * sizeof("0123456789ABCDEF")) |
Soby Mathew | b4c6df4 | 2022-11-09 11:13:29 +0000 | [diff] [blame] | 19 | |
AlexeiFedorov | 7b3c304 | 2023-06-28 15:41:11 +0100 | [diff] [blame] | 20 | #define MAX_STATUS_LEN sizeof("{RSI_ERROR_INPUT}") |
Soby Mathew | b4c6df4 | 2022-11-09 11:13:29 +0000 | [diff] [blame] | 21 | |
AlexeiFedorov | 7b3c304 | 2023-06-28 15:41:11 +0100 | [diff] [blame] | 22 | #define BUFFER_SIZE (MAX_NAME_LEN + PARAMS_STR_LEN + \ |
AlexeiFedorov | 6c11969 | 2023-04-21 12:31:15 +0100 | [diff] [blame] | 23 | sizeof(" > ") - 1UL + MAX_STATUS_LEN) |
Soby Mathew | b4c6df4 | 2022-11-09 11:13:29 +0000 | [diff] [blame] | 24 | |
AlexeiFedorov | 6c11969 | 2023-04-21 12:31:15 +0100 | [diff] [blame] | 25 | struct rsi_handler { |
| 26 | const char *fn_name; /* function name */ |
| 27 | unsigned int num_args; /* number of arguments */ |
| 28 | unsigned int num_vals; /* number of output values */ |
Soby Mathew | b4c6df4 | 2022-11-09 11:13:29 +0000 | [diff] [blame] | 29 | }; |
| 30 | |
AlexeiFedorov | 6c11969 | 2023-04-21 12:31:15 +0100 | [diff] [blame] | 31 | #define RSI_HANDLER_ID(_id) SMC64_FID_OFFSET_FROM_RANGE_MIN(RSI, SMC_RSI_##_id) |
Soby Mathew | b4c6df4 | 2022-11-09 11:13:29 +0000 | [diff] [blame] | 32 | |
AlexeiFedorov | 6c11969 | 2023-04-21 12:31:15 +0100 | [diff] [blame] | 33 | #define RSI_FUNCTION(_id, _in, _out)[RSI_HANDLER_ID(_id)] = { \ |
| 34 | .fn_name = #_id, \ |
| 35 | .num_args = _in, \ |
| 36 | .num_vals = _out \ |
| 37 | } |
| 38 | |
| 39 | static const struct rsi_handler rsi_logger[] = { |
| 40 | RSI_FUNCTION(ABI_VERSION, 0U, 1U), /* 0xC4000190 */ |
| 41 | RSI_FUNCTION(MEASUREMENT_READ, 1U, 8U), /* 0xC4000192 */ |
| 42 | RSI_FUNCTION(MEASUREMENT_EXTEND, 10U, 0U), /* 0xC4000193 */ |
| 43 | RSI_FUNCTION(ATTEST_TOKEN_INIT, 9U, 0U), /* 0xC4000194 */ |
| 44 | RSI_FUNCTION(ATTEST_TOKEN_CONTINUE, 1U, 1U), /* 0xC4000195 */ |
| 45 | RSI_FUNCTION(REALM_CONFIG, 1U, 0U), /* 0xC4000196 */ |
| 46 | RSI_FUNCTION(IPA_STATE_SET, 3U, 1U), /* 0xC4000197 */ |
| 47 | RSI_FUNCTION(IPA_STATE_GET, 1U, 1U), /* 0xC4000198 */ |
| 48 | RSI_FUNCTION(HOST_CALL, 1U, 0U) /* 0xC4000199 */ |
Soby Mathew | b4c6df4 | 2022-11-09 11:13:29 +0000 | [diff] [blame] | 49 | }; |
| 50 | |
AlexeiFedorov | 6c11969 | 2023-04-21 12:31:15 +0100 | [diff] [blame] | 51 | #define RSI_STATUS_STRING(_id)[RSI_##_id] = #_id |
Soby Mathew | b4c6df4 | 2022-11-09 11:13:29 +0000 | [diff] [blame] | 52 | |
AlexeiFedorov | 6c11969 | 2023-04-21 12:31:15 +0100 | [diff] [blame] | 53 | const char *rsi_status_string[] = { |
| 54 | RSI_STATUS_STRING(SUCCESS), |
| 55 | RSI_STATUS_STRING(ERROR_INPUT), |
| 56 | RSI_STATUS_STRING(ERROR_STATE), |
| 57 | RSI_STATUS_STRING(INCOMPLETE) |
| 58 | }; |
| 59 | |
| 60 | COMPILER_ASSERT(ARRAY_LEN(rsi_status_string) == RSI_ERROR_COUNT); |
| 61 | |
| 62 | static struct rsi_handler *fid_to_rsi_logger(unsigned int id) |
Soby Mathew | b4c6df4 | 2022-11-09 11:13:29 +0000 | [diff] [blame] | 63 | { |
AlexeiFedorov | 6c11969 | 2023-04-21 12:31:15 +0100 | [diff] [blame] | 64 | return (struct rsi_handler *)&rsi_logger[id - SMC_RSI_ABI_VERSION]; |
| 65 | } |
| 66 | |
| 67 | static size_t print_entry(unsigned int id, unsigned long args[], |
| 68 | char *buf, size_t len) |
| 69 | { |
| 70 | unsigned int num = 7U; /* up to seven arguments */ |
| 71 | int cnt; |
Soby Mathew | b4c6df4 | 2022-11-09 11:13:29 +0000 | [diff] [blame] | 72 | |
| 73 | switch (id) { |
AlexeiFedorov | 6c11969 | 2023-04-21 12:31:15 +0100 | [diff] [blame] | 74 | case SMC_RSI_ABI_VERSION ... SMC_RSI_HOST_CALL: { |
| 75 | struct rsi_handler *logger = fid_to_rsi_logger(id); |
Soby Mathew | b4c6df4 | 2022-11-09 11:13:29 +0000 | [diff] [blame] | 76 | |
AlexeiFedorov | 6c11969 | 2023-04-21 12:31:15 +0100 | [diff] [blame] | 77 | num = logger->num_args; |
| 78 | if (logger->fn_name != NULL) { |
| 79 | cnt = snprintf(buf, MAX_NAME_LEN + 1UL, |
| 80 | "%s%s", "SMC_RSI_", logger->fn_name); |
Soby Mathew | b4c6df4 | 2022-11-09 11:13:29 +0000 | [diff] [blame] | 81 | } else { |
| 82 | /* Handle gaps in RSI commands numbering */ |
AlexeiFedorov | 6c11969 | 2023-04-21 12:31:15 +0100 | [diff] [blame] | 83 | cnt = snprintf(buf, MAX_NAME_LEN + 1UL, |
| 84 | "%s%08x", "SMC_RSI_", id); |
Soby Mathew | b4c6df4 | 2022-11-09 11:13:29 +0000 | [diff] [blame] | 85 | } |
Soby Mathew | b4c6df4 | 2022-11-09 11:13:29 +0000 | [diff] [blame] | 86 | break; |
AlexeiFedorov | 6c11969 | 2023-04-21 12:31:15 +0100 | [diff] [blame] | 87 | } |
Soby Mathew | b4c6df4 | 2022-11-09 11:13:29 +0000 | [diff] [blame] | 88 | /* SMC32 PSCI calls */ |
| 89 | case SMC32_PSCI_FID_MIN ... SMC32_PSCI_FID_MAX: |
| 90 | FALLTHROUGH; |
| 91 | case SMC64_PSCI_FID_MIN ... SMC64_PSCI_FID_MAX: |
AlexeiFedorov | 6c11969 | 2023-04-21 12:31:15 +0100 | [diff] [blame] | 92 | cnt = snprintf(buf, MAX_NAME_LEN + 1UL, "%s%08x", "PSCI_", id); |
Soby Mathew | b4c6df4 | 2022-11-09 11:13:29 +0000 | [diff] [blame] | 93 | break; |
| 94 | |
| 95 | /* Other SMC calls */ |
| 96 | default: |
AlexeiFedorov | 6c11969 | 2023-04-21 12:31:15 +0100 | [diff] [blame] | 97 | cnt = snprintf(buf, MAX_NAME_LEN + 1UL, "%s%08x", "SMC_", id); |
Soby Mathew | b4c6df4 | 2022-11-09 11:13:29 +0000 | [diff] [blame] | 98 | break; |
| 99 | } |
| 100 | |
AlexeiFedorov | 6c11969 | 2023-04-21 12:31:15 +0100 | [diff] [blame] | 101 | assert((cnt > 0) && (cnt < (int)(MAX_NAME_LEN + 1))); |
Soby Mathew | b4c6df4 | 2022-11-09 11:13:29 +0000 | [diff] [blame] | 102 | |
AlexeiFedorov | 6c11969 | 2023-04-21 12:31:15 +0100 | [diff] [blame] | 103 | (void)memset(buf + cnt, (int)' ', MAX_NAME_LEN - (size_t)cnt); |
| 104 | |
| 105 | buf += MAX_NAME_LEN; |
| 106 | len -= MAX_NAME_LEN; |
| 107 | |
| 108 | /* Arguments */ |
| 109 | for (unsigned int i = 0U; i < num; i++) { |
| 110 | cnt = snprintf(buf, len, " %lx", args[i]); |
| 111 | assert((cnt > 0) && (cnt < (int)len)); |
| 112 | buf += cnt; |
| 113 | len -= (size_t)cnt; |
| 114 | } |
| 115 | |
| 116 | return len; |
Soby Mathew | b4c6df4 | 2022-11-09 11:13:29 +0000 | [diff] [blame] | 117 | } |
| 118 | |
| 119 | static int print_status(char *buf, size_t len, unsigned long res) |
| 120 | { |
| 121 | return_code_t rc = unpack_return_code(res); |
| 122 | |
| 123 | if ((unsigned long)rc.status >= RSI_ERROR_COUNT) { |
AlexeiFedorov | 6c11969 | 2023-04-21 12:31:15 +0100 | [diff] [blame] | 124 | return snprintf(buf, len, " > %lx", res); |
Soby Mathew | b4c6df4 | 2022-11-09 11:13:29 +0000 | [diff] [blame] | 125 | } |
| 126 | |
AlexeiFedorov | 6c11969 | 2023-04-21 12:31:15 +0100 | [diff] [blame] | 127 | return snprintf(buf, len, " > RSI_%s", |
| 128 | rsi_status_string[rc.status]); |
Soby Mathew | b4c6df4 | 2022-11-09 11:13:29 +0000 | [diff] [blame] | 129 | } |
| 130 | |
| 131 | static int print_code(char *buf, size_t len, unsigned long res) |
| 132 | { |
AlexeiFedorov | 6c11969 | 2023-04-21 12:31:15 +0100 | [diff] [blame] | 133 | return snprintf(buf, len, " > %lx", res); |
Soby Mathew | b4c6df4 | 2022-11-09 11:13:29 +0000 | [diff] [blame] | 134 | } |
| 135 | |
AlexeiFedorov | 6c11969 | 2023-04-21 12:31:15 +0100 | [diff] [blame] | 136 | void rsi_log_on_exit(unsigned int function_id, unsigned long args[], |
| 137 | unsigned long regs[], bool exit_to_rec) |
Soby Mathew | b4c6df4 | 2022-11-09 11:13:29 +0000 | [diff] [blame] | 138 | { |
| 139 | char buffer[BUFFER_SIZE]; |
AlexeiFedorov | 6c11969 | 2023-04-21 12:31:15 +0100 | [diff] [blame] | 140 | size_t len = print_entry(function_id, args, buffer, sizeof(buffer)); |
Soby Mathew | b4c6df4 | 2022-11-09 11:13:29 +0000 | [diff] [blame] | 141 | |
| 142 | /* Print result when execution continues in REC */ |
| 143 | if (exit_to_rec) { |
AlexeiFedorov | 6c11969 | 2023-04-21 12:31:15 +0100 | [diff] [blame] | 144 | char *buf = buffer + (sizeof(buffer) - len); |
| 145 | unsigned int num = 3U; /* results in X1-X3 */ |
| 146 | int cnt; |
| 147 | |
| 148 | switch (function_id) { |
| 149 | case SMC_RSI_MEASUREMENT_READ ... SMC_RSI_HOST_CALL: { |
| 150 | struct rsi_handler *logger = |
| 151 | fid_to_rsi_logger(function_id); |
| 152 | |
Soby Mathew | b4c6df4 | 2022-11-09 11:13:29 +0000 | [diff] [blame] | 153 | /* Print status */ |
AlexeiFedorov | 6c11969 | 2023-04-21 12:31:15 +0100 | [diff] [blame] | 154 | cnt = print_status(buf, len, regs[0]); |
| 155 | num = logger->num_vals; |
| 156 | break; |
| 157 | } |
| 158 | case SMC_RSI_ABI_VERSION: |
| 159 | num = 0U; |
| 160 | FALLTHROUGH; |
| 161 | default: |
Soby Mathew | b4c6df4 | 2022-11-09 11:13:29 +0000 | [diff] [blame] | 162 | /* Print result code */ |
AlexeiFedorov | 6c11969 | 2023-04-21 12:31:15 +0100 | [diff] [blame] | 163 | cnt = print_code(buf, len, regs[0]); |
Soby Mathew | b4c6df4 | 2022-11-09 11:13:29 +0000 | [diff] [blame] | 164 | } |
| 165 | |
AlexeiFedorov | 6c11969 | 2023-04-21 12:31:15 +0100 | [diff] [blame] | 166 | assert((cnt > 0) && (cnt < (int)len)); |
| 167 | |
| 168 | /* Print output values */ |
| 169 | for (unsigned int i = 1U; i <= num; i++) { |
| 170 | buf += cnt; |
| 171 | len -= (size_t)cnt; |
| 172 | cnt = snprintf(buf, len, " %lx", regs[i]); |
| 173 | assert((cnt > 0) && (cnt < (int)len)); |
| 174 | } |
Soby Mathew | b4c6df4 | 2022-11-09 11:13:29 +0000 | [diff] [blame] | 175 | } |
| 176 | |
| 177 | rmm_log("%s\n", buffer); |
| 178 | } |