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