]>
Commit | Line | Data |
---|---|---|
0923876d | 1 | /* |
e67e7249 | 2 | * efi_selftest_exitbootservices |
0923876d HS |
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 | ||
14 | static struct efi_boot_services *boottime; | |
15 | static struct efi_event *event_notify; | |
e67e7249 | 16 | static unsigned int notification_count; |
0923876d HS |
17 | |
18 | /* | |
e67e7249 | 19 | * Notification function, increments the notification count. |
0923876d HS |
20 | * |
21 | * @event notified event | |
e67e7249 | 22 | * @context pointer to the notification count |
0923876d HS |
23 | */ |
24 | static void EFIAPI notify(struct efi_event *event, void *context) | |
25 | { | |
e67e7249 HS |
26 | unsigned int *count = context; |
27 | ||
28 | ++*count; | |
0923876d HS |
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 | |
e67e7249 | 38 | * @return: EFI_ST_SUCCESS for success |
0923876d HS |
39 | */ |
40 | static int setup(const efi_handle_t handle, | |
41 | const struct efi_system_table *systable) | |
42 | { | |
43 | efi_status_t ret; | |
44 | ||
45 | boottime = systable->boottime; | |
46 | ||
e67e7249 | 47 | notification_count = 0; |
0923876d | 48 | ret = boottime->create_event(EVT_SIGNAL_EXIT_BOOT_SERVICES, |
e67e7249 HS |
49 | TPL_CALLBACK, notify, |
50 | (void *)¬ification_count, | |
0923876d HS |
51 | &event_notify); |
52 | if (ret != EFI_SUCCESS) { | |
53 | efi_st_error("could not create event\n"); | |
e67e7249 | 54 | return EFI_ST_FAILURE; |
0923876d | 55 | } |
e67e7249 | 56 | return EFI_ST_SUCCESS; |
0923876d HS |
57 | } |
58 | ||
59 | /* | |
60 | * Tear down unit test. | |
61 | * | |
62 | * Close the event created in setup. | |
e67e7249 HS |
63 | * |
64 | * @return: EFI_ST_SUCCESS for success | |
0923876d HS |
65 | */ |
66 | static int teardown(void) | |
67 | { | |
68 | efi_status_t ret; | |
69 | ||
70 | if (event_notify) { | |
71 | ret = boottime->close_event(event_notify); | |
72 | event_notify = NULL; | |
73 | if (ret != EFI_SUCCESS) { | |
74 | efi_st_error("could not close event\n"); | |
e67e7249 | 75 | return EFI_ST_FAILURE; |
0923876d HS |
76 | } |
77 | } | |
e67e7249 | 78 | return EFI_ST_SUCCESS; |
0923876d HS |
79 | } |
80 | ||
81 | /* | |
82 | * Execute unit test. | |
83 | * | |
84 | * Check that the notification function of the EVT_SIGNAL_EXIT_BOOT_SERVICES | |
85 | * event has been called. | |
86 | * | |
87 | * Call ExitBootServices again and check that the notification function is | |
88 | * not called again. | |
e67e7249 HS |
89 | * |
90 | * @return: EFI_ST_SUCCESS for success | |
0923876d HS |
91 | */ |
92 | static int execute(void) | |
93 | { | |
e67e7249 HS |
94 | if (notification_count != 1) { |
95 | efi_st_error("ExitBootServices was not notified\n"); | |
96 | return EFI_ST_FAILURE; | |
0923876d HS |
97 | } |
98 | efi_st_exit_boot_services(); | |
e67e7249 HS |
99 | if (notification_count != 1) { |
100 | efi_st_error("ExitBootServices was notified twice\n"); | |
101 | return EFI_ST_FAILURE; | |
0923876d | 102 | } |
e67e7249 | 103 | return EFI_ST_SUCCESS; |
0923876d HS |
104 | } |
105 | ||
106 | EFI_UNIT_TEST(exitbootservices) = { | |
107 | .name = "ExitBootServices", | |
108 | .phase = EFI_SETUP_BEFORE_BOOTTIME_EXIT, | |
109 | .setup = setup, | |
110 | .execute = execute, | |
111 | .teardown = teardown, | |
112 | }; |