]> Git Repo - J-u-boot.git/blob - common/event.c
Merge branch '2023-08-31-replace-more-init-hooks-with-events' into next
[J-u-boot.git] / common / event.c
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>
20 #include <relocate.h>
21
22 DECLARE_GLOBAL_DATA_PTR;
23
24 #if CONFIG_IS_ENABLED(EVENT_DEBUG)
25 const char *const type_name[] = {
26         "none",
27         "test",
28
29         /* Events related to driver model */
30         "dm_post_init_f",
31         "dm_pre_probe",
32         "dm_post_probe",
33         "dm_pre_remove",
34         "dm_post_remove",
35
36         /* init hooks */
37         "misc_init_f",
38         "fsp_init_r",
39         "last_stage_init",
40
41         /* Fpga load hook */
42         "fpga_load",
43
44         /* fdt hooks */
45         "ft_fixup",
46
47         /* main loop events */
48         "main_loop",
49 };
50
51 _Static_assert(ARRAY_SIZE(type_name) == EVT_COUNT, "event type_name size");
52 #endif
53
54 const char *event_type_name(enum event_t type)
55 {
56 #if CONFIG_IS_ENABLED(EVENT_DEBUG)
57         return type_name[type];
58 #else
59         return "(unknown)";
60 #endif
61 }
62
63 static int notify_static(struct event *ev)
64 {
65         struct evspy_info *start =
66                 ll_entry_start(struct evspy_info, evspy_info);
67         const int n_ents = ll_entry_count(struct evspy_info, evspy_info);
68         struct evspy_info *spy;
69
70         for (spy = start; spy != start + n_ents; spy++) {
71                 if (spy->type == ev->type) {
72                         int ret;
73
74                         log_debug("Sending event %x/%s to spy '%s'\n", ev->type,
75                                   event_type_name(ev->type), event_spy_id(spy));
76                         if (spy->flags & EVSPYF_SIMPLE) {
77                                 const struct evspy_info_simple *simple;
78
79                                 simple = (struct evspy_info_simple *)spy;
80                                 ret = simple->func();
81                         } else {
82                                 ret = spy->func(NULL, ev);
83                         }
84
85                         /*
86                          * TODO: Handle various return codes to
87                          *
88                          * - claim an event (no others will see it)
89                          * - return an error from the event
90                          */
91                         if (ret)
92                                 return log_msg_ret("spy", ret);
93                 }
94         }
95
96         return 0;
97 }
98
99 static int notify_dynamic(struct event *ev)
100 {
101         struct event_state *state = gd_event_state();
102         struct event_spy *spy, *next;
103
104         list_for_each_entry_safe(spy, next, &state->spy_head, sibling_node) {
105                 if (spy->type == ev->type) {
106                         int ret;
107
108                         log_debug("Sending event %x/%s to spy '%s'\n", ev->type,
109                                   event_type_name(ev->type), spy->id);
110                         ret = spy->func(spy->ctx, ev);
111
112                         /*
113                          * TODO: Handle various return codes to
114                          *
115                          * - claim an event (no others will see it)
116                          * - return an error from the event
117                          */
118                         if (ret)
119                                 return log_msg_ret("spy", ret);
120                 }
121         }
122
123         return 0;
124 }
125
126 int event_notify(enum event_t type, void *data, int size)
127 {
128         struct event event;
129         int ret;
130
131         event.type = type;
132         if (size > sizeof(event.data))
133                 return log_msg_ret("size", -E2BIG);
134         memcpy(&event.data, data, size);
135
136         ret = notify_static(&event);
137         if (ret)
138                 return log_msg_ret("sta", ret);
139
140         if (CONFIG_IS_ENABLED(EVENT_DYNAMIC)) {
141                 ret = notify_dynamic(&event);
142                 if (ret)
143                         return log_msg_ret("dyn", ret);
144         }
145
146         return 0;
147 }
148
149 int event_notify_null(enum event_t type)
150 {
151         return event_notify(type, NULL, 0);
152 }
153
154 void event_show_spy_list(void)
155 {
156         struct evspy_info *start =
157                 ll_entry_start(struct evspy_info, evspy_info);
158         const int n_ents = ll_entry_count(struct evspy_info, evspy_info);
159         struct evspy_info *spy;
160         const int size = sizeof(ulong) * 2;
161
162         printf("Seq  %-24s  %*s  %s\n", "Type", size, "Function", "ID");
163         for (spy = start; spy != start + n_ents; spy++) {
164                 printf("%3x  %-3x %-20s  %*p  %s\n", (uint)(spy - start),
165                        spy->type, event_type_name(spy->type), size, spy->func,
166                        event_spy_id(spy));
167         }
168 }
169
170 #if IS_ENABLED(CONFIG_NEEDS_MANUAL_RELOC)
171 int event_manual_reloc(void)
172 {
173         struct evspy_info *spy, *end;
174
175         spy = ll_entry_start(struct evspy_info, evspy_info);
176         end = ll_entry_end(struct evspy_info, evspy_info);
177         for (; spy < end; spy++)
178                 MANUAL_RELOC(spy->func);
179
180         return 0;
181 }
182 #endif
183
184 #if CONFIG_IS_ENABLED(EVENT_DYNAMIC)
185 static void spy_free(struct event_spy *spy)
186 {
187         list_del(&spy->sibling_node);
188 }
189
190 int event_register(const char *id, enum event_t type, event_handler_t func, void *ctx)
191 {
192         struct event_state *state = gd_event_state();
193         struct event_spy *spy;
194
195         spy = malloc(sizeof(*spy));
196         if (!spy)
197                 return log_msg_ret("alloc", -ENOMEM);
198
199         spy->id = id;
200         spy->type = type;
201         spy->func = func;
202         spy->ctx = ctx;
203         list_add_tail(&spy->sibling_node, &state->spy_head);
204
205         return 0;
206 }
207
208 int event_uninit(void)
209 {
210         struct event_state *state = gd_event_state();
211         struct event_spy *spy, *next;
212
213         list_for_each_entry_safe(spy, next, &state->spy_head, sibling_node)
214                 spy_free(spy);
215
216         return 0;
217 }
218
219 int event_init(void)
220 {
221         struct event_state *state = gd_event_state();
222
223         INIT_LIST_HEAD(&state->spy_head);
224
225         return 0;
226 }
227 #endif /* EVENT_DYNAMIC */
This page took 0.03794 seconds and 4 git commands to generate.