efi_selftest_controllers.c 10 KB

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