mtd: sf: Make sf_mtd.c more robust
[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                 /* Creating a new handle for the child controller */
138                 handle_child_controller[i] = 0;
139                 ret = boottime->install_protocol_interface(
140                         &handle_child_controller[i], &guid_child_controller,
141                         EFI_NATIVE_INTERFACE, NULL);
142                 if (ret != EFI_SUCCESS) {
143                         efi_st_error("InstallProtocolInterface failed\n");
144                         return EFI_ST_FAILURE;
145                 }
146                 ret = boottime->open_protocol(
147                         controller_handle, &guid_controller,
148                         &interface, handle_child_controller[i],
149                         handle_child_controller[i],
150                         EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER);
151                 if (ret != EFI_SUCCESS) {
152                         efi_st_error("OpenProtocol failed\n");
153                         return EFI_ST_FAILURE;
154                 }
155         }
156         return ret;
157 }
158
159 /*
160  * Remove a single child controller from the parent controller.
161  *
162  * @controller_handle   parent controller
163  * @child_handle        child controller
164  * @return              status code
165  */
166 static efi_status_t disconnect_child(efi_handle_t controller_handle,
167                                      efi_handle_t child_handle)
168 {
169         efi_status_t ret;
170
171         ret = boottime->close_protocol(
172                                 controller_handle, &guid_controller,
173                                 child_handle, child_handle);
174         if (ret != EFI_SUCCESS) {
175                 efi_st_error("Cannot close protocol\n");
176                 return ret;
177         }
178         ret = boottime->uninstall_protocol_interface(
179                                 child_handle, &guid_child_controller, NULL);
180         if (ret != EFI_SUCCESS) {
181                 efi_st_error("Cannot uninstall protocol interface\n");
182                 return ret;
183         }
184         return ret;
185 }
186
187 /*
188  * Remove child controllers and disconnect the controller.
189  *
190  * @this                        driver binding protocol
191  * @controller_handle           handle of the controller
192  * @number_of_children          number of child controllers to remove
193  * @child_handle_buffer         handles of the child controllers to remove
194  * @return                      status code
195  */
196 static efi_status_t EFIAPI stop(
197                 struct efi_driver_binding_protocol *this,
198                 efi_handle_t controller_handle,
199                 size_t number_of_children,
200                 efi_handle_t *child_handle_buffer)
201 {
202         efi_status_t ret;
203         efi_uintn_t count;
204         struct efi_open_protocol_info_entry *entry_buffer;
205
206         /* Destroy provided child controllers */
207         if (number_of_children) {
208                 efi_uintn_t i;
209
210                 for (i = 0; i < number_of_children; ++i) {
211                         ret = disconnect_child(controller_handle,
212                                                child_handle_buffer[i]);
213                         if (ret != EFI_SUCCESS)
214                                 return ret;
215                 }
216                 return EFI_SUCCESS;
217         }
218
219         /* Destroy all children */
220         ret = boottime->open_protocol_information(
221                                         controller_handle, &guid_controller,
222                                         &entry_buffer, &count);
223         if (ret != EFI_SUCCESS) {
224                 efi_st_error("OpenProtocolInformation failed\n");
225                 return ret;
226         }
227         while (count) {
228                 if (entry_buffer[--count].attributes &
229                     EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER) {
230                         ret = disconnect_child(
231                                         controller_handle,
232                                         entry_buffer[count].agent_handle);
233                         if (ret != EFI_SUCCESS)
234                                 return ret;
235                 }
236         }
237         ret = boottime->free_pool(entry_buffer);
238         if (ret != EFI_SUCCESS)
239                 efi_st_error("Cannot free buffer\n");
240
241         /* Detach driver from controller */
242         ret = boottime->close_protocol(
243                         controller_handle, &guid_controller,
244                         handle_driver, controller_handle);
245         if (ret != EFI_SUCCESS) {
246                 efi_st_error("Cannot close protocol\n");
247                 return ret;
248         }
249         return EFI_SUCCESS;
250 }
251
252 /* Driver binding protocol interface */
253 static struct efi_driver_binding_protocol binding_interface = {
254         supported,
255         start,
256         stop,
257         0xffffffff,
258         NULL,
259         NULL,
260         };
261
262 /*
263  * Setup unit test.
264  *
265  * @handle      handle of the loaded image
266  * @systable    system table
267  */
268 static int setup(const efi_handle_t img_handle,
269                  const struct efi_system_table *systable)
270 {
271         efi_status_t ret;
272
273         boottime = systable->boottime;
274
275         /* Create controller handle */
276         ret = boottime->install_protocol_interface(
277                         &handle_controller, &guid_controller,
278                         EFI_NATIVE_INTERFACE, &interface1);
279         if (ret != EFI_SUCCESS) {
280                 efi_st_error("InstallProtocolInterface failed\n");
281                 return EFI_ST_FAILURE;
282         }
283         /* Create driver handle */
284         ret = boottime->install_protocol_interface(
285                         &handle_driver,  &guid_driver_binding_protocol,
286                         EFI_NATIVE_INTERFACE, &binding_interface);
287         if (ret != EFI_SUCCESS) {
288                 efi_st_error("InstallProtocolInterface failed\n");
289                 return EFI_ST_FAILURE;
290         }
291
292         return EFI_ST_SUCCESS;
293 }
294
295 /*
296  * Execute unit test.
297  *
298  * The number of child controllers is checked after each of the following
299  * actions:
300  *
301  * Connect a controller to a driver.
302  * Disconnect and destroy a child controller.
303  * Disconnect and destroy the remaining child controllers.
304  *
305  * Connect a controller to a driver.
306  * Reinstall the driver protocol on the controller.
307  * Uninstall the driver protocol from the controller.
308  */
309 static int execute(void)
310 {
311         efi_status_t ret;
312         efi_uintn_t count;
313
314         /* Connect controller to driver */
315         ret = boottime->connect_controller(handle_controller, NULL, NULL, 1);
316         if (ret != EFI_SUCCESS) {
317                 efi_st_error("Failed to connect controller\n");
318                 return EFI_ST_FAILURE;
319         }
320         /* Check number of child controllers */
321         ret = count_child_controllers(handle_controller, &guid_controller,
322                                       &count);
323         if (ret != EFI_SUCCESS || count != NUMBER_OF_CHILD_CONTROLLERS) {
324                 efi_st_error("Number of children %u != %u\n",
325                              (unsigned int)count, NUMBER_OF_CHILD_CONTROLLERS);
326         }
327         /* Destroy second child controller */
328         ret = boottime->disconnect_controller(handle_controller,
329                                               handle_driver,
330                                               handle_child_controller[1]);
331         if (ret != EFI_SUCCESS) {
332                 efi_st_error("Failed to disconnect child controller\n");
333                 return EFI_ST_FAILURE;
334         }
335         /* Check number of child controllers */
336         ret = count_child_controllers(handle_controller, &guid_controller,
337                                       &count);
338         if (ret != EFI_SUCCESS || count != NUMBER_OF_CHILD_CONTROLLERS - 1) {
339                 efi_st_error("Destroying single child controller failed\n");
340                 return EFI_ST_FAILURE;
341         }
342         /* Destroy remaining child controllers and disconnect controller */
343         ret = boottime->disconnect_controller(handle_controller, NULL, NULL);
344         if (ret != EFI_SUCCESS) {
345                 efi_st_error("Failed to disconnect controller\n");
346                 return EFI_ST_FAILURE;
347         }
348         /* Check number of child controllers */
349         ret = count_child_controllers(handle_controller, &guid_controller,
350                                       &count);
351         if (ret != EFI_SUCCESS || count) {
352                 efi_st_error("Destroying child controllers failed\n");
353                 return EFI_ST_FAILURE;
354         }
355
356         /* Connect controller to driver */
357         ret = boottime->connect_controller(handle_controller, NULL, NULL, 1);
358         if (ret != EFI_SUCCESS) {
359                 efi_st_error("Failed to connect controller\n");
360                 return EFI_ST_FAILURE;
361         }
362         /* Check number of child controllers */
363         ret = count_child_controllers(handle_controller, &guid_controller,
364                                       &count);
365         if (ret != EFI_SUCCESS || count != NUMBER_OF_CHILD_CONTROLLERS) {
366                 efi_st_error("Number of children %u != %u\n",
367                              (unsigned int)count, NUMBER_OF_CHILD_CONTROLLERS);
368         }
369         /* Try to uninstall controller protocol using the wrong interface */
370         ret = boottime->uninstall_protocol_interface(handle_controller,
371                                                      &guid_controller,
372                                                      &interface2);
373         if (ret == EFI_SUCCESS) {
374                 efi_st_error(
375                         "Interface not checked when uninstalling protocol\n");
376                 return EFI_ST_FAILURE;
377         }
378         /* Reinstall controller protocol */
379         ret = boottime->reinstall_protocol_interface(handle_controller,
380                                                      &guid_controller,
381                                                      &interface1,
382                                                      &interface2);
383         if (ret != EFI_SUCCESS) {
384                 efi_st_error("Failed to reinstall protocols\n");
385                 return EFI_ST_FAILURE;
386         }
387         /* Check number of child controllers */
388         ret = count_child_controllers(handle_controller, &guid_controller,
389                                       &count);
390         if (ret != EFI_SUCCESS || count != NUMBER_OF_CHILD_CONTROLLERS) {
391                 efi_st_error("Number of children %u != %u\n",
392                              (unsigned int)count, NUMBER_OF_CHILD_CONTROLLERS);
393         }
394         /* Uninstall controller protocol */
395         ret = boottime->uninstall_protocol_interface(handle_controller,
396                                                      &guid_controller,
397                                                      &interface2);
398         if (ret != EFI_SUCCESS) {
399                 efi_st_error("Failed to uninstall protocols\n");
400                 return EFI_ST_FAILURE;
401         }
402         /* Check number of child controllers */
403         ret = count_child_controllers(handle_controller, &guid_controller,
404                                       &count);
405         if (ret == EFI_SUCCESS)
406                 efi_st_error("Uninstall failed\n");
407         return EFI_ST_SUCCESS;
408 }
409
410 EFI_UNIT_TEST(controllers) = {
411         .name = "controllers",
412         .phase = EFI_EXECUTE_BEFORE_BOOTTIME_EXIT,
413         .setup = setup,
414         .execute = execute,
415 };