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