1/*
2 * Test if our calling convention gymnastics actually work
3 */
4
5#include <efi.h>
6#include <efilib.h>
7
8#ifdef __x86_64__
9#include <x86_64/pe.h>
10#include <x86_64/efibind.h>
11#endif
12
13#if 0
14	asm volatile("out %0,%1" : : "a" ((uint8_t)a), "dN" (0x80));
15
16extern void dump_stack(void);
17asm(	".globl	dump_stack\n"
18	"dump_stack:\n"
19	"	movq %rsp, %rdi\n"
20	"	jmp *dump_stack_helper@GOTPCREL(%rip)\n"
21	".size	dump_stack, .-dump_stack");
22
23void dump_stack_helper(uint64_t rsp_val)
24{
25	uint64_t *rsp = (uint64_t *)rsp_val;
26	int x;
27
28	Print(L"%%rsp: 0x%08x%08x stack:\r\n",
29					(rsp_val & 0xffffffff00000000) >>32,
30					 rsp_val & 0xffffffff);
31	for (x = 0; x < 8; x++) {
32		Print(L"%08x: ", ((uint64_t)rsp) & 0xffffffff);
33		Print(L"%016x ", *rsp++);
34		Print(L"%016x ", *rsp++);
35		Print(L"%016x ", *rsp++);
36		Print(L"%016x\r\n", *rsp++);
37	}
38}
39#endif
40
41EFI_STATUS EFI_FUNCTION test_failure_callback(void)
42{
43	return EFI_UNSUPPORTED;
44}
45
46EFI_STATUS test_failure(void)
47{
48	return uefi_call_wrapper(test_failure_callback, 0);
49}
50
51EFI_STATUS EFI_FUNCTION test_call0_callback(void)
52{
53	return EFI_SUCCESS;
54}
55
56EFI_STATUS test_call0(void)
57{
58	return uefi_call_wrapper(test_call0_callback, 0);
59}
60
61EFI_STATUS EFI_FUNCTION test_call1_callback(UINT32 a)
62{
63	if (a != 0x12345678) {
64		return EFI_LOAD_ERROR;
65	}
66	return EFI_SUCCESS;
67}
68
69EFI_STATUS test_call1(void)
70{
71	return uefi_call_wrapper(test_call1_callback, 1,0x12345678);
72}
73
74EFI_STATUS EFI_FUNCTION test_call2_callback(UINT32 a, UINT32 b)
75{
76	if (a != 0x12345678) {
77		return EFI_LOAD_ERROR;
78	}
79	if (b != 0x23456789) {
80		return EFI_INVALID_PARAMETER;
81	}
82	return EFI_SUCCESS;
83}
84
85EFI_STATUS test_call2(void)
86{
87	return uefi_call_wrapper(test_call2_callback, 2,
88		0x12345678, 0x23456789);
89}
90
91EFI_STATUS EFI_FUNCTION test_call3_callback(UINT32 a, UINT32 b,
92	UINT32 c)
93{
94	if (a != 0x12345678)
95		return EFI_LOAD_ERROR;
96	if (b != 0x23456789)
97		return EFI_INVALID_PARAMETER;
98	if (c != 0x3456789a)
99		return EFI_UNSUPPORTED;
100	return EFI_SUCCESS;
101}
102
103EFI_STATUS test_call3(void)
104{
105	return uefi_call_wrapper(test_call3_callback, 3,
106		0x12345678, 0x23456789, 0x3456789a);
107}
108
109EFI_STATUS EFI_FUNCTION test_call4_callback(UINT32 a, UINT32 b,
110	UINT32 c, UINT32 d)
111{
112	if (a != 0x12345678)
113		return EFI_LOAD_ERROR;
114	if (b != 0x23456789)
115		return EFI_INVALID_PARAMETER;
116	if (c != 0x3456789a)
117		return EFI_UNSUPPORTED;
118	if (d != 0x456789ab)
119		return EFI_BAD_BUFFER_SIZE;
120
121	return EFI_SUCCESS;
122}
123
124EFI_STATUS test_call4(void)
125{
126	return uefi_call_wrapper(test_call4_callback, 4,
127		0x12345678, 0x23456789, 0x3456789a, 0x456789ab);
128}
129
130EFI_STATUS EFI_FUNCTION test_call5_callback(UINT32 a, UINT32 b,
131	UINT32 c, UINT32 d, UINT32 e)
132{
133	if (a != 0x12345678)
134		return EFI_LOAD_ERROR;
135	if (b != 0x23456789)
136		return EFI_INVALID_PARAMETER;
137	if (c != 0x3456789a)
138		return EFI_UNSUPPORTED;
139	if (d != 0x456789ab)
140		return EFI_BAD_BUFFER_SIZE;
141	if (e != 0x56789abc)
142		return EFI_BUFFER_TOO_SMALL;
143
144	return EFI_SUCCESS;
145}
146
147EFI_STATUS test_call5(void)
148{
149	return uefi_call_wrapper(test_call5_callback, 5,
150		0x12345678, 0x23456789, 0x3456789a, 0x456789ab, 0x56789abc);
151}
152
153EFI_STATUS EFI_FUNCTION test_call6_callback(UINT32 a, UINT32 b,
154	UINT32 c, UINT32 d, UINT32 e, UINT32 f)
155{
156	if (a != 0x12345678)
157		return EFI_LOAD_ERROR;
158	if (b != 0x23456789)
159		return EFI_INVALID_PARAMETER;
160	if (c != 0x3456789a)
161		return EFI_UNSUPPORTED;
162	if (d != 0x456789ab)
163		return EFI_BAD_BUFFER_SIZE;
164	if (e != 0x56789abc)
165		return EFI_BUFFER_TOO_SMALL;
166	if (f != 0x6789abcd)
167		return EFI_NOT_READY;
168
169	return EFI_SUCCESS;
170}
171
172EFI_STATUS test_call6(void)
173{
174	return uefi_call_wrapper(test_call6_callback, 6,
175		0x12345678, 0x23456789, 0x3456789a, 0x456789ab, 0x56789abc,
176		0x6789abcd);
177}
178
179EFI_STATUS EFI_FUNCTION test_call7_callback(UINT32 a, UINT32 b,
180	UINT32 c, UINT32 d, UINT32 e, UINT32 f, UINT32 g)
181{
182	if (a != 0x12345678)
183		return EFI_LOAD_ERROR;
184	if (b != 0x23456789)
185		return EFI_INVALID_PARAMETER;
186	if (c != 0x3456789a)
187		return EFI_UNSUPPORTED;
188	if (d != 0x456789ab)
189		return EFI_BAD_BUFFER_SIZE;
190	if (e != 0x56789abc)
191		return EFI_BUFFER_TOO_SMALL;
192	if (f != 0x6789abcd)
193		return EFI_NOT_READY;
194	if (g != 0x789abcde)
195		return EFI_DEVICE_ERROR;
196
197	return EFI_SUCCESS;
198}
199
200EFI_STATUS test_call7(void)
201{
202	return uefi_call_wrapper(test_call7_callback, 7,
203		0x12345678, 0x23456789, 0x3456789a, 0x456789ab,
204		0x56789abc, 0x6789abcd, 0x789abcde);
205}
206
207EFI_STATUS EFI_FUNCTION test_call8_callback(UINT32 a, UINT32 b,
208	UINT32 c, UINT32 d, UINT32 e, UINT32 f, UINT32 g, UINT32 h)
209{
210	if (a != 0x12345678)
211		return EFI_LOAD_ERROR;
212	if (b != 0x23456789)
213		return EFI_INVALID_PARAMETER;
214	if (c != 0x3456789a)
215		return EFI_UNSUPPORTED;
216	if (d != 0x456789ab)
217		return EFI_BAD_BUFFER_SIZE;
218	if (e != 0x56789abc)
219		return EFI_BUFFER_TOO_SMALL;
220	if (f != 0x6789abcd)
221		return EFI_NOT_READY;
222	if (g != 0x789abcde)
223		return EFI_DEVICE_ERROR;
224	if (h != 0x89abcdef)
225		return EFI_WRITE_PROTECTED;
226
227	return EFI_SUCCESS;
228}
229
230EFI_STATUS test_call8(void)
231{
232	return uefi_call_wrapper(test_call8_callback, 8,
233		0x12345678,
234		0x23456789,
235		0x3456789a,
236		0x456789ab,
237		0x56789abc,
238		0x6789abcd,
239		0x789abcde,
240		0x89abcdef);
241}
242
243EFI_STATUS EFI_FUNCTION test_call9_callback(UINT32 a, UINT32 b,
244	UINT32 c, UINT32 d, UINT32 e, UINT32 f, UINT32 g, UINT32 h, UINT32 i)
245{
246	if (a != 0x12345678)
247		return EFI_LOAD_ERROR;
248	if (b != 0x23456789)
249		return EFI_INVALID_PARAMETER;
250	if (c != 0x3456789a)
251		return EFI_UNSUPPORTED;
252	if (d != 0x456789ab)
253		return EFI_BAD_BUFFER_SIZE;
254	if (e != 0x56789abc)
255		return EFI_BUFFER_TOO_SMALL;
256	if (f != 0x6789abcd)
257		return EFI_NOT_READY;
258	if (g != 0x789abcde)
259		return EFI_DEVICE_ERROR;
260	if (h != 0x89abcdef)
261		return EFI_WRITE_PROTECTED;
262	if (i != 0x9abcdef0)
263		return EFI_OUT_OF_RESOURCES;
264
265	return EFI_SUCCESS;
266}
267
268EFI_STATUS test_call9(void)
269{
270	return uefi_call_wrapper(test_call9_callback, 9,
271		0x12345678,
272		0x23456789,
273		0x3456789a,
274		0x456789ab,
275		0x56789abc,
276		0x6789abcd,
277		0x789abcde,
278		0x89abcdef,
279		0x9abcdef0);
280}
281
282extern EFI_STATUS test_call10(void);
283EFI_STATUS EFI_FUNCTION test_call10_callback(UINT32 a, UINT32 b,
284	UINT32 c, UINT32 d, UINT32 e, UINT32 f, UINT32 g, UINT32 h, UINT32 i,
285	UINT32 j)
286{
287	if (a != 0x12345678)
288		return EFI_LOAD_ERROR;
289	if (b != 0x23456789)
290		return EFI_INVALID_PARAMETER;
291	if (c != 0x3456789a)
292		return EFI_UNSUPPORTED;
293	if (d != 0x456789ab)
294		return EFI_BAD_BUFFER_SIZE;
295	if (e != 0x56789abc)
296		return EFI_BUFFER_TOO_SMALL;
297	if (f != 0x6789abcd)
298		return EFI_NOT_READY;
299	if (g != 0x789abcde)
300		return EFI_DEVICE_ERROR;
301	if (h != 0x89abcdef)
302		return EFI_WRITE_PROTECTED;
303	if (i != 0x9abcdef0)
304		return EFI_OUT_OF_RESOURCES;
305	if (j != 0xabcdef01)
306		return EFI_VOLUME_CORRUPTED;
307
308	return EFI_SUCCESS;
309}
310
311EFI_STATUS test_call10(void)
312{
313	return uefi_call_wrapper(test_call10_callback, 10,
314		0x12345678,
315		0x23456789,
316		0x3456789a,
317		0x456789ab,
318		0x56789abc,
319		0x6789abcd,
320		0x789abcde,
321		0x89abcdef,
322		0x9abcdef0,
323		0xabcdef01);
324}
325
326EFI_STATUS
327efi_main (EFI_HANDLE *image, EFI_SYSTEM_TABLE *systab)
328{
329	EFI_STATUS rc = EFI_SUCCESS;
330
331	InitializeLib(image, systab);
332	PoolAllocationType = 2; /* klooj */
333
334#ifndef __x86_64__
335	uefi_call_wrapper(systab->ConOut->OutputString, 2, systab->ConOut,
336		L"This test is only valid on x86_64\n");
337	return EFI_UNSUPPORTED;
338#endif
339
340	__asm__ volatile("out %0,%1" : : "a" ((uint8_t)0x14), "dN" (0x80));
341
342	Print(L"Hello\r\n");
343	rc = test_failure();
344	if (EFI_ERROR(rc)) {
345		Print(L"Returning Failure works\n");
346	} else {
347		Print(L"Returning failure doesn't work.\r\n");
348		Print(L"%%rax was 0x%016x, should have been 0x%016x\n",
349			rc, EFI_UNSUPPORTED);
350		return EFI_INVALID_PARAMETER;
351	}
352
353	rc = test_call0();
354	if (!EFI_ERROR(rc)) {
355		Print(L"0 args works just fine here.\r\n");
356	} else {
357		Print(L"0 args failed: 0x%016x\n", rc);
358		return rc;
359	}
360
361	rc = test_call1();
362	if (!EFI_ERROR(rc)) {
363		Print(L"1 arg works just fine here.\r\n");
364	} else {
365		Print(L"1 arg failed: 0x%016x\n", rc);
366		return rc;
367	}
368
369	rc = test_call2();
370	if (!EFI_ERROR(rc)) {
371		Print(L"2 args works just fine here.\r\n");
372	} else {
373		Print(L"2 args failed: 0x%016x\n", rc);
374		return rc;
375	}
376
377	rc = test_call3();
378	if (!EFI_ERROR(rc)) {
379		Print(L"3 args works just fine here.\r\n");
380	} else {
381		Print(L"3 args failed: 0x%016x\n", rc);
382		return rc;
383	}
384
385	rc = test_call4();
386	if (!EFI_ERROR(rc)) {
387		Print(L"4 args works just fine here.\r\n");
388	} else {
389		Print(L"4 args failed: 0x%016x\n", rc);
390		return rc;
391	}
392
393	rc = test_call5();
394	if (!EFI_ERROR(rc)) {
395		Print(L"5 args works just fine here.\r\n");
396	} else {
397		Print(L"5 args failed: 0x%016x\n", rc);
398		return rc;
399	}
400
401	rc = test_call6();
402	if (!EFI_ERROR(rc)) {
403		Print(L"6 args works just fine here.\r\n");
404	} else {
405		Print(L"6 args failed: 0x%016x\n", rc);
406		return rc;
407	}
408
409	rc = test_call7();
410	if (!EFI_ERROR(rc)) {
411		Print(L"7 args works just fine here.\r\n");
412	} else {
413		Print(L"7 args failed: 0x%016x\n", rc);
414		return rc;
415	}
416
417	rc = test_call8();
418	if (!EFI_ERROR(rc)) {
419		Print(L"8 args works just fine here.\r\n");
420	} else {
421		Print(L"8 args failed: 0x%016x\n", rc);
422		return rc;
423	}
424
425	rc = test_call9();
426	if (!EFI_ERROR(rc)) {
427		Print(L"9 args works just fine here.\r\n");
428	} else {
429		Print(L"9 args failed: 0x%016x\n", rc);
430		return rc;
431	}
432
433	rc = test_call10();
434	if (!EFI_ERROR(rc)) {
435		Print(L"10 args works just fine here.\r\n");
436	} else {
437		Print(L"10 args failed: 0x%016x\n", rc);
438		return rc;
439	}
440
441	return rc;
442}
443