Pull request for UEFI sub-system for v2019.07-rc4

Corrections for boottime services for protocols and for the SetTime()
 service are provided.
 
 Error messages for the 'setenv -e' and 'bootefi bootmgr' commands are
 added.
 -----BEGIN PGP SIGNATURE-----
 
 iQIzBAABCAAdFiEEbcT5xx8ppvoGt20zxIHbvCwFGsQFAlzziRQACgkQxIHbvCwF
 GsRFwA/9HJejIxx8TjMBAixuV0QRpvNlSqT4UNruDxDn1+UELDLzXAm2hinY07lR
 l58ztrzcFx6dUcTWR13P7vVItaGKoIyDTHKfdKbdtUC5OQzApu9/Crb5/+NPf2cS
 bxuFVEtrgvdJ9HdtF5SxTevnJK8MXnb8ho8QmYr+rPC5AMAOPWBnMMiWuS330TAW
 znxiWN+Hiy1q9+0peAHRcvTl0gheRrEUHqdluKdLOEwdJul3XjQlvOG87QAcuTOx
 +Y6VPDl91E6WKIofILDMfCBLVVsEw5ruoW2e1Vo23UxtIkTkDtop0qe46wBAzsJe
 blEFtvOXaAPikuL9x2aGO2nwk2q87tRzbS5pEGWspWW/PX72k94Vgw4R9NXj9Wpp
 UPpG4BK2Eu1YohomHa/zmaJPdRUYg2cP34N1YAbLrEX9Ro7Nhmf+cBgckbR+GRuF
 C95hBCzRNYpPV9BRHZlLG58yiTN/OUcTRSA87dENycA9WFqI8LRlLfkn8BYBwUwO
 KhFMLOjUViYvu+t+HcqBSQWwLN7Iw0F8lOfRQkJ1EFym29QNpWH6HjykAKN3SwUn
 b+r2ZDBwtwqGxZfUcaJHjc1ZPtzYEF7F3csrnicO5F+nN0oQvd8zBSHylDbvwAzd
 L392XREU4gB5Z/qxPjRFZdlVRgRmE36bNc7jcezT/qeD7Cl7z9I=
 =A8+f
 -----END PGP SIGNATURE-----

Merge tag 'efi-2019-07-rc4' of git://git.denx.de/u-boot-efi

Pull request for UEFI sub-system for v2019.07-rc4

Corrections for boottime services for protocols and for the SetTime()
service are provided.

Error messages for the 'setenv -e' and 'bootefi bootmgr' commands are
added.
This commit is contained in:
Tom Rini 2019-06-02 18:19:45 -04:00
commit 38c2a8a001
12 changed files with 459 additions and 84 deletions

View File

@ -373,6 +373,8 @@ int do_env_set_efi(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
for ( ; argc > 0; argc--, argv++)
if (append_value(&value, &size, argv[0]) < 0) {
printf("## Failed to process an argument, %s\n",
argv[0]);
ret = CMD_RET_FAILURE;
goto out;
}
@ -381,6 +383,7 @@ int do_env_set_efi(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
len = utf8_utf16_strnlen(var_name, strlen(var_name));
var_name16 = malloc((len + 1) * 2);
if (!var_name16) {
printf("## Out of memory\n");
ret = CMD_RET_FAILURE;
goto out;
}
@ -392,7 +395,12 @@ int do_env_set_efi(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
EFI_VARIABLE_BOOTSERVICE_ACCESS |
EFI_VARIABLE_RUNTIME_ACCESS,
size, value));
ret = (ret == EFI_SUCCESS ? CMD_RET_SUCCESS : CMD_RET_FAILURE);
if (ret == EFI_SUCCESS) {
ret = CMD_RET_SUCCESS;
} else {
printf("## Failed to set EFI variable\n");
ret = CMD_RET_FAILURE;
}
out:
free(value);
free(var_name16);

View File

@ -23,7 +23,7 @@ static const unsigned char rtc_days_in_month[] = {
/*
* The number of days in the month.
*/
static int rtc_month_days(unsigned int month, unsigned int year)
int rtc_month_days(unsigned int month, unsigned int year)
{
return rtc_days_in_month[month] + (is_leap_year(year) && month == 1);
}

View File

@ -286,20 +286,38 @@ extern struct list_head efi_obj_list;
/* List of all events */
extern struct list_head efi_events;
/**
* struct efi_protocol_notification - handle for notified protocol
*
* When a protocol interface is installed for which an event was registered with
* the RegisterProtocolNotify() service this structure is used to hold the
* handle on which the protocol interface was installed.
*
* @link: link to list of all handles notified for this event
* @handle: handle on which the notified protocol interface was installed
*/
struct efi_protocol_notification {
struct list_head link;
efi_handle_t handle;
};
/**
* efi_register_notify_event - event registered by RegisterProtocolNotify()
*
* The address of this structure serves as registration value.
*
* @link: link to list of all registered events
* @event: registered event. The same event may registered for
* multiple GUIDs.
* @protocol: protocol for which the event is registered
* @link: link to list of all registered events
* @event: registered event. The same event may registered for multiple
* GUIDs.
* @protocol: protocol for which the event is registered
* @handles: linked list of all handles on which the notified protocol was
* installed
*/
struct efi_register_notify_event {
struct list_head link;
struct efi_event *event;
efi_guid_t protocol;
struct list_head handles;
};
/* List of all events registered by RegisterProtocolNotify() */
@ -576,6 +594,8 @@ efi_status_t __efi_runtime EFIAPI efi_get_time(
struct efi_time *time,
struct efi_time_cap *capabilities);
efi_status_t __efi_runtime EFIAPI efi_set_time(struct efi_time *time);
#ifdef CONFIG_CMD_BOOTEFI_SELFTEST
/*
* Entry point for the tests of the EFI API.

View File

@ -258,4 +258,12 @@ void rtc_to_tm(u64 time_t, struct rtc_time *time);
*/
unsigned long rtc_mktime(const struct rtc_time *time);
/**
* rtc_month_days() - The number of days in the month
*
* @month: month (January = 0)
* @year: year (4 digits)
*/
int rtc_month_days(unsigned int month, unsigned int year);
#endif /* _RTC_H_ */

View File

@ -18,6 +18,22 @@ config EFI_LOADER
if EFI_LOADER
config EFI_GET_TIME
bool "GetTime() runtime service"
depends on DM_RTC
default y
help
Provide the GetTime() runtime service at boottime. This service
can be used by an EFI application to read the real time clock.
config EFI_SET_TIME
bool "SetTime() runtime service"
depends on EFI_GET_TIME
default n
help
Provide the SetTime() runtime service at boottime. This service
can be used by an EFI application to adjust the real time clock.
config EFI_DEVICE_PATH_TO_TEXT
bool "Device path to text protocol"
default y

View File

@ -149,8 +149,11 @@ static efi_status_t try_load_entry(u16 n, efi_handle_t *handle)
ret = EFI_CALL(efi_load_image(true, efi_root, lo.file_path,
NULL, 0, handle));
if (ret != EFI_SUCCESS)
if (ret != EFI_SUCCESS) {
printf("Loading from Boot%04X '%ls' failed\n", n,
lo.label);
goto error;
}
attributes = EFI_VARIABLE_BOOTSERVICE_ACCESS |
EFI_VARIABLE_RUNTIME_ACCESS;
@ -215,6 +218,7 @@ efi_status_t efi_bootmgr_load(efi_handle_t *handle)
ret = try_load_entry(bootnext, handle);
if (ret == EFI_SUCCESS)
return ret;
printf("Loading from BootNext failed, falling back to BootOrder\n");
}
} else {
printf("Deleting BootNext failed\n");

View File

@ -921,6 +921,14 @@ static efi_status_t EFIAPI efi_close_event(struct efi_event *event)
list_for_each_entry_safe(item, next, &efi_register_notify_events,
link) {
if (event == item->event) {
struct efi_protocol_notification *hitem, *hnext;
/* Remove signaled handles */
list_for_each_entry_safe(hitem, hnext, &item->handles,
link) {
list_del(&hitem->link);
free(hitem);
}
list_del(&item->link);
free(item);
}
@ -1049,8 +1057,19 @@ efi_status_t efi_add_protocol(const efi_handle_t handle,
/* Notify registered events */
list_for_each_entry(event, &efi_register_notify_events, link) {
if (!guidcmp(protocol, &event->protocol))
if (!guidcmp(protocol, &event->protocol)) {
struct efi_protocol_notification *notif;
notif = calloc(1, sizeof(*notif));
if (!notif) {
list_del(&handler->link);
free(handler);
return EFI_OUT_OF_RESOURCES;
}
notif->handle = handle;
list_add_tail(&notif->link, &event->handles);
efi_signal_event(event->event, true);
}
}
if (!guidcmp(&efi_guid_device_path, protocol))
@ -1241,10 +1260,6 @@ static efi_status_t efi_uninstall_protocol
goto out;
/* Disconnect controllers */
efi_disconnect_all_drivers(efiobj, protocol, NULL);
if (!list_empty(&handler->open_infos)) {
r = EFI_ACCESS_DENIED;
goto out;
}
/* Close protocol */
list_for_each_entry_safe(item, pos, &handler->open_infos, link) {
if (item->info.attributes ==
@ -1332,6 +1347,7 @@ static efi_status_t EFIAPI efi_register_protocol_notify(
item->event = event;
memcpy(&item->protocol, protocol, sizeof(efi_guid_t));
INIT_LIST_HEAD(&item->handles);
list_add_tail(&item->link, &efi_register_notify_events);
@ -1359,7 +1375,6 @@ static int efi_search(enum efi_locate_search_type search_type,
switch (search_type) {
case ALL_HANDLES:
return 0;
case BY_REGISTER_NOTIFY:
case BY_PROTOCOL:
ret = efi_search_protocol(handle, protocol, NULL);
return (ret != EFI_SUCCESS);
@ -1369,6 +1384,27 @@ static int efi_search(enum efi_locate_search_type search_type,
}
}
/**
* efi_check_register_notify_event() - check if registration key is valid
*
* Check that a pointer is a valid registration key as returned by
* RegisterProtocolNotify().
*
* @key: registration key
* Return: valid registration key or NULL
*/
static struct efi_register_notify_event *efi_check_register_notify_event
(void *key)
{
struct efi_register_notify_event *event;
list_for_each_entry(event, &efi_register_notify_events, link) {
if (event == (struct efi_register_notify_event *)key)
return event;
}
return NULL;
}
/**
* efi_locate_handle() - locate handles implementing a protocol
*
@ -1390,7 +1426,8 @@ static efi_status_t efi_locate_handle(
{
struct efi_object *efiobj;
efi_uintn_t size = 0;
struct efi_register_notify_event *item, *event = NULL;
struct efi_register_notify_event *event;
struct efi_protocol_notification *handle = NULL;
/* Check parameters */
switch (search_type) {
@ -1400,17 +1437,9 @@ static efi_status_t efi_locate_handle(
if (!search_key)
return EFI_INVALID_PARAMETER;
/* Check that the registration key is valid */
list_for_each_entry(item, &efi_register_notify_events, link) {
if (item ==
(struct efi_register_notify_event *)search_key) {
event = item;
break;
}
}
event = efi_check_register_notify_event(search_key);
if (!event)
return EFI_INVALID_PARAMETER;
protocol = &event->protocol;
break;
case BY_PROTOCOL:
if (!protocol)
@ -1421,14 +1450,23 @@ 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, efiobj))
size += sizeof(void *);
if (search_type == BY_REGISTER_NOTIFY) {
if (list_empty(&event->handles))
return EFI_NOT_FOUND;
handle = list_first_entry(&event->handles,
struct efi_protocol_notification,
link);
efiobj = handle->handle;
size += sizeof(void *);
} else {
list_for_each_entry(efiobj, &efi_obj_list, link) {
if (!efi_search(search_type, protocol, efiobj))
size += sizeof(void *);
}
if (size == 0)
return EFI_NOT_FOUND;
}
if (size == 0)
return EFI_NOT_FOUND;
if (!buffer_size)
return EFI_INVALID_PARAMETER;
@ -1444,9 +1482,14 @@ static efi_status_t efi_locate_handle(
return EFI_INVALID_PARAMETER;
/* Then fill the array */
list_for_each_entry(efiobj, &efi_obj_list, link) {
if (!efi_search(search_type, protocol, efiobj))
*buffer++ = efiobj;
if (search_type == BY_REGISTER_NOTIFY) {
*buffer = efiobj;
list_del(&handle->link);
} else {
list_for_each_entry(efiobj, &efi_obj_list, link) {
if (!efi_search(search_type, protocol, efiobj))
*buffer++ = efiobj;
}
}
return EFI_SUCCESS;
@ -2013,7 +2056,6 @@ static efi_status_t EFIAPI efi_close_protocol(efi_handle_t handle,
item->info.controller_handle == controller_handle) {
efi_delete_open_info(item);
r = EFI_SUCCESS;
break;
}
}
out:
@ -2212,29 +2254,58 @@ static efi_status_t EFIAPI efi_locate_protocol(const efi_guid_t *protocol,
void *registration,
void **protocol_interface)
{
struct list_head *lhandle;
struct efi_handler *handler;
efi_status_t ret;
struct efi_object *efiobj;
EFI_ENTRY("%pUl, %p, %p", protocol, registration, protocol_interface);
/*
* The UEFI spec explicitly requires a protocol even if a registration
* key is provided. This differs from the logic in LocateHandle().
*/
if (!protocol || !protocol_interface)
return EFI_EXIT(EFI_INVALID_PARAMETER);
list_for_each(lhandle, &efi_obj_list) {
struct efi_object *efiobj;
struct efi_handler *handler;
efiobj = list_entry(lhandle, struct efi_object, link);
if (registration) {
struct efi_register_notify_event *event;
struct efi_protocol_notification *handle;
event = efi_check_register_notify_event(registration);
if (!event)
return EFI_EXIT(EFI_INVALID_PARAMETER);
/*
* The UEFI spec requires to return EFI_NOT_FOUND if no
* protocol instance matches protocol and registration.
* So let's do the same for a mismatch between protocol and
* registration.
*/
if (guidcmp(&event->protocol, protocol))
goto not_found;
if (list_empty(&event->handles))
goto not_found;
handle = list_first_entry(&event->handles,
struct efi_protocol_notification,
link);
efiobj = handle->handle;
list_del(&handle->link);
free(handle);
ret = efi_search_protocol(efiobj, protocol, &handler);
if (ret == EFI_SUCCESS) {
*protocol_interface = handler->protocol_interface;
return EFI_EXIT(EFI_SUCCESS);
if (ret == EFI_SUCCESS)
goto found;
} else {
list_for_each_entry(efiobj, &efi_obj_list, link) {
ret = efi_search_protocol(efiobj, protocol, &handler);
if (ret == EFI_SUCCESS)
goto found;
}
}
not_found:
*protocol_interface = NULL;
return EFI_EXIT(EFI_NOT_FOUND);
found:
*protocol_interface = handler->protocol_interface;
return EFI_EXIT(EFI_SUCCESS);
}
/**
@ -2561,34 +2632,50 @@ static efi_status_t efi_protocol_open(
if ((attributes & EFI_OPEN_PROTOCOL_BY_DRIVER) &&
(item->info.attributes == attributes))
return EFI_ALREADY_STARTED;
} else {
if (item->info.attributes &
EFI_OPEN_PROTOCOL_BY_DRIVER)
opened_by_driver = true;
}
if (item->info.attributes & EFI_OPEN_PROTOCOL_EXCLUSIVE)
opened_exclusive = true;
}
/* Only one controller can open the protocol exclusively */
if (opened_exclusive && attributes &
(EFI_OPEN_PROTOCOL_EXCLUSIVE | EFI_OPEN_PROTOCOL_BY_DRIVER))
return EFI_ACCESS_DENIED;
if (attributes & EFI_OPEN_PROTOCOL_EXCLUSIVE) {
if (opened_exclusive)
return EFI_ACCESS_DENIED;
} else if (attributes & EFI_OPEN_PROTOCOL_BY_DRIVER) {
if (opened_exclusive || opened_by_driver)
return EFI_ACCESS_DENIED;
}
/* Prepare exclusive opening */
if (attributes & EFI_OPEN_PROTOCOL_EXCLUSIVE) {
/* Try to disconnect controllers */
disconnect_next:
opened_by_driver = false;
list_for_each_entry(item, &handler->open_infos, link) {
efi_status_t ret;
if (item->info.attributes ==
EFI_OPEN_PROTOCOL_BY_DRIVER)
EFI_CALL(efi_disconnect_controller(
EFI_OPEN_PROTOCOL_BY_DRIVER) {
ret = EFI_CALL(efi_disconnect_controller(
item->info.controller_handle,
item->info.agent_handle,
NULL));
if (ret == EFI_SUCCESS)
/*
* Child controllers may have been
* removed from the open_infos list. So
* let's restart the loop.
*/
goto disconnect_next;
else
opened_by_driver = true;
}
}
opened_by_driver = false;
/* Check if all controllers are disconnected */
list_for_each_entry(item, &handler->open_infos, link) {
if (item->info.attributes & EFI_OPEN_PROTOCOL_BY_DRIVER)
opened_by_driver = true;
}
/* Only one controller can be connected */
/* Only one driver can be connected */
if (opened_by_driver)
return EFI_ACCESS_DENIED;
}
@ -2596,7 +2683,8 @@ static efi_status_t efi_protocol_open(
/* Find existing entry */
list_for_each_entry(item, &handler->open_infos, link) {
if (item->info.agent_handle == agent_handle &&
item->info.controller_handle == controller_handle)
item->info.controller_handle == controller_handle &&
item->info.attributes == attributes)
match = &item->info;
}
/* None found, create one */
@ -2985,7 +3073,7 @@ static efi_status_t EFIAPI efi_handle_protocol(efi_handle_t handle,
const efi_guid_t *protocol,
void **protocol_interface)
{
return efi_open_protocol(handle, protocol, protocol_interface, NULL,
return efi_open_protocol(handle, protocol, protocol_interface, efi_root,
NULL, EFI_OPEN_PROTOCOL_BY_HANDLE_PROTOCOL);
}

View File

@ -167,7 +167,7 @@ static efi_status_t EFIAPI efi_get_time_boottime(
struct efi_time *time,
struct efi_time_cap *capabilities)
{
#ifdef CONFIG_DM_RTC
#ifdef CONFIG_EFI_GET_TIME
efi_status_t ret = EFI_SUCCESS;
struct rtc_time tm;
struct udevice *dev;
@ -195,9 +195,9 @@ static efi_status_t EFIAPI efi_get_time_boottime(
time->hour = tm.tm_hour;
time->minute = tm.tm_min;
time->second = tm.tm_sec;
time->daylight = EFI_TIME_ADJUST_DAYLIGHT;
if (tm.tm_isdst > 0)
time->daylight |= EFI_TIME_IN_DAYLIGHT;
if (tm.tm_isdst)
time->daylight =
EFI_TIME_ADJUST_DAYLIGHT | EFI_TIME_IN_DAYLIGHT;
time->timezone = EFI_UNSPECIFIED_TIMEZONE;
if (capabilities) {
@ -214,6 +214,30 @@ out:
#endif
}
#ifdef CONFIG_EFI_SET_TIME
/**
* efi_validate_time() - checks if timestamp is valid
*
* @time: timestamp to validate
* Returns: 0 if timestamp is valid, 1 otherwise
*/
static int efi_validate_time(struct efi_time *time)
{
return (!time ||
time->year < 1900 || time->year > 9999 ||
!time->month || time->month > 12 || !time->day ||
time->day > rtc_month_days(time->month - 1, time->year) ||
time->hour > 23 || time->minute > 59 || time->second > 59 ||
time->nanosecond > 999999999 ||
time->daylight &
~(EFI_TIME_IN_DAYLIGHT | EFI_TIME_ADJUST_DAYLIGHT) ||
((time->timezone < -1440 || time->timezone > 1440) &&
time->timezone != EFI_UNSPECIFIED_TIMEZONE));
}
#endif
/**
* efi_set_time_boottime() - set current time
*
@ -228,14 +252,14 @@ out:
*/
static efi_status_t EFIAPI efi_set_time_boottime(struct efi_time *time)
{
#ifdef CONFIG_DM_RTC
#ifdef CONFIG_EFI_SET_TIME
efi_status_t ret = EFI_SUCCESS;
struct rtc_time tm;
struct udevice *dev;
EFI_ENTRY("%p", time);
if (!time) {
if (efi_validate_time(time)) {
ret = EFI_INVALID_PARAMETER;
goto out;
}
@ -252,7 +276,8 @@ static efi_status_t EFIAPI efi_set_time_boottime(struct efi_time *time)
tm.tm_hour = time->hour;
tm.tm_min = time->minute;
tm.tm_sec = time->second;
tm.tm_isdst = time->daylight == EFI_TIME_IN_DAYLIGHT;
tm.tm_isdst = time->daylight ==
(EFI_TIME_ADJUST_DAYLIGHT | EFI_TIME_IN_DAYLIGHT);
/* Calculate day of week */
rtc_calc_weekday(&tm);

View File

@ -26,8 +26,8 @@ efi_selftest_gop.o \
efi_selftest_loaded_image.o \
efi_selftest_manageprotocols.o \
efi_selftest_memory.o \
efi_selftest_open_protocol.o \
efi_selftest_register_notify.o \
efi_selftest_rtc.o \
efi_selftest_snp.o \
efi_selftest_textinput.o \
efi_selftest_textinputex.o \
@ -43,6 +43,7 @@ efi_selftest_unicode_collation.o
obj-$(CONFIG_CPU_V7) += efi_selftest_unaligned.o
obj-$(CONFIG_EFI_LOADER_HII) += efi_selftest_hii.o
obj-$(CONFIG_EFI_GET_TIME) += efi_selftest_rtc.o
ifeq ($(CONFIG_GENERATE_ACPI_TABLE),)
obj-y += efi_selftest_fdt.o

View File

@ -0,0 +1,205 @@
// SPDX-License-Identifier: GPL-2.0+
/*
* efi_selftest_open_protocol
*
* Copyright (c) 2019 Heinrich Schuchardt <xypron.glpk@gmx.de>
*
* This unit test checks that open protocol information is correctly updated
* when calling:
* HandleProtocol, OpenProtocol, OpenProtocolInformation, CloseProtocol.
*/
#include <efi_selftest.h>
/*
* The test currently does not actually call the interface function.
* So this is just a dummy structure.
*/
struct interface {
void (EFIAPI *inc)(void);
};
static struct efi_boot_services *boottime;
static efi_guid_t guid1 =
EFI_GUID(0x492a0e38, 0x1442, 0xf819,
0x14, 0xaa, 0x4b, 0x8d, 0x09, 0xfe, 0x5a, 0xb9);
static efi_handle_t handle1;
static struct interface interface1;
/*
* Setup unit test.
*
* Create a handle and install a protocol interface on it.
*
* @handle: handle of the loaded image
* @systable: system table
*/
static int setup(const efi_handle_t img_handle,
const struct efi_system_table *systable)
{
efi_status_t ret;
boottime = systable->boottime;
ret = boottime->install_protocol_interface(&handle1, &guid1,
EFI_NATIVE_INTERFACE,
&interface1);
if (ret != EFI_SUCCESS) {
efi_st_error("InstallProtocolInterface failed\n");
return EFI_ST_FAILURE;
}
if (!handle1) {
efi_st_error
("InstallProtocolInterface failed to create handle\n");
return EFI_ST_FAILURE;
}
return EFI_ST_SUCCESS;
}
/*
* Tear down unit test.
*
*/
static int teardown(void)
{
efi_status_t ret;
if (handle1) {
ret = boottime->uninstall_protocol_interface(handle1, &guid1,
&interface1);
if (ret != EFI_SUCCESS) {
efi_st_error("UninstallProtocolInterface failed\n");
return EFI_ST_FAILURE;
}
}
return EFI_ST_SUCCESS;
}
/*
* Execute unit test.
*
* Open the installed protocol twice via HandleProtocol() and once via
* OpenProtocol(EFI_OPEN_PROTOCOL_GET_PROTOCOL). Read the open protocol
* information and check the open counts. Finally close the protocol and
* check again.
*/
static int execute(void)
{
void *interface;
struct efi_open_protocol_info_entry *entry_buffer;
efi_uintn_t entry_count;
efi_handle_t firmware_handle;
efi_status_t ret;
ret = boottime->handle_protocol(handle1, &guid1, &interface);
if (ret != EFI_SUCCESS) {
efi_st_error("HandleProtocol failed\n");
return EFI_ST_FAILURE;
}
if (interface != &interface1) {
efi_st_error("HandleProtocol returned wrong interface\n");
return EFI_ST_FAILURE;
}
ret = boottime->open_protocol_information(handle1, &guid1,
&entry_buffer, &entry_count);
if (ret != EFI_SUCCESS) {
efi_st_error("OpenProtocolInformation failed\n");
return EFI_ST_FAILURE;
}
if (entry_count != 1) {
efi_st_error("Incorrect OpenProtocolInformation count\n");
efi_st_printf("Expected 1, got %u\n",
(unsigned int)entry_count);
return EFI_ST_FAILURE;
}
ret = boottime->free_pool(entry_buffer);
if (ret != EFI_SUCCESS) {
efi_st_error("FreePool failed\n");
return EFI_ST_FAILURE;
}
ret = boottime->handle_protocol(handle1, &guid1, &interface);
if (ret != EFI_SUCCESS) {
efi_st_error("HandleProtocol failed\n");
return EFI_ST_FAILURE;
}
ret = boottime->open_protocol_information(handle1, &guid1,
&entry_buffer, &entry_count);
if (ret != EFI_SUCCESS) {
efi_st_error("OpenProtocolInformation failed\n");
return EFI_ST_FAILURE;
}
if (entry_count != 1) {
efi_st_error("Incorrect OpenProtocolInformation count\n");
efi_st_printf("Expected 1, got %u\n",
(unsigned int)entry_count);
return EFI_ST_FAILURE;
}
if (entry_buffer[0].open_count != 2) {
efi_st_error("Incorrect open count: expected 2 got %u\n",
entry_buffer[0].open_count);
return EFI_ST_FAILURE;
}
firmware_handle = entry_buffer[0].agent_handle;
ret = boottime->free_pool(entry_buffer);
if (ret != EFI_SUCCESS) {
efi_st_error("FreePool failed\n");
return EFI_ST_FAILURE;
}
ret = boottime->open_protocol(handle1, &guid1, &interface,
firmware_handle, NULL,
EFI_OPEN_PROTOCOL_GET_PROTOCOL);
if (ret != EFI_SUCCESS) {
efi_st_error("OpenProtocol failed\n");
return EFI_ST_FAILURE;
}
ret = boottime->open_protocol_information(handle1, &guid1,
&entry_buffer, &entry_count);
if (ret != EFI_SUCCESS) {
efi_st_error("OpenProtocolInformation failed\n");
return EFI_ST_FAILURE;
}
if (entry_count != 2) {
efi_st_error("Incorrect OpenProtocolInformation count\n");
efi_st_printf("Expected 2, got %u\n",
(unsigned int)entry_count);
return EFI_ST_FAILURE;
}
if (entry_buffer[0].open_count + entry_buffer[1].open_count != 3) {
efi_st_error("Incorrect open count: expected 3 got %u\n",
entry_buffer[0].open_count +
entry_buffer[1].open_count);
return EFI_ST_FAILURE;
}
ret = boottime->free_pool(entry_buffer);
if (ret != EFI_SUCCESS) {
efi_st_error("FreePool failed\n");
return EFI_ST_FAILURE;
}
ret = boottime->close_protocol(handle1, &guid1, firmware_handle, NULL);
if (ret != EFI_SUCCESS) {
efi_st_error("CloseProtocol failed\n");
return EFI_ST_FAILURE;
}
ret = boottime->open_protocol_information(handle1, &guid1,
&entry_buffer, &entry_count);
if (ret != EFI_SUCCESS) {
efi_st_error("OpenProtocolInformation failed\n");
return EFI_ST_FAILURE;
}
if (entry_count) {
efi_st_error("Incorrect OpenProtocolInformation count\n");
efi_st_printf("Expected 0, got %u\n",
(unsigned int)entry_count);
return EFI_ST_FAILURE;
}
return EFI_ST_SUCCESS;
}
EFI_UNIT_TEST(openprot) = {
.name = "open protocol",
.phase = EFI_EXECUTE_BEFORE_BOOTTIME_EXIT,
.setup = setup,
.execute = execute,
.teardown = teardown,
};

View File

@ -47,15 +47,20 @@ static void EFIAPI notify(struct efi_event *event, void *context)
{
struct context *cp = context;
efi_status_t ret;
efi_uintn_t handle_count;
efi_handle_t *handles;
cp->notify_count++;
ret = boottime->locate_handle_buffer(BY_REGISTER_NOTIFY, NULL,
cp->registration_key,
&cp->handle_count,
&cp->handles);
if (ret != EFI_SUCCESS)
cp->handle_count = 0;
for (;;) {
ret = boottime->locate_handle_buffer(BY_REGISTER_NOTIFY, NULL,
cp->registration_key,
&handle_count, &handles);
if (ret != EFI_SUCCESS)
break;
cp->handle_count += handle_count;
cp->handles = handles;
}
}
/*
@ -170,7 +175,7 @@ static int execute(void)
efi_st_error("reinstall was notified too often\n");
return EFI_ST_FAILURE;
}
if (context.handle_count != 1) {
if (context.handle_count != 2) {
efi_st_error("LocateHandle failed\n");
return EFI_ST_FAILURE;
}
@ -195,7 +200,7 @@ static int execute(void)
efi_st_error("install was notified too often\n");
return EFI_ST_FAILURE;
}
if (context.handle_count != 2) {
if (context.handle_count != 3) {
efi_st_error("LocateHandle failed\n");
return EFI_ST_FAILURE;
}

View File

@ -40,7 +40,9 @@ static int setup(const efi_handle_t handle,
static int execute(void)
{
efi_status_t ret;
struct efi_time tm, tm_old, tm_new = {
struct efi_time tm_old;
#ifdef CONFIG_EFI_SET_TIME
struct efi_time tm, tm_new = {
.year = 2017,
.month = 5,
.day = 19,
@ -48,31 +50,23 @@ static int execute(void)
.minute = 47,
.second = 53,
};
#endif
/* Display current time */
ret = runtime->get_time(&tm_old, NULL);
if (ret != EFI_SUCCESS) {
#ifdef CONFIG_CMD_DATE
efi_st_error(EFI_ST_NO_RTC);
return EFI_ST_FAILURE;
#else
efi_st_todo(EFI_ST_NO_RTC);
return EFI_ST_SUCCESS;
#endif
}
efi_st_printf("Time according to real time clock: "
"%.4u-%.2u-%.2u %.2u:%.2u:%.2u\n",
tm_old.year, tm_old.month, tm_old.day,
tm_old.hour, tm_old.minute, tm_old.second);
#ifdef CONFIG_EFI_SET_TIME
ret = runtime->set_time(&tm_new);
if (ret != EFI_SUCCESS) {
#ifdef CONFIG_CMD_DATE
efi_st_error(EFI_ST_NO_RTC_SET);
return EFI_ST_FAILURE;
#else
efi_st_todo(EFI_ST_NO_RTC_SET);
return EFI_ST_SUCCESS;
#endif
}
ret = runtime->get_time(&tm, NULL);
if (ret != EFI_SUCCESS) {
@ -95,6 +89,7 @@ static int execute(void)
efi_st_error(EFI_ST_NO_RTC_SET);
return EFI_ST_FAILURE;
}
#endif
return EFI_ST_SUCCESS;
}