efi_selftest_manageprotocols.c 9.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354
  1. /*
  2. * efi_selftest_manageprotocols
  3. *
  4. * Copyright (c) 2017 Heinrich Schuchardt <xypron.glpk@gmx.de>
  5. *
  6. * SPDX-License-Identifier: GPL-2.0+
  7. *
  8. * This unit test checks the following protocol services:
  9. * InstallProtocolInterface, UninstallProtocolInterface,
  10. * InstallMultipleProtocolsInterfaces, UninstallMultipleProtocolsInterfaces,
  11. * HandleProtocol, ProtocolsPerHandle,
  12. * LocateHandle, LocateHandleBuffer.
  13. */
  14. #include <efi_selftest.h>
  15. /*
  16. * The test currently does not actually call the interface function.
  17. * So this is just a dummy structure.
  18. */
  19. struct interface {
  20. void (EFIAPI * inc)(void);
  21. };
  22. static struct efi_boot_services *boottime;
  23. static efi_guid_t guid1 =
  24. EFI_GUID(0x2e7ca819, 0x21d3, 0x0a3a,
  25. 0xf7, 0x91, 0x82, 0x1f, 0x7a, 0x83, 0x67, 0xaf);
  26. static efi_guid_t guid2 =
  27. EFI_GUID(0xf909f2bb, 0x90a8, 0x0d77,
  28. 0x94, 0x0c, 0x3e, 0xa8, 0xea, 0x38, 0xd6, 0x6f);
  29. static efi_guid_t guid3 =
  30. EFI_GUID(0x06d641a3, 0xf4e7, 0xe0c9,
  31. 0xe7, 0x8d, 0x41, 0x2d, 0x72, 0xa6, 0xb1, 0x24);
  32. static efi_handle_t handle1;
  33. static efi_handle_t handle2;
  34. static struct interface interface1;
  35. static struct interface interface2;
  36. static struct interface interface3;
  37. static struct interface interface4;
  38. /*
  39. * Find a handle in an array.
  40. *
  41. * @handle: handle to find
  42. * @count: number of entries in the array
  43. * @buffer: array to search
  44. */
  45. efi_status_t find_in_buffer(efi_handle_t handle, size_t count,
  46. efi_handle_t *buffer)
  47. {
  48. size_t i;
  49. for (i = 0; i < count; ++i) {
  50. if (buffer[i] == handle)
  51. return EFI_SUCCESS;
  52. }
  53. return EFI_NOT_FOUND;
  54. }
  55. /*
  56. * Setup unit test.
  57. *
  58. * Create two handles and install two out of three protocol interfaces on each
  59. * of them:
  60. *
  61. * handle1
  62. * guid1 interface1
  63. * guid3 interface3
  64. * handle2
  65. * guid1 interface4
  66. * guid2 interface2
  67. *
  68. * @handle: handle of the loaded image
  69. * @systable: system table
  70. */
  71. static int setup(const efi_handle_t img_handle,
  72. const struct efi_system_table *systable)
  73. {
  74. efi_status_t ret;
  75. efi_handle_t handle;
  76. boottime = systable->boottime;
  77. ret = boottime->install_protocol_interface(&handle1, &guid3,
  78. EFI_NATIVE_INTERFACE,
  79. &interface3);
  80. if (ret != EFI_SUCCESS) {
  81. efi_st_error("InstallProtocolInterface failed\n");
  82. return EFI_ST_FAILURE;
  83. }
  84. if (!handle1) {
  85. efi_st_error("InstallProtocolInterface failed to create handle\n");
  86. return EFI_ST_FAILURE;
  87. }
  88. handle = handle1;
  89. ret = boottime->install_protocol_interface(&handle1, &guid1,
  90. EFI_NATIVE_INTERFACE,
  91. &interface1);
  92. if (ret != EFI_SUCCESS) {
  93. efi_st_error("InstallProtocolInterface failed\n");
  94. return EFI_ST_FAILURE;
  95. }
  96. if (handle != handle1) {
  97. efi_st_error("InstallProtocolInterface failed to use handle\n");
  98. return EFI_ST_FAILURE;
  99. }
  100. ret = boottime->install_multiple_protocol_interfaces(&handle2,
  101. &guid1, &interface4, &guid2, &interface2, NULL);
  102. if (ret != EFI_SUCCESS) {
  103. efi_st_error("InstallMultipleProtocolInterfaces failed\n");
  104. return EFI_ST_FAILURE;
  105. }
  106. if (!handle2 || handle1 == handle2) {
  107. efi_st_error("InstallMultipleProtocolInterfaces failed to create handle\n");
  108. return EFI_ST_FAILURE;
  109. }
  110. return EFI_ST_SUCCESS;
  111. }
  112. /*
  113. * Tear down unit test.
  114. *
  115. */
  116. static int teardown(void)
  117. {
  118. return EFI_ST_SUCCESS;
  119. }
  120. /*
  121. * Execute unit test.
  122. *
  123. */
  124. static int execute(void)
  125. {
  126. struct interface *interface;
  127. efi_status_t ret;
  128. efi_handle_t *buffer;
  129. size_t buffer_size;
  130. efi_uintn_t count = 0;
  131. efi_guid_t **prot_buffer;
  132. efi_uintn_t prot_count;
  133. /*
  134. * Test HandleProtocol
  135. */
  136. ret = boottime->handle_protocol(handle1, &guid3, (void **)&interface);
  137. if (ret != EFI_SUCCESS) {
  138. efi_st_error("HandleProtocol failed to retrieve interface\n");
  139. return EFI_ST_FAILURE;
  140. }
  141. if (interface != &interface3) {
  142. efi_st_error("HandleProtocol returned wrong interface\n");
  143. return EFI_ST_FAILURE;
  144. }
  145. ret = boottime->handle_protocol(handle1, &guid2, (void **)&interface);
  146. if (ret == EFI_SUCCESS) {
  147. efi_st_error("HandleProtocol returned not installed interface\n");
  148. return EFI_ST_FAILURE;
  149. }
  150. /*
  151. * Test LocateHandleBuffer with AllHandles
  152. */
  153. ret = boottime->locate_handle_buffer(ALL_HANDLES, NULL, NULL,
  154. &count, &buffer);
  155. if (ret != EFI_SUCCESS) {
  156. efi_st_error("LocateHandleBuffer with AllHandles failed\n");
  157. return EFI_ST_FAILURE;
  158. }
  159. buffer_size = count;
  160. ret = find_in_buffer(handle1, count, buffer);
  161. if (ret != EFI_SUCCESS) {
  162. efi_st_error("LocateHandleBuffer failed to locate new handle\n");
  163. return EFI_ST_FAILURE;
  164. }
  165. ret = find_in_buffer(handle2, count, buffer);
  166. if (ret != EFI_SUCCESS) {
  167. efi_st_error("LocateHandleBuffer failed to locate new handle\n");
  168. return EFI_ST_FAILURE;
  169. }
  170. boottime->set_mem(buffer, sizeof(efi_handle_t) * buffer_size, 0);
  171. /*
  172. * Test error handling in UninstallMultipleProtocols
  173. *
  174. * Try to uninstall more protocols than there are installed.
  175. */
  176. ret = boottime->uninstall_multiple_protocol_interfaces(
  177. handle2,
  178. &guid1, &interface4,
  179. &guid2, &interface2,
  180. &guid3, &interface3,
  181. NULL);
  182. if (ret == EFI_SUCCESS) {
  183. efi_st_todo("UninstallMultipleProtocolInterfaces did not catch error\n");
  184. return EFI_ST_FAILURE;
  185. }
  186. /*
  187. * Test LocateHandleBuffer with ByProtocol
  188. */
  189. count = buffer_size;
  190. ret = boottime->locate_handle_buffer(BY_PROTOCOL, &guid1, NULL,
  191. &count, &buffer);
  192. if (ret != EFI_SUCCESS) {
  193. efi_st_error("LocateHandleBuffer failed to locate new handles\n");
  194. return EFI_ST_FAILURE;
  195. }
  196. if (count != 2) {
  197. efi_st_error("LocateHandleBuffer failed to locate new handles\n");
  198. return EFI_ST_FAILURE;
  199. }
  200. ret = find_in_buffer(handle1, count, buffer);
  201. if (ret != EFI_SUCCESS) {
  202. efi_st_error("LocateHandleBuffer failed to locate new handle\n");
  203. return EFI_ST_FAILURE;
  204. }
  205. ret = find_in_buffer(handle2, count, buffer);
  206. if (ret != EFI_SUCCESS) {
  207. efi_st_error("LocateHandleBuffer failed to locate new handle\n");
  208. return EFI_ST_FAILURE;
  209. }
  210. boottime->set_mem(buffer, sizeof(efi_handle_t) * buffer_size, 0);
  211. /*
  212. * Test LocateHandle with ByProtocol
  213. */
  214. count = buffer_size * sizeof(efi_handle_t);
  215. ret = boottime->locate_handle(BY_PROTOCOL, &guid1, NULL,
  216. &count, buffer);
  217. if (ret != EFI_SUCCESS) {
  218. efi_st_error("LocateHandle with ByProtocol failed\n");
  219. return EFI_ST_FAILURE;
  220. }
  221. if (count / sizeof(efi_handle_t) != 2) {
  222. efi_st_error("LocateHandle failed to locate new handles\n");
  223. return EFI_ST_FAILURE;
  224. }
  225. buffer_size = count;
  226. ret = find_in_buffer(handle1, count, buffer);
  227. if (ret != EFI_SUCCESS) {
  228. efi_st_error("LocateHandle failed to locate new handles\n");
  229. return EFI_ST_FAILURE;
  230. }
  231. ret = find_in_buffer(handle2, count, buffer);
  232. if (ret != EFI_SUCCESS) {
  233. efi_st_error("LocateHandle failed to locate new handles\n");
  234. return EFI_ST_FAILURE;
  235. }
  236. boottime->set_mem(buffer, sizeof(efi_handle_t) * buffer_size, 0);
  237. /*
  238. * Test LocateProtocol
  239. */
  240. ret = boottime->locate_protocol(&guid1, NULL, (void **)&interface);
  241. if (ret != EFI_SUCCESS) {
  242. efi_st_error("LocateProtocol failed\n");
  243. return EFI_ST_FAILURE;
  244. }
  245. if (interface != &interface1 && interface != &interface4) {
  246. efi_st_error("LocateProtocol failed to locate protocol\n");
  247. return EFI_ST_FAILURE;
  248. }
  249. /*
  250. * Test UninstallMultipleProtocols
  251. */
  252. ret = boottime->uninstall_multiple_protocol_interfaces(
  253. handle2,
  254. &guid1, &interface4,
  255. &guid2, &interface2,
  256. NULL);
  257. if (ret != EFI_SUCCESS) {
  258. efi_st_todo("UninstallMultipleProtocolInterfaces failed\n");
  259. /* This test is known to fail due to missing implementation */
  260. }
  261. /*
  262. * Check that the protocols are really uninstalled.
  263. */
  264. count = buffer_size;
  265. ret = boottime->locate_handle_buffer(BY_PROTOCOL, &guid1, NULL,
  266. &count, &buffer);
  267. if (ret != EFI_SUCCESS) {
  268. efi_st_error("LocateHandleBuffer failed\n");
  269. return EFI_ST_FAILURE;
  270. }
  271. if (count != 1) {
  272. efi_st_todo("UninstallMultipleProtocolInterfaces failed to uninstall protocols\n");
  273. /* This test is known to fail due to missing implementation */
  274. }
  275. ret = find_in_buffer(handle1, count, buffer);
  276. if (ret != EFI_SUCCESS) {
  277. efi_st_error("Failed to locate new handle\n");
  278. return EFI_ST_FAILURE;
  279. }
  280. boottime->set_mem(buffer, sizeof(efi_handle_t) * buffer_size, 0);
  281. /*
  282. * Test ProtocolsPerHandle
  283. */
  284. ret = boottime->protocols_per_handle(handle1,
  285. &prot_buffer, &prot_count);
  286. if (ret != EFI_SUCCESS) {
  287. efi_st_error("Failed to get protocols per handle\n");
  288. return EFI_ST_FAILURE;
  289. }
  290. if (prot_count != 2) {
  291. efi_st_error("Failed to get protocols per handle\n");
  292. return EFI_ST_FAILURE;
  293. }
  294. if (efi_st_memcmp(prot_buffer[0], &guid1, 16) &&
  295. efi_st_memcmp(prot_buffer[1], &guid1, 16)) {
  296. efi_st_error("Failed to get protocols per handle\n");
  297. return EFI_ST_FAILURE;
  298. }
  299. if (efi_st_memcmp(prot_buffer[0], &guid3, 16) &&
  300. efi_st_memcmp(prot_buffer[1], &guid3, 16)) {
  301. efi_st_error("Failed to get protocols per handle\n");
  302. return EFI_ST_FAILURE;
  303. }
  304. /*
  305. * Uninstall remaining protocols
  306. */
  307. ret = boottime->uninstall_protocol_interface(handle1, &guid1,
  308. &interface1);
  309. if (ret != EFI_SUCCESS) {
  310. efi_st_todo("UninstallProtocolInterface failed\n");
  311. /* This test is known to fail due to missing implementation */
  312. }
  313. ret = boottime->handle_protocol(handle1, &guid1, (void **)&interface);
  314. if (ret == EFI_SUCCESS) {
  315. efi_st_todo("UninstallProtocolInterface failed\n");
  316. /* This test is known to fail due to missing implementation */
  317. }
  318. ret = boottime->uninstall_protocol_interface(handle1, &guid3,
  319. &interface1);
  320. if (ret != EFI_SUCCESS) {
  321. efi_st_todo("UninstallProtocolInterface failed\n");
  322. /* This test is known to fail due to missing implementation */
  323. }
  324. return EFI_ST_SUCCESS;
  325. }
  326. EFI_UNIT_TEST(protserv) = {
  327. .name = "manage protocols",
  328. .phase = EFI_EXECUTE_BEFORE_BOOTTIME_EXIT,
  329. .setup = setup,
  330. .execute = execute,
  331. .teardown = teardown,
  332. };