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>
11 #include <utils_def.h>
12 
13 /* RMI handler uses 29 chars for function name */
14 #define	MAX_NAME_LEN	29U
15 
16 /* 5 64-bit parameters separated by space + 1 trailing space */
17 #define PARAMS_STR_LEN	(5U * sizeof("0123456789ABCDEF") + 1U)
18 
19 #define	MAX_STATUS_LEN	sizeof("{RSI_ERROR_INPUT}")
20 
21 #define	BUFFER_SIZE	(MAX_NAME_LEN + PARAMS_STR_LEN +	\
22 			sizeof("> ") - 1U +		\
23 			MAX_STATUS_LEN)
24 
25 #define RSI_FUNCTION(id) \
26 	[SMC_RSI_##id - SMC_RSI_ABI_VERSION] = #id
27 
28 static const char *rsi_logger[] = {
29 	RSI_FUNCTION(ABI_VERSION),		/* 0xC4000190 */
30 	RSI_FUNCTION(MEASUREMENT_READ),		/* 0xC4000192 */
31 	RSI_FUNCTION(MEASUREMENT_EXTEND),	/* 0xC4000193 */
32 	RSI_FUNCTION(ATTEST_TOKEN_INIT),	/* 0xC4000194 */
33 	RSI_FUNCTION(ATTEST_TOKEN_CONTINUE),	/* 0xC4000195 */
34 	RSI_FUNCTION(REALM_CONFIG),		/* 0xC4000196 */
35 	RSI_FUNCTION(IPA_STATE_SET),		/* 0xC4000197 */
36 	RSI_FUNCTION(IPA_STATE_GET),		/* 0xC4000198 */
37 	RSI_FUNCTION(HOST_CALL)			/* 0xC4000199 */
38 };
39 
40 #define RSI_STATUS_HANDLER(id)[id] = #id
41 
42 const char *rsi_status_handler[] = {
43 	RSI_STATUS_HANDLER(RSI_SUCCESS),
44 	RSI_STATUS_HANDLER(RSI_ERROR_INPUT),
45 	RSI_STATUS_HANDLER(RSI_ERROR_STATE),
46 	RSI_STATUS_HANDLER(RSI_INCOMPLETE)
47 };
48 
49 COMPILER_ASSERT(ARRAY_LEN(rsi_status_handler) == RSI_ERROR_COUNT);
50 
print_entry(unsigned int id,unsigned long args[5],char * buf,size_t len)51 static int print_entry(unsigned int id, unsigned long args[5],
52 		       char *buf, size_t len)
53 {
54 	char name[sizeof("SMC_RSI_ATTEST_TOKEN_CONTINUE")];
55 	int cnt __unused;
56 
57 	switch (id) {
58 	case SMC_RSI_ABI_VERSION ... SMC_RSI_HOST_CALL:
59 
60 		if (rsi_logger[id - SMC_RSI_ABI_VERSION] != NULL) {
61 			cnt = snprintf(name, sizeof(name), "%s%s", "SMC_RSI_",
62 			       rsi_logger[id - SMC_RSI_ABI_VERSION]);
63 		} else {
64 			/* Handle gaps in RSI commands numbering */
65 			cnt = snprintf(name, sizeof(name), "%s%08x", "SMC_RSI_", id);
66 		}
67 
68 		break;
69 
70 	/* SMC32 PSCI calls */
71 	case SMC32_PSCI_FID_MIN ... SMC32_PSCI_FID_MAX:
72 		FALLTHROUGH;
73 	case SMC64_PSCI_FID_MIN ... SMC64_PSCI_FID_MAX:
74 		cnt = snprintf(name, sizeof(name), "%s%08x", "PSCI_", id);
75 		break;
76 
77 	/* Other SMC calls */
78 	default:
79 		cnt = snprintf(name, sizeof(name), "%s%08x", "SMC_", id);
80 		break;
81 	}
82 
83 	assert((cnt > 0) && (cnt < sizeof(name)));
84 
85 	return snprintf(buf, len, "%-29s %8lx %8lx %8lx %8lx %8lx ",
86 			name, args[0], args[1], args[2], args[3], args[4]);
87 }
88 
print_status(char * buf,size_t len,unsigned long res)89 static int print_status(char *buf, size_t len, unsigned long res)
90 {
91 	return_code_t rc = unpack_return_code(res);
92 
93 	if ((unsigned long)rc.status >= RSI_ERROR_COUNT) {
94 		return snprintf(buf, len, "> %lx", res);
95 	}
96 
97 	return snprintf(buf, len, "> %s",
98 			rsi_status_handler[rc.status]);
99 }
100 
print_code(char * buf,size_t len,unsigned long res)101 static int print_code(char *buf, size_t len, unsigned long res)
102 {
103 	return snprintf(buf, len, "> %lx", res);
104 }
105 
rsi_log_on_exit(unsigned int function_id,unsigned long args[5],unsigned long res,bool exit_to_rec)106 void rsi_log_on_exit(unsigned int function_id, unsigned long args[5],
107 		     unsigned long res, bool exit_to_rec)
108 {
109 	char buffer[BUFFER_SIZE];
110 	char *buf_ptr = buffer;
111 	size_t buf_len = sizeof(buffer);
112 	int cnt = print_entry(function_id, args, buf_ptr, buf_len);
113 
114 	assert((cnt > 0) && (cnt < buf_len));
115 
116 	buf_ptr += cnt;
117 	buf_len -= cnt;
118 
119 	/* Print result when execution continues in REC */
120 	if (exit_to_rec) {
121 		if ((function_id >= SMC_RSI_MEASUREMENT_READ) &&
122 		    (function_id <= SMC_RSI_HOST_CALL)) {
123 			/* Print status */
124 			cnt = print_status(buf_ptr, buf_len, res);
125 		} else {
126 			/* Print result code */
127 			cnt = print_code(buf_ptr, buf_len, res);
128 		}
129 
130 		assert((cnt > 0) && (cnt < buf_len));
131 	}
132 
133 	rmm_log("%s\n", buffer);
134 }
135