123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219 |
- // SPDX-License-Identifier: GPL-2.0+
- /*
- * Events provide a general-purpose way to react to / subscribe to changes
- * within U-Boot
- *
- * Copyright 2021 Google LLC
- * Written by Simon Glass <sjg@chromium.org>
- */
- #define LOG_CATEGORY LOGC_EVENT
- #include <common.h>
- #include <event.h>
- #include <event_internal.h>
- #include <log.h>
- #include <linker_lists.h>
- #include <malloc.h>
- #include <asm/global_data.h>
- #include <linux/list.h>
- #include <relocate.h>
- DECLARE_GLOBAL_DATA_PTR;
- #if CONFIG_IS_ENABLED(EVENT_DEBUG)
- const char *const type_name[] = {
- "none",
- "test",
- /* Events related to driver model */
- "dm_post_init_f",
- "dm_post_init_r",
- "dm_pre_probe",
- "dm_post_probe",
- "dm_pre_remove",
- "dm_post_remove",
- /* init hooks */
- "misc_init_f",
- /* Fpga load hook */
- "fpga_load",
- /* fdt hooks */
- "ft_fixup",
- /* main loop events */
- "main_loop",
- };
- _Static_assert(ARRAY_SIZE(type_name) == EVT_COUNT, "event type_name size");
- #endif
- static const char *event_type_name(enum event_t type)
- {
- #if CONFIG_IS_ENABLED(EVENT_DEBUG)
- return type_name[type];
- #else
- return "(unknown)";
- #endif
- }
- static int notify_static(struct event *ev)
- {
- struct evspy_info *start =
- ll_entry_start(struct evspy_info, evspy_info);
- const int n_ents = ll_entry_count(struct evspy_info, evspy_info);
- struct evspy_info *spy;
- for (spy = start; spy != start + n_ents; spy++) {
- if (spy->type == ev->type) {
- int ret;
- log_debug("Sending event %x/%s to spy '%s'\n", ev->type,
- event_type_name(ev->type), event_spy_id(spy));
- ret = spy->func(NULL, ev);
- /*
- * TODO: Handle various return codes to
- *
- * - claim an event (no others will see it)
- * - return an error from the event
- */
- if (ret)
- return log_msg_ret("spy", ret);
- }
- }
- return 0;
- }
- static int notify_dynamic(struct event *ev)
- {
- struct event_state *state = gd_event_state();
- struct event_spy *spy, *next;
- list_for_each_entry_safe(spy, next, &state->spy_head, sibling_node) {
- if (spy->type == ev->type) {
- int ret;
- log_debug("Sending event %x/%s to spy '%s'\n", ev->type,
- event_type_name(ev->type), spy->id);
- ret = spy->func(spy->ctx, ev);
- /*
- * TODO: Handle various return codes to
- *
- * - claim an event (no others will see it)
- * - return an error from the event
- */
- if (ret)
- return log_msg_ret("spy", ret);
- }
- }
- return 0;
- }
- int event_notify(enum event_t type, void *data, int size)
- {
- struct event event;
- int ret;
- event.type = type;
- if (size > sizeof(event.data))
- return log_msg_ret("size", -E2BIG);
- memcpy(&event.data, data, size);
- ret = notify_static(&event);
- if (ret)
- return log_msg_ret("sta", ret);
- if (CONFIG_IS_ENABLED(EVENT_DYNAMIC)) {
- ret = notify_dynamic(&event);
- if (ret)
- return log_msg_ret("dyn", ret);
- }
- return 0;
- }
- int event_notify_null(enum event_t type)
- {
- return event_notify(type, NULL, 0);
- }
- void event_show_spy_list(void)
- {
- struct evspy_info *start =
- ll_entry_start(struct evspy_info, evspy_info);
- const int n_ents = ll_entry_count(struct evspy_info, evspy_info);
- struct evspy_info *spy;
- const int size = sizeof(ulong) * 2;
- printf("Seq %-24s %*s %s\n", "Type", size, "Function", "ID");
- for (spy = start; spy != start + n_ents; spy++) {
- printf("%3x %-3x %-20s %*p %s\n", (uint)(spy - start),
- spy->type, event_type_name(spy->type), size, spy->func,
- event_spy_id(spy));
- }
- }
- #if IS_ENABLED(CONFIG_NEEDS_MANUAL_RELOC)
- int event_manual_reloc(void)
- {
- struct evspy_info *spy, *end;
- spy = ll_entry_start(struct evspy_info, evspy_info);
- end = ll_entry_end(struct evspy_info, evspy_info);
- for (; spy < end; spy++)
- MANUAL_RELOC(spy->func);
- return 0;
- }
- #endif
- #if CONFIG_IS_ENABLED(EVENT_DYNAMIC)
- static void spy_free(struct event_spy *spy)
- {
- list_del(&spy->sibling_node);
- }
- int event_register(const char *id, enum event_t type, event_handler_t func, void *ctx)
- {
- struct event_state *state = gd_event_state();
- struct event_spy *spy;
- spy = malloc(sizeof(*spy));
- if (!spy)
- return log_msg_ret("alloc", -ENOMEM);
- spy->id = id;
- spy->type = type;
- spy->func = func;
- spy->ctx = ctx;
- list_add_tail(&spy->sibling_node, &state->spy_head);
- return 0;
- }
- int event_uninit(void)
- {
- struct event_state *state = gd_event_state();
- struct event_spy *spy, *next;
- list_for_each_entry_safe(spy, next, &state->spy_head, sibling_node)
- spy_free(spy);
- return 0;
- }
- int event_init(void)
- {
- struct event_state *state = gd_event_state();
- INIT_LIST_HEAD(&state->spy_head);
- return 0;
- }
- #endif /* EVENT_DYNAMIC */
|