efi_selftest_controllers.c 12 KB

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