183d290c5STom Rini // SPDX-License-Identifier: GPL-2.0+
26fc901c5SHeinrich Schuchardt /*
36fc901c5SHeinrich Schuchardt  * efi_selftest_event_groups
46fc901c5SHeinrich Schuchardt  *
56fc901c5SHeinrich Schuchardt  * Copyright (c) 2018 Heinrich Schuchardt <xypron.glpk@gmx.de>
66fc901c5SHeinrich Schuchardt  *
76fc901c5SHeinrich Schuchardt  * This test checks the notification of group events and the
86fc901c5SHeinrich Schuchardt  * following services:
96fc901c5SHeinrich Schuchardt  * CreateEventEx, CloseEvent, SignalEvent, CheckEvent.
106fc901c5SHeinrich Schuchardt  */
116fc901c5SHeinrich Schuchardt 
126fc901c5SHeinrich Schuchardt #include <efi_selftest.h>
136fc901c5SHeinrich Schuchardt 
146fc901c5SHeinrich Schuchardt #define GROUP_SIZE 16
156fc901c5SHeinrich Schuchardt 
166fc901c5SHeinrich Schuchardt static struct efi_boot_services *boottime;
176fc901c5SHeinrich Schuchardt static efi_guid_t event_group =
186fc901c5SHeinrich Schuchardt 	EFI_GUID(0x2335905b, 0xc3b9, 0x4221, 0xa3, 0x71,
196fc901c5SHeinrich Schuchardt 		 0x0e, 0x5b, 0x45, 0xc0, 0x56, 0x91);
206fc901c5SHeinrich Schuchardt 
216fc901c5SHeinrich Schuchardt /*
22*d8b2216cSHeinrich Schuchardt  * Notification function, increments the notification count if parameter
236fc901c5SHeinrich Schuchardt  * context is provided.
246fc901c5SHeinrich Schuchardt  *
256fc901c5SHeinrich Schuchardt  * @event	notified event
266fc901c5SHeinrich Schuchardt  * @context	pointer to the notification count
276fc901c5SHeinrich Schuchardt  */
notify(struct efi_event * event,void * context)286fc901c5SHeinrich Schuchardt static void EFIAPI notify(struct efi_event *event, void *context)
296fc901c5SHeinrich Schuchardt {
306fc901c5SHeinrich Schuchardt 	unsigned int *count = context;
316fc901c5SHeinrich Schuchardt 
326fc901c5SHeinrich Schuchardt 	if (count)
336fc901c5SHeinrich Schuchardt 		++*count;
346fc901c5SHeinrich Schuchardt }
356fc901c5SHeinrich Schuchardt 
366fc901c5SHeinrich Schuchardt /*
376fc901c5SHeinrich Schuchardt  * Setup unit test.
386fc901c5SHeinrich Schuchardt  *
396fc901c5SHeinrich Schuchardt  * @handle:	handle of the loaded image
406fc901c5SHeinrich Schuchardt  * @systable:	system table
416fc901c5SHeinrich Schuchardt  * @return:	EFI_ST_SUCCESS for success
426fc901c5SHeinrich Schuchardt  */
setup(const efi_handle_t handle,const struct efi_system_table * systable)436fc901c5SHeinrich Schuchardt static int setup(const efi_handle_t handle,
446fc901c5SHeinrich Schuchardt 		 const struct efi_system_table *systable)
456fc901c5SHeinrich Schuchardt {
466fc901c5SHeinrich Schuchardt 	boottime = systable->boottime;
476fc901c5SHeinrich Schuchardt 
486fc901c5SHeinrich Schuchardt 	return EFI_ST_SUCCESS;
496fc901c5SHeinrich Schuchardt }
506fc901c5SHeinrich Schuchardt 
516fc901c5SHeinrich Schuchardt /*
526fc901c5SHeinrich Schuchardt  * Execute unit test.
536fc901c5SHeinrich Schuchardt  *
546fc901c5SHeinrich Schuchardt  * Create multiple events in an event group. Signal each event once and check
556fc901c5SHeinrich Schuchardt  * that all events are notified once in each round.
566fc901c5SHeinrich Schuchardt  *
576fc901c5SHeinrich Schuchardt  * @return:	EFI_ST_SUCCESS for success
586fc901c5SHeinrich Schuchardt  */
execute(void)596fc901c5SHeinrich Schuchardt static int execute(void)
606fc901c5SHeinrich Schuchardt {
616fc901c5SHeinrich Schuchardt 	unsigned int counter[GROUP_SIZE] = {0};
626fc901c5SHeinrich Schuchardt 	struct efi_event *events[GROUP_SIZE];
636fc901c5SHeinrich Schuchardt 	size_t i, j;
646fc901c5SHeinrich Schuchardt 	efi_status_t ret;
656fc901c5SHeinrich Schuchardt 
666fc901c5SHeinrich Schuchardt 	for (i = 0; i < GROUP_SIZE; ++i) {
676fc901c5SHeinrich Schuchardt 		ret = boottime->create_event_ex(0, TPL_NOTIFY,
686fc901c5SHeinrich Schuchardt 						notify, (void *)&counter[i],
696fc901c5SHeinrich Schuchardt 						&event_group, &events[i]);
706fc901c5SHeinrich Schuchardt 		if (ret != EFI_SUCCESS) {
716fc901c5SHeinrich Schuchardt 			efi_st_error("Failed to create event\n");
726fc901c5SHeinrich Schuchardt 			return EFI_ST_FAILURE;
736fc901c5SHeinrich Schuchardt 		}
746fc901c5SHeinrich Schuchardt 	}
756fc901c5SHeinrich Schuchardt 
766fc901c5SHeinrich Schuchardt 	for (i = 0; i < GROUP_SIZE; ++i) {
776fc901c5SHeinrich Schuchardt 		ret = boottime->signal_event(events[i]);
786fc901c5SHeinrich Schuchardt 		if (ret != EFI_SUCCESS) {
796fc901c5SHeinrich Schuchardt 			efi_st_error("Failed to signal event\n");
806fc901c5SHeinrich Schuchardt 			return EFI_ST_FAILURE;
816fc901c5SHeinrich Schuchardt 		}
826fc901c5SHeinrich Schuchardt 		for (j = 0; j < GROUP_SIZE; ++j) {
836fc901c5SHeinrich Schuchardt 			if (counter[j] != i) {
846fc901c5SHeinrich Schuchardt 				efi_st_printf("i %u, j %u, count %u\n",
856fc901c5SHeinrich Schuchardt 					      (unsigned int)i, (unsigned int)j,
866fc901c5SHeinrich Schuchardt 					      (unsigned int)counter[j]);
876fc901c5SHeinrich Schuchardt 				efi_st_error(
886fc901c5SHeinrich Schuchardt 					"Notification function was called\n");
896fc901c5SHeinrich Schuchardt 				return EFI_ST_FAILURE;
906fc901c5SHeinrich Schuchardt 			}
916fc901c5SHeinrich Schuchardt 			/* Clear signaled state */
926fc901c5SHeinrich Schuchardt 			ret = boottime->check_event(events[j]);
936fc901c5SHeinrich Schuchardt 			if (ret != EFI_SUCCESS) {
946fc901c5SHeinrich Schuchardt 				efi_st_error("Event was not signaled\n");
956fc901c5SHeinrich Schuchardt 				return EFI_ST_FAILURE;
966fc901c5SHeinrich Schuchardt 			}
976fc901c5SHeinrich Schuchardt 			if (counter[j] != i) {
986fc901c5SHeinrich Schuchardt 				efi_st_printf("i %u, j %u, count %u\n",
996fc901c5SHeinrich Schuchardt 					      (unsigned int)i, (unsigned int)j,
1006fc901c5SHeinrich Schuchardt 					      (unsigned int)counter[j]);
1016fc901c5SHeinrich Schuchardt 				efi_st_error(
1026fc901c5SHeinrich Schuchardt 					"Notification function was called\n");
1036fc901c5SHeinrich Schuchardt 				return EFI_ST_FAILURE;
1046fc901c5SHeinrich Schuchardt 			}
1056fc901c5SHeinrich Schuchardt 			/* Call notification function  */
1066fc901c5SHeinrich Schuchardt 			ret = boottime->check_event(events[j]);
1076fc901c5SHeinrich Schuchardt 			if (ret != EFI_NOT_READY) {
1086fc901c5SHeinrich Schuchardt 				efi_st_error(
1096fc901c5SHeinrich Schuchardt 					"Signaled state not cleared\n");
1106fc901c5SHeinrich Schuchardt 				return EFI_ST_FAILURE;
1116fc901c5SHeinrich Schuchardt 			}
1126fc901c5SHeinrich Schuchardt 			if (counter[j] != i + 1) {
1136fc901c5SHeinrich Schuchardt 				efi_st_printf("i %u, j %u, count %u\n",
1146fc901c5SHeinrich Schuchardt 					      (unsigned int)i, (unsigned int)j,
1156fc901c5SHeinrich Schuchardt 					      (unsigned int)counter[j]);
1166fc901c5SHeinrich Schuchardt 				efi_st_error(
117*d8b2216cSHeinrich Schuchardt 					"Notification function not called\n");
1186fc901c5SHeinrich Schuchardt 				return EFI_ST_FAILURE;
1196fc901c5SHeinrich Schuchardt 			}
1206fc901c5SHeinrich Schuchardt 		}
1216fc901c5SHeinrich Schuchardt 	}
1226fc901c5SHeinrich Schuchardt 
1236fc901c5SHeinrich Schuchardt 	for (i = 0; i < GROUP_SIZE; ++i) {
1246fc901c5SHeinrich Schuchardt 		ret = boottime->close_event(events[i]);
1256fc901c5SHeinrich Schuchardt 		if (ret != EFI_SUCCESS) {
1266fc901c5SHeinrich Schuchardt 			efi_st_error("Failed to close event\n");
1276fc901c5SHeinrich Schuchardt 			return EFI_ST_FAILURE;
1286fc901c5SHeinrich Schuchardt 		}
1296fc901c5SHeinrich Schuchardt 	}
1306fc901c5SHeinrich Schuchardt 
1316fc901c5SHeinrich Schuchardt 	return EFI_ST_SUCCESS;
1326fc901c5SHeinrich Schuchardt }
1336fc901c5SHeinrich Schuchardt 
1346fc901c5SHeinrich Schuchardt EFI_UNIT_TEST(eventgoups) = {
1356fc901c5SHeinrich Schuchardt 	.name = "event groups",
1366fc901c5SHeinrich Schuchardt 	.phase = EFI_EXECUTE_BEFORE_BOOTTIME_EXIT,
1376fc901c5SHeinrich Schuchardt 	.setup = setup,
1386fc901c5SHeinrich Schuchardt 	.execute = execute,
1396fc901c5SHeinrich Schuchardt };
140