Blame view

lib/efi_selftest/efi_selftest_events.c 5.17 KB
83d290c56   Tom Rini   SPDX: Convert all...
1
  // SPDX-License-Identifier: GPL-2.0+
bd126692d   Heinrich Schuchardt   efi_selftest: pro...
2
3
4
5
6
  /*
   * efi_selftest_events
   *
   * Copyright (c) 2017 Heinrich Schuchardt <xypron.glpk@gmx.de>
   *
bd126692d   Heinrich Schuchardt   efi_selftest: pro...
7
8
9
10
11
12
13
14
15
   * This unit test uses timer events to check the implementation
   * of the following boottime services:
   * CreateEvent, CloseEvent, WaitForEvent, CheckEvent, SetTimer.
   */
  
  #include <efi_selftest.h>
  
  static struct efi_event *event_notify;
  static struct efi_event *event_wait;
e67e7249c   Heinrich Schuchardt   efi_selftest: mak...
16
  static unsigned int timer_ticks;
bd126692d   Heinrich Schuchardt   efi_selftest: pro...
17
18
19
  static struct efi_boot_services *boottime;
  
  /*
d8b2216c8   Heinrich Schuchardt   efi_selftest: fix...
20
   * Notification function, increments the notification count if parameter
e67e7249c   Heinrich Schuchardt   efi_selftest: mak...
21
   * context is provided.
bd126692d   Heinrich Schuchardt   efi_selftest: pro...
22
23
   *
   * @event	notified event
e67e7249c   Heinrich Schuchardt   efi_selftest: mak...
24
   * @context	pointer to the notification count
bd126692d   Heinrich Schuchardt   efi_selftest: pro...
25
26
27
   */
  static void EFIAPI notify(struct efi_event *event, void *context)
  {
e67e7249c   Heinrich Schuchardt   efi_selftest: mak...
28
29
30
31
  	unsigned int *count = context;
  
  	if (count)
  		++*count;
bd126692d   Heinrich Schuchardt   efi_selftest: pro...
32
33
34
35
36
37
38
39
40
41
  }
  
  /*
   * Setup unit test.
   *
   * Create two timer events.
   * One with EVT_NOTIFY_SIGNAL, the other with EVT_NOTIFY_WAIT.
   *
   * @handle:	handle of the loaded image
   * @systable:	system table
e67e7249c   Heinrich Schuchardt   efi_selftest: mak...
42
   * @return:	EFI_ST_SUCCESS for success
bd126692d   Heinrich Schuchardt   efi_selftest: pro...
43
44
45
46
47
48
49
50
51
   */
  static int setup(const efi_handle_t handle,
  		 const struct efi_system_table *systable)
  {
  	efi_status_t ret;
  
  	boottime = systable->boottime;
  
  	ret = boottime->create_event(EVT_TIMER | EVT_NOTIFY_SIGNAL,
e67e7249c   Heinrich Schuchardt   efi_selftest: mak...
52
  				     TPL_CALLBACK, notify, (void *)&timer_ticks,
bd126692d   Heinrich Schuchardt   efi_selftest: pro...
53
54
55
56
  				     &event_notify);
  	if (ret != EFI_SUCCESS) {
  		efi_st_error("could not create event
  ");
e67e7249c   Heinrich Schuchardt   efi_selftest: mak...
57
  		return EFI_ST_FAILURE;
bd126692d   Heinrich Schuchardt   efi_selftest: pro...
58
59
60
61
62
63
  	}
  	ret = boottime->create_event(EVT_TIMER | EVT_NOTIFY_WAIT,
  				     TPL_CALLBACK, notify, NULL, &event_wait);
  	if (ret != EFI_SUCCESS) {
  		efi_st_error("could not create event
  ");
e67e7249c   Heinrich Schuchardt   efi_selftest: mak...
64
  		return EFI_ST_FAILURE;
bd126692d   Heinrich Schuchardt   efi_selftest: pro...
65
  	}
e67e7249c   Heinrich Schuchardt   efi_selftest: mak...
66
  	return EFI_ST_SUCCESS;
bd126692d   Heinrich Schuchardt   efi_selftest: pro...
67
68
69
70
71
72
  }
  
  /*
   * Tear down unit test.
   *
   * Close the events created in setup.
e67e7249c   Heinrich Schuchardt   efi_selftest: mak...
73
74
   *
   * @return:	EFI_ST_SUCCESS for success
bd126692d   Heinrich Schuchardt   efi_selftest: pro...
75
76
77
78
79
80
81
82
83
84
85
   */
  static int teardown(void)
  {
  	efi_status_t ret;
  
  	if (event_notify) {
  		ret = boottime->close_event(event_notify);
  		event_notify = NULL;
  		if (ret != EFI_SUCCESS) {
  			efi_st_error("could not close event
  ");
e67e7249c   Heinrich Schuchardt   efi_selftest: mak...
86
  			return EFI_ST_FAILURE;
bd126692d   Heinrich Schuchardt   efi_selftest: pro...
87
88
89
90
91
92
93
94
  		}
  	}
  	if (event_wait) {
  		ret = boottime->close_event(event_wait);
  		event_wait = NULL;
  		if (ret != EFI_SUCCESS) {
  			efi_st_error("could not close event
  ");
e67e7249c   Heinrich Schuchardt   efi_selftest: mak...
95
  			return EFI_ST_FAILURE;
bd126692d   Heinrich Schuchardt   efi_selftest: pro...
96
97
  		}
  	}
e67e7249c   Heinrich Schuchardt   efi_selftest: mak...
98
  	return EFI_ST_SUCCESS;
bd126692d   Heinrich Schuchardt   efi_selftest: pro...
99
100
101
102
103
104
105
106
107
108
  }
  
  /*
   * Execute unit test.
   *
   * Run a 10 ms periodic timer and check that it is called 10 times
   * while waiting for 100 ms single shot timer.
   *
   * Run a 100 ms single shot timer and check that it is called once
   * while waiting for 100 ms periodic timer for two periods.
e67e7249c   Heinrich Schuchardt   efi_selftest: mak...
109
110
   *
   * @return:	EFI_ST_SUCCESS for success
bd126692d   Heinrich Schuchardt   efi_selftest: pro...
111
112
113
   */
  static int execute(void)
  {
f5a2a9389   Heinrich Schuchardt   efi_loader: consi...
114
  	efi_uintn_t index;
bd126692d   Heinrich Schuchardt   efi_selftest: pro...
115
116
117
  	efi_status_t ret;
  
  	/* Set 10 ms timer */
e67e7249c   Heinrich Schuchardt   efi_selftest: mak...
118
  	timer_ticks = 0;
bd126692d   Heinrich Schuchardt   efi_selftest: pro...
119
120
121
122
  	ret = boottime->set_timer(event_notify, EFI_TIMER_PERIODIC, 100000);
  	if (ret != EFI_SUCCESS) {
  		efi_st_error("Could not set timer
  ");
e67e7249c   Heinrich Schuchardt   efi_selftest: mak...
123
  		return EFI_ST_FAILURE;
bd126692d   Heinrich Schuchardt   efi_selftest: pro...
124
125
126
127
128
129
  	}
  	/* Set 100 ms timer */
  	ret = boottime->set_timer(event_wait, EFI_TIMER_RELATIVE, 1000000);
  	if (ret != EFI_SUCCESS) {
  		efi_st_error("Could not set timer
  ");
e67e7249c   Heinrich Schuchardt   efi_selftest: mak...
130
  		return EFI_ST_FAILURE;
bd126692d   Heinrich Schuchardt   efi_selftest: pro...
131
  	}
e67e7249c   Heinrich Schuchardt   efi_selftest: mak...
132
  	/* Set some arbitrary non-zero value to make change detectable. */
bd126692d   Heinrich Schuchardt   efi_selftest: pro...
133
134
135
136
137
  	index = 5;
  	ret = boottime->wait_for_event(1, &event_wait, &index);
  	if (ret != EFI_SUCCESS) {
  		efi_st_error("Could not wait for event
  ");
e67e7249c   Heinrich Schuchardt   efi_selftest: mak...
138
  		return EFI_ST_FAILURE;
bd126692d   Heinrich Schuchardt   efi_selftest: pro...
139
140
141
142
143
144
145
  	}
  	ret = boottime->check_event(event_wait);
  	if (ret != EFI_NOT_READY) {
  		efi_st_error("Signaled state was not cleared.
  ");
  		efi_st_printf("ret = %u
  ", (unsigned int)ret);
e67e7249c   Heinrich Schuchardt   efi_selftest: mak...
146
  		return EFI_ST_FAILURE;
bd126692d   Heinrich Schuchardt   efi_selftest: pro...
147
148
149
150
  	}
  	if (index != 0) {
  		efi_st_error("WaitForEvent returned wrong index
  ");
e67e7249c   Heinrich Schuchardt   efi_selftest: mak...
151
  		return EFI_ST_FAILURE;
bd126692d   Heinrich Schuchardt   efi_selftest: pro...
152
  	}
e67e7249c   Heinrich Schuchardt   efi_selftest: mak...
153
  	if (timer_ticks < 8 || timer_ticks > 12) {
ad50dcf8c   Heinrich Schuchardt   efi_selftest: avo...
154
155
  		efi_st_printf("Notification count periodic: %u
  ", timer_ticks);
bd126692d   Heinrich Schuchardt   efi_selftest: pro...
156
157
  		efi_st_error("Incorrect timing of events
  ");
e67e7249c   Heinrich Schuchardt   efi_selftest: mak...
158
  		return EFI_ST_FAILURE;
bd126692d   Heinrich Schuchardt   efi_selftest: pro...
159
160
  	}
  	ret = boottime->set_timer(event_notify, EFI_TIMER_STOP, 0);
1309a159c   Heinrich Schuchardt   efi_selftest: eve...
161
  	if (ret != EFI_SUCCESS) {
bd126692d   Heinrich Schuchardt   efi_selftest: pro...
162
163
  		efi_st_error("Could not cancel timer
  ");
e67e7249c   Heinrich Schuchardt   efi_selftest: mak...
164
  		return EFI_ST_FAILURE;
bd126692d   Heinrich Schuchardt   efi_selftest: pro...
165
166
  	}
  	/* Set 10 ms timer */
e67e7249c   Heinrich Schuchardt   efi_selftest: mak...
167
  	timer_ticks = 0;
bd126692d   Heinrich Schuchardt   efi_selftest: pro...
168
  	ret = boottime->set_timer(event_notify, EFI_TIMER_RELATIVE, 100000);
1309a159c   Heinrich Schuchardt   efi_selftest: eve...
169
  	if (ret != EFI_SUCCESS) {
bd126692d   Heinrich Schuchardt   efi_selftest: pro...
170
171
  		efi_st_error("Could not set timer
  ");
e67e7249c   Heinrich Schuchardt   efi_selftest: mak...
172
  		return EFI_ST_FAILURE;
bd126692d   Heinrich Schuchardt   efi_selftest: pro...
173
174
175
  	}
  	/* Set 100 ms timer */
  	ret = boottime->set_timer(event_wait, EFI_TIMER_PERIODIC, 1000000);
1309a159c   Heinrich Schuchardt   efi_selftest: eve...
176
  	if (ret != EFI_SUCCESS) {
bd126692d   Heinrich Schuchardt   efi_selftest: pro...
177
178
  		efi_st_error("Could not set timer
  ");
e67e7249c   Heinrich Schuchardt   efi_selftest: mak...
179
  		return EFI_ST_FAILURE;
bd126692d   Heinrich Schuchardt   efi_selftest: pro...
180
181
182
183
184
  	}
  	ret = boottime->wait_for_event(1, &event_wait, &index);
  	if (ret != EFI_SUCCESS) {
  		efi_st_error("Could not wait for event
  ");
e67e7249c   Heinrich Schuchardt   efi_selftest: mak...
185
  		return EFI_ST_FAILURE;
bd126692d   Heinrich Schuchardt   efi_selftest: pro...
186
  	}
e67e7249c   Heinrich Schuchardt   efi_selftest: mak...
187
  	if (timer_ticks != 1) {
ad50dcf8c   Heinrich Schuchardt   efi_selftest: avo...
188
189
190
  		efi_st_printf("Notification count single shot: %u
  ",
  			      timer_ticks);
bd126692d   Heinrich Schuchardt   efi_selftest: pro...
191
192
  		efi_st_error("Single shot timer failed
  ");
e67e7249c   Heinrich Schuchardt   efi_selftest: mak...
193
  		return EFI_ST_FAILURE;
bd126692d   Heinrich Schuchardt   efi_selftest: pro...
194
195
196
197
198
  	}
  	ret = boottime->wait_for_event(1, &event_wait, &index);
  	if (ret != EFI_SUCCESS) {
  		efi_st_error("Could not wait for event
  ");
e67e7249c   Heinrich Schuchardt   efi_selftest: mak...
199
  		return EFI_ST_FAILURE;
bd126692d   Heinrich Schuchardt   efi_selftest: pro...
200
  	}
e67e7249c   Heinrich Schuchardt   efi_selftest: mak...
201
  	if (timer_ticks != 1) {
ad50dcf8c   Heinrich Schuchardt   efi_selftest: avo...
202
203
204
  		efi_st_printf("Notification count stopped timer: %u
  ",
  			      timer_ticks);
bd126692d   Heinrich Schuchardt   efi_selftest: pro...
205
206
  		efi_st_error("Stopped timer fired
  ");
e67e7249c   Heinrich Schuchardt   efi_selftest: mak...
207
  		return EFI_ST_FAILURE;
bd126692d   Heinrich Schuchardt   efi_selftest: pro...
208
209
  	}
  	ret = boottime->set_timer(event_wait, EFI_TIMER_STOP, 0);
abe994633   Heinrich Schuchardt   efi_selftest: cor...
210
  	if (ret != EFI_SUCCESS) {
bd126692d   Heinrich Schuchardt   efi_selftest: pro...
211
212
  		efi_st_error("Could not cancel timer
  ");
e67e7249c   Heinrich Schuchardt   efi_selftest: mak...
213
  		return EFI_ST_FAILURE;
bd126692d   Heinrich Schuchardt   efi_selftest: pro...
214
  	}
e67e7249c   Heinrich Schuchardt   efi_selftest: mak...
215
  	return EFI_ST_SUCCESS;
bd126692d   Heinrich Schuchardt   efi_selftest: pro...
216
217
218
219
220
221
222
223
224
  }
  
  EFI_UNIT_TEST(events) = {
  	.name = "event services",
  	.phase = EFI_EXECUTE_BEFORE_BOOTTIME_EXIT,
  	.setup = setup,
  	.execute = execute,
  	.teardown = teardown,
  };