1
2
3
4
5
6
7
8
9
10
11
12#include <efi_selftest.h>
13
14
15
16
17
18struct interface {
19 void (EFIAPI * inc)(void);
20};
21
22struct context {
23 void *registration_key;
24 efi_uintn_t notify_count;
25 efi_uintn_t handle_count;
26 efi_handle_t *handles;
27};
28
29static struct efi_boot_services *boottime;
30static efi_guid_t guid1 =
31 EFI_GUID(0x2e7ca819, 0x21d3, 0x0a3a,
32 0xf7, 0x91, 0x82, 0x1f, 0x7a, 0x83, 0x67, 0xaf);
33static efi_guid_t guid2 =
34 EFI_GUID(0xf909f2bb, 0x90a8, 0x0d77,
35 0x94, 0x0c, 0x3e, 0xa8, 0xea, 0x38, 0xd6, 0x6f);
36static struct context context;
37static struct efi_event *event;
38
39
40
41
42
43
44
45
46static void EFIAPI notify(struct efi_event *event, void *context)
47{
48 struct context *cp = context;
49 efi_status_t ret;
50 efi_uintn_t handle_count;
51 efi_handle_t *handles;
52
53 cp->notify_count++;
54
55 for (;;) {
56 ret = boottime->locate_handle_buffer(BY_REGISTER_NOTIFY, NULL,
57 cp->registration_key,
58 &handle_count, &handles);
59 if (ret != EFI_SUCCESS)
60 break;
61 cp->handle_count += handle_count;
62 cp->handles = handles;
63 }
64}
65
66
67
68
69
70
71
72static int setup(const efi_handle_t img_handle,
73 const struct efi_system_table *systable)
74{
75 efi_status_t ret;
76
77 boottime = systable->boottime;
78
79 ret = boottime->create_event(EVT_NOTIFY_SIGNAL,
80 TPL_CALLBACK, notify, &context,
81 &event);
82 if (ret != EFI_SUCCESS) {
83 efi_st_error("could not create event\n");
84 return EFI_ST_FAILURE;
85 }
86
87 ret = boottime->register_protocol_notify(&guid1, event,
88 &context.registration_key);
89 if (ret != EFI_SUCCESS) {
90 efi_st_error("could not register event\n");
91 return EFI_ST_FAILURE;
92 }
93
94 return EFI_ST_SUCCESS;
95}
96
97
98
99
100
101static int teardown(void)
102{
103 efi_status_t ret;
104
105 if (event) {
106 ret = boottime->close_event(event);
107 event = NULL;
108 if (ret != EFI_SUCCESS) {
109 efi_st_error("could not close event\n");
110 return EFI_ST_FAILURE;
111 }
112 }
113
114 return EFI_ST_SUCCESS;
115}
116
117
118
119
120
121static int execute(void)
122{
123 efi_status_t ret;
124 efi_handle_t handle1 = NULL, handle2 = NULL;
125 struct interface interface1, interface2;
126
127 ret = boottime->install_protocol_interface(&handle1, &guid1,
128 EFI_NATIVE_INTERFACE,
129 &interface1);
130 if (ret != EFI_SUCCESS) {
131 efi_st_error("could not install interface\n");
132 return EFI_ST_FAILURE;
133 }
134 if (!context.notify_count) {
135 efi_st_error("install was not notified\n");
136 return EFI_ST_FAILURE;
137 }
138 if (context.notify_count > 1) {
139 efi_st_error("install was notified too often\n");
140 return EFI_ST_FAILURE;
141 }
142 if (context.handle_count != 1) {
143 efi_st_error("LocateHandle failed\n");
144 return EFI_ST_FAILURE;
145 }
146 ret = boottime->free_pool(context.handles);
147 if (ret != EFI_SUCCESS) {
148 efi_st_error("FreePool failed\n");
149 return EFI_ST_FAILURE;
150 }
151 context.notify_count = 0;
152 ret = boottime->install_protocol_interface(&handle1, &guid2,
153 EFI_NATIVE_INTERFACE,
154 &interface1);
155 if (ret != EFI_SUCCESS) {
156 efi_st_error("could not install interface\n");
157 return EFI_ST_FAILURE;
158 }
159 if (context.notify_count) {
160 efi_st_error("wrong protocol was notified\n");
161 return EFI_ST_FAILURE;
162 }
163 context.notify_count = 0;
164 ret = boottime->reinstall_protocol_interface(handle1, &guid1,
165 &interface1, &interface2);
166 if (ret != EFI_SUCCESS) {
167 efi_st_error("could not reinstall interface\n");
168 return EFI_ST_FAILURE;
169 }
170 if (!context.notify_count) {
171 efi_st_error("reinstall was not notified\n");
172 return EFI_ST_FAILURE;
173 }
174 if (context.notify_count > 1) {
175 efi_st_error("reinstall was notified too often\n");
176 return EFI_ST_FAILURE;
177 }
178 if (context.handle_count != 2) {
179 efi_st_error("LocateHandle failed\n");
180 return EFI_ST_FAILURE;
181 }
182 ret = boottime->free_pool(context.handles);
183 if (ret != EFI_SUCCESS) {
184 efi_st_error("FreePool failed\n");
185 return EFI_ST_FAILURE;
186 }
187 context.notify_count = 0;
188 ret = boottime->install_protocol_interface(&handle2, &guid1,
189 EFI_NATIVE_INTERFACE,
190 &interface1);
191 if (ret != EFI_SUCCESS) {
192 efi_st_error("could not install interface\n");
193 return EFI_ST_FAILURE;
194 }
195 if (!context.notify_count) {
196 efi_st_error("install was not notified\n");
197 return EFI_ST_FAILURE;
198 }
199 if (context.notify_count > 1) {
200 efi_st_error("install was notified too often\n");
201 return EFI_ST_FAILURE;
202 }
203 if (context.handle_count != 3) {
204 efi_st_error("LocateHandle failed\n");
205 return EFI_ST_FAILURE;
206 }
207 ret = boottime->free_pool(context.handles);
208 if (ret != EFI_SUCCESS) {
209 efi_st_error("FreePool failed\n");
210 return EFI_ST_FAILURE;
211 }
212
213 ret = boottime->uninstall_multiple_protocol_interfaces
214 (handle1, &guid1, &interface2,
215 &guid2, &interface1, NULL);
216 if (ret != EFI_SUCCESS) {
217 efi_st_error("UninstallMultipleProtocolInterfaces failed\n");
218 return EFI_ST_FAILURE;
219 }
220 ret = boottime->uninstall_multiple_protocol_interfaces
221 (handle2, &guid1, &interface1, NULL);
222 if (ret != EFI_SUCCESS) {
223 efi_st_error("UninstallMultipleProtocolInterfaces failed\n");
224 return EFI_ST_FAILURE;
225 }
226
227 return EFI_ST_SUCCESS;
228}
229
230EFI_UNIT_TEST(regprotnot) = {
231 .name = "register protocol notify",
232 .phase = EFI_EXECUTE_BEFORE_BOOTTIME_EXIT,
233 .setup = setup,
234 .execute = execute,
235 .teardown = teardown,
236};
237