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