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 #ifndef FWK_ID_H
12 #define FWK_ID_H
13
14 #include <internal/fwk_id.h>
15
16 #include <fwk_attributes.h>
17 #include <fwk_status.h>
18
19 #include <stdbool.h>
20 #include <stdint.h>
21
22 /*!
23 * \addtogroup GroupLibFramework Framework
24 * \{
25 */
26
27 /*!
28 * \defgroup GroupId Identifiers
29 * \{
30 */
31
32 /*!
33 * \brief Identifier type.
34 */
35 enum fwk_id_type {
36 /*! None */
37 FWK_ID_TYPE_NONE = __FWK_ID_TYPE_NONE,
38 /*! Module */
39 FWK_ID_TYPE_MODULE = __FWK_ID_TYPE_MODULE,
40 /*! Element */
41 FWK_ID_TYPE_ELEMENT = __FWK_ID_TYPE_ELEMENT,
42 /*! Sub-element */
43 FWK_ID_TYPE_SUB_ELEMENT = __FWK_ID_TYPE_SUB_ELEMENT,
44 /*! API */
45 FWK_ID_TYPE_API = __FWK_ID_TYPE_API,
46 /*! Event */
47 FWK_ID_TYPE_EVENT = __FWK_ID_TYPE_EVENT,
48 /*! Notification */
49 FWK_ID_TYPE_NOTIFICATION = __FWK_ID_TYPE_NOTIFICATION,
50 };
51
52 /*!
53 * \brief Build a 'none' identifier.
54 *
55 * \note This macro expands to a designated initializer, and can be used to
56 * initialize a ::fwk_id_t.
57 *
58 * \details Build an id that explicitly refers to nothing.
59 *
60 * Example usage:
61 * \code{.c}
62 * static const fwk_id_t unknown = FWK_ID_NONE_INIT;
63 * \endcode
64 *
65 * \return invalid identifier.
66 */
67 #define FWK_ID_NONE_INIT \
68 { \
69 .common = { \
70 .type = (uint32_t)__FWK_ID_TYPE_NONE, \
71 }, \
72 }
73
74 /*!
75 * \brief Build a 'none' identifier.
76 *
77 * \note This macro expands to a compound literal, and can be used as an lvalue
78 * expression returning type ::fwk_id_t.
79 *
80 * \details Build an id that explicitly refers to nothing.
81 *
82 * Example usage:
83 * \code{.c}
84 * fwk_id_t get_id(void)
85 * {
86 * if (...)
87 * return FWK_ID_NONE;
88 * }
89 * \endcode
90 *
91 * \return invalid identifier.
92 */
93 #define FWK_ID_NONE ((fwk_id_t)FWK_ID_NONE_INIT)
94
95 /*!
96 * \brief Build a module identifier from a module index.
97 *
98 * \note This macro expands to a designated initializer, and can be used to
99 * initialize a ::fwk_id_t.
100 *
101 * \details Example usage:
102 * \code{.c}
103 * static const fwk_id_t my_module = FWK_ID_MODULE_INIT(42);
104 * \endcode
105 *
106 * \param MODULE_IDX Module index.
107 *
108 * \return Module identifier.
109 */
110 #define FWK_ID_MODULE_INIT(MODULE_IDX) \
111 { \
112 .common = { \
113 .type = (uint32_t)__FWK_ID_TYPE_MODULE, \
114 .module_idx = (uint32_t)MODULE_IDX, \
115 }, \
116 }
117
118 /*!
119 * \brief Build a module identifier from a module index.
120 *
121 * \note This macro expands to a compound literal, and can be used as an lvalue
122 * expression returning type ::fwk_id_t.
123 *
124 * \details Example usage:
125 * \code{.c}
126 * fwk_id_t get_module_42(void)
127 * {
128 * return FWK_ID_MODULE(42);
129 * }
130 * \endcode
131 *
132 * \param MODULE_IDX Module index.
133 *
134 * \return Module identifier.
135 */
136 #define FWK_ID_MODULE(MODULE_IDX) ((fwk_id_t)FWK_ID_MODULE_INIT(MODULE_IDX))
137
138 /*!
139 * \brief Build an element identifier from a module index and an element index.
140 *
141 * \note This macro expands to a designated initializer, and can be used to
142 * initialize a ::fwk_id_t.
143 *
144 * \details Example usage:
145 * \code{.c}
146 * static const fwk_id_t my_element = FWK_ID_ELEMENT_INIT(42, 58);
147 * \endcode
148 *
149 * \param MODULE_IDX Module index.
150 * \param ELEMENT_IDX Element index.
151 *
152 * \return Element identifier.
153 */
154 #define FWK_ID_ELEMENT_INIT(MODULE_IDX, ELEMENT_IDX) \
155 { \
156 .element = { \
157 .type = (uint32_t)__FWK_ID_TYPE_ELEMENT, \
158 .module_idx = (uint32_t)MODULE_IDX, \
159 .element_idx = (uint32_t)ELEMENT_IDX, \
160 }, \
161 }
162
163 /*!
164 * \brief Build an element identifier from a module index and an element index.
165 *
166 * \note This macro expands to a compound literal, and can be used as an lvalue
167 * expression returning type ::fwk_id_t.
168 *
169 * \details Example usage:
170 * \code{.c}
171 * fwk_id_t get_element_42_58(void)
172 * {
173 * return FWK_ID_ELEMENT(42, 58);
174 * }
175 * \endcode
176 *
177 * \param MODULE_IDX Module index.
178 * \param ELEMENT_IDX Element index.
179 *
180 * \return Element identifier.
181 */
182 #define FWK_ID_ELEMENT(MODULE_IDX, ELEMENT_IDX) \
183 ((fwk_id_t)FWK_ID_ELEMENT_INIT(MODULE_IDX, ELEMENT_IDX))
184
185 /*!
186 * \brief Build a sub-element identifier from a module index, an element index
187 * and a sub-element index.
188 *
189 * \note This macro expands to a designated initializer, and can be used to
190 * initialize a ::fwk_id_t.
191 *
192 * \details Example usage:
193 * \code{.c}
194 * static const fwk_id_t my_sub_element =
195 FWK_ID_SUB_ELEMENT_INIT(42, 58, 1);
196 * \endcode
197 *
198 * \param MODULE_IDX Module index.
199 * \param ELEMENT_IDX Element index.
200 * \param SUB_ELEMENT_IDX Sub-element index.
201 *
202 * \return Sub-element identifier.
203 */
204 #define FWK_ID_SUB_ELEMENT_INIT(MODULE_IDX, ELEMENT_IDX, SUB_ELEMENT_IDX) \
205 { \
206 .sub_element = { \
207 .type = (uint32_t)__FWK_ID_TYPE_SUB_ELEMENT, \
208 .module_idx = (uint32_t)MODULE_IDX, \
209 .element_idx = (uint32_t)ELEMENT_IDX, \
210 .sub_element_idx = (uint32_t)SUB_ELEMENT_IDX, \
211 }, \
212 }
213
214 /*!
215 * \brief Build an sub-element identifier from a module index, an element index
216 * and a sub-element index.
217 *
218 * \note This macro expands to a compound literal, and can be used as an lvalue
219 * expression returning type ::fwk_id_t.
220 *
221 * \details Example usage:
222 * \code{.c}
223 * fwk_id_t get_sub_element_42_58_1(void)
224 * {
225 * return FWK_ID_SUB_ELEMENT(42, 58, 1);
226 * }
227 * \endcode
228 *
229 * \param MODULE_IDX Module index.
230 * \param ELEMENT_IDX Element index.
231 * \param SUB_ELEMENT_IDX Sub-element index.
232 *
233 * \return Sub-element identifier.
234 */
235 #define FWK_ID_SUB_ELEMENT(MODULE_IDX, ELEMENT_IDX, SUB_ELEMENT_IDX) \
236 ((fwk_id_t)FWK_ID_SUB_ELEMENT_INIT( \
237 MODULE_IDX, ELEMENT_IDX, SUB_ELEMENT_IDX))
238
239 /*!
240 * \brief Build an API identifier from a module index and an API index.
241 *
242 * \note This macro expands to a designated initializer, and can be used to
243 * initialize a ::fwk_id_t.
244 *
245 * \details Example usage:
246 * \code{.c}
247 * static const fwk_id_t my_api = FWK_ID_API_INIT(42, 14);
248 * \endcode
249 *
250 * \param MODULE_IDX Module index.
251 * \param API_IDX API index.
252 *
253 * \return API identifier.
254 */
255 #define FWK_ID_API_INIT(MODULE_IDX, API_IDX) \
256 { \
257 .api = { \
258 .type = (uint32_t)__FWK_ID_TYPE_API, \
259 .module_idx = (uint32_t)MODULE_IDX, \
260 .api_idx = (uint32_t)API_IDX, \
261 }, \
262 }
263
264 /*!
265 * \brief Build an API identifier from a module index and an API index.
266 *
267 * \note This macro expands to a compound literal, and can be used as an lvalue
268 * expression returning type ::fwk_id_t.
269 *
270 * \details Example usage:
271 * \code{.c}
272 * fwk_id_t get_api_42_14(void)
273 * {
274 * return FWK_ID_API(42, 14);
275 * }
276 * \endcode
277 *
278 * \param MODULE_IDX Module index.
279 * \param API_IDX API index.
280 *
281 * \return API identifier.
282 */
283 #define FWK_ID_API(MODULE_IDX, API_IDX) \
284 ((fwk_id_t)FWK_ID_API_INIT(MODULE_IDX, API_IDX))
285
286 /*!
287 * \brief Build an event identifier from a module index and an event index.
288 *
289 * \note This macro expands to a designated initializer, and can be used to
290 * initialize a ::fwk_id_t.
291 *
292 * \details Example usage:
293 * \code{.c}
294 * static const fwk_id_t my_event = FWK_ID_EVENT_INIT(42, 56);
295 * \endcode
296 *
297 * \param MODULE_IDX Module index.
298 * \param EVENT_IDX Event index.
299 *
300 * \return Event identifier.
301 */
302 #define FWK_ID_EVENT_INIT(MODULE_IDX, EVENT_IDX) \
303 { \
304 .event = { \
305 .type = (uint32_t)__FWK_ID_TYPE_EVENT, \
306 .module_idx = (uint32_t)MODULE_IDX, \
307 .event_idx = (uint32_t)EVENT_IDX, \
308 }, \
309 }
310
311 /*!
312 * \brief Build an event identifier from a module index and an event index.
313 *
314 * \note This macro expands to a compound literal, and can be used as an lvalue
315 * expression returning type ::fwk_id_t.
316 *
317 * \details Example usage:
318 * \code{.c}
319 * fwk_id_t get_event_42_56(void)
320 * {
321 * return FWK_ID_EVENT(42, 56);
322 * }
323 * \endcode
324 *
325 * \param MODULE_IDX Module index.
326 * \param EVENT_IDX Event index.
327 *
328 * \return Event identifier.
329 */
330 #define FWK_ID_EVENT(MODULE_IDX, EVENT_IDX) \
331 ((fwk_id_t)FWK_ID_EVENT_INIT(MODULE_IDX, EVENT_IDX))
332
333 /*!
334 * \brief Build a notification identifier from a module index and a
335 * notification index.
336 *
337 * \note This macro expands to a designated initializer, and can be used to
338 * initialize a ::fwk_id_t.
339 *
340 * \details Example usage:
341 * \code{.c}
342 * static const fwk_id_t my_notification =
343 FWK_ID_NOTIFICATION_INIT(42, 56);
344 * \endcode
345 *
346 * \param MODULE_IDX Module index.
347 * \param NOTIFICATION_IDX Notification index.
348 *
349 * \return Notification identifier.
350 */
351 #define FWK_ID_NOTIFICATION_INIT(MODULE_IDX, NOTIFICATION_IDX) \
352 { \
353 .notification = { \
354 .type = (uint32_t)__FWK_ID_TYPE_NOTIFICATION, \
355 .module_idx = (uint32_t)MODULE_IDX, \
356 .notification_idx = (uint32_t)NOTIFICATION_IDX, \
357 }, \
358 }
359
360 /*!
361 * \brief Build an notification identifier from a module index and a
362 * notification index.
363 *
364 * \note This macro expands to a compound literal, and can be used as an lvalue
365 * expression returning type ::fwk_id_t.
366 *
367 * \details Example usage:
368 * \code{.c}
369 * fwk_id_t get_notification_42_56(void)
370 * {
371 * return FWK_ID_NOTIFICATION(42, 56);
372 * }
373 * \endcode
374 *
375 * \param MODULE_IDX Module index.
376 * \param NOTIFICATION_IDX Notification index.
377 *
378 * \return Notification identifier.
379 */
380 #define FWK_ID_NOTIFICATION(MODULE_IDX, NOTIFICATION_IDX) \
381 ((fwk_id_t)FWK_ID_NOTIFICATION_INIT(MODULE_IDX, NOTIFICATION_IDX))
382
383 /*!
384 * \brief Build a string representation of an identifier.
385 *
386 * \details Strings returned by this macro are in the format <tt>[MMM]</tt> for
387 * module identifiers and <tt>[MMM:EEEE]</tt> for element identifiers,
388 * where \c M refers to the module index and \c E refers to the element
389 * index.
390 *
391 * \param ID Module or element identifier.
392 *
393 * \return String representation of the identifier.
394 *
395 * \hideinitializer
396 */
397 #define FWK_ID_STR(ID) (__fwk_id_str(ID).str)
398
399 /*!
400 * \brief Generic identifier.
401 */
402 typedef union __fwk_id fwk_id_t;
403
404 /*!
405 * \brief Generic optional identifier.
406 *
407 * \details Optionals identifiers are fwk_id_t elements which can be left
408 * undefined. This are only intended to be used for configuration
409 * proposes and should not be used to bypass fwk_id_t checks.
410 */
411 typedef fwk_id_t fwk_optional_id_t;
412
413 /*!
414 * \brief Check if the identifier type is valid.
415 *
416 * \param id Identifier.
417 *
418 * \retval true The identifier type is valid.
419 * \retval false The identifier type is not valid.
420 */
421 bool fwk_id_type_is_valid(fwk_id_t id) FWK_CONST FWK_LEAF FWK_NOTHROW;
422
423 /*!
424 * \brief Check if the identifier is of a certain identifier type.
425 *
426 * \param id Identifier.
427 * \param type Identifier type.
428 *
429 * \retval true The identifier is of the type specified.
430 * \retval false The identifier is not of the type specified.
431 */
432 bool fwk_id_is_type(fwk_id_t id, enum fwk_id_type type) FWK_CONST FWK_LEAF
433 FWK_NOTHROW;
434
435 /*!
436 * \brief Retrieve the type of an identifier.
437 *
438 * \param id Identifier.
439 *
440 * \return Identifier type.
441 */
442 enum fwk_id_type fwk_id_get_type(fwk_id_t id) FWK_CONST FWK_LEAF FWK_NOTHROW;
443
444 /*!
445 * \brief Check if two identifiers refer to the same entity.
446 *
447 * \param left First identifier.
448 * \param right Second identifier.
449 *
450 * \retval true The identifiers refer to the same entity.
451 * \retval false The identifiers do not refer to the same entity.
452 */
453 bool fwk_id_is_equal(fwk_id_t left, fwk_id_t right) FWK_CONST FWK_LEAF
454 FWK_NOTHROW;
455
456 /*!
457 * \brief Check if an optional identifier is defined.
458 *
459 * \param id Optional identifier.
460 *
461 * \retval true The optional identifiers is defined.
462 * \retval false The optional identifiers is not defined.
463 */
464 bool fwk_optional_id_is_defined(fwk_optional_id_t id) FWK_CONST FWK_LEAF
465 FWK_NOTHROW;
466
467 /*!
468 * \brief Retrieve the identifier of the module that owns a given identifier.
469 *
470 * \note If the given identifier already refers to a module, the returned
471 * identifier refers to that same module.
472 *
473 * \param id Identifier.
474 *
475 * \return Identifier of the owning module.
476 */
477 fwk_id_t fwk_id_build_module_id(fwk_id_t id) FWK_CONST FWK_LEAF FWK_NOTHROW;
478
479 /*!
480 * \brief Retrieve the identifier of an element for a given identifier and
481 * element index.
482 *
483 * \details Usually the given identifier will be a module identifier and the
484 * function will be used to build an element identifier for an element with
485 * the given index that is owned by that module.
486 *
487 * \note If the identifier provided refers to an element, sub-element, API,
488 * event, or notification instead of a module then the parent module of
489 * the identifier is used when building the returned element identifier.
490 *
491 * \param id Identifier.
492 * \param element_idx Element index.
493 *
494 * \return Element identifier associated with the element index for the module.
495 */
496 fwk_id_t fwk_id_build_element_id(fwk_id_t id, unsigned int element_idx)
497 FWK_CONST FWK_LEAF FWK_NOTHROW;
498
499 /*!
500 * \brief Retrieve the identifier of a sub-element for a given element
501 * identifier and sub-element index.
502 *
503 * \details The given identifier must be an element identifier and the
504 * function will be used to build an sub-element identifier for a
505 * sub-element with the given index that is owned by that element.
506 *
507 * \param id Identifier.
508 * \param sub_element_idx Sub-element index.
509 *
510 * \return Sub-element identifier associated with the sub-element index for the
511 * element.
512 */
513 fwk_id_t fwk_id_build_sub_element_id(fwk_id_t id, unsigned int sub_element_idx)
514 FWK_CONST FWK_LEAF FWK_NOTHROW;
515
516 /*!
517 * \brief Retrieve the identifier of an API for a given identifier and
518 * API index.
519 *
520 * \details Usually the given identifier will be a module identifier and the
521 * function will be used to build an API identifier for an API with the
522 * given index that is owned by that module.
523 *
524 * \note If the identifier provided refers to an element, sub-element, API,
525 * event, or notification instead of a module then the parent module of
526 * the identifier is used when building the returned API identifier.
527 *
528 * \param id Identifier.
529 * \param api_idx API index.
530 *
531 * \return API identifier associated with the API index for the module.
532 */
533 fwk_id_t fwk_id_build_api_id(fwk_id_t id, unsigned int api_idx)
534 FWK_CONST FWK_LEAF FWK_NOTHROW;
535
536 /*!
537 * \brief Retrieve the module index of an identifier.
538 *
539 * \param id Identifier.
540 *
541 * \return Module index.
542 *
543 * \note Since this function is used very frequently, inlining is useful
544 * to avoid function call overhead. The inlining is applicable only in
545 * release build.
546 */
547 #if !defined(NDEBUG)
548 unsigned int fwk_id_get_module_idx(fwk_id_t id) FWK_CONST FWK_LEAF FWK_NOTHROW;
549 #else
fwk_id_get_module_idx(fwk_id_t id)550 inline static unsigned int fwk_id_get_module_idx(fwk_id_t id)
551 {
552 return id.common.module_idx;
553 }
554 #endif
555
556 /*!
557 * \brief Retrieve the index of an element from its identifier or the identifier
558 * of one of its sub-element.
559 *
560 * \param element_id Element or sub-element identifier.
561 *
562 * \return Element index.
563 *
564 * \note Since this function is used very frequently, inlining is useful
565 * to avoid function call overhead. The inlining is applicable only in
566 * release build.
567 */
568 #if !defined(NDEBUG)
569 unsigned int fwk_id_get_element_idx(fwk_id_t element_id) FWK_CONST FWK_LEAF
570 FWK_NOTHROW;
571 #else
fwk_id_get_element_idx(fwk_id_t element_id)572 inline static unsigned int fwk_id_get_element_idx(fwk_id_t element_id)
573 {
574 return element_id.element.element_idx;
575 }
576 #endif
577
578 /*!
579 * \brief Retrieve the index of a sub-element from its identifier.
580 *
581 * \param sub_element_id Sub-element identifier.
582 *
583 * \return Sub-element index.
584 *
585 * \note Since this function is used very frequently, inlining is useful
586 * to avoid function call overhead. The inlining is applicable only in
587 * release build.
588 */
589 #if !defined(NDEBUG)
590 unsigned int fwk_id_get_sub_element_idx(
591 fwk_id_t sub_element_id) FWK_CONST FWK_LEAF FWK_NOTHROW;
592 #else
fwk_id_get_sub_element_idx(fwk_id_t sub_element_id)593 inline static unsigned int fwk_id_get_sub_element_idx(fwk_id_t sub_element_id)
594 {
595 return sub_element_id.sub_element.sub_element_idx;
596 }
597 #endif
598
599 /*!
600 * \brief Retrieve the index of an API from its identifier.
601 *
602 * \param api_id API identifier.
603 *
604 * \return API index.
605 */
606 unsigned int fwk_id_get_api_idx(fwk_id_t api_id) FWK_CONST FWK_LEAF FWK_NOTHROW;
607
608 /*!
609 * \brief Retrieve the index of an event from its identifier.
610 *
611 * \param event_id Event identifier.
612 *
613 * \return Event index.
614 */
615 unsigned int fwk_id_get_event_idx(fwk_id_t event_id) FWK_CONST FWK_LEAF
616 FWK_NOTHROW;
617
618 /*!
619 * \brief Retrieve the index of a notification from its identifier.
620 *
621 * \param notification_id Notification identifier.
622 *
623 * \return Notification index.
624 */
625 unsigned int fwk_id_get_notification_idx(
626 fwk_id_t notification_id) FWK_CONST FWK_LEAF FWK_NOTHROW;
627
628 /*!
629 * \internal
630 *
631 * \brief Verbose identifier string helper structure.
632 *
633 * \details C does not support returning an array from a function. This
634 * structure hides the array within a structure, and instead the structure
635 * is returned to the caller. This allows them to access the array without
636 * it decaying to a pointer when returned.
637 */
638 struct fwk_id_verbose_fmt {
639 char str[128]; /*!< Identifier string representation. */
640 };
641
642 /*!
643 * \internal
644 *
645 * \brief Generate a verbose string description of an identifier.
646 *
647 * \details Generates a string description of an identifier, including the names
648 * of any entities that form part of the identifier.
649 *
650 * \param[in] id Identifier to describe.
651 *
652 * \return Verbose string representation of the identifier.
653 */
654 struct fwk_id_verbose_fmt fwk_id_verbose_str(fwk_id_t id);
655
656 /*!
657 * \}
658 */
659
660 /*!
661 * \}
662 */
663
664 #endif /* FWK_ID_H */
665