1 /* 2 * Arm SCP/MCP Software 3 * Copyright (c) 2015-2022, Arm Limited and Contributors. All rights reserved. 4 * 5 * SPDX-License-Identifier: BSD-3-Clause 6 * 7 * Description: 8 * Module definitions. 9 */ 10 11 #ifndef FWK_MODULE_H 12 #define FWK_MODULE_H 13 14 #include <fwk_element.h> 15 #include <fwk_event.h> 16 #include <fwk_id.h> 17 #include <fwk_io.h> 18 19 #include <stdbool.h> 20 #include <stdint.h> 21 22 /*! 23 * \addtogroup GroupLibFramework Framework 24 * \{ 25 */ 26 27 /*! 28 * \defgroup GroupModule Modules 29 * \{ 30 */ 31 32 /*! 33 * \brief Module types. 34 */ 35 enum fwk_module_type { 36 /*! Hardware Abstraction Layer */ 37 FWK_MODULE_TYPE_HAL, 38 /*! Device driver */ 39 FWK_MODULE_TYPE_DRIVER, 40 /*! Protocol */ 41 FWK_MODULE_TYPE_PROTOCOL, 42 /*! Service provider */ 43 FWK_MODULE_TYPE_SERVICE, 44 /*! The number of defined module types */ 45 FWK_MODULE_TYPE_COUNT 46 }; 47 48 /*! 49 * \brief Module or element state flags. 50 */ 51 enum fwk_module_state { 52 /*! The module or element has not yet been initialized */ 53 FWK_MODULE_STATE_UNINITIALIZED = 0, 54 55 /*! The module or element has been initialized successfully */ 56 FWK_MODULE_STATE_INITIALIZED, 57 58 /*! The module or element has bound successfully */ 59 FWK_MODULE_STATE_BOUND, 60 61 /*! The module or element has started successfully */ 62 FWK_MODULE_STATE_STARTED, 63 64 /*! The module or element is suspended */ 65 FWK_MODULE_STATE_SUSPENDED, 66 67 /*! The number of defined module or element states */ 68 FWK_MODULE_STATE_COUNT 69 }; 70 71 /*! 72 * \brief Module descriptor. 73 */ 74 struct fwk_module { 75 /*! Module type */ 76 enum fwk_module_type type; 77 78 /*! Number of APIs defined by the module */ 79 unsigned int api_count; 80 81 /*! Number of events defined by the module */ 82 unsigned int event_count; 83 84 #ifdef BUILD_HAS_NOTIFICATION 85 /*! Number of notifications defined by the module */ 86 unsigned int notification_count; 87 #endif 88 89 /*! 90 * \brief Stream adapter. 91 * 92 * \details Every module may provide an optional stream adapter, which 93 * allows it to service input/output requests to and from other modules 94 * in a fashion similar to standard file operations in the standard 95 * library. 96 * 97 * This adapter handles adapter requests to the module, its elements, 98 * and its sub-elements. 99 */ 100 struct fwk_io_adapter adapter; 101 102 /*! 103 * \brief Pointer to the module initialization function. 104 * 105 * \details This function is invoked during the initialization stage, which 106 * is the first pre-runtime stage. It is called before any module 107 * element initialization is performed. This function must not make any 108 * assumptions about the initialization state of other modules or 109 * their elements. 110 * 111 * \note This function is \b mandatory and must be implemented by all 112 * modules. 113 * 114 * \param module_id Identifier of the module being initialized. 115 * \param element_count Number of module elements. 116 * \param data Module-specific configuration data. 117 * 118 * \retval ::FWK_SUCCESS The module was initialized successfully. 119 * \retval ::FWK_E_NOMEM A memory allocation failed. 120 * \return One of the other module-defined error codes. 121 */ 122 int (*init)(fwk_id_t module_id, unsigned int element_count, 123 const void *data); 124 125 /*! 126 * \brief Pointer to the module element initialization function. 127 * 128 * \details This function is invoked once for each module element during the 129 * initialization stage. Module element initialization occurs after the 130 * call to the module initialization function and before the call to 131 * the module post-initialization function. 132 * 133 * Elements are initialized in the order they are declared in the 134 * module configuration data. The initialization function must not 135 * make any assumptions about the initialization state of other modules 136 * and their elements. 137 * 138 * \note This function is \b mandatory for modules with elements. 139 * 140 * \param element_id Identifier of the module element being initialized. 141 * \param sub_element_count Number of sub-elements. 142 * \param data Element-specific configuration data. 143 * 144 * \retval ::FWK_SUCCESS The element was initialized successfully. 145 * \retval ::FWK_E_NOMEM A memory allocation failed. 146 * \return One of the other module-defined error codes. 147 */ 148 int (*element_init)(fwk_id_t element_id, unsigned int sub_element_count, 149 const void *data); 150 151 /*! 152 * \brief Pointer to the module post-initialization function. 153 * 154 * \details This function is invoked to finalize the module initialization 155 * once the module and its elements have been successfully initialized. 156 * 157 * The framework does not mandate a particular purpose for this 158 * function. It may be used to deal with dependencies between elements, 159 * for example. 160 * 161 * \note This function is \b optional. 162 * 163 * \param module_id Identifier of the module element. 164 * 165 * \retval ::FWK_SUCCESS The module post-initialization was successful. 166 * \retval ::FWK_E_NOMEM A memory allocation failed. 167 * \return One of the other module-defined error codes. 168 */ 169 int (*post_init)(fwk_id_t module_id); 170 171 /*! 172 * \brief Pointer to the bind function. 173 * 174 * \details This function provides a place for the module and its elements 175 * to bind to other modules and/or elements. Bindings expose APIs 176 * to other modules and elements, and form the core building block of 177 * cross-module interaction. 178 * 179 * This function is called by the framework during the bind stage of 180 * the pre-runtime phase. It is called once over the module and then 181 * over all its elements in the initial binding, and a second time to 182 * allow entities with more complex binding strategies to finalize 183 * their bindings. 184 * 185 * The first round of calls may be used by a module or element to 186 * discover the entities it needs to bind to, and the second round to 187 * bind to them. 188 * 189 * \note This function is \b optional. 190 * 191 * \param id Identifier of the module or element to bind. 192 * \param round Current call round, \c 0 for the first round \c 1 for 193 * the second round. 194 * 195 * \retval ::FWK_SUCCESS The binding was successful. 196 * \retval ::FWK_E_ACCESS At least one binding request was rejected. 197 * \retval ::FWK_E_NOMEM A memory allocation failed. 198 * \return One of the other module-defined error codes. 199 */ 200 int (*bind)(fwk_id_t id, unsigned int round); 201 202 /*! 203 * \brief Pointer to the start function. 204 * 205 * \details This function is called by the framework for the module and then 206 * for all of its elements during the start stage. Elements are 207 * started in the order they are declared in the module configuration 208 * data. 209 * 210 * The framework does not mandate a particular purpose for this 211 * function. It may be used to perform any final processing of the 212 * module and its elements before entering the runtime phase. A 213 * possible example of this would be a driver module that must enable 214 * an interrupt after it has completed initialization. 215 * 216 * \note This function is \b optional. 217 * 218 * \param id Identifier of the module or element to start. 219 * 220 * \retval ::FWK_SUCCESS The module or element was successfully started. 221 * \return One of the other module-defined error codes. 222 */ 223 int (*start)(fwk_id_t id); 224 225 /*! 226 * \brief Pointer to the stop function. 227 * 228 * \details This function is called by the framework for the module and then 229 * for all of its elements during the stop stage. Elements are 230 * stopped in the order they are declared in the module configuration 231 * data. 232 * 233 * The framework does not mandate a particular purpose for this 234 * function. It may be used to perform any final processing of the 235 * module and its elements before entering the suspend phase. 236 * 237 * \note This function is \b optional and aims to release software 238 * resources or to set hardware resources in a proper state before 239 * terminating the SCP software. 240 * 241 * \param id Identifier of the module or element to start. 242 * 243 * \retval ::FWK_SUCCESS The module or element was successfully started. 244 * \return One of the other module-defined error codes. 245 */ 246 int (*stop)(fwk_id_t id); 247 248 /*! 249 * \brief Pointer to the bind request processing function. 250 * 251 * \details This function is called by the framework when it receives a 252 * request from another entity to bind to the module, or an element of 253 * the module. It can be called only during the initialization phase 254 * once 'target_id' has been initialized and during the binding phase. 255 * 256 * It allows access control, for instance, to deny certain entities 257 * access. Furthermore, in the case where the module includes different 258 * implementations of an API, it allows the module to select the 259 * implementation to provide based on the requesting entity and/or 260 * target entity. 261 * 262 * \note This function is \b optional. 263 * 264 * \param source_id Identifier of the module or element making the 265 * bind request. 266 * \param target_id Identifier of the module or element to bind to. 267 * \param api_id Identifier of the API to return. 268 * \param [out] api Pointer to the API implementation to be used by the 269 * requester. 270 * 271 * \retval ::FWK_SUCCESS The binding request was accepted by the module or 272 * element. 273 * \retval ::FWK_E_ACCESS The binding request was rejected by the module or 274 * element. 275 * \return One of the other module-defined error codes. 276 */ 277 int (*process_bind_request)(fwk_id_t source_id, fwk_id_t target_id, 278 fwk_id_t api_id, const void **api); 279 280 /*! 281 * \brief Process an event. 282 * 283 * \details This function is called by the framework for events targeting 284 * the module or one of its elements. 285 * 286 * \note This function is \b optional. If a response event is expected and 287 * the ::fwk_event::is_delayed_response flag is not set by the 288 * processing function then the response event is immediately and 289 * automatically sent to the event's source by the framework. If 290 * however the ::fwk_event::is_delayed_response flag is set by the 291 * processing function then the framework does not send the response 292 * event and it is the responsability of the event's target to send it 293 * at some point. 294 * 295 * \param event Pointer to the event to be processed. 296 * \param [out] resp_event The response event to the provided event if 297 * any. 298 * 299 * \retval ::FWK_SUCCESS The event was processed successfully. 300 * \return One of the other module-defined error codes. 301 */ 302 int (*process_event)(const struct fwk_event *event, 303 struct fwk_event *resp_event); 304 305 /*! 306 * \brief Process a notification. 307 * 308 * \details This function is called by the framework when a notification is 309 * received by a module, element, or sub-element. 310 * 311 * \note This function is \b optional. 312 * 313 * \param event Pointer to the notification event to be processed. 314 * \param [out] resp_event The response event to the provided event, if 315 * any. 316 * 317 * \retval ::FWK_SUCCESS The notification was processed successfully. 318 * \return One of the other module-defined error codes. 319 */ 320 int (*process_notification)(const struct fwk_event *event, 321 struct fwk_event *resp_event); 322 323 }; 324 325 /*! 326 * \brief Define a static element table with the content of the table. 327 * 328 * \param[in] ... An array of elements in the form `{ X, Y, Z, { 0 } }`. 329 * 330 * \see ::fwk_module_elements::table 331 */ 332 #define FWK_MODULE_STATIC_ELEMENTS(...) \ 333 { \ 334 .type = FWK_MODULE_ELEMENTS_TYPE_STATIC, \ 335 .table = (const struct fwk_element[])__VA_ARGS__, \ 336 } 337 338 /*! 339 * \brief Define a static element table with a pointer to the table. 340 * 341 * \details Some element tables require extra preprocessing beforehand. As it is 342 * undefined behaviour for preprocessing macros to occur within macro 343 * argument lists, this macro has been provided to work around this 344 * language restriction. 345 * 346 * \param[in] TABLE Pointer to the static element table. 347 * 348 * \see ::fwk_module_elements::table 349 */ 350 #define FWK_MODULE_STATIC_ELEMENTS_PTR(TABLE) \ 351 { \ 352 .type = FWK_MODULE_ELEMENTS_TYPE_STATIC, \ 353 .table = TABLE, \ 354 } 355 356 /*! 357 * \brief Define a dynamic element table. 358 * 359 * \details Element table generators are functions that take a module identifier 360 * and return an element table. They will be called once the module has 361 * begun initialization, and may allocate a variable number of elements. 362 * 363 * \param[in] GENERATOR Function to generate the element table. 364 * 365 * \see ::fwk_module_elements::generator 366 */ 367 #define FWK_MODULE_DYNAMIC_ELEMENTS(GENERATOR) \ 368 { \ 369 .type = FWK_MODULE_ELEMENTS_TYPE_DYNAMIC, \ 370 .generator = (GENERATOR), \ 371 } 372 373 /*! 374 * \brief Element table type. 375 */ 376 enum fwk_module_elements_type { 377 FWK_MODULE_ELEMENTS_TYPE_NONE, /*!< No element table. */ 378 FWK_MODULE_ELEMENTS_TYPE_STATIC, /*<! Static element table. */ 379 FWK_MODULE_ELEMENTS_TYPE_DYNAMIC, /*<! Dynamic element table. */ 380 }; 381 382 /*! 383 * \brief Element table. 384 */ 385 struct fwk_module_elements { 386 /*! 387 * \brief Element table type. 388 * 389 * \details Elements may be statically defined, or they can be generated 390 * once the module comes online. 391 */ 392 enum fwk_module_elements_type type; 393 394 /*! 395 * \brief Element table data. 396 */ 397 union { 398 /*! 399 * \brief Pointer to the function to get the table of element 400 * descriptions. 401 * 402 * \param[in] module_id Identifier of the module. 403 * 404 * \details The table of module element descriptions ends with an 405 * invalid element description where the pointer to the element 406 * name is equal to `NULL`. 407 * 408 * \warning The framework does not copy the element description data 409 * and keep a pointer to the ones returned by this function. 410 * Pointers returned by this function must thus points to data 411 * with static storage or data stored in memory allocated from 412 * the memory management component. 413 * 414 * \return Pointer to table of element descriptions. 415 */ 416 const struct fwk_element *(*generator)(fwk_id_t module_id); 417 418 /*! 419 * \brief Table of element descriptions. 420 * 421 * \details The table of module element descriptions ends with an 422 * invalid element description where the pointer to the element 423 * name is equal to `NULL`. 424 */ 425 const struct fwk_element *table; 426 }; 427 }; 428 429 /*! 430 * \brief Module configuration. 431 */ 432 struct fwk_module_config { 433 /*! Pointer to the module-specific configuration data */ 434 const void *data; 435 436 /*! Element table */ 437 struct fwk_module_elements elements; 438 }; 439 440 /*! 441 * \brief Check if an identifier refers to a valid module. 442 * 443 * \param id Identifier to be checked. 444 * 445 * \retval true The identifier refers to a valid module. 446 * \retval false The identifier does not refer to a valid module. 447 */ 448 bool fwk_module_is_valid_module_id(fwk_id_t id); 449 450 /*! 451 * \brief Check if an identifier refers to a valid element. 452 * 453 * \param id Identifier to be checked. 454 * 455 * \retval true The identifier refers to a valid element. 456 * \retval false The identifier does not refer to a valid element. 457 */ 458 bool fwk_module_is_valid_element_id(fwk_id_t id); 459 460 /*! 461 * \brief Check if an identifier refers to a valid sub-element. 462 * 463 * \param id Identifier to be checked. 464 * 465 * \retval true The identifier refers to a valid sub-element. 466 * \retval false The identifier does not refer to a valid sub-element. 467 */ 468 bool fwk_module_is_valid_sub_element_id(fwk_id_t id); 469 470 /*! 471 * \brief Check if an identifier refers to a valid module, element or 472 * sub-element. 473 * 474 * \param id Identifier to be checked. 475 * 476 * \retval true The identifier refers to a valid module, element or 477 * sub-element. 478 * \retval false The identifier does not refer to a valid module, element or 479 * sub-element. 480 */ 481 bool fwk_module_is_valid_entity_id(fwk_id_t id); 482 483 /*! 484 * \brief Check if an identifier refers to a valid API. 485 * 486 * \param id Identifier to be checked. 487 * 488 * \retval true The identifier refers to a valid API. 489 * \retval false The identifier does not refer to a valid API. 490 */ 491 bool fwk_module_is_valid_api_id(fwk_id_t id); 492 493 /*! 494 * \brief Check if an identifier refers to a valid event. 495 * 496 * \param id Identifier to be checked. 497 * 498 * \retval true The identifier refers to a valid event. 499 * \retval false The identifier does not refer to a valid event. 500 */ 501 bool fwk_module_is_valid_event_id(fwk_id_t id); 502 503 /*! 504 * \brief Check if an identifier refers to a valid notification. 505 * 506 * \param id Identifier to be checked. 507 * 508 * \retval true The identifier refers to a valid notification. 509 * \retval false The identifier does not refer to a valid notification. 510 */ 511 bool fwk_module_is_valid_notification_id(fwk_id_t id); 512 513 /*! 514 * \brief Get the number of elements within a module. 515 * 516 * \param module_id Identifier of the module. 517 * 518 * \retval ::FWK_E_PARAM The identifier of the module is invalid. 519 * \return Number of module elements. 520 */ 521 int fwk_module_get_element_count(fwk_id_t module_id); 522 523 /*! 524 * \brief Get the number of sub-elements within an element. 525 * 526 * \param element_id Identifier of the element. 527 * 528 * \retval ::FWK_E_PARAM The identifier of the element is invalid. 529 * \return Number of sub-elements. 530 */ 531 int fwk_module_get_sub_element_count(fwk_id_t element_id); 532 533 /*! 534 * \brief Get the name of a element. 535 * 536 * \param id Identifier of the element. 537 * 538 * \return The pointer to the element name, NULL if the identifier is 539 * not valid. 540 */ 541 const char *fwk_module_get_element_name(fwk_id_t id); 542 543 /*! 544 * \brief Get the configuration data of a module or element. 545 * 546 * \param id Identifier of the module or element. 547 * 548 * \return The pointer to the module/element-specific configuration data, NULL 549 * if the identifier is not valid. 550 */ 551 const void *fwk_module_get_data(fwk_id_t id); 552 553 /*! 554 * \brief Bind to an API of a module or an element. 555 * 556 * \details The framework will accept the bind request in one of the two 557 * following cases: 558 * 1) The execution is at the pre-runtime initialization stage and the 559 * entity 'target_id' has already been initialized. 560 * 2) The execution is at the pre-runtime binding stage. 561 * 562 * \param target_id Identifier of the module or element to bind to. 563 * \param api_id Identifier of the API to return an implementation of. 564 * \param api [out] Pointer to storage for the pointer to the API. 565 * 566 * \retval ::FWK_SUCCESS The API was returned. 567 * \retval ::FWK_E_PARAM A least one of the identifiers is invalid. 568 * \retval ::FWK_E_STATE Call outside of the pre-runtime bind stage. 569 * \retval ::FWK_E_ACCESS The access to the API was refused. 570 * \retval ::FWK_E_HANDLER The returned API pointer is invalid (NULL). 571 */ 572 int fwk_module_bind(fwk_id_t target_id, fwk_id_t api_id, const void *api); 573 574 /*! 575 * \brief Get the [stream adapter](::fwk_module::adapter) of a module. 576 * 577 * \details Stream adapters are owned by the module, rather than its elements or 578 * sub-elements, but element and sub-element identifiers may also be 579 * provided to this function to get the adapter of the parent module. 580 * 581 * \param[out] adapter Pointer to the stream adapter belonging to the entity, or 582 * a null pointer value if the module has no registered adapter. 583 * \param[in] id Identifier of an entity. 584 * 585 * \return Status code representing the result of the operation. 586 * 587 * \retval ::FWK_SUCCESS The operation succeeded. 588 * \retval ::FWK_E_PARAM An invalid parameter was encountered: 589 * - The `adapter` parameter was a null pointer value. 590 * - The `id` parameter did not resolve to a valid entity. 591 */ 592 int fwk_module_adapter(const struct fwk_io_adapter **adapter, fwk_id_t id); 593 594 /*! 595 * \internal 596 * 597 * \brief Initialize the module component. 598 * 599 * \details Initializes the module framework component contexts, allowing 600 * module details to be accessed through the module interfaces. This does 601 * not start any modules. 602 */ 603 void fwk_module_init(void); 604 605 /*! 606 * \} 607 */ 608 609 /*! 610 * \} 611 */ 612 613 #endif /* FWK_MODULE_H */ 614