efi_selftest_controllers.c 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477
  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. static bool allow_removal;
  29. /*
  30. * Count child controllers
  31. *
  32. * @handle handle on which child controllers are installed
  33. * @protocol protocol for which the child controllers were installed
  34. * @count number of child controllers
  35. * Return: status code
  36. */
  37. static efi_status_t count_child_controllers(efi_handle_t handle,
  38. efi_guid_t *protocol,
  39. efi_uintn_t *count)
  40. {
  41. efi_status_t ret;
  42. efi_uintn_t entry_count;
  43. struct efi_open_protocol_info_entry *entry_buffer;
  44. *count = 0;
  45. ret = boottime->open_protocol_information(handle, protocol,
  46. &entry_buffer, &entry_count);
  47. if (ret != EFI_SUCCESS)
  48. return ret;
  49. if (!entry_count)
  50. return EFI_SUCCESS;
  51. while (entry_count) {
  52. if (entry_buffer[--entry_count].attributes &
  53. EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER)
  54. ++*count;
  55. }
  56. ret = boottime->free_pool(entry_buffer);
  57. if (ret != EFI_SUCCESS)
  58. efi_st_error("Cannot free buffer\n");
  59. return ret;
  60. }
  61. /*
  62. * Check if the driver supports the controller.
  63. *
  64. * @this driver binding protocol
  65. * @controller_handle handle of the controller
  66. * @remaining_device_path path specifying the child controller
  67. * Return: status code
  68. */
  69. static efi_status_t EFIAPI supported(
  70. struct efi_driver_binding_protocol *this,
  71. efi_handle_t controller_handle,
  72. struct efi_device_path *remaining_device_path)
  73. {
  74. efi_status_t ret;
  75. void *interface;
  76. ret = boottime->open_protocol(
  77. controller_handle, &guid_controller,
  78. &interface, handle_driver,
  79. controller_handle, EFI_OPEN_PROTOCOL_BY_DRIVER);
  80. switch (ret) {
  81. case EFI_ACCESS_DENIED:
  82. return ret;
  83. case EFI_ALREADY_STARTED:
  84. case EFI_SUCCESS:
  85. break;
  86. default:
  87. return EFI_UNSUPPORTED;
  88. }
  89. ret = boottime->close_protocol(
  90. controller_handle, &guid_controller,
  91. handle_driver, controller_handle);
  92. if (ret != EFI_SUCCESS)
  93. ret = EFI_UNSUPPORTED;
  94. return ret;
  95. }
  96. /*
  97. * Create child controllers and attach driver.
  98. *
  99. * @this driver binding protocol
  100. * @controller_handle handle of the controller
  101. * @remaining_device_path path specifying the child controller
  102. * Return: status code
  103. */
  104. static efi_status_t EFIAPI start(
  105. struct efi_driver_binding_protocol *this,
  106. efi_handle_t controller_handle,
  107. struct efi_device_path *remaining_device_path)
  108. {
  109. size_t i;
  110. efi_status_t ret;
  111. void *interface;
  112. /* Attach driver to controller */
  113. ret = boottime->open_protocol(
  114. controller_handle, &guid_controller,
  115. &interface, handle_driver,
  116. controller_handle, EFI_OPEN_PROTOCOL_BY_DRIVER);
  117. switch (ret) {
  118. case EFI_ACCESS_DENIED:
  119. return ret;
  120. case EFI_ALREADY_STARTED:
  121. case EFI_SUCCESS:
  122. break;
  123. default:
  124. return EFI_UNSUPPORTED;
  125. }
  126. /* Create child controllers */
  127. for (i = 0; i < NUMBER_OF_CHILD_CONTROLLERS; ++i) {
  128. /* Creating a new handle for the child controller */
  129. handle_child_controller[i] = 0;
  130. ret = boottime->install_protocol_interface(
  131. &handle_child_controller[i], &guid_child_controller,
  132. EFI_NATIVE_INTERFACE, NULL);
  133. if (ret != EFI_SUCCESS) {
  134. efi_st_error("InstallProtocolInterface failed\n");
  135. return EFI_ST_FAILURE;
  136. }
  137. ret = boottime->open_protocol(
  138. controller_handle, &guid_controller,
  139. &interface, handle_child_controller[i],
  140. handle_child_controller[i],
  141. EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER);
  142. if (ret != EFI_SUCCESS) {
  143. efi_st_error("OpenProtocol failed\n");
  144. return EFI_ST_FAILURE;
  145. }
  146. }
  147. return ret;
  148. }
  149. /*
  150. * Remove a single child controller from the parent controller.
  151. *
  152. * @controller_handle parent controller
  153. * @child_handle child controller
  154. * Return: status code
  155. */
  156. static efi_status_t disconnect_child(efi_handle_t controller_handle,
  157. efi_handle_t child_handle)
  158. {
  159. efi_status_t ret;
  160. ret = boottime->close_protocol(
  161. controller_handle, &guid_controller,
  162. child_handle, child_handle);
  163. if (ret != EFI_SUCCESS) {
  164. efi_st_error("Cannot close protocol\n");
  165. return ret;
  166. }
  167. ret = boottime->uninstall_protocol_interface(
  168. child_handle, &guid_child_controller, NULL);
  169. if (ret != EFI_SUCCESS) {
  170. efi_st_error("Cannot uninstall protocol interface\n");
  171. return ret;
  172. }
  173. return ret;
  174. }
  175. /*
  176. * Remove child controllers and disconnect the controller.
  177. *
  178. * @this driver binding protocol
  179. * @controller_handle handle of the controller
  180. * @number_of_children number of child controllers to remove
  181. * @child_handle_buffer handles of the child controllers to remove
  182. * Return: status code
  183. */
  184. static efi_status_t EFIAPI stop(
  185. struct efi_driver_binding_protocol *this,
  186. efi_handle_t controller_handle,
  187. size_t number_of_children,
  188. efi_handle_t *child_handle_buffer)
  189. {
  190. efi_status_t ret;
  191. efi_uintn_t count;
  192. struct efi_open_protocol_info_entry *entry_buffer;
  193. /* Destroy provided child controllers */
  194. if (number_of_children) {
  195. efi_uintn_t i;
  196. for (i = 0; i < number_of_children; ++i) {
  197. ret = disconnect_child(controller_handle,
  198. child_handle_buffer[i]);
  199. if (ret != EFI_SUCCESS)
  200. return ret;
  201. }
  202. return EFI_SUCCESS;
  203. }
  204. /* Destroy all children */
  205. ret = boottime->open_protocol_information(
  206. controller_handle, &guid_controller,
  207. &entry_buffer, &count);
  208. if (ret != EFI_SUCCESS) {
  209. efi_st_error("OpenProtocolInformation failed\n");
  210. return ret;
  211. }
  212. while (count) {
  213. if (entry_buffer[--count].attributes &
  214. EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER) {
  215. ret = disconnect_child(
  216. controller_handle,
  217. entry_buffer[count].agent_handle);
  218. if (ret != EFI_SUCCESS)
  219. return ret;
  220. }
  221. }
  222. ret = boottime->free_pool(entry_buffer);
  223. if (ret != EFI_SUCCESS)
  224. efi_st_error("Cannot free buffer\n");
  225. if (!allow_removal)
  226. return EFI_DEVICE_ERROR;
  227. /* Detach driver from controller */
  228. ret = boottime->close_protocol(
  229. controller_handle, &guid_controller,
  230. handle_driver, controller_handle);
  231. if (ret != EFI_SUCCESS) {
  232. efi_st_error("Cannot close protocol\n");
  233. return ret;
  234. }
  235. return EFI_SUCCESS;
  236. }
  237. /* Driver binding protocol interface */
  238. static struct efi_driver_binding_protocol binding_interface = {
  239. supported,
  240. start,
  241. stop,
  242. 0xffffffff,
  243. NULL,
  244. NULL,
  245. };
  246. /*
  247. * Setup unit test.
  248. *
  249. * @handle handle of the loaded image
  250. * @systable system table
  251. */
  252. static int setup(const efi_handle_t img_handle,
  253. const struct efi_system_table *systable)
  254. {
  255. efi_status_t ret;
  256. boottime = systable->boottime;
  257. handle_controller = NULL;
  258. handle_driver = NULL;
  259. /* Create controller handle */
  260. ret = boottime->install_protocol_interface(
  261. &handle_controller, &guid_controller,
  262. EFI_NATIVE_INTERFACE, &interface1);
  263. if (ret != EFI_SUCCESS) {
  264. efi_st_error("InstallProtocolInterface failed\n");
  265. return EFI_ST_FAILURE;
  266. }
  267. /* Create driver handle */
  268. ret = boottime->install_protocol_interface(
  269. &handle_driver, &guid_driver_binding_protocol,
  270. EFI_NATIVE_INTERFACE, &binding_interface);
  271. if (ret != EFI_SUCCESS) {
  272. efi_st_error("InstallProtocolInterface failed\n");
  273. return EFI_ST_FAILURE;
  274. }
  275. return EFI_ST_SUCCESS;
  276. }
  277. /*
  278. * Execute unit test.
  279. *
  280. * The number of child controllers is checked after each of the following
  281. * actions:
  282. *
  283. * Connect a controller to a driver.
  284. * Disconnect and destroy a child controller.
  285. * Disconnect and destroy the remaining child controllers.
  286. *
  287. * Connect a controller to a driver.
  288. * Reinstall the driver protocol on the controller.
  289. * Uninstall the driver protocol from the controller.
  290. */
  291. static int execute(void)
  292. {
  293. efi_status_t ret;
  294. efi_uintn_t count;
  295. /* Connect controller to driver */
  296. ret = boottime->connect_controller(handle_controller, NULL, NULL, 1);
  297. if (ret != EFI_SUCCESS) {
  298. efi_st_error("Failed to connect controller\n");
  299. return EFI_ST_FAILURE;
  300. }
  301. /* Check number of child controllers */
  302. ret = count_child_controllers(handle_controller, &guid_controller,
  303. &count);
  304. if (ret != EFI_SUCCESS || count != NUMBER_OF_CHILD_CONTROLLERS) {
  305. efi_st_error("Number of children %u != %u\n",
  306. (unsigned int)count, NUMBER_OF_CHILD_CONTROLLERS);
  307. }
  308. /* Destroy second child controller */
  309. ret = boottime->disconnect_controller(handle_controller,
  310. handle_driver,
  311. handle_child_controller[1]);
  312. if (ret != EFI_SUCCESS) {
  313. efi_st_error("Failed to disconnect child controller\n");
  314. return EFI_ST_FAILURE;
  315. }
  316. /* Check number of child controllers */
  317. ret = count_child_controllers(handle_controller, &guid_controller,
  318. &count);
  319. if (ret != EFI_SUCCESS || count != NUMBER_OF_CHILD_CONTROLLERS - 1) {
  320. efi_st_error("Destroying single child controller failed\n");
  321. return EFI_ST_FAILURE;
  322. }
  323. /* Destroy remaining child controllers and disconnect controller */
  324. allow_removal = true;
  325. ret = boottime->disconnect_controller(handle_controller, NULL, NULL);
  326. if (ret != EFI_SUCCESS) {
  327. efi_st_error("Failed to disconnect controller\n");
  328. return EFI_ST_FAILURE;
  329. }
  330. /* Check number of child controllers */
  331. ret = count_child_controllers(handle_controller, &guid_controller,
  332. &count);
  333. if (ret != EFI_SUCCESS || count) {
  334. efi_st_error("Destroying child controllers failed\n");
  335. return EFI_ST_FAILURE;
  336. }
  337. /* Connect controller to driver */
  338. ret = boottime->connect_controller(handle_controller, NULL, NULL, 1);
  339. if (ret != EFI_SUCCESS) {
  340. efi_st_error("Failed to connect controller\n");
  341. return EFI_ST_FAILURE;
  342. }
  343. /* Check number of child controllers */
  344. ret = count_child_controllers(handle_controller, &guid_controller,
  345. &count);
  346. if (ret != EFI_SUCCESS || count != NUMBER_OF_CHILD_CONTROLLERS) {
  347. efi_st_error("Number of children %u != %u\n",
  348. (unsigned int)count, NUMBER_OF_CHILD_CONTROLLERS);
  349. }
  350. /* Try to uninstall controller protocol using the wrong interface */
  351. ret = boottime->uninstall_protocol_interface(handle_controller,
  352. &guid_controller,
  353. &interface2);
  354. if (ret == EFI_SUCCESS) {
  355. efi_st_error(
  356. "Interface not checked when uninstalling protocol\n");
  357. return EFI_ST_FAILURE;
  358. }
  359. /* Reinstall controller protocol */
  360. ret = boottime->reinstall_protocol_interface(handle_controller,
  361. &guid_controller,
  362. &interface1,
  363. &interface2);
  364. if (ret != EFI_SUCCESS) {
  365. efi_st_error("Failed to reinstall protocols\n");
  366. return EFI_ST_FAILURE;
  367. }
  368. /* Check number of child controllers */
  369. ret = count_child_controllers(handle_controller, &guid_controller,
  370. &count);
  371. if (ret != EFI_SUCCESS || count != NUMBER_OF_CHILD_CONTROLLERS) {
  372. efi_st_error("Number of children %u != %u\n",
  373. (unsigned int)count, NUMBER_OF_CHILD_CONTROLLERS);
  374. }
  375. allow_removal = false;
  376. /* Try to uninstall controller protocol using the wrong interface */
  377. ret = boottime->uninstall_protocol_interface(handle_controller,
  378. &guid_controller,
  379. &interface1);
  380. if (ret != EFI_NOT_FOUND) {
  381. efi_st_error("Interface not checked when uninstalling protocol\n");
  382. return EFI_ST_FAILURE;
  383. }
  384. /*
  385. * Uninstall a protocol while Disconnect controller won't
  386. * allow it.
  387. */
  388. ret = boottime->uninstall_protocol_interface(handle_controller,
  389. &guid_controller,
  390. &interface2);
  391. if (ret != EFI_ACCESS_DENIED) {
  392. efi_st_error("Uninstall protocol interface failed\n");
  393. return EFI_ST_FAILURE;
  394. }
  395. /*
  396. * Check number of child controllers and make sure children have
  397. * been reconnected
  398. */
  399. ret = count_child_controllers(handle_controller, &guid_controller,
  400. &count);
  401. if (ret != EFI_SUCCESS || count != NUMBER_OF_CHILD_CONTROLLERS) {
  402. efi_st_error("Number of children %u != %u\n",
  403. (unsigned int)count, NUMBER_OF_CHILD_CONTROLLERS);
  404. }
  405. allow_removal = true;
  406. ret = boottime->uninstall_protocol_interface(handle_controller,
  407. &guid_controller,
  408. &interface2);
  409. if (ret != EFI_SUCCESS) {
  410. efi_st_error("Failed to uninstall protocols\n");
  411. return EFI_ST_FAILURE;
  412. }
  413. /* Check number of child controllers */
  414. ret = count_child_controllers(handle_controller, &guid_controller,
  415. &count);
  416. if (ret == EFI_SUCCESS || count) {
  417. efi_st_error("Uninstall failed\n");
  418. return EFI_ST_FAILURE;
  419. }
  420. return EFI_ST_SUCCESS;
  421. }
  422. /*
  423. * Tear down unit test.
  424. *
  425. */
  426. static int teardown(void)
  427. {
  428. efi_status_t ret;
  429. /* Uninstall binding protocol */
  430. ret = boottime->uninstall_protocol_interface(handle_driver,
  431. &guid_driver_binding_protocol,
  432. &binding_interface);
  433. if (ret != EFI_SUCCESS)
  434. efi_st_error("Failed to uninstall protocols\n");
  435. return ret;
  436. }
  437. EFI_UNIT_TEST(controllers) = {
  438. .name = "controllers",
  439. .phase = EFI_EXECUTE_BEFORE_BOOTTIME_EXIT,
  440. .setup = setup,
  441. .execute = execute,
  442. .teardown = teardown,
  443. };