efi_loader: implement SetTime
Implement the SetTime() runtime service. Extend the real time clock selftest to check setting the clock. Signed-off-by: Heinrich Schuchardt <xypron.glpk@gmx.de>
This commit is contained in:
parent
40920bdecc
commit
433bfe7b12
@ -214,7 +214,57 @@ out:
|
||||
#endif
|
||||
}
|
||||
|
||||
/**
|
||||
* efi_set_time_boottime() - set current time
|
||||
*
|
||||
* This function implements the SetTime() runtime service before
|
||||
* SetVirtualAddressMap() is called.
|
||||
*
|
||||
* See the Unified Extensible Firmware Interface (UEFI) specification
|
||||
* for details.
|
||||
*
|
||||
* @time: pointer to structure to with current time
|
||||
* Returns: status code
|
||||
*/
|
||||
static efi_status_t EFIAPI efi_set_time_boottime(struct efi_time *time)
|
||||
{
|
||||
#ifdef CONFIG_DM_RTC
|
||||
efi_status_t ret = EFI_SUCCESS;
|
||||
struct rtc_time tm;
|
||||
struct udevice *dev;
|
||||
|
||||
EFI_ENTRY("%p", time);
|
||||
|
||||
if (!time) {
|
||||
ret = EFI_INVALID_PARAMETER;
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (uclass_get_device(UCLASS_RTC, 0, &dev)) {
|
||||
ret = EFI_UNSUPPORTED;
|
||||
goto out;
|
||||
}
|
||||
|
||||
memset(&tm, 0, sizeof(tm));
|
||||
tm.tm_year = time->year;
|
||||
tm.tm_mon = time->month;
|
||||
tm.tm_mday = time->day;
|
||||
tm.tm_hour = time->hour;
|
||||
tm.tm_min = time->minute;
|
||||
tm.tm_sec = time->second;
|
||||
tm.tm_isdst = time->daylight == EFI_TIME_IN_DAYLIGHT;
|
||||
/* Calculate day of week */
|
||||
rtc_calc_weekday(&tm);
|
||||
|
||||
if (dm_rtc_set(dev, &tm))
|
||||
ret = EFI_DEVICE_ERROR;
|
||||
out:
|
||||
return EFI_EXIT(ret);
|
||||
#else
|
||||
EFI_ENTRY("%p", time);
|
||||
return EFI_EXIT(EFI_UNSUPPORTED);
|
||||
#endif
|
||||
}
|
||||
/**
|
||||
* efi_reset_system() - reset system
|
||||
*
|
||||
@ -271,6 +321,24 @@ efi_status_t __weak __efi_runtime EFIAPI efi_get_time(
|
||||
return EFI_DEVICE_ERROR;
|
||||
}
|
||||
|
||||
/**
|
||||
* efi_set_time() - set current time
|
||||
*
|
||||
* This function implements the SetTime runtime service after
|
||||
* SetVirtualAddressMap() is called. As the U-Boot driver are not available
|
||||
* anymore only an error code is returned.
|
||||
*
|
||||
* See the Unified Extensible Firmware Interface (UEFI) specification
|
||||
* for details.
|
||||
*
|
||||
* @time: pointer to structure to with current time
|
||||
* Returns: status code
|
||||
*/
|
||||
efi_status_t __weak __efi_runtime EFIAPI efi_set_time(struct efi_time *time)
|
||||
{
|
||||
return EFI_UNSUPPORTED;
|
||||
}
|
||||
|
||||
struct efi_runtime_detach_list_struct {
|
||||
void *ptr;
|
||||
void *patchto;
|
||||
@ -289,6 +357,9 @@ static const struct efi_runtime_detach_list_struct efi_runtime_detach_list[] = {
|
||||
/* RTC accessors are gone */
|
||||
.ptr = &efi_runtime_services.get_time,
|
||||
.patchto = &efi_get_time,
|
||||
}, {
|
||||
.ptr = &efi_runtime_services.set_time,
|
||||
.patchto = &efi_set_time,
|
||||
}, {
|
||||
/* Clean up system table */
|
||||
.ptr = &systab.con_in,
|
||||
@ -697,7 +768,7 @@ struct efi_runtime_services __efi_runtime_data efi_runtime_services = {
|
||||
.headersize = sizeof(struct efi_runtime_services),
|
||||
},
|
||||
.get_time = &efi_get_time_boottime,
|
||||
.set_time = (void *)&efi_device_error,
|
||||
.set_time = &efi_set_time_boottime,
|
||||
.get_wakeup_time = (void *)&efi_unimplemented,
|
||||
.set_wakeup_time = (void *)&efi_unimplemented,
|
||||
.set_virtual_address_map = &efi_set_virtual_address_map,
|
||||
|
@ -10,6 +10,7 @@
|
||||
#include <efi_selftest.h>
|
||||
|
||||
#define EFI_ST_NO_RTC "Could not read real time clock\n"
|
||||
#define EFI_ST_NO_RTC_SET "Could not set real time clock\n"
|
||||
|
||||
static struct efi_runtime_services *runtime;
|
||||
|
||||
@ -30,17 +31,26 @@ static int setup(const efi_handle_t handle,
|
||||
/*
|
||||
* Execute unit test.
|
||||
*
|
||||
* Display current time.
|
||||
* Read and display current time.
|
||||
* Set a new value and read it back.
|
||||
* Set the real time clock back the current time.
|
||||
*
|
||||
* @return: EFI_ST_SUCCESS for success
|
||||
*/
|
||||
static int execute(void)
|
||||
{
|
||||
efi_status_t ret;
|
||||
struct efi_time tm;
|
||||
struct efi_time tm, tm_old, tm_new = {
|
||||
.year = 2017,
|
||||
.month = 5,
|
||||
.day = 19,
|
||||
.hour = 13,
|
||||
.minute = 47,
|
||||
.second = 53,
|
||||
};
|
||||
|
||||
/* Display current time */
|
||||
ret = runtime->get_time(&tm, NULL);
|
||||
ret = runtime->get_time(&tm_old, NULL);
|
||||
if (ret != EFI_SUCCESS) {
|
||||
#ifdef CONFIG_CMD_DATE
|
||||
efi_st_error(EFI_ST_NO_RTC);
|
||||
@ -49,11 +59,41 @@ static int execute(void)
|
||||
efi_st_todo(EFI_ST_NO_RTC);
|
||||
return EFI_ST_SUCCESS;
|
||||
#endif
|
||||
} else {
|
||||
efi_st_printf("Time according to real time clock: "
|
||||
"%.4u-%.2u-%.2u %.2u:%.2u:%.2u\n",
|
||||
tm.year, tm.month, tm.day,
|
||||
tm.hour, tm.minute, tm.second);
|
||||
}
|
||||
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);
|
||||
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) {
|
||||
efi_st_error(EFI_ST_NO_RTC);
|
||||
return EFI_ST_FAILURE;
|
||||
}
|
||||
if (tm.year != tm_new.year ||
|
||||
tm.month != tm_new.month ||
|
||||
tm.day != tm_new.day ||
|
||||
tm.hour != tm_new.hour ||
|
||||
tm.minute != tm_new.minute ||
|
||||
tm.second < tm_new.second ||
|
||||
tm.second > tm_new.second + 2) {
|
||||
efi_st_error(EFI_ST_NO_RTC_SET);
|
||||
return EFI_ST_FAILURE;
|
||||
}
|
||||
/* Set time back to old value */
|
||||
ret = runtime->set_time(&tm_old);
|
||||
if (ret != EFI_SUCCESS) {
|
||||
efi_st_error(EFI_ST_NO_RTC_SET);
|
||||
return EFI_ST_FAILURE;
|
||||
}
|
||||
|
||||
return EFI_ST_SUCCESS;
|
||||
|
Loading…
Reference in New Issue
Block a user