]> Git Repo - J-u-boot.git/blame - common/event.c
Merge tag 'efi-2024-04-rc1-4' of https://source.denx.de/u-boot/custodians/u-boot-efi
[J-u-boot.git] / common / event.c
CommitLineData
87a5d1b5
SG
1// SPDX-License-Identifier: GPL-2.0+
2/*
3 * Events provide a general-purpose way to react to / subscribe to changes
4 * within U-Boot
5 *
6 * Copyright 2021 Google LLC
7 * Written by Simon Glass <[email protected]>
8 */
9
10#define LOG_CATEGORY LOGC_EVENT
11
12#include <common.h>
13#include <event.h>
14#include <event_internal.h>
15#include <log.h>
16#include <linker_lists.h>
17#include <malloc.h>
18#include <asm/global_data.h>
19#include <linux/list.h>
cebc8161 20#include <relocate.h>
87a5d1b5
SG
21
22DECLARE_GLOBAL_DATA_PTR;
23
24#if CONFIG_IS_ENABLED(EVENT_DEBUG)
25const char *const type_name[] = {
26 "none",
27 "test",
5b896ed5
SG
28
29 /* Events related to driver model */
b4966208 30 "dm_post_init_f",
27c7a629 31 "dm_post_init_r",
5b896ed5
SG
32 "dm_pre_probe",
33 "dm_post_probe",
34 "dm_pre_remove",
35 "dm_post_remove",
42fdcebf
SG
36
37 /* init hooks */
38 "misc_init_f",
13a7db9a 39 "fsp_init_r",
6092ce50 40 "settings_r",
91caa3bb 41 "last_stage_init",
98887ab8 42
a1190b4d
CT
43 /* Fpga load hook */
44 "fpga_load",
45
98887ab8
SG
46 /* fdt hooks */
47 "ft_fixup",
467bad5e
SG
48
49 /* main loop events */
50 "main_loop",
87a5d1b5
SG
51};
52
53_Static_assert(ARRAY_SIZE(type_name) == EVT_COUNT, "event type_name size");
54#endif
55
fb7dfca2 56const char *event_type_name(enum event_t type)
87a5d1b5
SG
57{
58#if CONFIG_IS_ENABLED(EVENT_DEBUG)
59 return type_name[type];
60#else
61 return "(unknown)";
62#endif
63}
64
65static int notify_static(struct event *ev)
66{
67 struct evspy_info *start =
68 ll_entry_start(struct evspy_info, evspy_info);
69 const int n_ents = ll_entry_count(struct evspy_info, evspy_info);
70 struct evspy_info *spy;
71
72 for (spy = start; spy != start + n_ents; spy++) {
73 if (spy->type == ev->type) {
74 int ret;
75
76 log_debug("Sending event %x/%s to spy '%s'\n", ev->type,
77 event_type_name(ev->type), event_spy_id(spy));
ba5e3e1e
SG
78 if (spy->flags & EVSPYF_SIMPLE) {
79 const struct evspy_info_simple *simple;
80
81 simple = (struct evspy_info_simple *)spy;
82 ret = simple->func();
83 } else {
84 ret = spy->func(NULL, ev);
85 }
87a5d1b5
SG
86
87 /*
88 * TODO: Handle various return codes to
89 *
90 * - claim an event (no others will see it)
91 * - return an error from the event
92 */
93 if (ret)
94 return log_msg_ret("spy", ret);
95 }
96 }
97
98 return 0;
99}
100
101static int notify_dynamic(struct event *ev)
102{
103 struct event_state *state = gd_event_state();
104 struct event_spy *spy, *next;
105
106 list_for_each_entry_safe(spy, next, &state->spy_head, sibling_node) {
107 if (spy->type == ev->type) {
108 int ret;
109
110 log_debug("Sending event %x/%s to spy '%s'\n", ev->type,
111 event_type_name(ev->type), spy->id);
112 ret = spy->func(spy->ctx, ev);
113
114 /*
115 * TODO: Handle various return codes to
116 *
117 * - claim an event (no others will see it)
118 * - return an error from the event
119 */
120 if (ret)
121 return log_msg_ret("spy", ret);
122 }
123 }
124
125 return 0;
126}
127
128int event_notify(enum event_t type, void *data, int size)
129{
130 struct event event;
131 int ret;
132
133 event.type = type;
134 if (size > sizeof(event.data))
135 return log_msg_ret("size", -E2BIG);
136 memcpy(&event.data, data, size);
137
138 ret = notify_static(&event);
139 if (ret)
19efd43b 140 return log_msg_ret("sta", ret);
87a5d1b5
SG
141
142 if (CONFIG_IS_ENABLED(EVENT_DYNAMIC)) {
143 ret = notify_dynamic(&event);
144 if (ret)
145 return log_msg_ret("dyn", ret);
146 }
147
148 return 0;
149}
150
151int event_notify_null(enum event_t type)
152{
153 return event_notify(type, NULL, 0);
154}
155
156void event_show_spy_list(void)
157{
158 struct evspy_info *start =
159 ll_entry_start(struct evspy_info, evspy_info);
160 const int n_ents = ll_entry_count(struct evspy_info, evspy_info);
161 struct evspy_info *spy;
162 const int size = sizeof(ulong) * 2;
163
164 printf("Seq %-24s %*s %s\n", "Type", size, "Function", "ID");
165 for (spy = start; spy != start + n_ents; spy++) {
166 printf("%3x %-3x %-20s %*p %s\n", (uint)(spy - start),
167 spy->type, event_type_name(spy->type), size, spy->func,
168 event_spy_id(spy));
169 }
170}
171
172#if CONFIG_IS_ENABLED(EVENT_DYNAMIC)
173static void spy_free(struct event_spy *spy)
174{
175 list_del(&spy->sibling_node);
176}
177
178int event_register(const char *id, enum event_t type, event_handler_t func, void *ctx)
179{
180 struct event_state *state = gd_event_state();
181 struct event_spy *spy;
182
87a5d1b5
SG
183 spy = malloc(sizeof(*spy));
184 if (!spy)
185 return log_msg_ret("alloc", -ENOMEM);
186
187 spy->id = id;
188 spy->type = type;
189 spy->func = func;
190 spy->ctx = ctx;
191 list_add_tail(&spy->sibling_node, &state->spy_head);
192
193 return 0;
194}
195
196int event_uninit(void)
197{
198 struct event_state *state = gd_event_state();
199 struct event_spy *spy, *next;
200
201 list_for_each_entry_safe(spy, next, &state->spy_head, sibling_node)
202 spy_free(spy);
203
204 return 0;
205}
206
207int event_init(void)
208{
209 struct event_state *state = gd_event_state();
210
211 INIT_LIST_HEAD(&state->spy_head);
212
213 return 0;
214}
215#endif /* EVENT_DYNAMIC */
This page took 0.120089 seconds and 4 git commands to generate.