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 facilities.
9  */
10 
11 #include <internal/fwk_core.h>
12 #include <internal/fwk_id.h>
13 #include <internal/fwk_module.h>
14 
15 #include <fwk_assert.h>
16 #include <fwk_cli_dbg.h>
17 #include <fwk_dlist.h>
18 #include <fwk_list.h>
19 #include <fwk_log.h>
20 #include <fwk_mm.h>
21 #include <fwk_module.h>
22 #include <fwk_module_idx.h>
23 #include <fwk_status.h>
24 
25 #include <stdbool.h>
26 
27 #if FMW_NOTIFICATION_MAX > 64
28 #    define FWK_MODULE_EVENT_COUNT FMW_NOTIFICATION_MAX
29 #else
30 #    define FWK_MODULE_EVENT_COUNT 64
31 #endif
32 
33 #define FWK_MODULE_BIND_ROUND_MAX 1
34 
35 /* Pre-runtime phase stages */
36 enum fwk_module_stage {
37     MODULE_STAGE_INITIALIZE,
38     MODULE_STAGE_BIND,
39     MODULE_STAGE_START,
40     MODULE_STAGE_STOP
41 };
42 
43 static struct {
44     /* Flag indicating whether all modules have been initialized */
45     bool initialized;
46 
47     /* Table of module contexts */
48     struct fwk_module_context module_ctx_table[FWK_MODULE_IDX_COUNT];
49 
50     /* Pre-runtime phase stage */
51     enum fwk_module_stage stage;
52 
53     /*
54      * Identifier of module or element currently binding to other modules or
55      * elements as part as of the binding stage.
56      */
57     fwk_id_t bind_id;
58 } fwk_module_ctx;
59 
60 extern const struct fwk_module *module_table[FWK_MODULE_IDX_COUNT];
61 extern const struct fwk_module_config
62     *module_config_table[FWK_MODULE_IDX_COUNT];
63 
64 static const char fwk_module_err_msg_line[] = "[MOD] Error %d in %s @%d";
65 static const char fwk_module_err_msg_func[] = "[MOD] Error %d in %s";
66 
fwk_module_count_elements(const struct fwk_element * elements)67 static size_t fwk_module_count_elements(const struct fwk_element *elements)
68 {
69     size_t count = 0;
70 
71     for (; elements[count].name != NULL; count++) {
72         continue;
73     }
74 
75     return count;
76 }
77 
78 #ifdef BUILD_HAS_NOTIFICATION
fwk_module_init_subscriptions(struct fwk_dlist ** list,size_t count)79 static void fwk_module_init_subscriptions(struct fwk_dlist **list, size_t count)
80 {
81     *list = fwk_mm_calloc(count, sizeof((*list)[0]));
82     if (*list == NULL) {
83         fwk_trap();
84     }
85 
86     for (size_t i = 0; i < count; i++) {
87         fwk_list_init(&((*list)[i]));
88     }
89 }
90 #endif
91 
fwk_module_init_element_ctx(struct fwk_element_ctx * ctx,const struct fwk_element * element,size_t notification_count)92 static void fwk_module_init_element_ctx(
93     struct fwk_element_ctx *ctx,
94     const struct fwk_element *element,
95     size_t notification_count)
96 {
97     *ctx = (struct fwk_element_ctx){
98         .state = FWK_MODULE_STATE_UNINITIALIZED,
99         .desc = element,
100         .sub_element_count = element->sub_element_count,
101     };
102 
103     fwk_list_init(&ctx->delayed_response_list);
104 
105 #ifdef BUILD_HAS_NOTIFICATION
106     if (notification_count > 0) {
107         fwk_module_init_subscriptions(
108             &ctx->subscription_dlist_table, notification_count);
109     }
110 #endif
111 }
112 
fwk_module_init_element_ctxs(struct fwk_module_context * ctx,const struct fwk_element * elements,size_t notification_count)113 static void fwk_module_init_element_ctxs(
114     struct fwk_module_context *ctx,
115     const struct fwk_element *elements,
116     size_t notification_count)
117 {
118     ctx->element_count = fwk_module_count_elements(elements);
119 
120     ctx->element_ctx_table =
121         fwk_mm_calloc(ctx->element_count, sizeof(ctx->element_ctx_table[0]));
122     if (ctx->element_ctx_table == NULL) {
123         fwk_trap();
124     }
125 
126     for (size_t i = 0; i < ctx->element_count; i++) {
127         fwk_module_init_element_ctx(
128             &ctx->element_ctx_table[i], &elements[i], notification_count);
129     }
130 }
131 
fwk_module_init(void)132 void fwk_module_init(void)
133 {
134     /*
135      * The loop index i gets the values corresponding to the
136      * enum fwk_module_idx
137      */
138     for (uint32_t i = 0U; i < (uint32_t)FWK_MODULE_IDX_COUNT; i++) {
139         struct fwk_module_context *ctx = &fwk_module_ctx.module_ctx_table[i];
140 
141         fwk_id_t id = FWK_ID_MODULE(i);
142 
143         const struct fwk_module *desc = module_table[i];
144         const struct fwk_module_config *config = module_config_table[i];
145 
146         *ctx = (struct fwk_module_context){
147             .id = id,
148 
149             .desc = desc,
150             .config = config,
151         };
152 
153         fwk_assert(ctx->desc != NULL);
154         fwk_assert(ctx->config != NULL);
155 
156         fwk_list_init(&ctx->delayed_response_list);
157 
158         if (config->elements.type == FWK_MODULE_ELEMENTS_TYPE_STATIC) {
159             size_t notification_count = 0;
160 
161 #ifdef BUILD_HAS_NOTIFICATION
162             notification_count = desc->notification_count;
163 #endif
164 
165             fwk_module_init_element_ctxs(
166                 ctx, config->elements.table, notification_count);
167         }
168 
169 #ifdef BUILD_HAS_NOTIFICATION
170         if (desc->notification_count > 0) {
171             fwk_module_init_subscriptions(
172                 &ctx->subscription_dlist_table, desc->notification_count);
173         }
174 #endif
175     }
176 }
177 
fwk_module_init_elements(struct fwk_module_context * ctx)178 static void fwk_module_init_elements(struct fwk_module_context *ctx)
179 {
180     int status;
181 
182     const struct fwk_module *desc = ctx->desc;
183 
184     if (desc->element_init == NULL) {
185         fwk_trap();
186     }
187 
188     for (size_t i = 0; i < ctx->element_count; i++) {
189         fwk_id_t element_id = fwk_id_build_element_id(ctx->id, (unsigned int)i);
190 
191         const struct fwk_element *element = ctx->element_ctx_table[i].desc;
192 
193         fwk_module_ctx.bind_id = element_id;
194 
195         /* Each element must have a valid pointer to specific data */
196         if (element->data == NULL) {
197             fwk_trap();
198         }
199 
200         status = desc->element_init(
201             element_id, element->sub_element_count, element->data);
202         if (status != FWK_SUCCESS) {
203             fwk_trap();
204         }
205 
206         ctx->state = FWK_MODULE_STATE_INITIALIZED;
207     }
208 }
209 
fwk_module_init_module(struct fwk_module_context * ctx)210 static void fwk_module_init_module(struct fwk_module_context *ctx)
211 {
212     int status;
213 
214     const struct fwk_module *desc = ctx->desc;
215     const struct fwk_module_config *config = ctx->config;
216 
217     if (desc->type >= FWK_MODULE_TYPE_COUNT) {
218         fwk_trap();
219     }
220 
221     if (desc->init == NULL) {
222         fwk_trap();
223     }
224 
225     if ((desc->api_count == 0) != (desc->process_bind_request == NULL)) {
226         fwk_trap();
227     }
228 
229     if (config->elements.type == FWK_MODULE_ELEMENTS_TYPE_DYNAMIC) {
230         size_t notification_count = 0;
231 
232         const struct fwk_element *elements = NULL;
233 
234         if (config->elements.generator == NULL) {
235             fwk_trap();
236         }
237 
238         elements = config->elements.generator(ctx->id);
239         if (elements == NULL) {
240             fwk_trap();
241         }
242 
243 #ifdef BUILD_HAS_NOTIFICATION
244         notification_count = desc->notification_count;
245 #endif
246 
247         fwk_module_init_element_ctxs(ctx, elements, notification_count);
248     }
249 
250     status = desc->init(ctx->id, ctx->element_count, config->data);
251     if (status != FWK_SUCCESS) {
252         fwk_trap();
253     }
254 
255     if (ctx->element_count > 0) {
256         fwk_module_init_elements(ctx);
257     }
258 
259     if (desc->post_init != NULL) {
260         status = desc->post_init(ctx->id);
261         if (status != FWK_SUCCESS) {
262             fwk_trap();
263         }
264     }
265 
266     ctx->state = FWK_MODULE_STATE_INITIALIZED;
267 }
268 
fwk_module_init_modules(void)269 static void fwk_module_init_modules(void)
270 {
271     for (unsigned int i = 0U; i < (unsigned int)FWK_MODULE_IDX_COUNT; i++) {
272         fwk_module_init_module(&fwk_module_ctx.module_ctx_table[i]);
273     }
274 }
275 
fwk_module_bind_elements(struct fwk_module_context * fwk_mod_ctx,unsigned int round)276 static int fwk_module_bind_elements(
277     struct fwk_module_context *fwk_mod_ctx,
278     unsigned int round)
279 {
280     int status;
281     const struct fwk_module *module;
282     unsigned int element_idx;
283 
284     module = fwk_mod_ctx->desc;
285 
286     for (element_idx = 0; element_idx < fwk_mod_ctx->element_count;
287          element_idx++) {
288         fwk_module_ctx.bind_id =
289             fwk_id_build_element_id(fwk_mod_ctx->id, element_idx);
290         status = module->bind(fwk_module_ctx.bind_id, round);
291         if (!fwk_expect(status == FWK_SUCCESS)) {
292             FWK_LOG_CRIT(fwk_module_err_msg_func, status, __func__);
293             return status;
294         }
295 
296         if (round == FWK_MODULE_BIND_ROUND_MAX) {
297             fwk_mod_ctx->element_ctx_table[element_idx].state =
298                 FWK_MODULE_STATE_BOUND;
299         }
300     }
301 
302     return FWK_SUCCESS;
303 }
304 
fwk_module_bind_module(struct fwk_module_context * fwk_mod_ctx,unsigned int round)305 static int fwk_module_bind_module(
306     struct fwk_module_context *fwk_mod_ctx,
307     unsigned int round)
308 {
309     int status;
310     const struct fwk_module *module;
311 
312     module = fwk_mod_ctx->desc;
313     if (module->bind == NULL) {
314         fwk_mod_ctx->state = FWK_MODULE_STATE_BOUND;
315         return FWK_SUCCESS;
316     }
317 
318     fwk_module_ctx.bind_id = fwk_mod_ctx->id;
319     status = module->bind(fwk_mod_ctx->id, round);
320     if (!fwk_expect(status == FWK_SUCCESS)) {
321         FWK_LOG_CRIT(fwk_module_err_msg_func, status, __func__);
322         return status;
323     }
324 
325     if (round == FWK_MODULE_BIND_ROUND_MAX) {
326         fwk_mod_ctx->state = FWK_MODULE_STATE_BOUND;
327     }
328 
329     return fwk_module_bind_elements(fwk_mod_ctx, round);
330 }
331 
fwk_module_bind_modules(unsigned int round)332 static int fwk_module_bind_modules(unsigned int round)
333 {
334     int status;
335     unsigned int module_idx;
336     struct fwk_module_context *fwk_mod_ctx;
337 
338     for (module_idx = 0; module_idx < FWK_MODULE_IDX_COUNT; module_idx++) {
339         fwk_mod_ctx = &fwk_module_ctx.module_ctx_table[module_idx];
340         status = fwk_module_bind_module(fwk_mod_ctx, round);
341         if (status != FWK_SUCCESS) {
342             return status;
343         }
344     }
345 
346     return FWK_SUCCESS;
347 }
348 
fwk_module_start_elements(struct fwk_module_context * fwk_mod_ctx)349 static int fwk_module_start_elements(struct fwk_module_context *fwk_mod_ctx)
350 {
351     int status;
352     const struct fwk_module *module;
353     unsigned int element_idx;
354 
355     module = fwk_mod_ctx->desc;
356     for (element_idx = 0; element_idx < fwk_mod_ctx->element_count;
357          element_idx++) {
358         if (module->start != NULL) {
359             status = module->start(
360                 fwk_id_build_element_id(fwk_mod_ctx->id, element_idx));
361             if (!fwk_expect(status == FWK_SUCCESS)) {
362                 FWK_LOG_CRIT(fwk_module_err_msg_func, status, __func__);
363                 return status;
364             }
365         }
366 
367         fwk_mod_ctx->element_ctx_table[element_idx].state =
368             FWK_MODULE_STATE_STARTED;
369     }
370 
371     return FWK_SUCCESS;
372 }
373 
fwk_module_start_module(struct fwk_module_context * fwk_mod_ctx)374 static int fwk_module_start_module(struct fwk_module_context *fwk_mod_ctx)
375 {
376     int status;
377     const struct fwk_module *module;
378 
379     module = fwk_mod_ctx->desc;
380 
381     if (module->start != NULL) {
382         status = module->start(fwk_mod_ctx->id);
383         if (!fwk_expect(status == FWK_SUCCESS)) {
384             FWK_LOG_CRIT(fwk_module_err_msg_func, status, __func__);
385             return status;
386         }
387     }
388 
389     fwk_mod_ctx->state = FWK_MODULE_STATE_STARTED;
390 
391     return fwk_module_start_elements(fwk_mod_ctx);
392 }
393 
start_modules(void)394 static int start_modules(void)
395 {
396     int status;
397     unsigned int module_idx;
398     struct fwk_module_context *fwk_mod_ctx;
399 
400     for (module_idx = 0; module_idx < FWK_MODULE_IDX_COUNT; module_idx++) {
401         fwk_mod_ctx = &fwk_module_ctx.module_ctx_table[module_idx];
402         status = fwk_module_start_module(fwk_mod_ctx);
403         if (status != FWK_SUCCESS) {
404             return status;
405         }
406     }
407 
408     return FWK_SUCCESS;
409 }
410 
fwk_module_start(void)411 int fwk_module_start(void)
412 {
413     int status;
414     unsigned int bind_round;
415 
416     if (fwk_module_ctx.initialized) {
417         FWK_LOG_CRIT(fwk_module_err_msg_func, FWK_E_STATE, __func__);
418         return FWK_E_STATE;
419     }
420 
421     CLI_DEBUGGER();
422 
423     status = __fwk_init(FWK_MODULE_EVENT_COUNT);
424     if (status != FWK_SUCCESS) {
425         return status;
426     }
427 
428     fwk_module_ctx.stage = MODULE_STAGE_INITIALIZE;
429     fwk_module_init_modules();
430 
431     fwk_module_ctx.stage = MODULE_STAGE_BIND;
432     for (bind_round = 0; bind_round <= FWK_MODULE_BIND_ROUND_MAX;
433          bind_round++) {
434         status = fwk_module_bind_modules(bind_round);
435         if (status != FWK_SUCCESS) {
436             return status;
437         }
438     }
439 
440     fwk_module_ctx.stage = MODULE_STAGE_START;
441     status = start_modules();
442     if (status != FWK_SUCCESS) {
443         return status;
444     }
445 
446     fwk_module_ctx.initialized = true;
447 
448     FWK_LOG_CRIT("[FWK] Module initialization complete!");
449 
450     return FWK_SUCCESS;
451 }
452 
fwk_module_stop_elements(struct fwk_module_context * fwk_mod_ctx)453 static int fwk_module_stop_elements(struct fwk_module_context *fwk_mod_ctx)
454 {
455     int status;
456     const struct fwk_module *module;
457     unsigned int element_idx;
458 
459     module = fwk_mod_ctx->desc;
460 
461     for (element_idx = 0; element_idx < fwk_mod_ctx->element_count;
462          element_idx++) {
463         if (module->stop != NULL) {
464             status = module->stop(
465                 fwk_id_build_element_id(fwk_mod_ctx->id, element_idx));
466             if (!fwk_expect(status == FWK_SUCCESS)) {
467                 FWK_LOG_CRIT(fwk_module_err_msg_func, status, __func__);
468                 return status;
469             }
470         }
471 
472         fwk_mod_ctx->element_ctx_table[element_idx].state =
473             FWK_MODULE_STATE_SUSPENDED;
474     }
475 
476     return FWK_SUCCESS;
477 }
478 
fwk_module_stop_module(struct fwk_module_context * fwk_mod_ctx)479 static int fwk_module_stop_module(struct fwk_module_context *fwk_mod_ctx)
480 {
481     int status;
482     const struct fwk_module *module;
483 
484     module = fwk_mod_ctx->desc;
485 
486     if (module->stop != NULL) {
487         status = module->stop(fwk_mod_ctx->id);
488         if (!fwk_expect(status == FWK_SUCCESS)) {
489             FWK_LOG_CRIT(fwk_module_err_msg_func, status, __func__);
490             return status;
491         }
492     }
493 
494     fwk_mod_ctx->state = FWK_MODULE_STATE_SUSPENDED;
495 
496     return fwk_module_stop_elements(fwk_mod_ctx);
497 }
498 
stop_modules(void)499 static int stop_modules(void)
500 {
501     int status;
502     unsigned int module_idx;
503     struct fwk_module_context *fwk_mod_ctx;
504 
505     for (module_idx = 0; module_idx < FWK_MODULE_IDX_COUNT; module_idx++) {
506         fwk_mod_ctx = &fwk_module_ctx.module_ctx_table[module_idx];
507         status = fwk_module_stop_module(fwk_mod_ctx);
508         if (status != FWK_SUCCESS) {
509             return status;
510         }
511     }
512 
513     return FWK_SUCCESS;
514 }
515 
fwk_module_stop(void)516 int fwk_module_stop(void)
517 {
518     int status;
519 
520     if (!fwk_module_ctx.initialized) {
521         FWK_LOG_CRIT(fwk_module_err_msg_func, FWK_E_STATE, __func__);
522         return FWK_E_STATE;
523     }
524 
525     fwk_module_ctx.stage = MODULE_STAGE_STOP;
526     status = stop_modules();
527     if (status != FWK_SUCCESS) {
528         return status;
529     }
530 
531     return FWK_SUCCESS;
532 }
533 
fwk_module_get_ctx(fwk_id_t id)534 struct fwk_module_context *fwk_module_get_ctx(fwk_id_t id)
535 {
536     return &fwk_module_ctx.module_ctx_table[fwk_id_get_module_idx(id)];
537 }
538 
fwk_module_get_element_ctx(fwk_id_t element_id)539 struct fwk_element_ctx *fwk_module_get_element_ctx(fwk_id_t element_id)
540 {
541     struct fwk_module_context *fwk_mod_ctx = fwk_module_get_ctx(element_id);
542 
543     return &fwk_mod_ctx->element_ctx_table[element_id.element.element_idx];
544 }
545 
fwk_module_get_state(fwk_id_t id,enum fwk_module_state * state)546 int fwk_module_get_state(fwk_id_t id, enum fwk_module_state *state)
547 {
548     if (state == NULL) {
549         return FWK_E_PARAM;
550     }
551 
552     if (fwk_module_is_valid_element_id(id) ||
553         fwk_module_is_valid_sub_element_id(id)) {
554         *state = fwk_module_get_element_ctx(id)->state;
555     } else {
556         if (fwk_module_is_valid_module_id(id)) {
557             *state = fwk_module_get_ctx(id)->state;
558         } else {
559             return FWK_E_PARAM;
560         }
561     }
562 
563     return FWK_SUCCESS;
564 }
565 
fwk_module_reset(void)566 void fwk_module_reset(void)
567 {
568     fwk_module_init();
569 }
570 
fwk_module_is_valid_module_id(fwk_id_t id)571 bool fwk_module_is_valid_module_id(fwk_id_t id)
572 {
573     if (!fwk_id_is_type(id, FWK_ID_TYPE_MODULE)) {
574         return false;
575     }
576 
577     if (fwk_id_get_module_idx(id) >= FWK_MODULE_IDX_COUNT) {
578         return false;
579     }
580 
581     return true;
582 }
583 
fwk_module_is_valid_element_id(fwk_id_t id)584 bool fwk_module_is_valid_element_id(fwk_id_t id)
585 {
586     unsigned int module_idx;
587 
588     if (!fwk_id_is_type(id, FWK_ID_TYPE_ELEMENT)) {
589         return false;
590     }
591 
592     module_idx = fwk_id_get_module_idx(id);
593     if (module_idx >= FWK_MODULE_IDX_COUNT) {
594         return false;
595     }
596 
597     return (
598         fwk_id_get_element_idx(id) <
599         fwk_module_ctx.module_ctx_table[module_idx].element_count);
600 }
601 
fwk_module_is_valid_sub_element_id(fwk_id_t id)602 bool fwk_module_is_valid_sub_element_id(fwk_id_t id)
603 {
604     unsigned int module_idx;
605     struct fwk_module_context *fwk_mod_ctx;
606     unsigned int element_idx;
607 
608     if (!fwk_id_is_type(id, FWK_ID_TYPE_SUB_ELEMENT)) {
609         return false;
610     }
611 
612     module_idx = fwk_id_get_module_idx(id);
613     if (module_idx >= FWK_MODULE_IDX_COUNT) {
614         return false;
615     }
616     fwk_mod_ctx = &fwk_module_ctx.module_ctx_table[module_idx];
617 
618     element_idx = fwk_id_get_element_idx(id);
619     if (element_idx >= fwk_mod_ctx->element_count) {
620         return false;
621     }
622 
623     return (
624         fwk_id_get_sub_element_idx(id) <
625         fwk_mod_ctx->element_ctx_table[element_idx].sub_element_count);
626 }
627 
fwk_module_is_valid_entity_id(fwk_id_t id)628 bool fwk_module_is_valid_entity_id(fwk_id_t id)
629 {
630     bool return_status = false;
631 
632     switch (fwk_id_get_type(id)) {
633     case FWK_ID_TYPE_MODULE:
634         return_status = fwk_module_is_valid_module_id(id);
635         break;
636 
637     case FWK_ID_TYPE_ELEMENT:
638         return_status = fwk_module_is_valid_element_id(id);
639         break;
640 
641     case FWK_ID_TYPE_SUB_ELEMENT:
642         return_status = fwk_module_is_valid_sub_element_id(id);
643         break;
644 
645     default:
646         break;
647     }
648 
649     return return_status;
650 }
651 
fwk_module_is_valid_api_id(fwk_id_t id)652 bool fwk_module_is_valid_api_id(fwk_id_t id)
653 {
654     unsigned int module_idx;
655 
656     if (!fwk_id_is_type(id, FWK_ID_TYPE_API)) {
657         return false;
658     }
659 
660     module_idx = fwk_id_get_module_idx(id);
661     if (module_idx >= FWK_MODULE_IDX_COUNT) {
662         return false;
663     }
664 
665     return (
666         fwk_id_get_api_idx(id) <
667         fwk_module_ctx.module_ctx_table[module_idx].desc->api_count);
668 }
669 
fwk_module_is_valid_event_id(fwk_id_t id)670 bool fwk_module_is_valid_event_id(fwk_id_t id)
671 {
672     unsigned int module_idx;
673 
674     if (!fwk_id_is_type(id, FWK_ID_TYPE_EVENT)) {
675         return false;
676     }
677 
678     module_idx = fwk_id_get_module_idx(id);
679     if (module_idx >= FWK_MODULE_IDX_COUNT) {
680         return false;
681     }
682 
683     return (
684         fwk_id_get_event_idx(id) <
685         fwk_module_ctx.module_ctx_table[module_idx].desc->event_count);
686 }
687 
fwk_module_is_valid_notification_id(fwk_id_t id)688 bool fwk_module_is_valid_notification_id(fwk_id_t id)
689 {
690 #ifdef BUILD_HAS_NOTIFICATION
691     unsigned int module_idx;
692 
693     if (!fwk_id_is_type(id, FWK_ID_TYPE_NOTIFICATION)) {
694         return false;
695     }
696 
697     module_idx = fwk_id_get_module_idx(id);
698     if (module_idx >= FWK_MODULE_IDX_COUNT) {
699         return false;
700     }
701 
702     return (
703         fwk_id_get_notification_idx(id) <
704         fwk_module_ctx.module_ctx_table[module_idx].desc->notification_count);
705 #else
706     return false;
707 #endif
708 }
709 
fwk_module_get_element_count(fwk_id_t id)710 int fwk_module_get_element_count(fwk_id_t id)
711 {
712     if (fwk_module_is_valid_module_id(id)) {
713         return (int)fwk_module_get_ctx(id)->element_count;
714     } else {
715         return FWK_E_PARAM;
716     }
717 }
718 
fwk_module_get_sub_element_count(fwk_id_t element_id)719 int fwk_module_get_sub_element_count(fwk_id_t element_id)
720 {
721     if (fwk_module_is_valid_element_id(element_id)) {
722         return (int)fwk_module_get_element_ctx(element_id)->sub_element_count;
723     } else {
724         return FWK_E_PARAM;
725     }
726 }
727 
fwk_module_get_element_name(fwk_id_t id)728 const char *fwk_module_get_element_name(fwk_id_t id)
729 {
730     if (fwk_module_is_valid_element_id(id)) {
731         return fwk_module_get_element_ctx(id)->desc->name;
732     }
733 
734     fwk_unexpected();
735     return NULL;
736 }
737 
fwk_module_get_data(fwk_id_t id)738 const void *fwk_module_get_data(fwk_id_t id)
739 {
740     if (fwk_module_is_valid_element_id(id) ||
741         fwk_module_is_valid_sub_element_id(id)) {
742         return fwk_module_get_element_ctx(id)->desc->data;
743     } else if (fwk_module_is_valid_module_id(id)) {
744         return fwk_module_get_ctx(id)->config->data;
745     }
746 
747     fwk_unexpected();
748     return NULL;
749 }
750 
fwk_module_bind(fwk_id_t target_id,fwk_id_t api_id,const void * api)751 int fwk_module_bind(fwk_id_t target_id, fwk_id_t api_id, const void *api)
752 {
753     int status = FWK_E_PARAM;
754     struct fwk_module_context *fwk_mod_ctx;
755 
756     if (!fwk_module_is_valid_entity_id(target_id)) {
757         goto error;
758     }
759 
760     if (!fwk_module_is_valid_api_id(api_id)) {
761         goto error;
762     }
763 
764     if (fwk_id_get_module_idx(target_id) != fwk_id_get_module_idx(api_id)) {
765         goto error;
766     }
767 
768     if (api == NULL) {
769         goto error;
770     }
771 
772     fwk_mod_ctx = fwk_module_get_ctx(target_id);
773 
774     if (((fwk_module_ctx.stage != MODULE_STAGE_INITIALIZE) ||
775          (fwk_mod_ctx->state != FWK_MODULE_STATE_INITIALIZED)) &&
776         (fwk_module_ctx.stage != MODULE_STAGE_BIND)) {
777         status = FWK_E_STATE;
778         goto error;
779     }
780 
781     status = fwk_mod_ctx->desc->process_bind_request(
782         fwk_module_ctx.bind_id, target_id, api_id, (const void **)api);
783     if (!fwk_expect(status == FWK_SUCCESS)) {
784         FWK_LOG_CRIT(fwk_module_err_msg_line, status, __func__, __LINE__);
785         return status;
786     }
787 
788     if (*(void **)api == NULL) {
789         status = FWK_E_HANDLER;
790         goto error;
791     }
792 
793     return FWK_SUCCESS;
794 
795 error:
796     fwk_check((bool)false);
797     FWK_LOG_CRIT(fwk_module_err_msg_func, status, __func__);
798     return status;
799 }
800 
fwk_module_adapter(const struct fwk_io_adapter ** adapter,fwk_id_t id)801 int fwk_module_adapter(const struct fwk_io_adapter **adapter, fwk_id_t id)
802 {
803     unsigned int idx;
804 
805     if (adapter == NULL) {
806         return FWK_E_PARAM;
807     }
808 
809     *adapter = NULL;
810 
811     if (!fwk_module_is_valid_entity_id(id)) {
812         return FWK_E_PARAM;
813     }
814 
815     idx = fwk_id_get_module_idx(id);
816 
817     *adapter = &module_table[idx]->adapter;
818 
819     return FWK_SUCCESS;
820 }
821