1 /*
2 * SPDX-License-Identifier: BSD-3-Clause
3 * SPDX-FileCopyrightText: Copyright TF-RMM Contributors.
4 */
5
6 #ifndef STATUS_H
7 #define STATUS_H
8
9 #include <stdbool.h>
10
11 /*
12 * Status codes which can be returned from RMM commands.
13 *
14 * For each code, the meaning of return_code_t::index is stated.
15 */
16 typedef enum {
17 /*
18 * Command completed successfully.
19 *
20 * index is zero.
21 */
22 RMI_SUCCESS = 0,
23
24 /*
25 * The value of a command input value caused the command to fail.
26 *
27 * index is zero.
28 */
29 RMI_ERROR_INPUT = 1,
30
31 /*
32 * An attribute of a Realm does not match the expected value.
33 *
34 * index varies between usages.
35 */
36 RMI_ERROR_REALM = 2,
37
38 /*
39 * An attribute of a REC does not match the expected value.
40 *
41 * index is zero.
42 */
43 RMI_ERROR_REC = 3,
44
45 /*
46 * An RTT walk terminated before reaching the target RTT level,
47 * or reached an RTTE with an unexpected value.
48 *
49 * index: RTT level at which the walk terminated
50 */
51 RMI_ERROR_RTT = 4,
52
53 /*
54 * An operation cannot be completed because a resource is in use.
55 *
56 * index is zero.
57 */
58 RMI_ERROR_IN_USE = 5,
59
60 RMI_ERROR_COUNT
61 } status_t;
62
63 /*
64 * Logical representation of return code returned by RMM commands.
65 * Each failure mode of a given command should return a unique return code, so
66 * that the caller can use it to unambiguously identify the failure mode. To
67 * avoid having a very large list of enumerated values, the return code is
68 * composed of a status which identifies the category of the error (for example,
69 * an address was misaligned), and an index which disambiguates between multiple
70 * similar failure modes (for example, a command may take multiple addresses as
71 * its input; the index identifies _which_ of them was misaligned.)
72 */
73 typedef struct {
74 status_t status;
75 unsigned int index;
76 } return_code_t;
77
78 /*
79 * Convenience function for creating a return_code_t.
80 */
make_return_code(unsigned int status,unsigned int index)81 static inline return_code_t make_return_code(unsigned int status,
82 unsigned int index)
83 {
84 return (return_code_t) {status, index};
85 }
86
87 /*
88 * Pack a return_code_t into a binary format, suitable for storing in a
89 * register before exit from the RMM.
90 */
pack_struct_return_code(return_code_t return_code)91 static inline unsigned long pack_struct_return_code(return_code_t return_code)
92 {
93 return (unsigned long)(return_code.status | (return_code.index << 8));
94 }
95
96 /*
97 * Pack a return code into a binary format, suitable for storing in a register
98 * on exit from the RMM.
99 */
pack_return_code(unsigned int status,unsigned int index)100 static inline unsigned long pack_return_code(unsigned int status, unsigned int index)
101 {
102 /* The width of @status and @index is 8 bits */
103 assert((status <= 0xffU) && (index <= 0xffU));
104 return pack_struct_return_code(make_return_code(status, index));
105 }
106
107 /*
108 * Unpacks a return code.
109 */
unpack_return_code(unsigned long error_code)110 static inline return_code_t unpack_return_code(unsigned long error_code)
111 {
112 return make_return_code(error_code & 0xffU, error_code >> 8);
113 }
114
115 #define MAX_ERR 4095
116
117 /*
118 * Cast a status value to a pointer.
119 */
status_ptr(status_t status)120 static inline void *status_ptr(status_t status)
121 {
122 return (void *)(-1 * (unsigned long)status);
123 }
124
125 /*
126 * Check whether a pointer value represents an error.
127 */
ptr_is_err(const void * ptr)128 static inline bool ptr_is_err(const void *ptr)
129 {
130 return (unsigned long)ptr >= (unsigned long)(-MAX_ERR);
131 }
132
133 /*
134 * Cast a pointer to a status value.
135 */
ptr_status(const void * ptr)136 static inline status_t ptr_status(const void *ptr)
137 {
138 return (status_t)(-1 * (unsigned long)ptr);
139 }
140
141 #endif /* STATUS_H */
142