efi_selftest_exitbootservices.c 2.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111
  1. // SPDX-License-Identifier: GPL-2.0+
  2. /*
  3. * efi_selftest_exitbootservices
  4. *
  5. * Copyright (c) 2017 Heinrich Schuchardt <xypron.glpk@gmx.de>
  6. *
  7. * This unit test checks that the notification function of an
  8. * EVT_SIGNAL_EXIT_BOOT_SERVICES event is called exactly once.
  9. */
  10. #include <efi_selftest.h>
  11. static struct efi_boot_services *boottime;
  12. static struct efi_event *event_notify;
  13. static unsigned int notification_count;
  14. /*
  15. * Notification function, increments the notification count.
  16. *
  17. * @event notified event
  18. * @context pointer to the notification count
  19. */
  20. static void EFIAPI notify(struct efi_event *event, void *context)
  21. {
  22. unsigned int *count = context;
  23. ++*count;
  24. }
  25. /*
  26. * Setup unit test.
  27. *
  28. * Create an EVT_SIGNAL_EXIT_BOOT_SERVICES event.
  29. *
  30. * @handle: handle of the loaded image
  31. * @systable: system table
  32. * @return: EFI_ST_SUCCESS for success
  33. */
  34. static int setup(const efi_handle_t handle,
  35. const struct efi_system_table *systable)
  36. {
  37. efi_status_t ret;
  38. boottime = systable->boottime;
  39. notification_count = 0;
  40. ret = boottime->create_event(EVT_SIGNAL_EXIT_BOOT_SERVICES,
  41. TPL_CALLBACK, notify,
  42. (void *)&notification_count,
  43. &event_notify);
  44. if (ret != EFI_SUCCESS) {
  45. efi_st_error("could not create event\n");
  46. return EFI_ST_FAILURE;
  47. }
  48. return EFI_ST_SUCCESS;
  49. }
  50. /*
  51. * Tear down unit test.
  52. *
  53. * Close the event created in setup.
  54. *
  55. * @return: EFI_ST_SUCCESS for success
  56. */
  57. static int teardown(void)
  58. {
  59. efi_status_t ret;
  60. if (event_notify) {
  61. ret = boottime->close_event(event_notify);
  62. event_notify = NULL;
  63. if (ret != EFI_SUCCESS) {
  64. efi_st_error("could not close event\n");
  65. return EFI_ST_FAILURE;
  66. }
  67. }
  68. return EFI_ST_SUCCESS;
  69. }
  70. /*
  71. * Execute unit test.
  72. *
  73. * Check that the notification function of the EVT_SIGNAL_EXIT_BOOT_SERVICES
  74. * event has been called.
  75. *
  76. * Call ExitBootServices again and check that the notification function is
  77. * not called again.
  78. *
  79. * @return: EFI_ST_SUCCESS for success
  80. */
  81. static int execute(void)
  82. {
  83. if (notification_count != 1) {
  84. efi_st_error("ExitBootServices was not notified\n");
  85. return EFI_ST_FAILURE;
  86. }
  87. efi_st_exit_boot_services();
  88. if (notification_count != 1) {
  89. efi_st_error("ExitBootServices was notified twice\n");
  90. return EFI_ST_FAILURE;
  91. }
  92. return EFI_ST_SUCCESS;
  93. }
  94. EFI_UNIT_TEST(exitbootservices) = {
  95. .name = "ExitBootServices",
  96. .phase = EFI_SETUP_BEFORE_BOOTTIME_EXIT,
  97. .setup = setup,
  98. .execute = execute,
  99. .teardown = teardown,
  100. };