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:
commit
38c2a8a001
@ -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);
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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.
|
||||
|
@ -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_ */
|
||||
|
@ -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
|
||||
|
@ -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");
|
||||
|
@ -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(¬if->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);
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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
|
||||
|
205
lib/efi_selftest/efi_selftest_open_protocol.c
Normal file
205
lib/efi_selftest/efi_selftest_open_protocol.c
Normal 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,
|
||||
};
|
@ -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;
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user