From 842a8e434e48e3d4d7a862c4a1676a698aa0954d Mon Sep 17 00:00:00 2001 From: Heinrich Schuchardt Date: Sun, 27 Aug 2017 00:51:04 +0200 Subject: efi_loader: support 16 protocols per efi_object 8 protocols per efi_object is insufficient for iPXE. Signed-off-by: Heinrich Schuchardt Reviewed-by: Simon Glass Reviewed-by: Rob Clark Signed-off-by: Alexander Graf --- include/efi_loader.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'include') diff --git a/include/efi_loader.h b/include/efi_loader.h index 2f081f89965..90db7900014 100644 --- a/include/efi_loader.h +++ b/include/efi_loader.h @@ -112,8 +112,8 @@ struct efi_handler { struct efi_object { /* Every UEFI object is part of a global object list */ struct list_head link; - /* We support up to 8 "protocols" an object can be accessed through */ - struct efi_handler protocols[8]; + /* We support up to 16 "protocols" an object can be accessed through */ + struct efi_handler protocols[16]; /* The object spawner can either use this for data or as identifier */ void *handle; }; -- cgit v1.3.1 From e190e8972faf4d5b09e2a92fefc54a1832fd67da Mon Sep 17 00:00:00 2001 From: Heinrich Schuchardt Date: Wed, 4 Oct 2017 15:03:24 +0200 Subject: efi_loader: use type bool for event states Queued and signaled describe boolean states of events. So let's use type bool and rename the structure members to is_queued and is_signaled. Update the comments for is_queued and is_signaled. Reported-by: Simon Glass Signed-off-by: Heinrich Schuchardt Reviewed-by: Rob Clark Reviewed-by: Rob Clark Signed-off-by: Alexander Graf --- include/efi_loader.h | 8 ++++---- lib/efi_loader/efi_boottime.c | 32 ++++++++++++++++---------------- lib/efi_loader/efi_console.c | 2 +- 3 files changed, 21 insertions(+), 21 deletions(-) (limited to 'include') diff --git a/include/efi_loader.h b/include/efi_loader.h index 90db7900014..e1179b7dcd1 100644 --- a/include/efi_loader.h +++ b/include/efi_loader.h @@ -136,8 +136,8 @@ struct efi_object { * @nofify_function: Function to call when the event is triggered * @notify_context: Data to be passed to the notify function * @trigger_type: Type of timer, see efi_set_timer - * @queued: The notification functionis queued - * @signaled: The event occured + * @queued: The notification function is queued + * @signaled: The event occurred. The event is in the signaled state. */ struct efi_event { uint32_t type; @@ -147,8 +147,8 @@ struct efi_event { u64 trigger_next; u64 trigger_time; enum efi_timer_delay trigger_type; - int queued; - int signaled; + bool is_queued; + bool is_signaled; }; diff --git a/lib/efi_loader/efi_boottime.c b/lib/efi_loader/efi_boottime.c index c8f39b5b10a..cb688e16e93 100644 --- a/lib/efi_loader/efi_boottime.c +++ b/lib/efi_loader/efi_boottime.c @@ -164,14 +164,14 @@ static u64 efi_div10(u64 a) void efi_signal_event(struct efi_event *event) { if (event->notify_function) { - event->queued = 1; + event->is_queued = true; /* Check TPL */ if (efi_tpl >= event->notify_tpl) return; EFI_CALL_VOID(event->notify_function(event, event->notify_context)); } - event->queued = 0; + event->is_queued = false; } static efi_status_t efi_unsupported(const char *funcname) @@ -316,8 +316,8 @@ efi_status_t efi_create_event(uint32_t type, UINTN notify_tpl, efi_events[i].notify_context = notify_context; /* Disable timers on bootup */ efi_events[i].trigger_next = -1ULL; - efi_events[i].queued = 0; - efi_events[i].signaled = 0; + efi_events[i].is_queued = false; + efi_events[i].is_signaled = false; *event = &efi_events[i]; return EFI_SUCCESS; } @@ -350,7 +350,7 @@ void efi_timer_check(void) for (i = 0; i < ARRAY_SIZE(efi_events); ++i) { if (!efi_events[i].type) continue; - if (efi_events[i].queued) + if (efi_events[i].is_queued) efi_signal_event(&efi_events[i]); if (!(efi_events[i].type & EVT_TIMER) || now < efi_events[i].trigger_next) @@ -366,7 +366,7 @@ void efi_timer_check(void) default: continue; } - efi_events[i].signaled = 1; + efi_events[i].is_signaled = true; efi_signal_event(&efi_events[i]); } WATCHDOG_RESET(); @@ -403,7 +403,7 @@ efi_status_t efi_set_timer(struct efi_event *event, enum efi_timer_delay type, } event->trigger_type = type; event->trigger_time = trigger_time; - event->signaled = 0; + event->is_signaled = false; return EFI_SUCCESS; } return EFI_INVALID_PARAMETER; @@ -440,14 +440,14 @@ static efi_status_t EFIAPI efi_wait_for_event(unsigned long num_events, known_event: if (!event[i]->type || event[i]->type & EVT_NOTIFY_SIGNAL) return EFI_EXIT(EFI_INVALID_PARAMETER); - if (!event[i]->signaled) + if (!event[i]->is_signaled) efi_signal_event(event[i]); } /* Wait for signal */ for (;;) { for (i = 0; i < num_events; ++i) { - if (event[i]->signaled) + if (event[i]->is_signaled) goto out; } /* Allow events to occur. */ @@ -459,7 +459,7 @@ out: * Reset the signal which is passed to the caller to allow periodic * events to occur. */ - event[i]->signaled = 0; + event[i]->is_signaled = false; if (index) *index = i; @@ -474,9 +474,9 @@ static efi_status_t EFIAPI efi_signal_event_ext(struct efi_event *event) for (i = 0; i < ARRAY_SIZE(efi_events); ++i) { if (event != &efi_events[i]) continue; - if (event->signaled) + if (event->is_signaled) break; - event->signaled = 1; + event->is_signaled = true; if (event->type & EVT_NOTIFY_SIGNAL) efi_signal_event(event); break; @@ -493,8 +493,8 @@ static efi_status_t EFIAPI efi_close_event(struct efi_event *event) if (event == &efi_events[i]) { event->type = 0; event->trigger_next = -1ULL; - event->queued = 0; - event->signaled = 0; + event->is_queued = false; + event->is_signaled = false; return EFI_EXIT(EFI_SUCCESS); } } @@ -512,9 +512,9 @@ static efi_status_t EFIAPI efi_check_event(struct efi_event *event) continue; if (!event->type || event->type & EVT_NOTIFY_SIGNAL) break; - if (!event->signaled) + if (!event->is_signaled) efi_signal_event(event); - if (event->signaled) + if (event->is_signaled) return EFI_EXIT(EFI_SUCCESS); return EFI_EXIT(EFI_NOT_READY); } diff --git a/lib/efi_loader/efi_console.c b/lib/efi_loader/efi_console.c index fd5398d61d9..1bdf36b4ae7 100644 --- a/lib/efi_loader/efi_console.c +++ b/lib/efi_loader/efi_console.c @@ -460,7 +460,7 @@ static void EFIAPI efi_console_timer_notify(struct efi_event *event, { EFI_ENTRY("%p, %p", event, context); if (tstc()) { - efi_con_in.wait_for_key->signaled = 1; + efi_con_in.wait_for_key->is_signaled = true; efi_signal_event(efi_con_in.wait_for_key); } EFI_EXIT(EFI_SUCCESS); -- cgit v1.3.1 From e67e7249c8000d72b4c4b985fdeb3e103d65aa9e Mon Sep 17 00:00:00 2001 From: Heinrich Schuchardt Date: Wed, 4 Oct 2017 15:31:26 +0200 Subject: efi_selftest: make tests easier to read Rename counter to more illustrative names. Update notification function description. Simplify notification function. Add comment for arbitrary non-zero value. Document @return. Use constants for return values of setup, execute, teardown. Reported-by: Simon Glass Signed-off-by: Heinrich Schuchardt Reviewed-by: Simon Glass Signed-off-by: Alexander Graf --- include/efi_selftest.h | 3 + lib/efi_selftest/efi_selftest.c | 15 +++-- lib/efi_selftest/efi_selftest_events.c | 80 ++++++++++++---------- lib/efi_selftest/efi_selftest_exitbootservices.c | 46 +++++++------ lib/efi_selftest/efi_selftest_tpl.c | 85 +++++++++++++----------- 5 files changed, 129 insertions(+), 100 deletions(-) (limited to 'include') diff --git a/include/efi_selftest.h b/include/efi_selftest.h index 76304a2b2a7..beb662d4e1b 100644 --- a/include/efi_selftest.h +++ b/include/efi_selftest.h @@ -14,6 +14,9 @@ #include #include +#define EFI_ST_SUCCESS 0 +#define EFI_ST_FAILURE 1 + /* * Prints an error message. * diff --git a/lib/efi_selftest/efi_selftest.c b/lib/efi_selftest/efi_selftest.c index ff00254c219..45d8d3d384c 100644 --- a/lib/efi_selftest/efi_selftest.c +++ b/lib/efi_selftest/efi_selftest.c @@ -66,16 +66,17 @@ void efi_st_exit_boot_services(void) * * @test the test to be executed * @failures counter that will be incremented if a failure occurs + * @return EFI_ST_SUCCESS for success */ static int setup(struct efi_unit_test *test, unsigned int *failures) { int ret; if (!test->setup) - return 0; + return EFI_ST_SUCCESS; efi_st_printf("\nSetting up '%s'\n", test->name); ret = test->setup(handle, systable); - if (ret) { + if (ret != EFI_ST_SUCCESS) { efi_st_error("Setting up '%s' failed\n", test->name); ++*failures; } else { @@ -89,16 +90,17 @@ static int setup(struct efi_unit_test *test, unsigned int *failures) * * @test the test to be executed * @failures counter that will be incremented if a failure occurs + * @return EFI_ST_SUCCESS for success */ static int execute(struct efi_unit_test *test, unsigned int *failures) { int ret; if (!test->execute) - return 0; + return EFI_ST_SUCCESS; efi_st_printf("\nExecuting '%s'\n", test->name); ret = test->execute(); - if (ret) { + if (ret != EFI_ST_SUCCESS) { efi_st_error("Executing '%s' failed\n", test->name); ++*failures; } else { @@ -112,16 +114,17 @@ static int execute(struct efi_unit_test *test, unsigned int *failures) * * @test the test to be torn down * @failures counter that will be incremented if a failure occurs + * @return EFI_ST_SUCCESS for success */ static int teardown(struct efi_unit_test *test, unsigned int *failures) { int ret; if (!test->teardown) - return 0; + return EFI_ST_SUCCESS; efi_st_printf("\nTearing down '%s'\n", test->name); ret = test->teardown(); - if (ret) { + if (ret != EFI_ST_SUCCESS) { efi_st_error("Tearing down '%s' failed\n", test->name); ++*failures; } else { diff --git a/lib/efi_selftest/efi_selftest_events.c b/lib/efi_selftest/efi_selftest_events.c index c4f66952b9f..532f165d437 100644 --- a/lib/efi_selftest/efi_selftest_events.c +++ b/lib/efi_selftest/efi_selftest_events.c @@ -14,20 +14,22 @@ static struct efi_event *event_notify; static struct efi_event *event_wait; -static unsigned int counter; +static unsigned int timer_ticks; static struct efi_boot_services *boottime; /* - * Notification function, increments a counter. + * Notification function, increments the notfication count if parameter + * context is provided. * * @event notified event - * @context pointer to the counter + * @context pointer to the notification count */ static void EFIAPI notify(struct efi_event *event, void *context) { - if (!context) - return; - ++*(unsigned int *)context; + unsigned int *count = context; + + if (count) + ++*count; } /* @@ -38,6 +40,7 @@ static void EFIAPI notify(struct efi_event *event, void *context) * * @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) @@ -47,25 +50,27 @@ static int setup(const efi_handle_t handle, boottime = systable->boottime; ret = boottime->create_event(EVT_TIMER | EVT_NOTIFY_SIGNAL, - TPL_CALLBACK, notify, (void *)&counter, + TPL_CALLBACK, notify, (void *)&timer_ticks, &event_notify); if (ret != EFI_SUCCESS) { efi_st_error("could not create event\n"); - return 1; + 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 1; + return EFI_ST_FAILURE; } - return 0; + return EFI_ST_SUCCESS; } /* * Tear down unit test. * * Close the events created in setup. + * + * @return: EFI_ST_SUCCESS for success */ static int teardown(void) { @@ -76,7 +81,7 @@ static int teardown(void) event_notify = NULL; if (ret != EFI_SUCCESS) { efi_st_error("could not close event\n"); - return 1; + return EFI_ST_FAILURE; } } if (event_wait) { @@ -84,10 +89,10 @@ static int teardown(void) event_wait = NULL; if (ret != EFI_SUCCESS) { efi_st_error("could not close event\n"); - return 1; + return EFI_ST_FAILURE; } } - return 0; + return EFI_ST_SUCCESS; } /* @@ -98,6 +103,8 @@ static int teardown(void) * * 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) { @@ -105,85 +112,86 @@ static int execute(void) efi_status_t ret; /* Set 10 ms timer */ - counter = 0; + 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 1; + 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 1; + 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 1; + 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 1; + return EFI_ST_FAILURE; } if (index != 0) { efi_st_error("WaitForEvent returned wrong index\n"); - return 1; + return EFI_ST_FAILURE; } - efi_st_printf("Counter periodic: %u\n", counter); - if (counter < 8 || counter > 12) { + efi_st_printf("Notification count periodic: %u\n", timer_ticks); + if (timer_ticks < 8 || timer_ticks > 12) { efi_st_error("Incorrect timing of events\n"); - return 1; + 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 1; + return EFI_ST_FAILURE; } /* Set 10 ms timer */ - counter = 0; + 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 1; + 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 1; + 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 1; + return EFI_ST_FAILURE; } - efi_st_printf("Counter single shot: %u\n", counter); - if (counter != 1) { + efi_st_printf("Notification count single shot: %u\n", timer_ticks); + if (timer_ticks != 1) { efi_st_error("Single shot timer failed\n"); - return 1; + 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 1; + return EFI_ST_FAILURE; } - efi_st_printf("Stopped counter: %u\n", counter); - if (counter != 1) { + efi_st_printf("Notification count stopped timer: %u\n", timer_ticks); + if (timer_ticks != 1) { efi_st_error("Stopped timer fired\n"); - return 1; + return EFI_ST_FAILURE; } ret = boottime->set_timer(event_wait, EFI_TIMER_STOP, 0); if (index != 0) { efi_st_error("Could not cancel timer\n"); - return 1; + return EFI_ST_FAILURE; } - return 0; + return EFI_ST_SUCCESS; } EFI_UNIT_TEST(events) = { diff --git a/lib/efi_selftest/efi_selftest_exitbootservices.c b/lib/efi_selftest/efi_selftest_exitbootservices.c index 60271e61808..cddd11d52b0 100644 --- a/lib/efi_selftest/efi_selftest_exitbootservices.c +++ b/lib/efi_selftest/efi_selftest_exitbootservices.c @@ -1,5 +1,5 @@ /* - * efi_selftest_events + * efi_selftest_exitbootservices * * Copyright (c) 2017 Heinrich Schuchardt * @@ -13,19 +13,19 @@ static struct efi_boot_services *boottime; static struct efi_event *event_notify; -static unsigned int counter; +static unsigned int notification_count; /* - * Notification function, increments a counter. + * Notification function, increments the notification count. * * @event notified event - * @context pointer to the counter + * @context pointer to the notification count */ static void EFIAPI notify(struct efi_event *event, void *context) { - if (!context) - return; - ++*(unsigned int *)context; + unsigned int *count = context; + + ++*count; } /* @@ -35,6 +35,7 @@ static void EFIAPI notify(struct efi_event *event, void *context) * * @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) @@ -43,21 +44,24 @@ static int setup(const efi_handle_t handle, boottime = systable->boottime; - counter = 0; + notification_count = 0; ret = boottime->create_event(EVT_SIGNAL_EXIT_BOOT_SERVICES, - TPL_CALLBACK, notify, (void *)&counter, + TPL_CALLBACK, notify, + (void *)¬ification_count, &event_notify); if (ret != EFI_SUCCESS) { efi_st_error("could not create event\n"); - return 1; + return EFI_ST_FAILURE; } - return 0; + return EFI_ST_SUCCESS; } /* * Tear down unit test. * * Close the event created in setup. + * + * @return: EFI_ST_SUCCESS for success */ static int teardown(void) { @@ -68,10 +72,10 @@ static int teardown(void) event_notify = NULL; if (ret != EFI_SUCCESS) { efi_st_error("could not close event\n"); - return 1; + return EFI_ST_FAILURE; } } - return 0; + return EFI_ST_SUCCESS; } /* @@ -82,19 +86,21 @@ static int teardown(void) * * Call ExitBootServices again and check that the notification function is * not called again. + * + * @return: EFI_ST_SUCCESS for success */ static int execute(void) { - if (counter != 1) { - efi_st_error("ExitBootServices was not notified"); - return 1; + if (notification_count != 1) { + efi_st_error("ExitBootServices was not notified\n"); + return EFI_ST_FAILURE; } efi_st_exit_boot_services(); - if (counter != 1) { - efi_st_error("ExitBootServices was notified twice"); - return 1; + if (notification_count != 1) { + efi_st_error("ExitBootServices was notified twice\n"); + return EFI_ST_FAILURE; } - return 0; + return EFI_ST_SUCCESS; } EFI_UNIT_TEST(exitbootservices) = { diff --git a/lib/efi_selftest/efi_selftest_tpl.c b/lib/efi_selftest/efi_selftest_tpl.c index 90ace0f51e1..5d13f3b52da 100644 --- a/lib/efi_selftest/efi_selftest_tpl.c +++ b/lib/efi_selftest/efi_selftest_tpl.c @@ -13,20 +13,20 @@ static struct efi_event *event_notify; static struct efi_event *event_wait; -static unsigned int counter; +static unsigned int notification_count; static struct efi_boot_services *boottime; /* - * Notification function, increments a counter. + * Notification function, increments the notification count. * * @event notified event - * @context pointer to the counter + * @context pointer to the notification count */ static void EFIAPI notify(struct efi_event *event, void *context) { - if (!context) - return; - ++*(unsigned int *)context; + unsigned int *count = context; + + ++*count; } /* @@ -37,6 +37,7 @@ static void EFIAPI notify(struct efi_event *event, void *context) * * @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) @@ -46,25 +47,28 @@ static int setup(const efi_handle_t handle, boottime = systable->boottime; ret = boottime->create_event(EVT_TIMER | EVT_NOTIFY_SIGNAL, - TPL_CALLBACK, notify, (void *)&counter, + TPL_CALLBACK, notify, + (void *)¬ification_count, &event_notify); if (ret != EFI_SUCCESS) { efi_st_error("could not create event\n"); - return 1; + return EFI_ST_FAILURE; } ret = boottime->create_event(EVT_TIMER | EVT_NOTIFY_WAIT, TPL_HIGH_LEVEL, notify, NULL, &event_wait); if (ret != EFI_SUCCESS) { efi_st_error("could not create event\n"); - return 1; + return EFI_ST_FAILURE; } - return 0; + return EFI_ST_SUCCESS; } /* * Tear down unit test. * * Close the events created in setup. + * + * @return: EFI_ST_SUCCESS for success */ static int teardown(void) { @@ -75,7 +79,7 @@ static int teardown(void) event_notify = NULL; if (ret != EFI_SUCCESS) { efi_st_error("could not close event\n"); - return 1; + return EFI_ST_FAILURE; } } if (event_wait) { @@ -83,11 +87,11 @@ static int teardown(void) event_wait = NULL; if (ret != EFI_SUCCESS) { efi_st_error("could not close event\n"); - return 1; + return EFI_ST_FAILURE; } } boottime->restore_tpl(TPL_APPLICATION); - return 0; + return EFI_ST_SUCCESS; } /* @@ -101,6 +105,8 @@ static int teardown(void) * * Lower the TPL level and check that the queued notification * function is called. + * + * @return: EFI_ST_SUCCESS for success */ static int execute(void) { @@ -109,100 +115,103 @@ static int execute(void) UINTN old_tpl; /* Set 10 ms timer */ - counter = 0; + notification_count = 0; ret = boottime->set_timer(event_notify, EFI_TIMER_PERIODIC, 100000); if (ret != EFI_SUCCESS) { efi_st_error("Could not set timer\n"); - return 1; + 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 1; + return EFI_ST_FAILURE; } 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 1; + 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 1; + return EFI_ST_FAILURE; } if (index != 0) { efi_st_error("WaitForEvent returned wrong index\n"); - return 1; + return EFI_ST_FAILURE; } - efi_st_printf("Counter with TPL level TPL_APPLICATION: %u\n", counter); - if (counter < 8 || counter > 12) { + efi_st_printf("Notification count with TPL level TPL_APPLICATION: %u\n", + notification_count); + if (notification_count < 8 || notification_count > 12) { efi_st_error("Incorrect timing of events\n"); - return 1; + 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 1; + return EFI_ST_FAILURE; } /* Raise TPL level */ old_tpl = boottime->raise_tpl(TPL_CALLBACK); if (old_tpl != TPL_APPLICATION) { efi_st_error("Initial TPL level was not TPL_APPLICATION"); - return 1; + return EFI_ST_FAILURE; } /* Set 10 ms timer */ - counter = 0; + notification_count = 0; ret = boottime->set_timer(event_notify, EFI_TIMER_PERIODIC, 100000); if (index != 0) { efi_st_error("Could not set timer\n"); - return 1; + 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 1; + return EFI_ST_FAILURE; } do { ret = boottime->check_event(event_wait); } while (ret == EFI_NOT_READY); if (ret != EFI_SUCCESS) { efi_st_error("Could not check event\n"); - return 1; + return EFI_ST_FAILURE; } - efi_st_printf("Counter with TPL level TPL_CALLBACK: %u\n", counter); - if (counter != 0) { + efi_st_printf("Notification count with TPL level TPL_CALLBACK: %u\n", + notification_count); + if (notification_count != 0) { efi_st_error("Suppressed timer fired\n"); - return 1; + return EFI_ST_FAILURE; } /* Set 1 ms timer */ ret = boottime->set_timer(event_wait, EFI_TIMER_RELATIVE, 1000); if (ret != EFI_SUCCESS) { efi_st_error("Could not set timer\n"); - return 1; + return EFI_ST_FAILURE; } /* Restore the old TPL level */ boottime->restore_tpl(TPL_APPLICATION); ret = boottime->wait_for_event(1, &event_wait, &index); if (ret != EFI_SUCCESS) { efi_st_error("Could not wait for event\n"); - return 1; + return EFI_ST_FAILURE; } - efi_st_printf("Counter with TPL level TPL_APPLICATION: %u\n", counter); - if (counter < 1) { + efi_st_printf("Notification count with TPL level TPL_APPLICATION: %u\n", + notification_count); + if (notification_count < 1) { efi_st_error("Queued timer event did not fire\n"); - return 1; + return EFI_ST_FAILURE; } ret = boottime->set_timer(event_wait, EFI_TIMER_STOP, 0); if (index != 0) { efi_st_error("Could not cancel timer\n"); - return 1; + return EFI_ST_FAILURE; } - return 0; + return EFI_ST_SUCCESS; } EFI_UNIT_TEST(tpl) = { -- cgit v1.3.1 From fc05a9590689b70fffdb9914e9867ea53fd579fa Mon Sep 17 00:00:00 2001 From: Heinrich Schuchardt Date: Thu, 5 Oct 2017 16:35:52 +0200 Subject: efi_loader: parameters of CopyMem and SetMem The UEFI spec defines the length parameters of CopyMem and SetMem as UINTN. We should size_t here. The source buffer of CopyMem should be marked as const. Signed-off-by: Heinrich Schuchardt Reviewed-by: Simon Glass Signed-off-by: Alexander Graf --- include/efi_api.h | 7 +++---- lib/efi_loader/efi_boottime.c | 10 +++++----- 2 files changed, 8 insertions(+), 9 deletions(-) (limited to 'include') diff --git a/include/efi_api.h b/include/efi_api.h index c3b9032a48d..0b1a383e610 100644 --- a/include/efi_api.h +++ b/include/efi_api.h @@ -156,10 +156,9 @@ struct efi_boot_services { void *handle, ...); efi_status_t (EFIAPI *calculate_crc32)(void *data, unsigned long data_size, uint32_t *crc32); - void (EFIAPI *copy_mem)(void *destination, void *source, - unsigned long length); - void (EFIAPI *set_mem)(void *buffer, unsigned long size, - uint8_t value); + void (EFIAPI *copy_mem)(void *destination, const void *source, + size_t length); + void (EFIAPI *set_mem)(void *buffer, size_t size, uint8_t value); void *create_event_ex; }; diff --git a/lib/efi_loader/efi_boottime.c b/lib/efi_loader/efi_boottime.c index b8b98f2c4af..c48ff2cd2a8 100644 --- a/lib/efi_loader/efi_boottime.c +++ b/lib/efi_loader/efi_boottime.c @@ -1863,10 +1863,10 @@ static efi_status_t EFIAPI efi_calculate_crc32(void *data, * @source source of the copy operation * @length number of bytes to copy */ -static void EFIAPI efi_copy_mem(void *destination, void *source, - unsigned long length) +static void EFIAPI efi_copy_mem(void *destination, const void *source, + size_t length) { - EFI_ENTRY("%p, %p, %ld", destination, source, length); + EFI_ENTRY("%p, %p, %ld", destination, source, (unsigned long)length); memcpy(destination, source, length); EFI_EXIT(EFI_SUCCESS); } @@ -1882,9 +1882,9 @@ static void EFIAPI efi_copy_mem(void *destination, void *source, * @size size of buffer in bytes * @value byte to copy to the buffer */ -static void EFIAPI efi_set_mem(void *buffer, unsigned long size, uint8_t value) +static void EFIAPI efi_set_mem(void *buffer, size_t size, uint8_t value) { - EFI_ENTRY("%p, %ld, 0x%x", buffer, size, value); + EFI_ENTRY("%p, %ld, 0x%x", buffer, (unsigned long)size, value); memset(buffer, value, size); EFI_EXIT(EFI_SUCCESS); } -- cgit v1.3.1 From 5a9682d0ddd9328eb581b18a8b263c3834943942 Mon Sep 17 00:00:00 2001 From: Heinrich Schuchardt Date: Thu, 5 Oct 2017 16:35:53 +0200 Subject: efi_loader: pass GUIDs as const efi_guid_t * We need to call some boottime services internally. Our GUIDs are stored as const efi_guid_t *. The boottime services never change GUIDs. So we can define the parameters as const efi_guid_t *. Signed-off-by: Heinrich Schuchardt Reviewed-by: Simon Glass Signed-off-by: Alexander Graf --- include/efi_api.h | 27 ++++++++++++++------------- lib/efi_loader/efi_boottime.c | 40 +++++++++++++++++++++------------------- 2 files changed, 35 insertions(+), 32 deletions(-) (limited to 'include') diff --git a/include/efi_api.h b/include/efi_api.h index 0b1a383e610..aa4306aac94 100644 --- a/include/efi_api.h +++ b/include/efi_api.h @@ -77,24 +77,25 @@ struct efi_boot_services { efi_status_t (EFIAPI *check_event)(struct efi_event *event); #define EFI_NATIVE_INTERFACE 0x00000000 efi_status_t (EFIAPI *install_protocol_interface)( - void **handle, efi_guid_t *protocol, + void **handle, const efi_guid_t *protocol, int protocol_interface_type, void *protocol_interface); efi_status_t (EFIAPI *reinstall_protocol_interface)( - void *handle, efi_guid_t *protocol, + void *handle, const efi_guid_t *protocol, void *old_interface, void *new_interface); efi_status_t (EFIAPI *uninstall_protocol_interface)(void *handle, - efi_guid_t *protocol, void *protocol_interface); - efi_status_t (EFIAPI *handle_protocol)(efi_handle_t, efi_guid_t *, - void **); + const efi_guid_t *protocol, void *protocol_interface); + efi_status_t (EFIAPI *handle_protocol)(efi_handle_t, + const efi_guid_t *protocol, + void **protocol_interface); void *reserved; efi_status_t (EFIAPI *register_protocol_notify)( - efi_guid_t *protocol, struct efi_event *event, + const efi_guid_t *protocol, struct efi_event *event, void **registration); efi_status_t (EFIAPI *locate_handle)( enum efi_locate_search_type search_type, - efi_guid_t *protocol, void *search_key, + const efi_guid_t *protocol, void *search_key, unsigned long *buffer_size, efi_handle_t *buffer); - efi_status_t (EFIAPI *locate_device_path)(efi_guid_t *protocol, + efi_status_t (EFIAPI *locate_device_path)(const efi_guid_t *protocol, struct efi_device_path **device_path, efi_handle_t *device); efi_status_t (EFIAPI *install_configuration_table)( @@ -131,14 +132,14 @@ struct efi_boot_services { #define EFI_OPEN_PROTOCOL_BY_DRIVER 0x00000010 #define EFI_OPEN_PROTOCOL_EXCLUSIVE 0x00000020 efi_status_t (EFIAPI *open_protocol)(efi_handle_t handle, - efi_guid_t *protocol, void **interface, + const efi_guid_t *protocol, void **interface, efi_handle_t agent_handle, efi_handle_t controller_handle, u32 attributes); efi_status_t (EFIAPI *close_protocol)(void *handle, - efi_guid_t *protocol, void *agent_handle, + const efi_guid_t *protocol, void *agent_handle, void *controller_handle); efi_status_t(EFIAPI *open_protocol_information)(efi_handle_t handle, - efi_guid_t *protocol, + const efi_guid_t *protocol, struct efi_open_protocol_info_entry **entry_buffer, unsigned long *entry_count); efi_status_t (EFIAPI *protocols_per_handle)(efi_handle_t handle, @@ -146,9 +147,9 @@ struct efi_boot_services { unsigned long *protocols_buffer_count); efi_status_t (EFIAPI *locate_handle_buffer) ( enum efi_locate_search_type search_type, - efi_guid_t *protocol, void *search_key, + const efi_guid_t *protocol, void *search_key, unsigned long *no_handles, efi_handle_t **buffer); - efi_status_t (EFIAPI *locate_protocol)(efi_guid_t *protocol, + efi_status_t (EFIAPI *locate_protocol)(const efi_guid_t *protocol, void *registration, void **protocol_interface); efi_status_t (EFIAPI *install_multiple_protocol_interfaces)( void **handle, ...); diff --git a/lib/efi_loader/efi_boottime.c b/lib/efi_loader/efi_boottime.c index c48ff2cd2a8..e5adc17faba 100644 --- a/lib/efi_loader/efi_boottime.c +++ b/lib/efi_loader/efi_boottime.c @@ -704,7 +704,7 @@ static efi_status_t EFIAPI efi_check_event(struct efi_event *event) * @return status code */ static efi_status_t EFIAPI efi_install_protocol_interface(void **handle, - efi_guid_t *protocol, int protocol_interface_type, + const efi_guid_t *protocol, int protocol_interface_type, void *protocol_interface) { struct list_head *lhandle; @@ -776,7 +776,7 @@ out: * @return status code */ static efi_status_t EFIAPI efi_install_protocol_interface_ext(void **handle, - efi_guid_t *protocol, int protocol_interface_type, + const efi_guid_t *protocol, int protocol_interface_type, void *protocol_interface) { EFI_ENTRY("%p, %pUl, %d, %p", handle, protocol, protocol_interface_type, @@ -802,7 +802,7 @@ static efi_status_t EFIAPI efi_install_protocol_interface_ext(void **handle, * @return status code */ static efi_status_t EFIAPI efi_reinstall_protocol_interface(void *handle, - efi_guid_t *protocol, void *old_interface, + const efi_guid_t *protocol, void *old_interface, void *new_interface) { EFI_ENTRY("%p, %pUl, %p, %p", handle, protocol, old_interface, @@ -823,7 +823,7 @@ static efi_status_t EFIAPI efi_reinstall_protocol_interface(void *handle, * @return status code */ static efi_status_t EFIAPI efi_uninstall_protocol_interface(void *handle, - efi_guid_t *protocol, void *protocol_interface) + const efi_guid_t *protocol, void *protocol_interface) { struct list_head *lhandle; int i; @@ -876,7 +876,7 @@ out: * @return status code */ static efi_status_t EFIAPI efi_uninstall_protocol_interface_ext(void *handle, - efi_guid_t *protocol, void *protocol_interface) + const efi_guid_t *protocol, void *protocol_interface) { EFI_ENTRY("%p, %pUl, %p", handle, protocol, protocol_interface); @@ -897,9 +897,10 @@ static efi_status_t EFIAPI efi_uninstall_protocol_interface_ext(void *handle, * @registration key for retrieving the registration information * @return status code */ -static efi_status_t EFIAPI efi_register_protocol_notify(efi_guid_t *protocol, - struct efi_event *event, - void **registration) +static efi_status_t EFIAPI efi_register_protocol_notify( + const efi_guid_t *protocol, + struct efi_event *event, + void **registration) { EFI_ENTRY("%pUl, %p, %p", protocol, event, registration); return EFI_EXIT(EFI_OUT_OF_RESOURCES); @@ -917,7 +918,7 @@ static efi_status_t EFIAPI efi_register_protocol_notify(efi_guid_t *protocol, * @return 0 if the handle implements the protocol */ static int efi_search(enum efi_locate_search_type search_type, - efi_guid_t *protocol, void *search_key, + const efi_guid_t *protocol, void *search_key, struct efi_object *efiobj) { int i; @@ -954,7 +955,7 @@ static int efi_search(enum efi_locate_search_type search_type, */ static efi_status_t efi_locate_handle( enum efi_locate_search_type search_type, - efi_guid_t *protocol, void *search_key, + const efi_guid_t *protocol, void *search_key, unsigned long *buffer_size, efi_handle_t *buffer) { struct list_head *lhandle; @@ -1006,7 +1007,7 @@ static efi_status_t efi_locate_handle( */ static efi_status_t EFIAPI efi_locate_handle_ext( enum efi_locate_search_type search_type, - efi_guid_t *protocol, void *search_key, + const efi_guid_t *protocol, void *search_key, unsigned long *buffer_size, efi_handle_t *buffer) { EFI_ENTRY("%d, %pUl, %p, %p, %p", search_type, protocol, search_key, @@ -1028,7 +1029,8 @@ static efi_status_t EFIAPI efi_locate_handle_ext( * @device handle of the device * @return status code */ -static efi_status_t EFIAPI efi_locate_device_path(efi_guid_t *protocol, +static efi_status_t EFIAPI efi_locate_device_path( + const efi_guid_t *protocol, struct efi_device_path **device_path, efi_handle_t *device) { @@ -1567,7 +1569,7 @@ static efi_status_t EFIAPI efi_disconnect_controller(void *controller_handle, * @return status code */ static efi_status_t EFIAPI efi_close_protocol(void *handle, - efi_guid_t *protocol, + const efi_guid_t *protocol, void *agent_handle, void *controller_handle) { @@ -1590,7 +1592,7 @@ static efi_status_t EFIAPI efi_close_protocol(void *handle, * @return status code */ static efi_status_t EFIAPI efi_open_protocol_information(efi_handle_t handle, - efi_guid_t *protocol, + const efi_guid_t *protocol, struct efi_open_protocol_info_entry **entry_buffer, unsigned long *entry_count) { @@ -1679,7 +1681,7 @@ static efi_status_t EFIAPI efi_protocols_per_handle(void *handle, */ static efi_status_t EFIAPI efi_locate_handle_buffer( enum efi_locate_search_type search_type, - efi_guid_t *protocol, void *search_key, + const efi_guid_t *protocol, void *search_key, unsigned long *no_handles, efi_handle_t **buffer) { efi_status_t r; @@ -1721,7 +1723,7 @@ out: * @registration registration key passed to the notification function * @protocol_interface interface implementing the protocol */ -static efi_status_t EFIAPI efi_locate_protocol(efi_guid_t *protocol, +static efi_status_t EFIAPI efi_locate_protocol(const efi_guid_t *protocol, void *registration, void **protocol_interface) { @@ -1774,7 +1776,7 @@ static efi_status_t EFIAPI efi_install_multiple_protocol_interfaces( EFI_ENTRY("%p", handle); va_list argptr; - efi_guid_t *protocol; + const efi_guid_t *protocol; void *protocol_interface; efi_status_t r = EFI_SUCCESS; int i = 0; @@ -1905,7 +1907,7 @@ static void EFIAPI efi_set_mem(void *buffer, size_t size, uint8_t value) * @return status code */ static efi_status_t EFIAPI efi_open_protocol( - void *handle, efi_guid_t *protocol, + void *handle, const efi_guid_t *protocol, void **protocol_interface, void *agent_handle, void *controller_handle, uint32_t attributes) { @@ -1989,7 +1991,7 @@ out: * @return status code */ static efi_status_t EFIAPI efi_handle_protocol(void *handle, - efi_guid_t *protocol, + const efi_guid_t *protocol, void **protocol_interface) { return efi_open_protocol(handle, protocol, protocol_interface, NULL, -- cgit v1.3.1 From ca379e1bf16e59841f15ed34088eb1362bf2bd35 Mon Sep 17 00:00:00 2001 From: Heinrich Schuchardt Date: Thu, 5 Oct 2017 16:35:54 +0200 Subject: efi_loader: wrong type in wait_for_event The UEFI spec defines parameter index of WaitForEvent as UINTN*. So we should use size_t here. I deliberately do not use UINTN because I hold a following patch that will eliminate UINTN because uppercase types to not match the U-Boot coding style. Signed-off-by: Heinrich Schuchardt Reviewed-by: Simon Glass Signed-off-by: Alexander Graf --- include/efi_api.h | 2 +- lib/efi_loader/efi_boottime.c | 2 +- lib/efi_selftest/efi_selftest_events.c | 2 +- lib/efi_selftest/efi_selftest_tpl.c | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) (limited to 'include') diff --git a/include/efi_api.h b/include/efi_api.h index aa4306aac94..c44dc9d0cbd 100644 --- a/include/efi_api.h +++ b/include/efi_api.h @@ -71,7 +71,7 @@ struct efi_boot_services { enum efi_timer_delay type, uint64_t trigger_time); efi_status_t (EFIAPI *wait_for_event)(unsigned long number_of_events, - struct efi_event **event, unsigned long *index); + struct efi_event **event, size_t *index); efi_status_t (EFIAPI *signal_event)(struct efi_event *event); efi_status_t (EFIAPI *close_event)(struct efi_event *event); efi_status_t (EFIAPI *check_event)(struct efi_event *event); diff --git a/lib/efi_loader/efi_boottime.c b/lib/efi_loader/efi_boottime.c index e5adc17faba..976d5822f7d 100644 --- a/lib/efi_loader/efi_boottime.c +++ b/lib/efi_loader/efi_boottime.c @@ -553,7 +553,7 @@ static efi_status_t EFIAPI efi_set_timer_ext(struct efi_event *event, */ static efi_status_t EFIAPI efi_wait_for_event(unsigned long num_events, struct efi_event **event, - unsigned long *index) + size_t *index) { int i, j; diff --git a/lib/efi_selftest/efi_selftest_events.c b/lib/efi_selftest/efi_selftest_events.c index 532f165d437..b2cdc150da2 100644 --- a/lib/efi_selftest/efi_selftest_events.c +++ b/lib/efi_selftest/efi_selftest_events.c @@ -108,7 +108,7 @@ static int teardown(void) */ static int execute(void) { - unsigned long index; + size_t index; efi_status_t ret; /* Set 10 ms timer */ diff --git a/lib/efi_selftest/efi_selftest_tpl.c b/lib/efi_selftest/efi_selftest_tpl.c index 5d13f3b52da..0b78ee75956 100644 --- a/lib/efi_selftest/efi_selftest_tpl.c +++ b/lib/efi_selftest/efi_selftest_tpl.c @@ -110,7 +110,7 @@ static int teardown(void) */ static int execute(void) { - unsigned long index; + size_t index; efi_status_t ret; UINTN old_tpl; -- cgit v1.3.1 From 84a12ce64e08257d9e8eb7b9e7c2b232a2a35ebf Mon Sep 17 00:00:00 2001 From: Heinrich Schuchardt Date: Thu, 5 Oct 2017 16:35:55 +0200 Subject: efi_loader: incorrect definition of EFI_SIMPLE_NETWORK_PROTOCOL WaitForPacket is an event and not a function pointer. Signed-off-by: Heinrich Schuchardt Reviewed-by: Simon Glass Signed-off-by: Alexander Graf --- include/efi_api.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'include') diff --git a/include/efi_api.h b/include/efi_api.h index c44dc9d0cbd..308baeec497 100644 --- a/include/efi_api.h +++ b/include/efi_api.h @@ -633,7 +633,7 @@ struct efi_simple_network ulong *header_size, ulong *buffer_size, void *buffer, struct efi_mac_address *src_addr, struct efi_mac_address *dest_addr, u16 *protocol); - void (EFIAPI *waitforpacket)(void); + struct efi_event *wait_for_packet; struct efi_simple_network_mode *mode; }; -- cgit v1.3.1 From 2e0864a47e223d1581acfb49e4ec2f68615da3dc Mon Sep 17 00:00:00 2001 From: Heinrich Schuchardt Date: Thu, 5 Oct 2017 16:35:56 +0200 Subject: efi_loader: correct bits of receive_filters bit mask Remove extraneous commas. Add comment. Signed-off-by: Heinrich Schuchardt Reviewed-by: Simon Glass Signed-off-by: Alexander Graf --- include/efi_api.h | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) (limited to 'include') diff --git a/include/efi_api.h b/include/efi_api.h index 308baeec497..8c227ce7039 100644 --- a/include/efi_api.h +++ b/include/efi_api.h @@ -593,11 +593,12 @@ struct efi_simple_network_mode { u8 media_present; }; -#define EFI_SIMPLE_NETWORK_RECEIVE_UNICAST 0x01, -#define EFI_SIMPLE_NETWORK_RECEIVE_MULTICAST 0x02, -#define EFI_SIMPLE_NETWORK_RECEIVE_BROADCAST 0x04, -#define EFI_SIMPLE_NETWORK_RECEIVE_PROMISCUOUS 0x08, -#define EFI_SIMPLE_NETWORK_RECEIVE_PROMISCUOUS_MULTICAST 0x10, +/* receive_filters bit mask */ +#define EFI_SIMPLE_NETWORK_RECEIVE_UNICAST 0x01 +#define EFI_SIMPLE_NETWORK_RECEIVE_MULTICAST 0x02 +#define EFI_SIMPLE_NETWORK_RECEIVE_BROADCAST 0x04 +#define EFI_SIMPLE_NETWORK_RECEIVE_PROMISCUOUS 0x08 +#define EFI_SIMPLE_NETWORK_RECEIVE_PROMISCUOUS_MULTICAST 0x10 struct efi_simple_network { -- cgit v1.3.1 From bdecf974f168af49f5deb2d325e7ad8f3ad4a52e Mon Sep 17 00:00:00 2001 From: Heinrich Schuchardt Date: Thu, 5 Oct 2017 16:35:57 +0200 Subject: efi_loader: fill simple network protocol revision Provide the simple network protocol revision. This revision number could be used to identify backwards compatible enhancements of the protocol. Signed-off-by: Heinrich Schuchardt Reviewed-by: Simon Glass Signed-off-by: Alexander Graf --- include/efi_api.h | 3 +++ lib/efi_loader/efi_net.c | 1 + 2 files changed, 4 insertions(+) (limited to 'include') diff --git a/include/efi_api.h b/include/efi_api.h index 8c227ce7039..2f31464cb3f 100644 --- a/include/efi_api.h +++ b/include/efi_api.h @@ -600,6 +600,9 @@ struct efi_simple_network_mode { #define EFI_SIMPLE_NETWORK_RECEIVE_PROMISCUOUS 0x08 #define EFI_SIMPLE_NETWORK_RECEIVE_PROMISCUOUS_MULTICAST 0x10 +/* revision of the simple network protocol */ +#define EFI_SIMPLE_NETWORK_PROTOCOL_REVISION 0x00010000 + struct efi_simple_network { u64 revision; diff --git a/lib/efi_loader/efi_net.c b/lib/efi_loader/efi_net.c index 91f1e4a69e1..fb23bcf6332 100644 --- a/lib/efi_loader/efi_net.c +++ b/lib/efi_loader/efi_net.c @@ -228,6 +228,7 @@ int efi_net_register(void) netobj->parent.protocols[2].guid = &efi_pxe_guid; netobj->parent.protocols[2].protocol_interface = &netobj->pxe; netobj->parent.handle = &netobj->net; + netobj->net.revision = EFI_SIMPLE_NETWORK_PROTOCOL_REVISION; netobj->net.start = efi_net_start; netobj->net.stop = efi_net_stop; netobj->net.initialize = efi_net_initialize; -- cgit v1.3.1 From 891b3d9051690d0ba39da4eda1d15773ebfee2b6 Mon Sep 17 00:00:00 2001 From: Heinrich Schuchardt Date: Thu, 5 Oct 2017 16:36:02 +0200 Subject: efi_loader: fix efi_net_get_status The returned interrupt status was wrong. As out transmit buffer is empty we need to always set EFI_SIMPLE_NETWORK_TRANSMIT_INTERRUPT. When we have received a packet we need to set EFI_SIMPLE_NETWORK_RECEIVE_INTERRUPT. Furthermore we should call efi_timer_check() to handle events. Signed-off-by: Heinrich Schuchardt Reviewed-by: Simon Glass Signed-off-by: Alexander Graf --- include/efi_api.h | 6 ++++++ lib/efi_loader/efi_net.c | 11 ++++++++--- 2 files changed, 14 insertions(+), 3 deletions(-) (limited to 'include') diff --git a/include/efi_api.h b/include/efi_api.h index 2f31464cb3f..1f349db2462 100644 --- a/include/efi_api.h +++ b/include/efi_api.h @@ -600,6 +600,12 @@ struct efi_simple_network_mode { #define EFI_SIMPLE_NETWORK_RECEIVE_PROMISCUOUS 0x08 #define EFI_SIMPLE_NETWORK_RECEIVE_PROMISCUOUS_MULTICAST 0x10 +/* interrupt status bit mask */ +#define EFI_SIMPLE_NETWORK_RECEIVE_INTERRUPT 0x01 +#define EFI_SIMPLE_NETWORK_TRANSMIT_INTERRUPT 0x02 +#define EFI_SIMPLE_NETWORK_COMMAND_INTERRUPT 0x04 +#define EFI_SIMPLE_NETWORK_SOFTWARE_INTERRUPT 0x08 + /* revision of the simple network protocol */ #define EFI_SIMPLE_NETWORK_PROTOCOL_REVISION 0x00010000 diff --git a/lib/efi_loader/efi_net.c b/lib/efi_loader/efi_net.c index cd46d2db534..b16463ba1a1 100644 --- a/lib/efi_loader/efi_net.c +++ b/lib/efi_loader/efi_net.c @@ -133,9 +133,14 @@ static efi_status_t EFIAPI efi_net_get_status(struct efi_simple_network *this, { EFI_ENTRY("%p, %p, %p", this, int_status, txbuf); - /* We send packets synchronously, so nothing is outstanding */ - if (int_status) - *int_status = 0; + efi_timer_check(); + + if (int_status) { + /* We send packets synchronously, so nothing is outstanding */ + *int_status = EFI_SIMPLE_NETWORK_TRANSMIT_INTERRUPT; + if (new_rx_packet) + *int_status |= EFI_SIMPLE_NETWORK_RECEIVE_INTERRUPT; + } if (txbuf) *txbuf = new_tx_packet; -- cgit v1.3.1 From 8db174d651e3f92ddb9660f1f8b8755b902c3c11 Mon Sep 17 00:00:00 2001 From: Heinrich Schuchardt Date: Thu, 5 Oct 2017 16:36:03 +0200 Subject: efi_loader: size fields in SimpleNetworkProtocol The size fields in the Simple Network Protocol are all UINTN in the UEFI spec. So use size_t. Provide a function description of the receive function. Signed-off-by: Heinrich Schuchardt Reviewed-by: Simon Glass Signed-off-by: Alexander Graf --- include/efi_api.h | 4 ++-- lib/efi_loader/efi_net.c | 24 ++++++++++++++++++++---- 2 files changed, 22 insertions(+), 6 deletions(-) (limited to 'include') diff --git a/include/efi_api.h b/include/efi_api.h index 1f349db2462..a9a6494afef 100644 --- a/include/efi_api.h +++ b/include/efi_api.h @@ -636,11 +636,11 @@ struct efi_simple_network efi_status_t (EFIAPI *get_status)(struct efi_simple_network *this, u32 *int_status, void **txbuf); efi_status_t (EFIAPI *transmit)(struct efi_simple_network *this, - ulong header_size, ulong buffer_size, void *buffer, + size_t header_size, size_t buffer_size, void *buffer, struct efi_mac_address *src_addr, struct efi_mac_address *dest_addr, u16 *protocol); efi_status_t (EFIAPI *receive)(struct efi_simple_network *this, - ulong *header_size, ulong *buffer_size, void *buffer, + size_t *header_size, size_t *buffer_size, void *buffer, struct efi_mac_address *src_addr, struct efi_mac_address *dest_addr, u16 *protocol); struct efi_event *wait_for_packet; diff --git a/lib/efi_loader/efi_net.c b/lib/efi_loader/efi_net.c index b16463ba1a1..4546b436031 100644 --- a/lib/efi_loader/efi_net.c +++ b/lib/efi_loader/efi_net.c @@ -150,12 +150,13 @@ static efi_status_t EFIAPI efi_net_get_status(struct efi_simple_network *this, } static efi_status_t EFIAPI efi_net_transmit(struct efi_simple_network *this, - ulong header_size, ulong buffer_size, void *buffer, + size_t header_size, size_t buffer_size, void *buffer, struct efi_mac_address *src_addr, struct efi_mac_address *dest_addr, u16 *protocol) { - EFI_ENTRY("%p, %lx, %lx, %p, %p, %p, %p", this, header_size, - buffer_size, buffer, src_addr, dest_addr, protocol); + EFI_ENTRY("%p, %lu, %lu, %p, %p, %p, %p", this, + (unsigned long)header_size, (unsigned long)buffer_size, + buffer, src_addr, dest_addr, protocol); efi_timer_check(); @@ -183,8 +184,23 @@ static void efi_net_push(void *pkt, int len) wait_for_packet->is_signaled = true; } +/* + * Receive a packet from a network interface. + * + * This function implements the Receive service of the Simple Network Protocol. + * See the UEFI spec for details. + * + * @this the instance of the Simple Network Protocol + * @header_size size of the media header + * @buffer_size size of the buffer to receive the packet + * @buffer buffer to receive the packet + * @src_addr source MAC address + * @dest_addr destination MAC address + * @protocol protocol + * @return status code + */ static efi_status_t EFIAPI efi_net_receive(struct efi_simple_network *this, - ulong *header_size, ulong *buffer_size, void *buffer, + size_t *header_size, size_t *buffer_size, void *buffer, struct efi_mac_address *src_addr, struct efi_mac_address *dest_addr, u16 *protocol) { -- cgit v1.3.1 From 9820c2f30c028f40d22fdc892799fd7088f23bc7 Mon Sep 17 00:00:00 2001 From: Heinrich Schuchardt Date: Thu, 5 Oct 2017 16:36:05 +0200 Subject: efi_selftest: correct definition of efi_st_error Enclose definition in parantheses to allow using efi_st_error like a void function. Signed-off-by: Heinrich Schuchardt Reviewed-by: Simon Glass Signed-off-by: Alexander Graf --- include/efi_selftest.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'include') diff --git a/include/efi_selftest.h b/include/efi_selftest.h index beb662d4e1b..2f0992f06ee 100644 --- a/include/efi_selftest.h +++ b/include/efi_selftest.h @@ -23,8 +23,8 @@ * @... format string followed by fields to print */ #define efi_st_error(...) \ - efi_st_printf("%s(%u):\nERROR: ", __FILE__, __LINE__); \ - efi_st_printf(__VA_ARGS__) \ + (efi_st_printf("%s(%u):\nERROR: ", __FILE__, __LINE__), \ + efi_st_printf(__VA_ARGS__)) \ /* * A test may be setup and executed at boottime, -- cgit v1.3.1 From 5ca23ed5bc63832baa24a6107537fdd229c458ae Mon Sep 17 00:00:00 2001 From: Heinrich Schuchardt Date: Thu, 5 Oct 2017 16:36:07 +0200 Subject: efi_loader: supply EFI network test This patch provides an EFI application to check the correct function of the Simple Network Protocol implementation. It sends a DHCP request and analyzes the DHCP offer. Different error conditions including a 10s timeout are checked. A successful execution will look like this: => bootefi nettest Scanning disk ide.blk#0... Found 1 disks WARNING: Invalid device tree, expect boot to fail Network test DHCP Discover DHCP reply received from 192.168.76.2 (52:55:c0:a8:4c:02) as broadcast message. OK. The test was completed successfully. Signed-off-by: Heinrich Schuchardt Reviewed-by: Simon Glass Signed-off-by: Alexander Graf --- include/efi_selftest.h | 11 + lib/efi_selftest/Makefile | 8 +- lib/efi_selftest/efi_selftest_snp.c | 424 +++++++++++++++++++++++++++++++++++ lib/efi_selftest/efi_selftest_util.c | 25 +++ 4 files changed, 467 insertions(+), 1 deletion(-) create mode 100644 lib/efi_selftest/efi_selftest_snp.c create mode 100644 lib/efi_selftest/efi_selftest_util.c (limited to 'include') diff --git a/include/efi_selftest.h b/include/efi_selftest.h index 2f0992f06ee..7ec42a0406b 100644 --- a/include/efi_selftest.h +++ b/include/efi_selftest.h @@ -60,6 +60,17 @@ void efi_st_exit_boot_services(void); void efi_st_printf(const char *fmt, ...) __attribute__ ((format (__printf__, 1, 2))); +/* + * Compare memory. + * We cannot use lib/string.c due to different CFLAGS values. + * + * @buf1: first buffer + * @buf2: second buffer + * @length: number of bytes to compare + * @return: 0 if both buffers contain the same bytes + */ +int efi_st_memcmp(const void *buf1, const void *buf2, size_t length); + /* * Reads an Unicode character from the input device. * diff --git a/lib/efi_selftest/Makefile b/lib/efi_selftest/Makefile index 30f19609330..e446046e022 100644 --- a/lib/efi_selftest/Makefile +++ b/lib/efi_selftest/Makefile @@ -15,12 +15,18 @@ CFLAGS_efi_selftest_events.o := $(CFLAGS_EFI) CFLAGS_REMOVE_efi_selftest_events.o := $(CFLAGS_NON_EFI) CFLAGS_efi_selftest_exitbootservices.o := $(CFLAGS_EFI) CFLAGS_REMOVE_efi_selftest_exitbootservices.o := $(CFLAGS_NON_EFI) +CFLAGS_efi_selftest_snp.o := $(CFLAGS_EFI) +CFLAGS_REMOVE_efi_selftest_snp.o := $(CFLAGS_NON_EFI) CFLAGS_efi_selftest_tpl.o := $(CFLAGS_EFI) CFLAGS_REMOVE_efi_selftest_tpl.o := $(CFLAGS_NON_EFI) +CFLAGS_efi_selftest_util.o := $(CFLAGS_EFI) +CFLAGS_REMOVE_efi_selftest_util.o := $(CFLAGS_NON_EFI) obj-$(CONFIG_CMD_BOOTEFI_SELFTEST) += \ efi_selftest.o \ efi_selftest_console.o \ efi_selftest_events.o \ efi_selftest_exitbootservices.o \ -efi_selftest_tpl.o +efi_selftest_snp.o \ +efi_selftest_tpl.o \ +efi_selftest_util.o diff --git a/lib/efi_selftest/efi_selftest_snp.c b/lib/efi_selftest/efi_selftest_snp.c new file mode 100644 index 00000000000..638be0147df --- /dev/null +++ b/lib/efi_selftest/efi_selftest_snp.c @@ -0,0 +1,424 @@ +/* + * efi_selftest_snp + * + * Copyright (c) 2017 Heinrich Schuchardt + * + * SPDX-License-Identifier: GPL-2.0+ + * + * This unit test covers the Simple Network Protocol as well as + * the CopyMem and SetMem boottime services. + * + * A DHCP discover message is sent. The test is successful if a + * DHCP reply is received. + * + * TODO: Once ConnectController and DisconnectController are implemented + * we should connect our code as controller. + */ + +#include + +/* + * MAC address for broadcasts + */ +static const u8 BROADCAST_MAC[] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff}; + +struct dhcp_hdr { + u8 op; +#define BOOTREQUEST 1 +#define BOOTREPLY 2 + u8 htype; +# define HWT_ETHER 1 + u8 hlen; +# define HWL_ETHER 6 + u8 hops; + u32 xid; + u16 secs; + u16 flags; +#define DHCP_FLAGS_UNICAST 0x0000 +#define DHCP_FLAGS_BROADCAST 0x0080 + u32 ciaddr; + u32 yiaddr; + u32 siaddr; + u32 giaddr; + u8 chaddr[16]; + u8 sname[64]; + u8 file[128]; +}; + +/* + * Message type option. + */ +#define DHCP_MESSAGE_TYPE 0x35 +#define DHCPDISCOVER 1 +#define DHCPOFFER 2 +#define DHCPREQUEST 3 +#define DHCPDECLINE 4 +#define DHCPACK 5 +#define DHCPNAK 6 +#define DHCPRELEASE 7 + +struct dhcp { + struct ethernet_hdr eth_hdr; + struct ip_udp_hdr ip_udp; + struct dhcp_hdr dhcp_hdr; + u8 opt[128]; +} __packed; + +static struct efi_boot_services *boottime; +static struct efi_simple_network *net; +static struct efi_event *timer; +static const efi_guid_t efi_net_guid = EFI_SIMPLE_NETWORK_GUID; +/* IP packet ID */ +static unsigned int net_ip_id; + +/* + * Compute the checksum of the IP header. We cover even values of length only. + * We cannot use net/checksum.c due to different CFLAGS values. + * + * @buf: IP header + * @len: length of header in bytes + * @return: checksum + */ +static unsigned int efi_ip_checksum(const void *buf, size_t len) +{ + size_t i; + u32 sum = 0; + const u16 *pos = buf; + + for (i = 0; i < len; i += 2) + sum += *pos++; + + sum = (sum >> 16) + (sum & 0xffff); + sum += sum >> 16; + sum = ~sum & 0xffff; + + return sum; +} + +/* + * Transmit a DHCPDISCOVER message. + */ +static efi_status_t send_dhcp_discover(void) +{ + efi_status_t ret; + struct dhcp p = {}; + + /* + * Fill ethernet header + */ + boottime->copy_mem(p.eth_hdr.et_dest, (void *)BROADCAST_MAC, ARP_HLEN); + boottime->copy_mem(p.eth_hdr.et_src, &net->mode->current_address, + ARP_HLEN); + p.eth_hdr.et_protlen = htons(PROT_IP); + /* + * Fill IP header + */ + p.ip_udp.ip_hl_v = 0x45; + p.ip_udp.ip_len = htons(sizeof(struct dhcp) - + sizeof(struct ethernet_hdr)); + p.ip_udp.ip_id = htons(++net_ip_id); + p.ip_udp.ip_off = htons(IP_FLAGS_DFRAG); + p.ip_udp.ip_ttl = 0xff; /* time to live */ + p.ip_udp.ip_p = IPPROTO_UDP; + boottime->set_mem(&p.ip_udp.ip_dst, 4, 0xff); + p.ip_udp.ip_sum = efi_ip_checksum(&p.ip_udp, IP_HDR_SIZE); + + /* + * Fill UDP header + */ + p.ip_udp.udp_src = htons(68); + p.ip_udp.udp_dst = htons(67); + p.ip_udp.udp_len = htons(sizeof(struct dhcp) - + sizeof(struct ethernet_hdr) - + sizeof(struct ip_hdr)); + /* + * Fill DHCP header + */ + p.dhcp_hdr.op = BOOTREQUEST; + p.dhcp_hdr.htype = HWT_ETHER; + p.dhcp_hdr.hlen = HWL_ETHER; + p.dhcp_hdr.flags = htons(DHCP_FLAGS_UNICAST); + boottime->copy_mem(&p.dhcp_hdr.chaddr, + &net->mode->current_address, ARP_HLEN); + /* + * Fill options + */ + p.opt[0] = 0x63; /* DHCP magic cookie */ + p.opt[1] = 0x82; + p.opt[2] = 0x53; + p.opt[3] = 0x63; + p.opt[4] = DHCP_MESSAGE_TYPE; + p.opt[5] = 0x01; /* length */ + p.opt[6] = DHCPDISCOVER; + p.opt[7] = 0x39; /* maximum message size */ + p.opt[8] = 0x02; /* length */ + p.opt[9] = 0x02; /* 576 bytes */ + p.opt[10] = 0x40; + p.opt[11] = 0xff; /* end of options */ + + /* + * Transmit DHCPDISCOVER message. + */ + ret = net->transmit(net, 0, sizeof(struct dhcp), &p, NULL, NULL, 0); + if (ret != EFI_SUCCESS) + efi_st_error("Sending a DHCP request failed\n"); + else + efi_st_printf("DHCP Discover\n"); + return ret; +} + +/* + * Setup unit test. + * + * Create a 1 s periodic timer. + * Start the network driver. + * + * @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; + + /* + * Create a timer event. + */ + ret = boottime->create_event(EVT_TIMER, TPL_CALLBACK, NULL, NULL, + &timer); + if (ret != EFI_SUCCESS) { + efi_st_error("Failed to create event\n"); + return EFI_ST_FAILURE; + } + /* + * Set timer period to 1s. + */ + ret = boottime->set_timer(timer, EFI_TIMER_PERIODIC, 10000000); + if (ret != EFI_SUCCESS) { + efi_st_error("Failed to locate simple network protocol\n"); + return EFI_ST_FAILURE; + } + /* + * Find an interface implementing the SNP protocol. + */ + ret = boottime->locate_protocol(&efi_net_guid, NULL, (void **)&net); + if (ret != EFI_SUCCESS) { + efi_st_error("Failed to locate simple network protocol\n"); + return EFI_ST_FAILURE; + } + /* + * Check hardware address size. + */ + if (!net->mode) { + efi_st_error("Mode not provided\n"); + return EFI_ST_FAILURE; + } + if (net->mode->hwaddr_size != ARP_HLEN) { + efi_st_error("HwAddressSize = %u, expected %u\n", + net->mode->hwaddr_size, ARP_HLEN); + return EFI_ST_FAILURE; + } + /* + * Check that WaitForPacket event exists. + */ + if (!net->wait_for_packet) { + efi_st_error("WaitForPacket event missing\n"); + return EFI_ST_FAILURE; + } + /* + * Initialize network adapter. + */ + ret = net->initialize(net, 0, 0); + if (ret != EFI_SUCCESS) { + efi_st_error("Failed to initialize network adapter\n"); + return EFI_ST_FAILURE; + } + /* + * Start network adapter. + */ + ret = net->start(net); + if (ret != EFI_SUCCESS) { + efi_st_error("Failed to start network adapter\n"); + return EFI_ST_FAILURE; + } + return EFI_ST_SUCCESS; +} + +/* + * Execute unit test. + * + * A DHCP discover message is sent. The test is successful if a + * DHCP reply is received within 10 seconds. + * + * @return: EFI_ST_SUCCESS for success + */ +static int execute(void) +{ + efi_status_t ret; + struct efi_event *events[2]; + size_t index; + union { + struct dhcp p; + u8 b[PKTSIZE]; + } buffer; + struct efi_mac_address srcaddr; + struct efi_mac_address destaddr; + size_t buffer_size; + u8 *addr; + /* + * The timeout is to occur after 10 s. + */ + unsigned int timeout = 10; + + /* + * Send DHCP discover message + */ + ret = send_dhcp_discover(); + if (ret != EFI_SUCCESS) + return EFI_ST_FAILURE; + + /* + * If we would call WaitForEvent only with the WaitForPacket event, + * our code would block until a packet is received which might never + * occur. By calling WaitFor event with both a timer event and the + * WaitForPacket event we can escape this blocking situation. + * + * If the timer event occurs before we have received a DHCP reply + * a further DHCP discover message is sent. + */ + events[0] = timer; + events[1] = net->wait_for_packet; + for (;;) { + /* + * Wait for packet to be received or timer event. + */ + boottime->wait_for_event(2, events, &index); + if (index == 0) { + /* + * The timer event occurred. Check for timeout. + */ + --timeout; + if (!timeout) { + efi_st_error("Timeout occurred\n"); + return EFI_ST_FAILURE; + } + /* + * Send further DHCP discover message + */ + ret = send_dhcp_discover(); + if (ret != EFI_SUCCESS) + return EFI_ST_FAILURE; + continue; + } + /* + * Receive packet + */ + buffer_size = sizeof(buffer); + net->receive(net, NULL, &buffer_size, &buffer, + &srcaddr, &destaddr, NULL); + if (ret != EFI_SUCCESS) { + efi_st_error("Failed to receive packet"); + return EFI_ST_FAILURE; + } + /* + * Check the packet is meant for this system. + * Unfortunately QEMU ignores the broadcast flag. + * So we have to check for broadcasts too. + */ + if (efi_st_memcmp(&destaddr, &net->mode->current_address, + ARP_HLEN) && + efi_st_memcmp(&destaddr, BROADCAST_MAC, ARP_HLEN)) + continue; + /* + * Check this is a DHCP reply + */ + if (buffer.p.eth_hdr.et_protlen != ntohs(PROT_IP) || + buffer.p.ip_udp.ip_hl_v != 0x45 || + buffer.p.ip_udp.ip_p != IPPROTO_UDP || + buffer.p.ip_udp.udp_src != ntohs(67) || + buffer.p.ip_udp.udp_dst != ntohs(68) || + buffer.p.dhcp_hdr.op != BOOTREPLY) + continue; + /* + * We successfully received a DHCP reply. + */ + break; + } + + /* + * Write a log message. + */ + addr = (u8 *)&buffer.p.ip_udp.ip_src; + efi_st_printf("DHCP reply received from %u.%u.%u.%u (%pm) ", + addr[0], addr[1], addr[2], addr[3], &srcaddr); + if (!efi_st_memcmp(&destaddr, BROADCAST_MAC, ARP_HLEN)) + efi_st_printf("as broadcast message.\n"); + else + efi_st_printf("as unicast message.\n"); + + return EFI_ST_SUCCESS; +} + +/* + * Tear down unit test. + * + * Close the timer event created in setup. + * Shut down the network adapter. + * + * @return: EFI_ST_SUCCESS for success + */ +static int teardown(void) +{ + efi_status_t ret; + int exit_status = EFI_ST_SUCCESS; + + if (timer) { + /* + * Stop timer. + */ + ret = boottime->set_timer(timer, EFI_TIMER_STOP, 0); + if (ret != EFI_SUCCESS) { + efi_st_error("Failed to stop timer"); + exit_status = EFI_ST_FAILURE; + } + /* + * Close timer event. + */ + ret = boottime->close_event(timer); + if (ret != EFI_SUCCESS) { + efi_st_error("Failed to close event"); + exit_status = EFI_ST_FAILURE; + } + } + if (net) { + /* + * Stop network adapter. + */ + ret = net->stop(net); + if (ret != EFI_SUCCESS) { + efi_st_error("Failed to stop network adapter\n"); + exit_status = EFI_ST_FAILURE; + } + /* + * Shut down network adapter. + */ + ret = net->shutdown(net); + if (ret != EFI_SUCCESS) { + efi_st_error("Failed to shut down network adapter\n"); + exit_status = EFI_ST_FAILURE; + } + } + + return exit_status; +} + +EFI_UNIT_TEST(snp) = { + .name = "simple network protocol", + .phase = EFI_EXECUTE_BEFORE_BOOTTIME_EXIT, + .setup = setup, + .execute = execute, + .teardown = teardown, +}; diff --git a/lib/efi_selftest/efi_selftest_util.c b/lib/efi_selftest/efi_selftest_util.c new file mode 100644 index 00000000000..c9c295e2fbe --- /dev/null +++ b/lib/efi_selftest/efi_selftest_util.c @@ -0,0 +1,25 @@ +/* + * efi_selftest_util + * + * Copyright (c) 2017 Heinrich Schuchardt + * + * SPDX-License-Identifier: GPL-2.0+ + * + * Utility functions + */ + +#include + +int efi_st_memcmp(const void *buf1, const void *buf2, size_t length) +{ + const u8 *pos1 = buf1; + const u8 *pos2 = buf2; + + for (; length; --length) { + if (*pos1 != *pos2) + return pos1 - pos2; + ++pos1; + ++pos2; + } + return EFI_ST_SUCCESS; +} -- cgit v1.3.1 From 984f251feeb932cfe551cbd62c5f7f5e073b6cc3 Mon Sep 17 00:00:00 2001 From: Heinrich Schuchardt Date: Mon, 9 Oct 2017 21:09:05 +0200 Subject: efi_loader: MAX_UTF8_PER_UTF16 = 3 The constant MAX_UTF8_PER_UTF16 is used to calculate required memory when converting from UTF-16 to UTF-8. If this constant is too big we waste memory. A code point encoded by one UTF-16 symbol is converted to a maximum of three UTF-8 symbols, e.g. 0xffff could be encoded as 0xef 0xbf 0xbf. The first byte carries four bits, the second and third byte carry six bits each. A code point encoded by two UTF-16 symbols is converted to four UTF-8 symbols. So in this case we need a maximum of two UTF-8 symbols per UTF-16 symbol. As the overall maximum is three UTF-8 symobls per UTF-16 symbol we need MAX_UTF8_PER_UTF16 = 3. Fixes: 78178bb0c9d lib: add some utf16 handling helpers Signed-off-by: Heinrich Schuchardt Signed-off-by: Alexander Graf --- include/charset.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'include') diff --git a/include/charset.h b/include/charset.h index 39279f746a6..37a32784998 100644 --- a/include/charset.h +++ b/include/charset.h @@ -9,7 +9,7 @@ #ifndef __CHARSET_H_ #define __CHARSET_H_ -#define MAX_UTF8_PER_UTF16 4 +#define MAX_UTF8_PER_UTF16 3 /** * utf16_strlen() - Get the length of an utf16 string @@ -52,7 +52,7 @@ uint16_t *utf16_strdup(const uint16_t *s); * Converts 'size' characters of the utf16 string 'src' to utf8 * written to the 'dest' buffer. * - * NOTE that a single utf16 character can generate up to 4 utf8 + * NOTE that a single utf16 character can generate up to 3 utf8 * characters. See MAX_UTF8_PER_UTF16. * * @dest the destination buffer to write the utf8 characters -- cgit v1.3.1 From bf19273e81eb5e23c9bc14c3881f92a120565561 Mon Sep 17 00:00:00 2001 From: Rob Clark Date: Tue, 10 Oct 2017 08:23:06 -0400 Subject: efi_loader: Add mem-mapped for fallback When we don't have a real device/image path, such as 'bootefi hello', construct a mem-mapped device-path. This fixes 'bootefi hello' after devicepath refactoring. Fixes: 95c5553ea2 ("efi_loader: refactor boot device and loaded_image handling") Signed-off-by: Rob Clark Acked-by: Heinrich Schuchardt Signed-off-by: Alexander Graf --- cmd/bootefi.c | 23 +++++++++++++++++++++++ include/efi_api.h | 8 ++++++++ include/efi_loader.h | 3 +++ lib/efi_loader/efi_device_path.c | 24 ++++++++++++++++++++++++ lib/efi_loader/efi_device_path_to_text.c | 9 +++++++++ 5 files changed, 67 insertions(+) (limited to 'include') diff --git a/cmd/bootefi.c b/cmd/bootefi.c index b7087e3da87..478bc116e24 100644 --- a/cmd/bootefi.c +++ b/cmd/bootefi.c @@ -127,6 +127,7 @@ static unsigned long do_bootefi_exec(void *efi, void *fdt, { struct efi_loaded_image loaded_image_info = {}; struct efi_object loaded_image_info_obj = {}; + struct efi_device_path *memdp = NULL; ulong ret; ulong (*entry)(void *image_handle, struct efi_system_table *st) @@ -135,6 +136,20 @@ static unsigned long do_bootefi_exec(void *efi, void *fdt, const efi_guid_t fdt_guid = EFI_FDT_GUID; bootm_headers_t img = { 0 }; + /* + * Special case for efi payload not loaded from disk, such as + * 'bootefi hello' or for example payload loaded directly into + * memory via jtag/etc: + */ + if (!device_path && !image_path) { + printf("WARNING: using memory device/image path, this may confuse some payloads!\n"); + /* actual addresses filled in after efi_load_pe() */ + memdp = efi_dp_from_mem(0, 0, 0); + device_path = image_path = memdp; + } else { + assert(device_path && image_path); + } + /* Initialize and populate EFI object list */ if (!efi_obj_list_initalized) efi_init_obj_list(); @@ -181,6 +196,14 @@ static unsigned long do_bootefi_exec(void *efi, void *fdt, goto exit; } + if (memdp) { + struct efi_device_path_memory *mdp = (void *)memdp; + mdp->memory_type = loaded_image_info.image_code_type; + mdp->start_address = (uintptr_t)loaded_image_info.image_base; + mdp->end_address = mdp->start_address + + loaded_image_info.image_size; + } + /* we don't support much: */ env_set("efi_8be4df61-93ca-11d2-aa0d-00e098032b8c_OsIndicationsSupported", "{ro,boot}(blob)0000000000000000"); diff --git a/include/efi_api.h b/include/efi_api.h index a9a6494afef..94c15b279ac 100644 --- a/include/efi_api.h +++ b/include/efi_api.h @@ -297,8 +297,16 @@ struct efi_mac_addr { } __packed; #define DEVICE_PATH_TYPE_HARDWARE_DEVICE 0x01 +# define DEVICE_PATH_SUB_TYPE_MEMORY 0x03 # define DEVICE_PATH_SUB_TYPE_VENDOR 0x04 +struct efi_device_path_memory { + struct efi_device_path dp; + u32 memory_type; + u64 start_address; + u64 end_address; +} __packed; + struct efi_device_path_vendor { struct efi_device_path dp; efi_guid_t guid; diff --git a/include/efi_loader.h b/include/efi_loader.h index e1179b7dcd1..1b92edbd77c 100644 --- a/include/efi_loader.h +++ b/include/efi_loader.h @@ -259,6 +259,9 @@ struct efi_device_path *efi_dp_from_part(struct blk_desc *desc, int part); struct efi_device_path *efi_dp_from_file(struct blk_desc *desc, int part, const char *path); struct efi_device_path *efi_dp_from_eth(void); +struct efi_device_path *efi_dp_from_mem(uint32_t mem_type, + uint64_t start_address, + uint64_t end_address); void efi_dp_split_file_path(struct efi_device_path *full_path, struct efi_device_path **device_path, struct efi_device_path **file_path); diff --git a/lib/efi_loader/efi_device_path.c b/lib/efi_loader/efi_device_path.c index 5d5c3b34646..f6e368e029b 100644 --- a/lib/efi_loader/efi_device_path.c +++ b/lib/efi_loader/efi_device_path.c @@ -538,6 +538,30 @@ struct efi_device_path *efi_dp_from_eth(void) } #endif +/* Construct a device-path for memory-mapped image */ +struct efi_device_path *efi_dp_from_mem(uint32_t memory_type, + uint64_t start_address, + uint64_t end_address) +{ + struct efi_device_path_memory *mdp; + void *buf, *start; + + start = buf = dp_alloc(sizeof(*mdp) + sizeof(END)); + + mdp = buf; + mdp->dp.type = DEVICE_PATH_TYPE_HARDWARE_DEVICE; + mdp->dp.sub_type = DEVICE_PATH_SUB_TYPE_MEMORY; + mdp->dp.length = sizeof(*mdp); + mdp->memory_type = memory_type; + mdp->start_address = start_address; + mdp->end_address = end_address; + buf = &mdp[1]; + + *((struct efi_device_path *)buf) = END; + + return start; +} + /* * Helper to split a full device path (containing both device and file * parts) into it's constituent parts. diff --git a/lib/efi_loader/efi_device_path_to_text.c b/lib/efi_loader/efi_device_path_to_text.c index 1a5ef3919ba..62771338f03 100644 --- a/lib/efi_loader/efi_device_path_to_text.c +++ b/lib/efi_loader/efi_device_path_to_text.c @@ -24,6 +24,15 @@ static char *dp_unknown(char *s, struct efi_device_path *dp) static char *dp_hardware(char *s, struct efi_device_path *dp) { switch (dp->sub_type) { + case DEVICE_PATH_SUB_TYPE_MEMORY: { + struct efi_device_path_memory *mdp = + (struct efi_device_path_memory *)dp; + s += sprintf(s, "/MemoryMapped(0x%x,0x%llx,0x%llx)", + mdp->memory_type, + mdp->start_address, + mdp->end_address); + break; + } case DEVICE_PATH_SUB_TYPE_VENDOR: { struct efi_device_path_vendor *vdp = (struct efi_device_path_vendor *)dp; -- cgit v1.3.1 From 2d5dc2a52d412964031c9920d354ad5bdc91c654 Mon Sep 17 00:00:00 2001 From: Rob Clark Date: Tue, 10 Oct 2017 08:23:01 -0400 Subject: efi_loader: console support for color attributes MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Shell.efi uses this, and supporting color attributes makes things look nicer. Map the EFI fg/bg color attributes to ANSI escape sequences. Not all colors have a perfect match, but spec just says "Devices supporting a different number of text colors are required to emulate the above colors to the best of the device’s capabilities". Signed-off-by: Rob Clark Tested-by: Heinrich Schuchardt Reviewed-by: Alexander Graf [agraf: s/unsigned/unsigned int/] Signed-off-by: Alexander Graf --- include/efi_api.h | 33 +++++++++++++++++++++++++++++++++ lib/efi_loader/efi_console.c | 27 +++++++++++++++++++++++++-- 2 files changed, 58 insertions(+), 2 deletions(-) (limited to 'include') diff --git a/include/efi_api.h b/include/efi_api.h index 94c15b279ac..fcd7483ab21 100644 --- a/include/efi_api.h +++ b/include/efi_api.h @@ -433,6 +433,39 @@ struct simple_text_output_mode { EFI_GUID(0x387477c2, 0x69c7, 0x11d2, \ 0x8e, 0x39, 0x0, 0xa0, 0xc9, 0x69, 0x72, 0x3b) +#define EFI_BLACK 0x00 +#define EFI_BLUE 0x01 +#define EFI_GREEN 0x02 +#define EFI_CYAN 0x03 +#define EFI_RED 0x04 +#define EFI_MAGENTA 0x05 +#define EFI_BROWN 0x06 +#define EFI_LIGHTGRAY 0x07 +#define EFI_BRIGHT 0x08 +#define EFI_DARKGRAY 0x08 +#define EFI_LIGHTBLUE 0x09 +#define EFI_LIGHTGREEN 0x0a +#define EFI_LIGHTCYAN 0x0b +#define EFI_LIGHTRED 0x0c +#define EFI_LIGHTMAGENTA 0x0d +#define EFI_YELLOW 0x0e +#define EFI_WHITE 0x0f +#define EFI_BACKGROUND_BLACK 0x00 +#define EFI_BACKGROUND_BLUE 0x10 +#define EFI_BACKGROUND_GREEN 0x20 +#define EFI_BACKGROUND_CYAN 0x30 +#define EFI_BACKGROUND_RED 0x40 +#define EFI_BACKGROUND_MAGENTA 0x50 +#define EFI_BACKGROUND_BROWN 0x60 +#define EFI_BACKGROUND_LIGHTGRAY 0x70 + +/* extract foreground color from EFI attribute */ +#define EFI_ATTR_FG(attr) ((attr) & 0x07) +/* treat high bit of FG as bright/bold (similar to edk2) */ +#define EFI_ATTR_BOLD(attr) (((attr) >> 3) & 0x01) +/* extract background color from EFI attribute */ +#define EFI_ATTR_BG(attr) (((attr) >> 4) & 0x7) + struct efi_simple_text_output_protocol { void *reset; efi_status_t (EFIAPI *output_string)( diff --git a/lib/efi_loader/efi_console.c b/lib/efi_loader/efi_console.c index 1bdf36b4ae7..01732aafead 100644 --- a/lib/efi_loader/efi_console.c +++ b/lib/efi_loader/efi_console.c @@ -307,14 +307,37 @@ static efi_status_t EFIAPI efi_cout_set_mode( return EFI_EXIT(EFI_SUCCESS); } +static const struct { + unsigned int fg; + unsigned int bg; +} color[] = { + { 30, 40 }, /* 0: black */ + { 34, 44 }, /* 1: blue */ + { 32, 42 }, /* 2: green */ + { 36, 46 }, /* 3: cyan */ + { 31, 41 }, /* 4: red */ + { 35, 45 }, /* 5: magenta */ + { 33, 43 }, /* 6: brown, map to yellow as edk2 does*/ + { 37, 47 }, /* 7: light grey, map to white */ +}; + +/* See EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL.SetAttribute(). */ static efi_status_t EFIAPI efi_cout_set_attribute( struct efi_simple_text_output_protocol *this, unsigned long attribute) { + unsigned int bold = EFI_ATTR_BOLD(attribute); + unsigned int fg = EFI_ATTR_FG(attribute); + unsigned int bg = EFI_ATTR_BG(attribute); + EFI_ENTRY("%p, %lx", this, attribute); - /* Just ignore attributes (colors) for now */ - return EFI_EXIT(EFI_UNSUPPORTED); + if (attribute) + printf(ESC"[%u;%u;%um", bold, color[fg].fg, color[bg].bg); + else + printf(ESC"[0;37;40m"); + + return EFI_EXIT(EFI_SUCCESS); } static efi_status_t EFIAPI efi_cout_clear_screen( -- cgit v1.3.1