efi_selftest_register_notify.c 5.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236
  1. // SPDX-License-Identifier: GPL-2.0+
  2. /*
  3. * efi_selftest_register_notify
  4. *
  5. * Copyright (c) 2019 Heinrich Schuchardt <xypron.glpk@gmx.de>
  6. *
  7. * This unit test checks the following protocol services:
  8. * InstallProtocolInterface, UninstallProtocolInterface,
  9. * RegisterProtocolNotify, CreateEvent, CloseEvent.
  10. */
  11. #include <efi_selftest.h>
  12. /*
  13. * The test currently does not actually call the interface function.
  14. * So this is just a dummy structure.
  15. */
  16. struct interface {
  17. void (EFIAPI * inc)(void);
  18. };
  19. struct context {
  20. void *registration_key;
  21. efi_uintn_t notify_count;
  22. efi_uintn_t handle_count;
  23. efi_handle_t *handles;
  24. };
  25. static struct efi_boot_services *boottime;
  26. static efi_guid_t guid1 =
  27. EFI_GUID(0x2e7ca819, 0x21d3, 0x0a3a,
  28. 0xf7, 0x91, 0x82, 0x1f, 0x7a, 0x83, 0x67, 0xaf);
  29. static efi_guid_t guid2 =
  30. EFI_GUID(0xf909f2bb, 0x90a8, 0x0d77,
  31. 0x94, 0x0c, 0x3e, 0xa8, 0xea, 0x38, 0xd6, 0x6f);
  32. static struct context context;
  33. static struct efi_event *event;
  34. /*
  35. * Notification function, increments the notification count if parameter
  36. * context is provided.
  37. *
  38. * @event notified event
  39. * @context pointer to the notification count
  40. */
  41. static void EFIAPI notify(struct efi_event *event, void *context)
  42. {
  43. struct context *cp = context;
  44. efi_status_t ret;
  45. efi_uintn_t handle_count;
  46. efi_handle_t *handles;
  47. cp->notify_count++;
  48. for (;;) {
  49. ret = boottime->locate_handle_buffer(BY_REGISTER_NOTIFY, NULL,
  50. cp->registration_key,
  51. &handle_count, &handles);
  52. if (ret != EFI_SUCCESS)
  53. break;
  54. cp->handle_count += handle_count;
  55. cp->handles = handles;
  56. }
  57. }
  58. /*
  59. * Setup unit test.
  60. *
  61. * @handle: handle of the loaded image
  62. * @systable: system table
  63. */
  64. static int setup(const efi_handle_t img_handle,
  65. const struct efi_system_table *systable)
  66. {
  67. efi_status_t ret;
  68. boottime = systable->boottime;
  69. ret = boottime->create_event(EVT_NOTIFY_SIGNAL,
  70. TPL_CALLBACK, notify, &context,
  71. &event);
  72. if (ret != EFI_SUCCESS) {
  73. efi_st_error("could not create event\n");
  74. return EFI_ST_FAILURE;
  75. }
  76. ret = boottime->register_protocol_notify(&guid1, event,
  77. &context.registration_key);
  78. if (ret != EFI_SUCCESS) {
  79. efi_st_error("could not register event\n");
  80. return EFI_ST_FAILURE;
  81. }
  82. return EFI_ST_SUCCESS;
  83. }
  84. /*
  85. * Tear down unit test.
  86. *
  87. */
  88. static int teardown(void)
  89. {
  90. efi_status_t ret;
  91. if (event) {
  92. ret = boottime->close_event(event);
  93. event = NULL;
  94. if (ret != EFI_SUCCESS) {
  95. efi_st_error("could not close event\n");
  96. return EFI_ST_FAILURE;
  97. }
  98. }
  99. return EFI_ST_SUCCESS;
  100. }
  101. /*
  102. * Execute unit test.
  103. *
  104. */
  105. static int execute(void)
  106. {
  107. efi_status_t ret;
  108. efi_handle_t handle1 = NULL, handle2 = NULL;
  109. struct interface interface1, interface2;
  110. ret = boottime->install_protocol_interface(&handle1, &guid1,
  111. EFI_NATIVE_INTERFACE,
  112. &interface1);
  113. if (ret != EFI_SUCCESS) {
  114. efi_st_error("could not install interface\n");
  115. return EFI_ST_FAILURE;
  116. }
  117. if (!context.notify_count) {
  118. efi_st_error("install was not notified\n");
  119. return EFI_ST_FAILURE;
  120. }
  121. if (context.notify_count > 1) {
  122. efi_st_error("install was notified too often\n");
  123. return EFI_ST_FAILURE;
  124. }
  125. if (context.handle_count != 1) {
  126. efi_st_error("LocateHandle failed\n");
  127. return EFI_ST_FAILURE;
  128. }
  129. ret = boottime->free_pool(context.handles);
  130. if (ret != EFI_SUCCESS) {
  131. efi_st_error("FreePool failed\n");
  132. return EFI_ST_FAILURE;
  133. }
  134. context.notify_count = 0;
  135. ret = boottime->install_protocol_interface(&handle1, &guid2,
  136. EFI_NATIVE_INTERFACE,
  137. &interface1);
  138. if (ret != EFI_SUCCESS) {
  139. efi_st_error("could not install interface\n");
  140. return EFI_ST_FAILURE;
  141. }
  142. if (context.notify_count) {
  143. efi_st_error("wrong protocol was notified\n");
  144. return EFI_ST_FAILURE;
  145. }
  146. context.notify_count = 0;
  147. ret = boottime->reinstall_protocol_interface(handle1, &guid1,
  148. &interface1, &interface2);
  149. if (ret != EFI_SUCCESS) {
  150. efi_st_error("could not reinstall interface\n");
  151. return EFI_ST_FAILURE;
  152. }
  153. if (!context.notify_count) {
  154. efi_st_error("reinstall was not notified\n");
  155. return EFI_ST_FAILURE;
  156. }
  157. if (context.notify_count > 1) {
  158. efi_st_error("reinstall was notified too often\n");
  159. return EFI_ST_FAILURE;
  160. }
  161. if (context.handle_count != 2) {
  162. efi_st_error("LocateHandle failed\n");
  163. return EFI_ST_FAILURE;
  164. }
  165. ret = boottime->free_pool(context.handles);
  166. if (ret != EFI_SUCCESS) {
  167. efi_st_error("FreePool failed\n");
  168. return EFI_ST_FAILURE;
  169. }
  170. context.notify_count = 0;
  171. ret = boottime->install_protocol_interface(&handle2, &guid1,
  172. EFI_NATIVE_INTERFACE,
  173. &interface1);
  174. if (ret != EFI_SUCCESS) {
  175. efi_st_error("could not install interface\n");
  176. return EFI_ST_FAILURE;
  177. }
  178. if (!context.notify_count) {
  179. efi_st_error("install was not notified\n");
  180. return EFI_ST_FAILURE;
  181. }
  182. if (context.notify_count > 1) {
  183. efi_st_error("install was notified too often\n");
  184. return EFI_ST_FAILURE;
  185. }
  186. if (context.handle_count != 3) {
  187. efi_st_error("LocateHandle failed\n");
  188. return EFI_ST_FAILURE;
  189. }
  190. ret = boottime->free_pool(context.handles);
  191. if (ret != EFI_SUCCESS) {
  192. efi_st_error("FreePool failed\n");
  193. return EFI_ST_FAILURE;
  194. }
  195. ret = boottime->uninstall_multiple_protocol_interfaces
  196. (handle1, &guid1, &interface2,
  197. &guid2, &interface1, NULL);
  198. if (ret != EFI_SUCCESS) {
  199. efi_st_error("UninstallMultipleProtocolInterfaces failed\n");
  200. return EFI_ST_FAILURE;
  201. }
  202. ret = boottime->uninstall_multiple_protocol_interfaces
  203. (handle2, &guid1, &interface1, NULL);
  204. if (ret != EFI_SUCCESS) {
  205. efi_st_error("UninstallMultipleProtocolInterfaces failed\n");
  206. return EFI_ST_FAILURE;
  207. }
  208. return EFI_ST_SUCCESS;
  209. }
  210. EFI_UNIT_TEST(regprotnot) = {
  211. .name = "register protocol notify",
  212. .phase = EFI_EXECUTE_BEFORE_BOOTTIME_EXIT,
  213. .setup = setup,
  214. .execute = execute,
  215. .teardown = teardown,
  216. };