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