All of lore.kernel.org
 help / color / mirror / Atom feed
* [U-Boot] [PATCH 0/5] efi_loader: implement event groups
@ 2018-02-18 14:17 Heinrich Schuchardt
  2018-02-18 14:17 ` [U-Boot] [PATCH 1/5] efi_loader: fix formatting errors Heinrich Schuchardt
                   ` (4 more replies)
  0 siblings, 5 replies; 8+ messages in thread
From: Heinrich Schuchardt @ 2018-02-18 14:17 UTC (permalink / raw)
  To: u-boot

The patch series provides support for event groups. If any event of the
group is signaled all other events are signaled too.

The events are managed in a linked list instead of an array.

Some formatting errors are fixed.

Heinrich Schuchardt (5):
  efi_loader: fix formatting errors
  efi_loader: manage events in a linked list
  efi_loader: define GUIDS for event groups
  efi_loader: implement event groups
  efi_selftest: unit test for event groups

 include/efi_api.h                            |  21 ++
 include/efi_loader.h                         |  28 ++-
 lib/efi_loader/efi_boottime.c                | 339 ++++++++++++++++-----------
 lib/efi_loader/efi_console.c                 |   6 +-
 lib/efi_loader/efi_net.c                     |   4 +-
 lib/efi_loader/efi_runtime.c                 |  11 +
 lib/efi_loader/efi_watchdog.c                |   2 +-
 lib/efi_selftest/Makefile                    |   1 +
 lib/efi_selftest/efi_selftest_event_groups.c | 140 +++++++++++
 9 files changed, 400 insertions(+), 152 deletions(-)
 create mode 100644 lib/efi_selftest/efi_selftest_event_groups.c

-- 
2.14.2

^ permalink raw reply	[flat|nested] 8+ messages in thread

* [U-Boot] [PATCH 1/5] efi_loader: fix formatting errors
  2018-02-18 14:17 [U-Boot] [PATCH 0/5] efi_loader: implement event groups Heinrich Schuchardt
@ 2018-02-18 14:17 ` Heinrich Schuchardt
  2018-02-18 14:17 ` [U-Boot] [PATCH 2/5] efi_loader: manage events in a linked list Heinrich Schuchardt
                   ` (3 subsequent siblings)
  4 siblings, 0 replies; 8+ messages in thread
From: Heinrich Schuchardt @ 2018-02-18 14:17 UTC (permalink / raw)
  To: u-boot

Fix formatting errors in efi_boottime.c indicated by
scripts/checkpatch.py.

Signed-off-by: Heinrich Schuchardt <xypron.glpk@gmx.de>
---
 lib/efi_loader/efi_boottime.c | 48 +++++++++++++++++++++++--------------------
 1 file changed, 26 insertions(+), 22 deletions(-)

diff --git a/lib/efi_loader/efi_boottime.c b/lib/efi_loader/efi_boottime.c
index 15235f6d07..75f7c50295 100644
--- a/lib/efi_loader/efi_boottime.c
+++ b/lib/efi_loader/efi_boottime.c
@@ -123,6 +123,7 @@ static const char *indent_string(int level)
 {
 	const char *indent = "                    ";
 	const int max = strlen(indent);
+
 	level = min(max, level * 2);
 	return &indent[max - level];
 }
@@ -257,7 +258,7 @@ static efi_status_t EFIAPI efi_free_pages_ext(uint64_t memory,
 {
 	efi_status_t r;
 
-	EFI_ENTRY("%"PRIx64", 0x%zx", memory, pages);
+	EFI_ENTRY("%" PRIx64 ", 0x%zx", memory, pages);
 	r = efi_free_pages(memory, pages);
 	return EFI_EXIT(r);
 }
@@ -586,7 +587,6 @@ static efi_status_t EFIAPI efi_create_event_ext(
 					 notify_context, event));
 }
 
-
 /*
  * Check if a timer event has occurred or a queued notification function should
  * be called.
@@ -688,7 +688,7 @@ static efi_status_t EFIAPI efi_set_timer_ext(struct efi_event *event,
 					     enum efi_timer_delay type,
 					     uint64_t trigger_time)
 {
-	EFI_ENTRY("%p, %d, %"PRIx64, event, type, trigger_time);
+	EFI_ENTRY("%p, %d, %" PRIx64, event, type, trigger_time);
 	return EFI_EXIT(efi_set_timer(event, type, trigger_time));
 }
 
@@ -1264,7 +1264,7 @@ static efi_status_t efi_locate_handle(
 	/* Count how much space we need */
 	list_for_each_entry(efiobj, &efi_obj_list, link) {
 		if (!efi_search(search_type, protocol, search_key, efiobj))
-			size += sizeof(void*);
+			size += sizeof(void *);
 	}
 
 	if (*buffer_size < size) {
@@ -1315,7 +1315,7 @@ static efi_status_t EFIAPI efi_locate_handle_ext(
 static void efi_remove_configuration_table(int i)
 {
 	struct efi_configuration_table *this = &efi_conf_table[i];
-	struct efi_configuration_table *next = &efi_conf_table[i+1];
+	struct efi_configuration_table *next = &efi_conf_table[i + 1];
 	struct efi_configuration_table *end = &efi_conf_table[systab.nr_tables];
 
 	memmove(this, next, (ulong)end - (ulong)next);
@@ -1332,7 +1332,8 @@ static void efi_remove_configuration_table(int i)
  * @table		table to be installed
  * @return		status code
  */
-efi_status_t efi_install_configuration_table(const efi_guid_t *guid, void *table)
+efi_status_t efi_install_configuration_table(const efi_guid_t *guid,
+					     void *table)
 {
 	int i;
 
@@ -1638,8 +1639,9 @@ static efi_status_t EFIAPI efi_start_image(efi_handle_t image_handle,
  * @return		status code
  */
 static efi_status_t EFIAPI efi_exit(efi_handle_t image_handle,
-			efi_status_t exit_status, unsigned long exit_data_size,
-			int16_t *exit_data)
+				    efi_status_t exit_status,
+				    unsigned long exit_data_size,
+				    int16_t *exit_data)
 {
 	/*
 	 * We require that the handle points to the original loaded
@@ -1652,7 +1654,7 @@ static efi_status_t EFIAPI efi_exit(efi_handle_t image_handle,
 	 * TODO: We should call the unload procedure of the loaded
 	 *	 image protocol.
 	 */
-	struct efi_loaded_image *loaded_image_info = (void*)image_handle;
+	struct efi_loaded_image *loaded_image_info = (void *)image_handle;
 
 	EFI_ENTRY("%p, %ld, %ld, %p", image_handle, exit_status,
 		  exit_data_size, exit_data);
@@ -1789,7 +1791,8 @@ static efi_status_t EFIAPI efi_exit_boot_services(efi_handle_t image_handle,
  */
 static efi_status_t EFIAPI efi_get_next_monotonic_count(uint64_t *count)
 {
-	static uint64_t mono = 0;
+	static uint64_t mono;
+
 	EFI_ENTRY("%p", count);
 	*count = mono++;
 	return EFI_EXIT(EFI_SUCCESS);
@@ -1830,7 +1833,7 @@ static efi_status_t EFIAPI efi_set_watchdog_timer(unsigned long timeout,
 						  unsigned long data_size,
 						  uint16_t *watchdog_data)
 {
-	EFI_ENTRY("%ld, 0x%"PRIx64", %ld, %p", timeout, watchdog_code,
+	EFI_ENTRY("%ld, 0x%" PRIx64 ", %ld, %p", timeout, watchdog_code,
 		  data_size, watchdog_data);
 	return EFI_EXIT(efi_set_watchdog(timeout));
 }
@@ -1895,8 +1898,8 @@ out:
  * @entry_count		number of entries available in the buffer
  * @return		status code
  */
-static efi_status_t EFIAPI efi_open_protocol_information(efi_handle_t handle,
-			const efi_guid_t *protocol,
+static efi_status_t EFIAPI efi_open_protocol_information(
+			efi_handle_t handle, const efi_guid_t *protocol,
 			struct efi_open_protocol_info_entry **entry_buffer,
 			efi_uintn_t *entry_count)
 {
@@ -2881,15 +2884,16 @@ static const struct efi_boot_services efi_boot_services = {
 	.protocols_per_handle = efi_protocols_per_handle,
 	.locate_handle_buffer = efi_locate_handle_buffer,
 	.locate_protocol = efi_locate_protocol,
-	.install_multiple_protocol_interfaces = efi_install_multiple_protocol_interfaces,
-	.uninstall_multiple_protocol_interfaces = efi_uninstall_multiple_protocol_interfaces,
+	.install_multiple_protocol_interfaces =
+			efi_install_multiple_protocol_interfaces,
+	.uninstall_multiple_protocol_interfaces =
+			efi_uninstall_multiple_protocol_interfaces,
 	.calculate_crc32 = efi_calculate_crc32,
 	.copy_mem = efi_copy_mem,
 	.set_mem = efi_set_mem,
 	.create_event_ex = efi_create_event_ex,
 };
 
-
 static uint16_t __efi_runtime_data firmware_vendor[] = L"Das U-Boot";
 
 struct efi_system_table __efi_runtime_data systab = {
@@ -2899,11 +2903,11 @@ struct efi_system_table __efi_runtime_data systab = {
 		.headersize = sizeof(struct efi_table_hdr),
 	},
 	.fw_vendor = (long)firmware_vendor,
-	.con_in = (void*)&efi_con_in,
-	.con_out = (void*)&efi_con_out,
-	.std_err = (void*)&efi_con_out,
-	.runtime = (void*)&efi_runtime_services,
-	.boottime = (void*)&efi_boot_services,
+	.con_in = (void *)&efi_con_in,
+	.con_out = (void *)&efi_con_out,
+	.std_err = (void *)&efi_con_out,
+	.runtime = (void *)&efi_runtime_services,
+	.boottime = (void *)&efi_boot_services,
 	.nr_tables = 0,
-	.tables = (void*)efi_conf_table,
+	.tables = (void *)efi_conf_table,
 };
-- 
2.14.2

^ permalink raw reply related	[flat|nested] 8+ messages in thread

* [U-Boot] [PATCH 2/5] efi_loader: manage events in a linked list
  2018-02-18 14:17 [U-Boot] [PATCH 0/5] efi_loader: implement event groups Heinrich Schuchardt
  2018-02-18 14:17 ` [U-Boot] [PATCH 1/5] efi_loader: fix formatting errors Heinrich Schuchardt
@ 2018-02-18 14:17 ` Heinrich Schuchardt
  2018-02-18 14:17 ` [U-Boot] [PATCH 3/5] efi_loader: define GUIDS for event groups Heinrich Schuchardt
                   ` (2 subsequent siblings)
  4 siblings, 0 replies; 8+ messages in thread
From: Heinrich Schuchardt @ 2018-02-18 14:17 UTC (permalink / raw)
  To: u-boot

Lift the limit on the number of events by using a linked list.

This also allows to have events with type == 0.

This patch is based on Rob's patch
efi_loader: fix events
https://lists.denx.de/pipermail/u-boot/2017-October/309348.html

Suggested-by: Rob Clark <robdclark@gmail.com>
Signed-off-by: Heinrich Schuchardt <xypron.glpk@gmx.de>
---
 include/efi_loader.h          |  11 +--
 lib/efi_loader/efi_boottime.c | 192 +++++++++++++++++++-----------------------
 2 files changed, 93 insertions(+), 110 deletions(-)

diff --git a/include/efi_loader.h b/include/efi_loader.h
index 3ccbb98aaf..7f703c6ef7 100644
--- a/include/efi_loader.h
+++ b/include/efi_loader.h
@@ -146,17 +146,19 @@ struct efi_object {
 /**
  * struct efi_event
  *
+ * @link:		Link to list of all events
  * @type:		Type of event, see efi_create_event
  * @notify_tpl:		Task priority level of notifications
- * @trigger_time:	Period of the timer
- * @trigger_next:	Next time to trigger the timer
  * @nofify_function:	Function to call when the event is triggered
  * @notify_context:	Data to be passed to the notify function
+ * @trigger_time:	Period of the timer
+ * @trigger_next:	Next time to trigger the timer
  * @trigger_type:	Type of timer, see efi_set_timer
- * @queued:		The notification function is queued
- * @signaled:		The event occurred. The event is in the signaled state.
+ * @is_queued:		The notification function is queued
+ * @is_signaled:	The event occurred. The event is in the signaled state.
  */
 struct efi_event {
+	struct list_head link;
 	uint32_t type;
 	efi_uintn_t notify_tpl;
 	void (EFIAPI *notify_function)(struct efi_event *event, void *context);
@@ -168,7 +170,6 @@ struct efi_event {
 	bool is_signaled;
 };
 
-
 /* This list contains all UEFI objects we know of */
 extern struct list_head efi_obj_list;
 
diff --git a/lib/efi_loader/efi_boottime.c b/lib/efi_loader/efi_boottime.c
index 75f7c50295..4acb1e092a 100644
--- a/lib/efi_loader/efi_boottime.c
+++ b/lib/efi_loader/efi_boottime.c
@@ -26,6 +26,9 @@ static efi_uintn_t efi_tpl = TPL_APPLICATION;
 /* This list contains all the EFI objects our payload has access to */
 LIST_HEAD(efi_obj_list);
 
+/* List of all events */
+static LIST_HEAD(efi_events);
+
 /*
  * If we're running on nasty systems (32bit ARM booting into non-EFI Linux)
  * we need to do trickery with caches. Since we don't want to break the EFI
@@ -473,10 +476,23 @@ void efi_delete_handle(struct efi_object *obj)
 }
 
 /*
- * Our event capabilities are very limited. Only a small limited
- * number of events is allowed to coexist.
+ * Check if a pointer is a valid event.
+ *
+ * @event		pointer to check
+ * @return		status code
  */
-static struct efi_event efi_events[16];
+static efi_status_t efi_is_event(const struct efi_event *event)
+{
+	const struct efi_event *evt;
+
+	if (!event)
+		return EFI_INVALID_PARAMETER;
+	list_for_each_entry(evt, &efi_events, link) {
+		if (evt == event)
+			return EFI_SUCCESS;
+	}
+	return EFI_INVALID_PARAMETER;
+}
 
 /*
  * Create an event.
@@ -499,7 +515,7 @@ efi_status_t efi_create_event(uint32_t type, efi_uintn_t notify_tpl,
 					void *context),
 			      void *notify_context, struct efi_event **event)
 {
-	int i;
+	struct efi_event *evt;
 
 	if (event == NULL)
 		return EFI_INVALID_PARAMETER;
@@ -507,25 +523,24 @@ efi_status_t efi_create_event(uint32_t type, efi_uintn_t notify_tpl,
 	if ((type & EVT_NOTIFY_SIGNAL) && (type & EVT_NOTIFY_WAIT))
 		return EFI_INVALID_PARAMETER;
 
-	if ((type & (EVT_NOTIFY_SIGNAL|EVT_NOTIFY_WAIT)) &&
+	if ((type & (EVT_NOTIFY_SIGNAL | EVT_NOTIFY_WAIT)) &&
 	    notify_function == NULL)
 		return EFI_INVALID_PARAMETER;
 
-	for (i = 0; i < ARRAY_SIZE(efi_events); ++i) {
-		if (efi_events[i].type)
-			continue;
-		efi_events[i].type = type;
-		efi_events[i].notify_tpl = notify_tpl;
-		efi_events[i].notify_function = notify_function;
-		efi_events[i].notify_context = notify_context;
-		/* Disable timers on bootup */
-		efi_events[i].trigger_next = -1ULL;
-		efi_events[i].is_queued = false;
-		efi_events[i].is_signaled = false;
-		*event = &efi_events[i];
-		return EFI_SUCCESS;
-	}
-	return EFI_OUT_OF_RESOURCES;
+	evt = calloc(1, sizeof(struct efi_event));
+	if (!evt)
+		return EFI_OUT_OF_RESOURCES;
+	evt->type = type;
+	evt->notify_tpl = notify_tpl;
+	evt->notify_function = notify_function;
+	evt->notify_context = notify_context;
+	/* Disable timers on bootup */
+	evt->trigger_next = -1ULL;
+	evt->is_queued = false;
+	evt->is_signaled = false;
+	list_add_tail(&evt->link, &efi_events);
+	*event = evt;
+	return EFI_SUCCESS;
 }
 
 /*
@@ -596,30 +611,26 @@ static efi_status_t EFIAPI efi_create_event_ext(
  */
 void efi_timer_check(void)
 {
-	int i;
+	struct efi_event *evt;
 	u64 now = timer_get_us();
 
-	for (i = 0; i < ARRAY_SIZE(efi_events); ++i) {
-		if (!efi_events[i].type)
+	list_for_each_entry(evt, &efi_events, link) {
+		if (evt->is_queued)
+			efi_signal_event(evt, true);
+		if (!(evt->type & EVT_TIMER) || now < evt->trigger_next)
 			continue;
-		if (efi_events[i].is_queued)
-			efi_signal_event(&efi_events[i], true);
-		if (!(efi_events[i].type & EVT_TIMER) ||
-		    now < efi_events[i].trigger_next)
-			continue;
-		switch (efi_events[i].trigger_type) {
+		switch (evt->trigger_type) {
 		case EFI_TIMER_RELATIVE:
-			efi_events[i].trigger_type = EFI_TIMER_STOP;
+			evt->trigger_type = EFI_TIMER_STOP;
 			break;
 		case EFI_TIMER_PERIODIC:
-			efi_events[i].trigger_next +=
-				efi_events[i].trigger_time;
+			evt->trigger_next += evt->trigger_time;
 			break;
 		default:
 			continue;
 		}
-		efi_events[i].is_signaled = true;
-		efi_signal_event(&efi_events[i], true);
+		evt->is_signaled = true;
+		efi_signal_event(evt, true);
 	}
 	WATCHDOG_RESET();
 }
@@ -638,7 +649,9 @@ void efi_timer_check(void)
 efi_status_t efi_set_timer(struct efi_event *event, enum efi_timer_delay type,
 			   uint64_t trigger_time)
 {
-	int i;
+	/* Check that the event is valid */
+	if (efi_is_event(event) != EFI_SUCCESS || !(event->type & EVT_TIMER))
+		return EFI_INVALID_PARAMETER;
 
 	/*
 	 * The parameter defines a multiple of 100ns.
@@ -646,30 +659,21 @@ efi_status_t efi_set_timer(struct efi_event *event, enum efi_timer_delay type,
 	 */
 	do_div(trigger_time, 10);
 
-	for (i = 0; i < ARRAY_SIZE(efi_events); ++i) {
-		if (event != &efi_events[i])
-			continue;
-
-		if (!(event->type & EVT_TIMER))
-			break;
-		switch (type) {
-		case EFI_TIMER_STOP:
-			event->trigger_next = -1ULL;
-			break;
-		case EFI_TIMER_PERIODIC:
-		case EFI_TIMER_RELATIVE:
-			event->trigger_next =
-				timer_get_us() + trigger_time;
-			break;
-		default:
-			return EFI_INVALID_PARAMETER;
-		}
-		event->trigger_type = type;
-		event->trigger_time = trigger_time;
-		event->is_signaled = false;
-		return EFI_SUCCESS;
+	switch (type) {
+	case EFI_TIMER_STOP:
+		event->trigger_next = -1ULL;
+		break;
+	case EFI_TIMER_PERIODIC:
+	case EFI_TIMER_RELATIVE:
+		event->trigger_next = timer_get_us() + trigger_time;
+		break;
+	default:
+		return EFI_INVALID_PARAMETER;
 	}
-	return EFI_INVALID_PARAMETER;
+	event->trigger_type = type;
+	event->trigger_time = trigger_time;
+	event->is_signaled = false;
+	return EFI_SUCCESS;
 }
 
 /*
@@ -708,7 +712,7 @@ static efi_status_t EFIAPI efi_wait_for_event(efi_uintn_t num_events,
 					      struct efi_event **event,
 					      efi_uintn_t *index)
 {
-	int i, j;
+	int i;
 
 	EFI_ENTRY("%zd, %p, %p", num_events, event, index);
 
@@ -719,12 +723,8 @@ static efi_status_t EFIAPI efi_wait_for_event(efi_uintn_t num_events,
 	if (efi_tpl != TPL_APPLICATION)
 		return EFI_EXIT(EFI_UNSUPPORTED);
 	for (i = 0; i < num_events; ++i) {
-		for (j = 0; j < ARRAY_SIZE(efi_events); ++j) {
-			if (event[i] == &efi_events[j])
-				goto known_event;
-		}
-		return EFI_EXIT(EFI_INVALID_PARAMETER);
-known_event:
+		if (efi_is_event(event[i]) != EFI_SUCCESS)
+			return EFI_EXIT(EFI_INVALID_PARAMETER);
 		if (!event[i]->type || event[i]->type & EVT_NOTIFY_SIGNAL)
 			return EFI_EXIT(EFI_INVALID_PARAMETER);
 		if (!event[i]->is_signaled)
@@ -768,18 +768,13 @@ out:
  */
 static efi_status_t EFIAPI efi_signal_event_ext(struct efi_event *event)
 {
-	int i;
-
 	EFI_ENTRY("%p", event);
-	for (i = 0; i < ARRAY_SIZE(efi_events); ++i) {
-		if (event != &efi_events[i])
-			continue;
-		if (event->is_signaled)
-			break;
+	if (efi_is_event(event) != EFI_SUCCESS)
+		return EFI_EXIT(EFI_INVALID_PARAMETER);
+	if (!event->is_signaled) {
 		event->is_signaled = true;
 		if (event->type & EVT_NOTIFY_SIGNAL)
 			efi_signal_event(event, true);
-		break;
 	}
 	return EFI_EXIT(EFI_SUCCESS);
 }
@@ -796,19 +791,12 @@ static efi_status_t EFIAPI efi_signal_event_ext(struct efi_event *event)
  */
 static efi_status_t EFIAPI efi_close_event(struct efi_event *event)
 {
-	int i;
-
 	EFI_ENTRY("%p", event);
-	for (i = 0; i < ARRAY_SIZE(efi_events); ++i) {
-		if (event == &efi_events[i]) {
-			event->type = 0;
-			event->trigger_next = -1ULL;
-			event->is_queued = false;
-			event->is_signaled = false;
-			return EFI_EXIT(EFI_SUCCESS);
-		}
-	}
-	return EFI_EXIT(EFI_INVALID_PARAMETER);
+	if (efi_is_event(event) != EFI_SUCCESS)
+		return EFI_EXIT(EFI_INVALID_PARAMETER);
+	list_del(&event->link);
+	free(event);
+	return EFI_EXIT(EFI_SUCCESS);
 }
 
 /*
@@ -826,24 +814,18 @@ static efi_status_t EFIAPI efi_close_event(struct efi_event *event)
  */
 static efi_status_t EFIAPI efi_check_event(struct efi_event *event)
 {
-	int i;
-
 	EFI_ENTRY("%p", event);
 	efi_timer_check();
-	for (i = 0; i < ARRAY_SIZE(efi_events); ++i) {
-		if (event != &efi_events[i])
-			continue;
-		if (!event->type || event->type & EVT_NOTIFY_SIGNAL)
-			break;
-		if (!event->is_signaled)
-			efi_signal_event(event, true);
-		if (event->is_signaled) {
-			event->is_signaled = false;
-			return EFI_EXIT(EFI_SUCCESS);
-		}
-		return EFI_EXIT(EFI_NOT_READY);
+	if (efi_is_event(event) != EFI_SUCCESS ||
+	    event->type & EVT_NOTIFY_SIGNAL)
+		return EFI_EXIT(EFI_INVALID_PARAMETER);
+	if (!event->is_signaled)
+		efi_signal_event(event, true);
+	if (event->is_signaled) {
+		event->is_signaled = false;
+		return EFI_EXIT(EFI_SUCCESS);
 	}
-	return EFI_EXIT(EFI_INVALID_PARAMETER);
+	return EFI_EXIT(EFI_NOT_READY);
 }
 
 /*
@@ -1729,7 +1711,7 @@ static void efi_exit_caches(void)
 static efi_status_t EFIAPI efi_exit_boot_services(efi_handle_t image_handle,
 						  unsigned long map_key)
 {
-	int i;
+	struct efi_event *evt;
 
 	EFI_ENTRY("%p, %ld", image_handle, map_key);
 
@@ -1741,11 +1723,11 @@ static efi_status_t EFIAPI efi_exit_boot_services(efi_handle_t image_handle,
 		return EFI_EXIT(EFI_SUCCESS);
 
 	/* Notify that ExitBootServices is invoked. */
-	for (i = 0; i < ARRAY_SIZE(efi_events); ++i) {
-		if (efi_events[i].type != EVT_SIGNAL_EXIT_BOOT_SERVICES)
+	list_for_each_entry(evt, &efi_events, link) {
+		if (evt->type != EVT_SIGNAL_EXIT_BOOT_SERVICES)
 			continue;
-		efi_events[i].is_signaled = true;
-		efi_signal_event(&efi_events[i], false);
+		evt->is_signaled = true;
+		efi_signal_event(evt, false);
 	}
 
 	/* TODO Should persist EFI variables here */
-- 
2.14.2

^ permalink raw reply related	[flat|nested] 8+ messages in thread

* [U-Boot] [PATCH 3/5] efi_loader: define GUIDS for event groups
  2018-02-18 14:17 [U-Boot] [PATCH 0/5] efi_loader: implement event groups Heinrich Schuchardt
  2018-02-18 14:17 ` [U-Boot] [PATCH 1/5] efi_loader: fix formatting errors Heinrich Schuchardt
  2018-02-18 14:17 ` [U-Boot] [PATCH 2/5] efi_loader: manage events in a linked list Heinrich Schuchardt
@ 2018-02-18 14:17 ` Heinrich Schuchardt
  2018-02-18 14:17 ` [U-Boot] [PATCH 4/5] efi_loader: implement " Heinrich Schuchardt
  2018-02-18 14:17 ` [U-Boot] [PATCH 5/5] efi_selftest: unit test for " Heinrich Schuchardt
  4 siblings, 0 replies; 8+ messages in thread
From: Heinrich Schuchardt @ 2018-02-18 14:17 UTC (permalink / raw)
  To: u-boot

Event groups are used to signal multiple events at the same time.
They are identified by GUIDs. This patch provided the predefined
GUIDs of UEFI specification 2.7.

Signed-off-by: Heinrich Schuchardt <xypron.glpk@gmx.de>
---
 include/efi_api.h             | 21 +++++++++++++++++++++
 include/efi_loader.h          | 10 ++++++++++
 lib/efi_loader/efi_boottime.c | 16 ++++++++++++++++
 3 files changed, 47 insertions(+)

diff --git a/include/efi_api.h b/include/efi_api.h
index 13ed80ac97..d20058540a 100644
--- a/include/efi_api.h
+++ b/include/efi_api.h
@@ -244,6 +244,27 @@ struct efi_runtime_services {
 			u64 maximum_variable_size);
 };
 
+/* EFI event group GUID definitions */
+#define EFI_EVENT_GROUP_EXIT_BOOT_SERVICES \
+	EFI_GUID(0x27abf055, 0xb1b8, 0x4c26, 0x80, 0x48, \
+		 0x74, 0x8f, 0x37, 0xba, 0xa2, 0xdf)
+
+#define EFI_EVENT_GROUP_VIRTUAL_ADDRESS_CHANGE \
+	EFI_GUID(0x13fa7698, 0xc831, 0x49c7, 0x87, 0xea, \
+		 0x8f, 0x43, 0xfc, 0xc2, 0x51, 0x96)
+
+#define EFI_EVENT_GROUP_MEMORY_MAP_CHANGE \
+	EFI_GUID(0x78bee926, 0x692f, 0x48fd, 0x9e, 0xdb, \
+		 0x01, 0x42, 0x2e, 0xf0, 0xd7, 0xab)
+
+#define EFI_EVENT_GROUP_READY_TO_BOOT \
+	EFI_GUID(0x7ce88fb3, 0x4bd7, 0x4679, 0x87, 0xa8, \
+		 0xa8, 0xd8, 0xde, 0xe5, 0x0d, 0x2b)
+
+#define EFI_EVENT_GROUP_RESET_SYSTEM \
+	EFI_GUID(0x62da6a56, 0x13fb, 0x485a, 0xa8, 0xda, \
+		 0xa3, 0xdd, 0x79, 0x12, 0xcb, 0x6b)
+
 /* EFI Configuration Table and GUID definitions */
 #define NULL_GUID \
 	EFI_GUID(0x00000000, 0x0000, 0x0000, 0x00, 0x00, \
diff --git a/include/efi_loader.h b/include/efi_loader.h
index 7f703c6ef7..e2cd249171 100644
--- a/include/efi_loader.h
+++ b/include/efi_loader.h
@@ -93,6 +93,16 @@ extern const efi_guid_t efi_guid_console_control;
 extern const efi_guid_t efi_guid_device_path;
 /* GUID of the EFI_DRIVER_BINDING_PROTOCOL */
 extern const efi_guid_t efi_guid_driver_binding_protocol;
+/* event group ExitBootServices() invoked */
+extern const efi_guid_t efi_guid_event_group_exit_boot_services;
+/* event group SetVirtualAddressMap() invoked */
+extern const efi_guid_t efi_guid_event_group_virtual_address_change;
+/* event group memory map changed */
+extern const efi_guid_t efi_guid_event_group_memory_map_change;
+/* event group boot manager about to boot */
+extern const efi_guid_t efi_guid_event_group_ready_to_boot;
+/* event group ResetSystem() invoked (before ExitBootServices) */
+extern const efi_guid_t efi_guid_event_group_reset_system;
 /* GUID of the device tree table */
 extern const efi_guid_t efi_guid_fdt;
 extern const efi_guid_t efi_guid_loaded_image;
diff --git a/lib/efi_loader/efi_boottime.c b/lib/efi_loader/efi_boottime.c
index 4acb1e092a..da3c852b44 100644
--- a/lib/efi_loader/efi_boottime.c
+++ b/lib/efi_loader/efi_boottime.c
@@ -65,6 +65,22 @@ const efi_guid_t efi_guid_fdt = EFI_FDT_GUID;
 const efi_guid_t efi_guid_driver_binding_protocol =
 			EFI_DRIVER_BINDING_PROTOCOL_GUID;
 
+/* event group ExitBootServices() invoked */
+const efi_guid_t efi_guid_event_group_exit_boot_services =
+			EFI_EVENT_GROUP_EXIT_BOOT_SERVICES;
+/* event group SetVirtualAddressMap() invoked */
+const efi_guid_t efi_guid_event_group_virtual_address_change =
+			EFI_EVENT_GROUP_VIRTUAL_ADDRESS_CHANGE;
+/* event group memory map changed */
+const efi_guid_t efi_guid_event_group_memory_map_change =
+			EFI_EVENT_GROUP_MEMORY_MAP_CHANGE;
+/* event group boot manager about to boot */
+const efi_guid_t efi_guid_event_group_ready_to_boot =
+			EFI_EVENT_GROUP_READY_TO_BOOT;
+/* event group ResetSystem() invoked (before ExitBootServices) */
+const efi_guid_t efi_guid_event_group_reset_system =
+			EFI_EVENT_GROUP_RESET_SYSTEM;
+
 static efi_status_t EFIAPI efi_disconnect_controller(
 					efi_handle_t controller_handle,
 					efi_handle_t driver_image_handle,
-- 
2.14.2

^ permalink raw reply related	[flat|nested] 8+ messages in thread

* [U-Boot] [PATCH 4/5] efi_loader: implement event groups
  2018-02-18 14:17 [U-Boot] [PATCH 0/5] efi_loader: implement event groups Heinrich Schuchardt
                   ` (2 preceding siblings ...)
  2018-02-18 14:17 ` [U-Boot] [PATCH 3/5] efi_loader: define GUIDS for event groups Heinrich Schuchardt
@ 2018-02-18 14:17 ` Heinrich Schuchardt
  2018-02-18 14:17 ` [U-Boot] [PATCH 5/5] efi_selftest: unit test for " Heinrich Schuchardt
  4 siblings, 0 replies; 8+ messages in thread
From: Heinrich Schuchardt @ 2018-02-18 14:17 UTC (permalink / raw)
  To: u-boot

If an event of a group event is signaled all other events of the same
group are signaled too.

Function efi_signal_event is renamed to efi_queue_event.
A new function efi_signal_event is introduced that checks if an event
belongs to a group and than signals all events of the group.
Event group notifciation is implemented for ExitBootServices,
InstallConfigurationTable, and ResetSystem.

Signed-off-by: Heinrich Schuchardt <xypron.glpk@gmx.de>
---
 include/efi_loader.h          |  7 ++-
 lib/efi_loader/efi_boottime.c | 99 ++++++++++++++++++++++++++++++++++---------
 lib/efi_loader/efi_console.c  |  6 +--
 lib/efi_loader/efi_net.c      |  4 +-
 lib/efi_loader/efi_runtime.c  | 11 +++++
 lib/efi_loader/efi_watchdog.c |  2 +-
 6 files changed, 101 insertions(+), 28 deletions(-)

diff --git a/include/efi_loader.h b/include/efi_loader.h
index e2cd249171..b1999f08c6 100644
--- a/include/efi_loader.h
+++ b/include/efi_loader.h
@@ -161,6 +161,7 @@ struct efi_object {
  * @notify_tpl:		Task priority level of notifications
  * @nofify_function:	Function to call when the event is triggered
  * @notify_context:	Data to be passed to the notify function
+ * @group:		Event group
  * @trigger_time:	Period of the timer
  * @trigger_next:	Next time to trigger the timer
  * @trigger_type:	Type of timer, see efi_set_timer
@@ -173,6 +174,7 @@ struct efi_event {
 	efi_uintn_t notify_tpl;
 	void (EFIAPI *notify_function)(struct efi_event *event, void *context);
 	void *notify_context;
+	const efi_guid_t *group;
 	u64 trigger_next;
 	u64 trigger_time;
 	enum efi_timer_delay trigger_type;
@@ -182,6 +184,8 @@ struct efi_event {
 
 /* This list contains all UEFI objects we know of */
 extern struct list_head efi_obj_list;
+/* List of all events */
+extern struct list_head efi_events;
 
 /* Called by bootefi to make console interface available */
 int efi_console_register(void);
@@ -248,7 +252,8 @@ efi_status_t efi_create_event(uint32_t type, efi_uintn_t notify_tpl,
 			      void (EFIAPI *notify_function) (
 					struct efi_event *event,
 					void *context),
-			      void *notify_context, struct efi_event **event);
+			      void *notify_context, efi_guid_t *group,
+			      struct efi_event **event);
 /* Call this to set a timer */
 efi_status_t efi_set_timer(struct efi_event *event, enum efi_timer_delay type,
 			   uint64_t trigger_time);
diff --git a/lib/efi_loader/efi_boottime.c b/lib/efi_loader/efi_boottime.c
index da3c852b44..32b8149fe7 100644
--- a/lib/efi_loader/efi_boottime.c
+++ b/lib/efi_loader/efi_boottime.c
@@ -27,7 +27,7 @@ static efi_uintn_t efi_tpl = TPL_APPLICATION;
 LIST_HEAD(efi_obj_list);
 
 /* List of all events */
-static LIST_HEAD(efi_events);
+LIST_HEAD(efi_events);
 
 /*
  * If we're running on nasty systems (32bit ARM booting into non-EFI Linux)
@@ -176,7 +176,7 @@ const char *__efi_nesting_dec(void)
  * @event	event to signal
  * @check_tpl	check the TPL level
  */
-void efi_signal_event(struct efi_event *event, bool check_tpl)
+static void efi_queue_event(struct efi_event *event, bool check_tpl)
 {
 	if (event->notify_function) {
 		event->is_queued = true;
@@ -189,6 +189,50 @@ void efi_signal_event(struct efi_event *event, bool check_tpl)
 	event->is_queued = false;
 }
 
+/*
+ * Signal an EFI event.
+ *
+ * This function signals an event. If the event belongs to an event group
+ * all events of the group are signaled. If they are of type EVT_NOTIFY_SIGNAL
+ * their notification function is queued.
+ *
+ * For the SignalEvent service see efi_signal_event_ext.
+ *
+ * @event	event to signal
+ * @check_tpl	check the TPL level
+ */
+void efi_signal_event(struct efi_event *event, bool check_tpl)
+{
+	if (event->group) {
+		struct efi_event *evt;
+
+		/*
+		 * The signaled state has to set before executing any
+		 * notification function
+		 */
+		list_for_each_entry(evt, &efi_events, link) {
+			if (!evt->group || guidcmp(evt->group, event->group))
+				continue;
+			if (evt->is_signaled)
+				continue;
+			evt->is_signaled = true;
+			if (evt->type & EVT_NOTIFY_SIGNAL &&
+			    evt->notify_function)
+				evt->is_queued = true;
+		}
+		list_for_each_entry(evt, &efi_events, link) {
+			if (!evt->group || guidcmp(evt->group, event->group))
+				continue;
+			if (evt->is_queued)
+				efi_queue_event(evt, check_tpl);
+		}
+	} else if (!event->is_signaled) {
+		event->is_signaled = true;
+		if (event->type & EVT_NOTIFY_SIGNAL)
+			efi_queue_event(event, check_tpl);
+	}
+}
+
 /*
  * Raise the task priority level.
  *
@@ -529,7 +573,8 @@ efi_status_t efi_create_event(uint32_t type, efi_uintn_t notify_tpl,
 			      void (EFIAPI *notify_function) (
 					struct efi_event *event,
 					void *context),
-			      void *notify_context, struct efi_event **event)
+			      void *notify_context, efi_guid_t *group,
+			      struct efi_event **event)
 {
 	struct efi_event *evt;
 
@@ -550,6 +595,7 @@ efi_status_t efi_create_event(uint32_t type, efi_uintn_t notify_tpl,
 	evt->notify_tpl = notify_tpl;
 	evt->notify_function = notify_function;
 	evt->notify_context = notify_context;
+	evt->group = group;
 	/* Disable timers on bootup */
 	evt->trigger_next = -1ULL;
 	evt->is_queued = false;
@@ -585,10 +631,8 @@ efi_status_t EFIAPI efi_create_event_ex(uint32_t type, efi_uintn_t notify_tpl,
 {
 	EFI_ENTRY("%d, 0x%zx, %p, %p, %pUl", type, notify_tpl, notify_function,
 		  notify_context, event_group);
-	if (event_group)
-		return EFI_EXIT(EFI_UNSUPPORTED);
 	return EFI_EXIT(efi_create_event(type, notify_tpl, notify_function,
-					 notify_context, event));
+					 notify_context, event_group, event));
 }
 
 /*
@@ -615,7 +659,7 @@ static efi_status_t EFIAPI efi_create_event_ext(
 	EFI_ENTRY("%d, 0x%zx, %p, %p", type, notify_tpl, notify_function,
 		  notify_context);
 	return EFI_EXIT(efi_create_event(type, notify_tpl, notify_function,
-					 notify_context, event));
+					 notify_context, NULL, event));
 }
 
 /*
@@ -632,7 +676,7 @@ void efi_timer_check(void)
 
 	list_for_each_entry(evt, &efi_events, link) {
 		if (evt->is_queued)
-			efi_signal_event(evt, true);
+			efi_queue_event(evt, true);
 		if (!(evt->type & EVT_TIMER) || now < evt->trigger_next)
 			continue;
 		switch (evt->trigger_type) {
@@ -645,7 +689,7 @@ void efi_timer_check(void)
 		default:
 			continue;
 		}
-		evt->is_signaled = true;
+		evt->is_signaled = false;
 		efi_signal_event(evt, true);
 	}
 	WATCHDOG_RESET();
@@ -744,7 +788,7 @@ static efi_status_t EFIAPI efi_wait_for_event(efi_uintn_t num_events,
 		if (!event[i]->type || event[i]->type & EVT_NOTIFY_SIGNAL)
 			return EFI_EXIT(EFI_INVALID_PARAMETER);
 		if (!event[i]->is_signaled)
-			efi_signal_event(event[i], true);
+			efi_queue_event(event[i], true);
 	}
 
 	/* Wait for signal */
@@ -787,11 +831,7 @@ static efi_status_t EFIAPI efi_signal_event_ext(struct efi_event *event)
 	EFI_ENTRY("%p", event);
 	if (efi_is_event(event) != EFI_SUCCESS)
 		return EFI_EXIT(EFI_INVALID_PARAMETER);
-	if (!event->is_signaled) {
-		event->is_signaled = true;
-		if (event->type & EVT_NOTIFY_SIGNAL)
-			efi_signal_event(event, true);
-	}
+	efi_signal_event(event, true);
 	return EFI_EXIT(EFI_SUCCESS);
 }
 
@@ -836,7 +876,7 @@ static efi_status_t EFIAPI efi_check_event(struct efi_event *event)
 	    event->type & EVT_NOTIFY_SIGNAL)
 		return EFI_EXIT(EFI_INVALID_PARAMETER);
 	if (!event->is_signaled)
-		efi_signal_event(event, true);
+		efi_queue_event(event, true);
 	if (event->is_signaled) {
 		event->is_signaled = false;
 		return EFI_EXIT(EFI_SUCCESS);
@@ -1333,6 +1373,7 @@ static void efi_remove_configuration_table(int i)
 efi_status_t efi_install_configuration_table(const efi_guid_t *guid,
 					     void *table)
 {
+	struct efi_event *evt;
 	int i;
 
 	if (!guid)
@@ -1345,7 +1386,7 @@ efi_status_t efi_install_configuration_table(const efi_guid_t *guid,
 				efi_conf_table[i].table = table;
 			else
 				efi_remove_configuration_table(i);
-			return EFI_SUCCESS;
+			goto out;
 		}
 	}
 
@@ -1361,6 +1402,15 @@ efi_status_t efi_install_configuration_table(const efi_guid_t *guid,
 	efi_conf_table[i].table = table;
 	systab.nr_tables = i + 1;
 
+out:
+	/* Notify that the configuration table was changed */
+	list_for_each_entry(evt, &efi_events, link) {
+		if (evt->group && !guidcmp(evt->group, guid)) {
+			efi_signal_event(evt, false);
+			break;
+		}
+	}
+
 	return EFI_SUCCESS;
 }
 
@@ -1738,12 +1788,19 @@ static efi_status_t EFIAPI efi_exit_boot_services(efi_handle_t image_handle,
 	if (!systab.boottime)
 		return EFI_EXIT(EFI_SUCCESS);
 
+	/* Add related events to the event group */
+	list_for_each_entry(evt, &efi_events, link) {
+		if (evt->type == EVT_SIGNAL_EXIT_BOOT_SERVICES)
+			evt->group = &efi_guid_event_group_exit_boot_services;
+	}
 	/* Notify that ExitBootServices is invoked. */
 	list_for_each_entry(evt, &efi_events, link) {
-		if (evt->type != EVT_SIGNAL_EXIT_BOOT_SERVICES)
-			continue;
-		evt->is_signaled = true;
-		efi_signal_event(evt, false);
+		if (evt->group &&
+		    !guidcmp(evt->group,
+			     &efi_guid_event_group_exit_boot_services)) {
+			efi_signal_event(evt, false);
+			break;
+		}
 	}
 
 	/* TODO Should persist EFI variables here */
diff --git a/lib/efi_loader/efi_console.c b/lib/efi_loader/efi_console.c
index 3cb580e3ed..d35893dc2a 100644
--- a/lib/efi_loader/efi_console.c
+++ b/lib/efi_loader/efi_console.c
@@ -488,14 +488,14 @@ int efi_console_register(void)
 		goto out_of_memory;
 
 	/* Create console events */
-	r = efi_create_event(EVT_NOTIFY_WAIT, TPL_CALLBACK,
-			     efi_key_notify, NULL, &efi_con_in.wait_for_key);
+	r = efi_create_event(EVT_NOTIFY_WAIT, TPL_CALLBACK, efi_key_notify,
+			     NULL, NULL, &efi_con_in.wait_for_key);
 	if (r != EFI_SUCCESS) {
 		printf("ERROR: Failed to register WaitForKey event\n");
 		return r;
 	}
 	r = efi_create_event(EVT_TIMER | EVT_NOTIFY_SIGNAL, TPL_CALLBACK,
-			     efi_console_timer_notify, NULL,
+			     efi_console_timer_notify, NULL, NULL,
 			     &console_timer_event);
 	if (r != EFI_SUCCESS) {
 		printf("ERROR: Failed to register console event\n");
diff --git a/lib/efi_loader/efi_net.c b/lib/efi_loader/efi_net.c
index e7fed79450..b88dc91f58 100644
--- a/lib/efi_loader/efi_net.c
+++ b/lib/efi_loader/efi_net.c
@@ -341,7 +341,7 @@ efi_status_t efi_net_register(void)
 	 * Create WaitForPacket event.
 	 */
 	r = efi_create_event(EVT_NOTIFY_WAIT, TPL_CALLBACK,
-			     efi_network_timer_notify, NULL,
+			     efi_network_timer_notify, NULL, NULL,
 			     &wait_for_packet);
 	if (r != EFI_SUCCESS) {
 		printf("ERROR: Failed to register network event\n");
@@ -355,7 +355,7 @@ efi_status_t efi_net_register(void)
 	 * has been received.
 	 */
 	r = efi_create_event(EVT_TIMER | EVT_NOTIFY_SIGNAL, TPL_CALLBACK,
-			     efi_network_timer_notify, NULL,
+			     efi_network_timer_notify, NULL, NULL,
 			     &network_timer_event);
 	if (r != EFI_SUCCESS) {
 		printf("ERROR: Failed to register network event\n");
diff --git a/lib/efi_loader/efi_runtime.c b/lib/efi_loader/efi_runtime.c
index e2b86828cd..d0f213ea4f 100644
--- a/lib/efi_loader/efi_runtime.c
+++ b/lib/efi_loader/efi_runtime.c
@@ -78,9 +78,20 @@ static void EFIAPI efi_reset_system_boottime(
 			efi_status_t reset_status,
 			unsigned long data_size, void *reset_data)
 {
+	struct efi_event *evt;
+
 	EFI_ENTRY("%d %lx %lx %p", reset_type, reset_status, data_size,
 		  reset_data);
 
+	/* Notify reset */
+	list_for_each_entry(evt, &efi_events, link) {
+		if (evt->group &&
+		    !guidcmp(evt->group,
+			     &efi_guid_event_group_reset_system)) {
+			efi_signal_event(evt, false);
+			break;
+		}
+	}
 	switch (reset_type) {
 	case EFI_RESET_COLD:
 	case EFI_RESET_WARM:
diff --git a/lib/efi_loader/efi_watchdog.c b/lib/efi_loader/efi_watchdog.c
index b1c35a8e29..d12e51da0a 100644
--- a/lib/efi_loader/efi_watchdog.c
+++ b/lib/efi_loader/efi_watchdog.c
@@ -67,7 +67,7 @@ efi_status_t efi_watchdog_register(void)
 	 * Create a timer event.
 	 */
 	r = efi_create_event(EVT_TIMER | EVT_NOTIFY_SIGNAL, TPL_CALLBACK,
-			     efi_watchdog_timer_notify, NULL,
+			     efi_watchdog_timer_notify, NULL, NULL,
 			     &watchdog_timer_event);
 	if (r != EFI_SUCCESS) {
 		printf("ERROR: Failed to register watchdog event\n");
-- 
2.14.2

^ permalink raw reply related	[flat|nested] 8+ messages in thread

* [U-Boot] [PATCH 5/5] efi_selftest: unit test for event groups
  2018-02-18 14:17 [U-Boot] [PATCH 0/5] efi_loader: implement event groups Heinrich Schuchardt
                   ` (3 preceding siblings ...)
  2018-02-18 14:17 ` [U-Boot] [PATCH 4/5] efi_loader: implement " Heinrich Schuchardt
@ 2018-02-18 14:17 ` Heinrich Schuchardt
  2018-03-12 17:59   ` Heinrich Schuchardt
  4 siblings, 1 reply; 8+ messages in thread
From: Heinrich Schuchardt @ 2018-02-18 14:17 UTC (permalink / raw)
  To: u-boot

Supply a unit test for event groups.

Create multiple events in an event group. Signal each event once and check
that all events are notified once in each round.

Signed-off-by: Heinrich Schuchardt <xypron.glpk@gmx.de>
---
 lib/efi_selftest/Makefile                    |   1 +
 lib/efi_selftest/efi_selftest_event_groups.c | 140 +++++++++++++++++++++++++++
 2 files changed, 141 insertions(+)
 create mode 100644 lib/efi_selftest/efi_selftest_event_groups.c

diff --git a/lib/efi_selftest/Makefile b/lib/efi_selftest/Makefile
index b975da2955..51af1055e9 100644
--- a/lib/efi_selftest/Makefile
+++ b/lib/efi_selftest/Makefile
@@ -19,6 +19,7 @@ efi_selftest_controllers.o \
 efi_selftest_console.o \
 efi_selftest_devicepath.o \
 efi_selftest_events.o \
+efi_selftest_event_groups.o \
 efi_selftest_exitbootservices.o \
 efi_selftest_fdt.o \
 efi_selftest_gop.o \
diff --git a/lib/efi_selftest/efi_selftest_event_groups.c b/lib/efi_selftest/efi_selftest_event_groups.c
new file mode 100644
index 0000000000..79e4ea1ce2
--- /dev/null
+++ b/lib/efi_selftest/efi_selftest_event_groups.c
@@ -0,0 +1,140 @@
+/*
+ * efi_selftest_event_groups
+ *
+ * Copyright (c) 2018 Heinrich Schuchardt <xypron.glpk@gmx.de>
+ *
+ * SPDX-License-Identifier:     GPL-2.0+
+ *
+ * This test checks the notification of group events and the
+ * following services:
+ * CreateEventEx, CloseEvent, SignalEvent, CheckEvent.
+ */
+
+#include <efi_selftest.h>
+
+#define GROUP_SIZE 16
+
+static struct efi_boot_services *boottime;
+static efi_guid_t event_group =
+	EFI_GUID(0x2335905b, 0xc3b9, 0x4221, 0xa3, 0x71,
+		 0x0e, 0x5b, 0x45, 0xc0, 0x56, 0x91);
+
+/*
+ * 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.
+ *
+ * @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)
+{
+	boottime = systable->boottime;
+
+	return EFI_ST_SUCCESS;
+}
+
+/*
+ * Execute unit test.
+ *
+ * Create multiple events in an event group. Signal each event once and check
+ * that all events are notified once in each round.
+ *
+ * @return:	EFI_ST_SUCCESS for success
+ */
+static int execute(void)
+{
+	unsigned int counter[GROUP_SIZE] = {0};
+	struct efi_event *events[GROUP_SIZE];
+	size_t i, j;
+	efi_status_t ret;
+
+	for (i = 0; i < GROUP_SIZE; ++i) {
+		ret = boottime->create_event_ex(0, TPL_NOTIFY,
+						notify, (void *)&counter[i],
+						&event_group, &events[i]);
+		if (ret != EFI_SUCCESS) {
+			efi_st_error("Failed to create event\n");
+			return EFI_ST_FAILURE;
+		}
+	}
+
+	for (i = 0; i < GROUP_SIZE; ++i) {
+		ret = boottime->signal_event(events[i]);
+		if (ret != EFI_SUCCESS) {
+			efi_st_error("Failed to signal event\n");
+			return EFI_ST_FAILURE;
+		}
+		for (j = 0; j < GROUP_SIZE; ++j) {
+			if (counter[j] != i) {
+				efi_st_printf("i %u, j %u, count %u\n",
+					      (unsigned int)i, (unsigned int)j,
+					      (unsigned int)counter[j]);
+				efi_st_error(
+					"Notification function was called\n");
+				return EFI_ST_FAILURE;
+			}
+			/* Clear signaled state */
+			ret = boottime->check_event(events[j]);
+			if (ret != EFI_SUCCESS) {
+				efi_st_error("Event was not signaled\n");
+				return EFI_ST_FAILURE;
+			}
+			if (counter[j] != i) {
+				efi_st_printf("i %u, j %u, count %u\n",
+					      (unsigned int)i, (unsigned int)j,
+					      (unsigned int)counter[j]);
+				efi_st_error(
+					"Notification function was called\n");
+				return EFI_ST_FAILURE;
+			}
+			/* Call notification function  */
+			ret = boottime->check_event(events[j]);
+			if (ret != EFI_NOT_READY) {
+				efi_st_error(
+					"Signaled state not cleared\n");
+				return EFI_ST_FAILURE;
+			}
+			if (counter[j] != i + 1) {
+				efi_st_printf("i %u, j %u, count %u\n",
+					      (unsigned int)i, (unsigned int)j,
+					      (unsigned int)counter[j]);
+				efi_st_error(
+					"Nofification function not called\n");
+				return EFI_ST_FAILURE;
+			}
+		}
+	}
+
+	for (i = 0; i < GROUP_SIZE; ++i) {
+		ret = boottime->close_event(events[i]);
+		if (ret != EFI_SUCCESS) {
+			efi_st_error("Failed to close event\n");
+			return EFI_ST_FAILURE;
+		}
+	}
+
+	return EFI_ST_SUCCESS;
+}
+
+EFI_UNIT_TEST(eventgoups) = {
+	.name = "event groups",
+	.phase = EFI_EXECUTE_BEFORE_BOOTTIME_EXIT,
+	.setup = setup,
+	.execute = execute,
+};
-- 
2.14.2

^ permalink raw reply related	[flat|nested] 8+ messages in thread

* [U-Boot] [PATCH 5/5] efi_selftest: unit test for event groups
  2018-02-18 14:17 ` [U-Boot] [PATCH 5/5] efi_selftest: unit test for " Heinrich Schuchardt
@ 2018-03-12 17:59   ` Heinrich Schuchardt
  2018-03-12 19:50     ` Alexander Graf
  0 siblings, 1 reply; 8+ messages in thread
From: Heinrich Schuchardt @ 2018-03-12 17:59 UTC (permalink / raw)
  To: u-boot

On 02/18/2018 03:17 PM, Heinrich Schuchardt wrote:
> Supply a unit test for event groups.
> 
> Create multiple events in an event group. Signal each event once and check
> that all events are notified once in each round.
> 
> Signed-off-by: Heinrich Schuchardt <xypron.glpk@gmx.de>

Hello Alex,

you merged patch 1-4 of this series. Is there a problem with this patch
providing a unit test?

Regards

Heinrich

^ permalink raw reply	[flat|nested] 8+ messages in thread

* [U-Boot] [PATCH 5/5] efi_selftest: unit test for event groups
  2018-03-12 17:59   ` Heinrich Schuchardt
@ 2018-03-12 19:50     ` Alexander Graf
  0 siblings, 0 replies; 8+ messages in thread
From: Alexander Graf @ 2018-03-12 19:50 UTC (permalink / raw)
  To: u-boot



On 12.03.18 18:59, Heinrich Schuchardt wrote:
> On 02/18/2018 03:17 PM, Heinrich Schuchardt wrote:
>> Supply a unit test for event groups.
>>
>> Create multiple events in an event group. Signal each event once and check
>> that all events are notified once in each round.
>>
>> Signed-off-by: Heinrich Schuchardt <xypron.glpk@gmx.de>
> 
> Hello Alex,
> 
> you merged patch 1-4 of this series. Is there a problem with this patch
> providing a unit test?

Not at all, it probably just slipped through :)


Alex

^ permalink raw reply	[flat|nested] 8+ messages in thread

end of thread, other threads:[~2018-03-12 19:50 UTC | newest]

Thread overview: 8+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2018-02-18 14:17 [U-Boot] [PATCH 0/5] efi_loader: implement event groups Heinrich Schuchardt
2018-02-18 14:17 ` [U-Boot] [PATCH 1/5] efi_loader: fix formatting errors Heinrich Schuchardt
2018-02-18 14:17 ` [U-Boot] [PATCH 2/5] efi_loader: manage events in a linked list Heinrich Schuchardt
2018-02-18 14:17 ` [U-Boot] [PATCH 3/5] efi_loader: define GUIDS for event groups Heinrich Schuchardt
2018-02-18 14:17 ` [U-Boot] [PATCH 4/5] efi_loader: implement " Heinrich Schuchardt
2018-02-18 14:17 ` [U-Boot] [PATCH 5/5] efi_selftest: unit test for " Heinrich Schuchardt
2018-03-12 17:59   ` Heinrich Schuchardt
2018-03-12 19:50     ` Alexander Graf

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.