blob: 60271e618089e2fb95495e1cd39ef76cb25c2a6d [file] [log] [blame]
Heinrich Schuchardt630d1342017-09-15 10:06:19 +02001/*
2 * efi_selftest_events
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 that the notification function of an
9 * EVT_SIGNAL_EXIT_BOOT_SERVICES event is called exactly once.
10 */
11
12#include <efi_selftest.h>
13
14static struct efi_boot_services *boottime;
15static struct efi_event *event_notify;
16static unsigned int counter;
17
18/*
19 * Notification function, increments a counter.
20 *
21 * @event notified event
22 * @context pointer to the counter
23 */
24static void EFIAPI notify(struct efi_event *event, void *context)
25{
26 if (!context)
27 return;
28 ++*(unsigned int *)context;
29}
30
31/*
32 * Setup unit test.
33 *
34 * Create an EVT_SIGNAL_EXIT_BOOT_SERVICES event.
35 *
36 * @handle: handle of the loaded image
37 * @systable: system table
38 */
39static int setup(const efi_handle_t handle,
40 const struct efi_system_table *systable)
41{
42 efi_status_t ret;
43
44 boottime = systable->boottime;
45
46 counter = 0;
47 ret = boottime->create_event(EVT_SIGNAL_EXIT_BOOT_SERVICES,
48 TPL_CALLBACK, notify, (void *)&counter,
49 &event_notify);
50 if (ret != EFI_SUCCESS) {
51 efi_st_error("could not create event\n");
52 return 1;
53 }
54 return 0;
55}
56
57/*
58 * Tear down unit test.
59 *
60 * Close the event created in setup.
61 */
62static int teardown(void)
63{
64 efi_status_t ret;
65
66 if (event_notify) {
67 ret = boottime->close_event(event_notify);
68 event_notify = NULL;
69 if (ret != EFI_SUCCESS) {
70 efi_st_error("could not close event\n");
71 return 1;
72 }
73 }
74 return 0;
75}
76
77/*
78 * Execute unit test.
79 *
80 * Check that the notification function of the EVT_SIGNAL_EXIT_BOOT_SERVICES
81 * event has been called.
82 *
83 * Call ExitBootServices again and check that the notification function is
84 * not called again.
85 */
86static int execute(void)
87{
88 if (counter != 1) {
89 efi_st_error("ExitBootServices was not notified");
90 return 1;
91 }
92 efi_st_exit_boot_services();
93 if (counter != 1) {
94 efi_st_error("ExitBootServices was notified twice");
95 return 1;
96 }
97 return 0;
98}
99
100EFI_UNIT_TEST(exitbootservices) = {
101 .name = "ExitBootServices",
102 .phase = EFI_SETUP_BEFORE_BOOTTIME_EXIT,
103 .setup = setup,
104 .execute = execute,
105 .teardown = teardown,
106};