efi_selftest_exitbootservices.c 2.0 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788
  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. * Execute unit test.
  52. *
  53. * Check that the notification function of the EVT_SIGNAL_EXIT_BOOT_SERVICES
  54. * event has been called.
  55. *
  56. * Call ExitBootServices again and check that the notification function is
  57. * not called again.
  58. *
  59. * @return: EFI_ST_SUCCESS for success
  60. */
  61. static int execute(void)
  62. {
  63. if (notification_count != 1) {
  64. efi_st_error("ExitBootServices was not notified\n");
  65. return EFI_ST_FAILURE;
  66. }
  67. efi_st_exit_boot_services();
  68. if (notification_count != 1) {
  69. efi_st_error("ExitBootServices was notified twice\n");
  70. return EFI_ST_FAILURE;
  71. }
  72. return EFI_ST_SUCCESS;
  73. }
  74. EFI_UNIT_TEST(exitbootservices) = {
  75. .name = "ExitBootServices",
  76. .phase = EFI_SETUP_BEFORE_BOOTTIME_EXIT,
  77. .setup = setup,
  78. .execute = execute,
  79. };