// SPDX-License-Identifier: GPL-2.0+
/*
 * efi_selftest_events
 *
 * Copyright (c) 2017 Heinrich Schuchardt <xypron.glpk@gmx.de>
 *
 * 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;
static unsigned int timer_ticks;
static struct efi_boot_services *boottime;

/*
 * Notification function, increments the notfication count if parameter
 * context is provided.
 *
 * @event	notified event
 * @context	pointer to the notification count
 */
static void EFIAPI notify(struct efi_event *event, void *context)
{
	unsigned int *count = context;

	if (count)
		++*count;
}

/*
 * 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
 * @return:	EFI_ST_SUCCESS for success
 */
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,
				     TPL_CALLBACK, notify, (void *)&timer_ticks,
				     &event_notify);
	if (ret != EFI_SUCCESS) {
		efi_st_error("could not create event\n");
		return EFI_ST_FAILURE;
	}
	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\n");
		return EFI_ST_FAILURE;
	}
	return EFI_ST_SUCCESS;
}

/*
 * Tear down unit test.
 *
 * Close the events created in setup.
 *
 * @return:	EFI_ST_SUCCESS for success
 */
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\n");
			return EFI_ST_FAILURE;
		}
	}
	if (event_wait) {
		ret = boottime->close_event(event_wait);
		event_wait = NULL;
		if (ret != EFI_SUCCESS) {
			efi_st_error("could not close event\n");
			return EFI_ST_FAILURE;
		}
	}
	return EFI_ST_SUCCESS;
}

/*
 * 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.
 *
 * @return:	EFI_ST_SUCCESS for success
 */
static int execute(void)
{
	efi_uintn_t index;
	efi_status_t ret;

	/* Set 10 ms timer */
	timer_ticks = 0;
	ret = boottime->set_timer(event_notify, EFI_TIMER_PERIODIC, 100000);
	if (ret != EFI_SUCCESS) {
		efi_st_error("Could not set timer\n");
		return EFI_ST_FAILURE;
	}
	/* 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\n");
		return EFI_ST_FAILURE;
	}

	/* Set some arbitrary non-zero value to make change detectable. */
	index = 5;
	ret = boottime->wait_for_event(1, &event_wait, &index);
	if (ret != EFI_SUCCESS) {
		efi_st_error("Could not wait for event\n");
		return EFI_ST_FAILURE;
	}
	ret = boottime->check_event(event_wait);
	if (ret != EFI_NOT_READY) {
		efi_st_error("Signaled state was not cleared.\n");
		efi_st_printf("ret = %u\n", (unsigned int)ret);
		return EFI_ST_FAILURE;
	}
	if (index != 0) {
		efi_st_error("WaitForEvent returned wrong index\n");
		return EFI_ST_FAILURE;
	}
	if (timer_ticks < 8 || timer_ticks > 12) {
		efi_st_printf("Notification count periodic: %u\n", timer_ticks);
		efi_st_error("Incorrect timing of events\n");
		return EFI_ST_FAILURE;
	}
	ret = boottime->set_timer(event_notify, EFI_TIMER_STOP, 0);
	if (index != 0) {
		efi_st_error("Could not cancel timer\n");
		return EFI_ST_FAILURE;
	}
	/* Set 10 ms timer */
	timer_ticks = 0;
	ret = boottime->set_timer(event_notify, EFI_TIMER_RELATIVE, 100000);
	if (index != 0) {
		efi_st_error("Could not set timer\n");
		return EFI_ST_FAILURE;
	}
	/* Set 100 ms timer */
	ret = boottime->set_timer(event_wait, EFI_TIMER_PERIODIC, 1000000);
	if (index != 0) {
		efi_st_error("Could not set timer\n");
		return EFI_ST_FAILURE;
	}
	ret = boottime->wait_for_event(1, &event_wait, &index);
	if (ret != EFI_SUCCESS) {
		efi_st_error("Could not wait for event\n");
		return EFI_ST_FAILURE;
	}
	if (timer_ticks != 1) {
		efi_st_printf("Notification count single shot: %u\n",
			      timer_ticks);
		efi_st_error("Single shot timer failed\n");
		return EFI_ST_FAILURE;
	}
	ret = boottime->wait_for_event(1, &event_wait, &index);
	if (ret != EFI_SUCCESS) {
		efi_st_error("Could not wait for event\n");
		return EFI_ST_FAILURE;
	}
	if (timer_ticks != 1) {
		efi_st_printf("Notification count stopped timer: %u\n",
			      timer_ticks);
		efi_st_error("Stopped timer fired\n");
		return EFI_ST_FAILURE;
	}
	ret = boottime->set_timer(event_wait, EFI_TIMER_STOP, 0);
	if (ret != EFI_SUCCESS) {
		efi_st_error("Could not cancel timer\n");
		return EFI_ST_FAILURE;
	}

	return EFI_ST_SUCCESS;
}

EFI_UNIT_TEST(events) = {
	.name = "event services",
	.phase = EFI_EXECUTE_BEFORE_BOOTTIME_EXIT,
	.setup = setup,
	.execute = execute,
	.teardown = teardown,
};
