Merge git://git.denx.de/u-boot-dm
[platform/kernel/u-boot.git] / lib / efi_selftest / efi_selftest_controllers.c
1 // SPDX-License-Identifier: GPL-2.0+
2 /*
3  * efi_selftest_controllers
4  *
5  * Copyright (c) 2017 Heinrich Schuchardt <xypron.glpk@gmx.de>
6  *
7  * This unit test checks the following protocol services:
8  * ConnectController, DisconnectController,
9  * InstallProtocol, ReinstallProtocol, UninstallProtocol,
10  * OpenProtocol, CloseProtcol, OpenProtocolInformation
11  */
12
13 #include <efi_selftest.h>
14
15 #define NUMBER_OF_CHILD_CONTROLLERS 4
16
17 static int interface1 = 1;
18 static int interface2 = 2;
19 static struct efi_boot_services *boottime;
20 const efi_guid_t guid_driver_binding_protocol =
21                         EFI_DRIVER_BINDING_PROTOCOL_GUID;
22 static efi_guid_t guid_controller =
23         EFI_GUID(0xe6ab1d96, 0x6bff, 0xdb42,
24                  0xaa, 0x05, 0xc8, 0x1f, 0x7f, 0x45, 0x26, 0x34);
25 static efi_guid_t guid_child_controller =
26         EFI_GUID(0x1d41f6f5, 0x2c41, 0xddfb,
27                  0xe2, 0x9b, 0xb8, 0x0e, 0x2e, 0xe8, 0x3a, 0x85);
28 static efi_handle_t handle_controller;
29 static efi_handle_t handle_child_controller[NUMBER_OF_CHILD_CONTROLLERS];
30 static efi_handle_t handle_driver;
31
32 /*
33  * Count child controllers
34  *
35  * @handle      handle on which child controllers are installed
36  * @protocol    protocol for which the child controlles where installed
37  * @count       number of child controllers
38  * @return      status code
39  */
40 static efi_status_t count_child_controllers(efi_handle_t handle,
41                                             efi_guid_t *protocol,
42                                             efi_uintn_t *count)
43 {
44         efi_status_t ret;
45         efi_uintn_t entry_count;
46         struct efi_open_protocol_info_entry *entry_buffer;
47
48         *count = 0;
49         ret = boottime->open_protocol_information(handle, protocol,
50                                                   &entry_buffer, &entry_count);
51         if (ret != EFI_SUCCESS)
52                 return ret;
53         if (!entry_count)
54                 return EFI_SUCCESS;
55         while (entry_count) {
56                 if (entry_buffer[--entry_count].attributes &
57                     EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER)
58                         ++*count;
59         }
60         ret = boottime->free_pool(entry_buffer);
61         if (ret != EFI_SUCCESS)
62                 efi_st_error("Cannot free buffer\n");
63         return ret;
64 }
65
66 /*
67  * Check if the driver supports the controller.
68  *
69  * @this                        driver binding protocol
70  * @controller_handle           handle of the controller
71  * @remaining_device_path       path specifying the child controller
72  * @return                      status code
73  */
74 static efi_status_t EFIAPI supported(
75                 struct efi_driver_binding_protocol *this,
76                 efi_handle_t controller_handle,
77                 struct efi_device_path *remaining_device_path)
78 {
79         efi_status_t ret;
80         void *interface;
81
82         ret = boottime->open_protocol(
83                         controller_handle, &guid_controller,
84                         &interface, handle_driver,
85                         controller_handle, EFI_OPEN_PROTOCOL_BY_DRIVER);
86         switch (ret) {
87         case EFI_ACCESS_DENIED:
88         case EFI_ALREADY_STARTED:
89                 return ret;
90         case EFI_SUCCESS:
91                 break;
92         default:
93                 return EFI_UNSUPPORTED;
94         }
95         ret = boottime->close_protocol(
96                                 controller_handle, &guid_controller,
97                                 handle_driver, controller_handle);
98         if (ret != EFI_SUCCESS)
99                 ret = EFI_UNSUPPORTED;
100         return ret;
101 }
102
103 /*
104  * Create child controllers and attach driver.
105  *
106  * @this                        driver binding protocol
107  * @controller_handle           handle of the controller
108  * @remaining_device_path       path specifying the child controller
109  * @return                      status code
110  */
111 static efi_status_t EFIAPI start(
112                 struct efi_driver_binding_protocol *this,
113                 efi_handle_t controller_handle,
114                 struct efi_device_path *remaining_device_path)
115 {
116         size_t i;
117         efi_status_t ret;
118         void *interface;
119
120         /* Attach driver to controller */
121         ret = boottime->open_protocol(
122                         controller_handle, &guid_controller,
123                         &interface, handle_driver,
124                         controller_handle, EFI_OPEN_PROTOCOL_BY_DRIVER);
125         switch (ret) {
126         case EFI_ACCESS_DENIED:
127         case EFI_ALREADY_STARTED:
128                 return ret;
129         case EFI_SUCCESS:
130                 break;
131         default:
132                 return EFI_UNSUPPORTED;
133         }
134
135         /* Create child controllers */
136         for (i = 0; i < NUMBER_OF_CHILD_CONTROLLERS; ++i) {
137                 ret = boottime->install_protocol_interface(
138                         &handle_child_controller[i], &guid_child_controller,
139                         EFI_NATIVE_INTERFACE, NULL);
140                 if (ret != EFI_SUCCESS) {
141                         efi_st_error("InstallProtocolInterface failed\n");
142                         return EFI_ST_FAILURE;
143                 }
144                 ret = boottime->open_protocol(
145                         controller_handle, &guid_controller,
146                         &interface, handle_child_controller[i],
147                         handle_child_controller[i],
148                         EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER);
149                 if (ret != EFI_SUCCESS) {
150                         efi_st_error("OpenProtocol failed\n");
151                         return EFI_ST_FAILURE;
152                 }
153         }
154         return ret;
155 }
156
157 /*
158  * Remove a single child controller from the parent controller.
159  *
160  * @controller_handle   parent controller
161  * @child_handle        child controller
162  * @return              status code
163  */
164 static efi_status_t disconnect_child(efi_handle_t controller_handle,
165                                      efi_handle_t child_handle)
166 {
167         efi_status_t ret;
168
169         ret = boottime->close_protocol(
170                                 controller_handle, &guid_controller,
171                                 child_handle, child_handle);
172         if (ret != EFI_SUCCESS) {
173                 efi_st_error("Cannot close protocol\n");
174                 return ret;
175         }
176         ret = boottime->uninstall_protocol_interface(
177                                 child_handle, &guid_child_controller, NULL);
178         if (ret != EFI_SUCCESS) {
179                 efi_st_error("Cannot uninstall protocol interface\n");
180                 return ret;
181         }
182         return ret;
183 }
184
185 /*
186  * Remove child controllers and disconnect the controller.
187  *
188  * @this                        driver binding protocol
189  * @controller_handle           handle of the controller
190  * @number_of_children          number of child controllers to remove
191  * @child_handle_buffer         handles of the child controllers to remove
192  * @return                      status code
193  */
194 static efi_status_t EFIAPI stop(
195                 struct efi_driver_binding_protocol *this,
196                 efi_handle_t controller_handle,
197                 size_t number_of_children,
198                 efi_handle_t *child_handle_buffer)
199 {
200         efi_status_t ret;
201         efi_uintn_t count;
202         struct efi_open_protocol_info_entry *entry_buffer;
203
204         /* Destroy provided child controllers */
205         if (number_of_children) {
206                 efi_uintn_t i;
207
208                 for (i = 0; i < number_of_children; ++i) {
209                         ret = disconnect_child(controller_handle,
210                                                child_handle_buffer[i]);
211                         if (ret != EFI_SUCCESS)
212                                 return ret;
213                 }
214                 return EFI_SUCCESS;
215         }
216
217         /* Destroy all children */
218         ret = boottime->open_protocol_information(
219                                         controller_handle, &guid_controller,
220                                         &entry_buffer, &count);
221         if (ret != EFI_SUCCESS) {
222                 efi_st_error("OpenProtocolInformation failed\n");
223                 return ret;
224         }
225         while (count) {
226                 if (entry_buffer[--count].attributes &
227                     EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER) {
228                         ret = disconnect_child(
229                                         controller_handle,
230                                         entry_buffer[count].agent_handle);
231                         if (ret != EFI_SUCCESS)
232                                 return ret;
233                 }
234         }
235         ret = boottime->free_pool(entry_buffer);
236         if (ret != EFI_SUCCESS)
237                 efi_st_error("Cannot free buffer\n");
238
239         /* Detach driver from controller */
240         ret = boottime->close_protocol(
241                         controller_handle, &guid_controller,
242                         handle_driver, controller_handle);
243         if (ret != EFI_SUCCESS) {
244                 efi_st_error("Cannot close protocol\n");
245                 return ret;
246         }
247         return EFI_SUCCESS;
248 }
249
250 /* Driver binding protocol interface */
251 static struct efi_driver_binding_protocol binding_interface = {
252         supported,
253         start,
254         stop,
255         0xffffffff,
256         NULL,
257         NULL,
258         };
259
260 /*
261  * Setup unit test.
262  *
263  * @handle      handle of the loaded image
264  * @systable    system table
265  */
266 static int setup(const efi_handle_t img_handle,
267                  const struct efi_system_table *systable)
268 {
269         efi_status_t ret;
270
271         boottime = systable->boottime;
272
273         /* Create controller handle */
274         ret = boottime->install_protocol_interface(
275                         &handle_controller, &guid_controller,
276                         EFI_NATIVE_INTERFACE, &interface1);
277         if (ret != EFI_SUCCESS) {
278                 efi_st_error("InstallProtocolInterface failed\n");
279                 return EFI_ST_FAILURE;
280         }
281         /* Create driver handle */
282         ret = boottime->install_protocol_interface(
283                         &handle_driver,  &guid_driver_binding_protocol,
284                         EFI_NATIVE_INTERFACE, &binding_interface);
285         if (ret != EFI_SUCCESS) {
286                 efi_st_error("InstallProtocolInterface failed\n");
287                 return EFI_ST_FAILURE;
288         }
289
290         return EFI_ST_SUCCESS;
291 }
292
293 /*
294  * Execute unit test.
295  *
296  * The number of child controllers is checked after each of the following
297  * actions:
298  *
299  * Connect a controller to a driver.
300  * Disconnect and destroy a child controller.
301  * Disconnect and destroy the remaining child controllers.
302  *
303  * Connect a controller to a driver.
304  * Reinstall the driver protocol on the controller.
305  * Uninstall the driver protocol from the controller.
306  */
307 static int execute(void)
308 {
309         efi_status_t ret;
310         efi_uintn_t count;
311
312         /* Connect controller to driver */
313         ret = boottime->connect_controller(handle_controller, NULL, NULL, 1);
314         if (ret != EFI_SUCCESS) {
315                 efi_st_error("Failed to connect controller\n");
316                 return EFI_ST_FAILURE;
317         }
318         /* Check number of child controllers */
319         ret = count_child_controllers(handle_controller, &guid_controller,
320                                       &count);
321         if (ret != EFI_SUCCESS || count != NUMBER_OF_CHILD_CONTROLLERS) {
322                 efi_st_error("Number of children %u != %u\n",
323                              (unsigned int)count, NUMBER_OF_CHILD_CONTROLLERS);
324         }
325         /* Destroy second child controller */
326         ret = boottime->disconnect_controller(handle_controller,
327                                               handle_driver,
328                                               handle_child_controller[1]);
329         if (ret != EFI_SUCCESS) {
330                 efi_st_error("Failed to disconnect child controller\n");
331                 return EFI_ST_FAILURE;
332         }
333         /* Check number of child controllers */
334         ret = count_child_controllers(handle_controller, &guid_controller,
335                                       &count);
336         if (ret != EFI_SUCCESS || count != NUMBER_OF_CHILD_CONTROLLERS - 1) {
337                 efi_st_error("Destroying single child controller failed\n");
338                 return EFI_ST_FAILURE;
339         }
340         /* Destroy remaining child controllers and disconnect controller */
341         ret = boottime->disconnect_controller(handle_controller, NULL, NULL);
342         if (ret != EFI_SUCCESS) {
343                 efi_st_error("Failed to disconnect controller\n");
344                 return EFI_ST_FAILURE;
345         }
346         /* Check number of child controllers */
347         ret = count_child_controllers(handle_controller, &guid_controller,
348                                       &count);
349         if (ret != EFI_SUCCESS || count) {
350                 efi_st_error("Destroying child controllers failed\n");
351                 return EFI_ST_FAILURE;
352         }
353
354         /* Connect controller to driver */
355         ret = boottime->connect_controller(handle_controller, NULL, NULL, 1);
356         if (ret != EFI_SUCCESS) {
357                 efi_st_error("Failed to connect controller\n");
358                 return EFI_ST_FAILURE;
359         }
360         /* Check number of child controllers */
361         ret = count_child_controllers(handle_controller, &guid_controller,
362                                       &count);
363         if (ret != EFI_SUCCESS || count != NUMBER_OF_CHILD_CONTROLLERS) {
364                 efi_st_error("Number of children %u != %u\n",
365                              (unsigned int)count, NUMBER_OF_CHILD_CONTROLLERS);
366         }
367         /* Try to uninstall controller protocol using the wrong interface */
368         ret = boottime->uninstall_protocol_interface(handle_controller,
369                                                      &guid_controller,
370                                                      &interface2);
371         if (ret == EFI_SUCCESS) {
372                 efi_st_error(
373                         "Interface not checked when uninstalling protocol\n");
374                 return EFI_ST_FAILURE;
375         }
376         /* Reinstall controller protocol */
377         ret = boottime->reinstall_protocol_interface(handle_controller,
378                                                      &guid_controller,
379                                                      &interface1,
380                                                      &interface2);
381         if (ret != EFI_SUCCESS) {
382                 efi_st_error("Failed to reinstall protocols\n");
383                 return EFI_ST_FAILURE;
384         }
385         /* Check number of child controllers */
386         ret = count_child_controllers(handle_controller, &guid_controller,
387                                       &count);
388         if (ret != EFI_SUCCESS || count != NUMBER_OF_CHILD_CONTROLLERS) {
389                 efi_st_error("Number of children %u != %u\n",
390                              (unsigned int)count, NUMBER_OF_CHILD_CONTROLLERS);
391         }
392         /* Uninstall controller protocol */
393         ret = boottime->uninstall_protocol_interface(handle_controller,
394                                                      &guid_controller,
395                                                      &interface2);
396         if (ret != EFI_SUCCESS) {
397                 efi_st_error("Failed to uninstall protocols\n");
398                 return EFI_ST_FAILURE;
399         }
400         /* Check number of child controllers */
401         ret = count_child_controllers(handle_controller, &guid_controller,
402                                       &count);
403         if (ret == EFI_SUCCESS)
404                 efi_st_error("Uninstall failed\n");
405         return EFI_ST_SUCCESS;
406 }
407
408 EFI_UNIT_TEST(controllers) = {
409         .name = "controllers",
410         .phase = EFI_EXECUTE_BEFORE_BOOTTIME_EXIT,
411         .setup = setup,
412         .execute = execute,
413 };