efi_selftest_controllers.c 11 KB

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