1 /*
2  * Arm SCP/MCP Software
3  * Copyright (c) 2015-2021, Arm Limited and Contributors. All rights reserved.
4  *
5  * SPDX-License-Identifier: BSD-3-Clause
6  *
7  * Description:
8  *     Identifiers.
9  */
10 
11 #include <internal/fwk_id.h>
12 
13 #include <fwk_assert.h>
14 #include <fwk_attributes.h>
15 #include <fwk_id.h>
16 #include <fwk_macros.h>
17 #include <fwk_module.h>
18 
19 #include <stdint.h>
20 #include <stdio.h>
21 #include <string.h>
22 
fwk_id_format(char * buffer,size_t buffer_size,fwk_id_t id)23 static void fwk_id_format(char *buffer, size_t buffer_size, fwk_id_t id)
24 {
25     static const char *types[__FWK_ID_TYPE_COUNT] = {
26         [__FWK_ID_TYPE_INVALID] = "INV",
27         [__FWK_ID_TYPE_NONE] = "NON",
28         [__FWK_ID_TYPE_MODULE] = "MOD",
29         [__FWK_ID_TYPE_ELEMENT] = "ELM",
30         [__FWK_ID_TYPE_SUB_ELEMENT] = "SUB",
31         [__FWK_ID_TYPE_API] = "API",
32         [__FWK_ID_TYPE_EVENT] = "EVT",
33         [__FWK_ID_TYPE_NOTIFICATION] = "NOT",
34     };
35 
36     size_t length = 0;
37 
38     enum __fwk_id_type com_id_type = (enum __fwk_id_type)id.common.type;
39 
40     unsigned int indices[] = { 0, 0, 0 };
41 
42     fwk_assert(buffer_size > 0);
43 
44     if (id.common.type >= FWK_ARRAY_SIZE(types) ||
45         id.common.type == (uint32_t)__FWK_ID_TYPE_INVALID) {
46         (void)snprintf(
47             buffer,
48             buffer_size,
49             "[%s]",
50             types[(uint32_t)__FWK_ID_TYPE_INVALID]);
51         return;
52     }
53 
54     indices[0] = id.common.module_idx;
55 
56     switch (com_id_type) {
57     case __FWK_ID_TYPE_SUB_ELEMENT:
58         indices[2] = id.sub_element.sub_element_idx;
59 
60         FWK_FALLTHROUGH;
61 
62     case __FWK_ID_TYPE_ELEMENT:
63         indices[1] = id.element.element_idx;
64 
65         break;
66 
67     case __FWK_ID_TYPE_API:
68         indices[1] = id.api.api_idx;
69 
70         break;
71 
72     case __FWK_ID_TYPE_EVENT:
73         indices[1] = id.event.event_idx;
74 
75         break;
76 
77     case __FWK_ID_TYPE_NOTIFICATION:
78         indices[1] = id.notification.notification_idx;
79 
80         break;
81 
82     default:
83         break;
84     }
85 
86     length += snprintf(
87         buffer + length,
88         buffer_size - length,
89         "[%s %u",
90         types[id.common.type],
91         indices[0]);
92 
93     switch (com_id_type) {
94     case __FWK_ID_TYPE_ELEMENT:
95     case __FWK_ID_TYPE_SUB_ELEMENT:
96     case __FWK_ID_TYPE_API:
97     case __FWK_ID_TYPE_EVENT:
98     case __FWK_ID_TYPE_NOTIFICATION:
99         length +=
100             snprintf(buffer + length, buffer_size - length, ":%u", indices[1]);
101 
102         break;
103 
104     default:
105         break;
106     }
107 
108     switch (com_id_type) {
109     case __FWK_ID_TYPE_SUB_ELEMENT:
110         length +=
111             snprintf(buffer + length, buffer_size - length, ":%u", indices[2]);
112 
113         break;
114 
115     default:
116         break;
117     }
118 
119     (void)snprintf(buffer + length, buffer_size - length, "]");
120 }
121 
__fwk_id_str(fwk_id_t id)122 struct __fwk_id_fmt __fwk_id_str(fwk_id_t id)
123 {
124     struct __fwk_id_fmt fmt = { { 0 } };
125 
126     fwk_id_format(fmt.str, sizeof(fmt.str), id);
127 
128     return fmt;
129 }
130 
fwk_id_is_type(fwk_id_t id,enum fwk_id_type type)131 bool fwk_id_is_type(fwk_id_t id, enum fwk_id_type type)
132 {
133     fwk_assert(id.common.type != __FWK_ID_TYPE_INVALID);
134     fwk_assert(id.common.type < __FWK_ID_TYPE_COUNT);
135 
136     return id.common.type == type;
137 }
138 
fwk_id_type_is_valid(fwk_id_t id)139 bool fwk_id_type_is_valid(fwk_id_t id)
140 {
141     if ((id.common.type != __FWK_ID_TYPE_INVALID) &&
142         (id.common.type < __FWK_ID_TYPE_COUNT)) {
143         return true;
144     }
145 
146     return false;
147 }
148 
fwk_id_get_type(fwk_id_t id)149 enum fwk_id_type fwk_id_get_type(fwk_id_t id)
150 {
151     fwk_assert(id.common.type != __FWK_ID_TYPE_INVALID);
152     fwk_assert(id.common.type < __FWK_ID_TYPE_COUNT);
153 
154     return (enum fwk_id_type)id.common.type;
155 }
156 
fwk_id_is_equal(fwk_id_t left,fwk_id_t right)157 bool fwk_id_is_equal(fwk_id_t left, fwk_id_t right)
158 {
159     fwk_assert(left.common.type != __FWK_ID_TYPE_INVALID);
160     fwk_assert(left.common.type < __FWK_ID_TYPE_COUNT);
161 
162     return left.value == right.value;
163 }
164 
fwk_optional_id_is_defined(fwk_optional_id_t id)165 bool fwk_optional_id_is_defined(fwk_optional_id_t id)
166 {
167     fwk_assert(id.common.type < __FWK_ID_TYPE_COUNT);
168     return id.common.type != __FWK_ID_TYPE_INVALID;
169 }
170 
fwk_id_build_module_id(fwk_id_t id)171 fwk_id_t fwk_id_build_module_id(fwk_id_t id)
172 {
173     fwk_assert(id.common.type != __FWK_ID_TYPE_INVALID);
174     fwk_assert(id.common.type < __FWK_ID_TYPE_COUNT);
175 
176     return FWK_ID_MODULE(id.common.module_idx);
177 }
178 
fwk_id_build_element_id(fwk_id_t id,unsigned int element_idx)179 fwk_id_t fwk_id_build_element_id(fwk_id_t id, unsigned int element_idx)
180 {
181     fwk_assert(id.common.type != __FWK_ID_TYPE_INVALID);
182     fwk_assert(id.common.type < __FWK_ID_TYPE_COUNT);
183 
184     return FWK_ID_ELEMENT(id.common.module_idx, element_idx);
185 }
186 
fwk_id_build_sub_element_id(fwk_id_t id,unsigned int sub_element_idx)187 fwk_id_t fwk_id_build_sub_element_id(fwk_id_t id, unsigned int sub_element_idx)
188 {
189     fwk_assert(id.common.type == __FWK_ID_TYPE_ELEMENT);
190 
191     return FWK_ID_SUB_ELEMENT(
192         id.common.module_idx, id.element.element_idx, sub_element_idx);
193 }
194 
fwk_id_build_api_id(fwk_id_t id,unsigned int api_idx)195 fwk_id_t fwk_id_build_api_id(fwk_id_t id, unsigned int api_idx)
196 {
197     fwk_assert(id.common.type != __FWK_ID_TYPE_INVALID);
198     fwk_assert(id.common.type < __FWK_ID_TYPE_COUNT);
199 
200     return FWK_ID_API(id.common.module_idx, api_idx);
201 }
202 
203 /*
204  * Following functions are enabled only for debug build, release build
205  * will use inline equivalents, see fwk_id.h
206  */
207 #if !defined(NDEBUG)
fwk_id_get_module_idx(fwk_id_t id)208 unsigned int fwk_id_get_module_idx(fwk_id_t id)
209 {
210     fwk_assert(id.common.type != __FWK_ID_TYPE_INVALID);
211     fwk_assert(id.common.type < __FWK_ID_TYPE_COUNT);
212 
213     return id.common.module_idx;
214 }
215 
fwk_id_get_element_idx(fwk_id_t element_id)216 unsigned int fwk_id_get_element_idx(fwk_id_t element_id)
217 {
218     fwk_assert(
219         (element_id.common.type == __FWK_ID_TYPE_ELEMENT) ||
220         (element_id.common.type == __FWK_ID_TYPE_SUB_ELEMENT));
221 
222     return element_id.element.element_idx;
223 }
224 
fwk_id_get_sub_element_idx(fwk_id_t sub_element_id)225 unsigned int fwk_id_get_sub_element_idx(fwk_id_t sub_element_id)
226 {
227     fwk_assert(sub_element_id.common.type == __FWK_ID_TYPE_SUB_ELEMENT);
228 
229     return sub_element_id.sub_element.sub_element_idx;
230 }
231 #endif
232 
fwk_id_get_api_idx(fwk_id_t api_id)233 unsigned int fwk_id_get_api_idx(fwk_id_t api_id)
234 {
235     fwk_assert(api_id.common.type == __FWK_ID_TYPE_API);
236 
237     return api_id.api.api_idx;
238 }
239 
fwk_id_get_event_idx(fwk_id_t event_id)240 unsigned int fwk_id_get_event_idx(fwk_id_t event_id)
241 {
242     fwk_assert(event_id.common.type == __FWK_ID_TYPE_EVENT);
243 
244     return event_id.event.event_idx;
245 }
246 
fwk_id_get_notification_idx(fwk_id_t notification_id)247 unsigned int fwk_id_get_notification_idx(fwk_id_t notification_id)
248 {
249     fwk_assert(notification_id.common.type == __FWK_ID_TYPE_NOTIFICATION);
250 
251     return notification_id.notification.notification_idx;
252 }
253 
254 static_assert(sizeof(fwk_id_t) == sizeof(uint32_t),
255     "fwk_id_t has invalid size");
256