提交 433bfe7b 编写于 作者: H Heinrich Schuchardt

efi_loader: implement SetTime

Implement the SetTime() runtime service.

Extend the real time clock selftest to check setting the clock.
Signed-off-by: NHeinrich Schuchardt <xypron.glpk@gmx.de>
上级 40920bde
...@@ -214,7 +214,57 @@ out: ...@@ -214,7 +214,57 @@ out:
#endif #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 * efi_reset_system() - reset system
* *
...@@ -271,6 +321,24 @@ efi_status_t __weak __efi_runtime EFIAPI efi_get_time( ...@@ -271,6 +321,24 @@ efi_status_t __weak __efi_runtime EFIAPI efi_get_time(
return EFI_DEVICE_ERROR; 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 { struct efi_runtime_detach_list_struct {
void *ptr; void *ptr;
void *patchto; void *patchto;
...@@ -289,6 +357,9 @@ static const struct efi_runtime_detach_list_struct efi_runtime_detach_list[] = { ...@@ -289,6 +357,9 @@ static const struct efi_runtime_detach_list_struct efi_runtime_detach_list[] = {
/* RTC accessors are gone */ /* RTC accessors are gone */
.ptr = &efi_runtime_services.get_time, .ptr = &efi_runtime_services.get_time,
.patchto = &efi_get_time, .patchto = &efi_get_time,
}, {
.ptr = &efi_runtime_services.set_time,
.patchto = &efi_set_time,
}, { }, {
/* Clean up system table */ /* Clean up system table */
.ptr = &systab.con_in, .ptr = &systab.con_in,
...@@ -697,7 +768,7 @@ struct efi_runtime_services __efi_runtime_data efi_runtime_services = { ...@@ -697,7 +768,7 @@ struct efi_runtime_services __efi_runtime_data efi_runtime_services = {
.headersize = sizeof(struct efi_runtime_services), .headersize = sizeof(struct efi_runtime_services),
}, },
.get_time = &efi_get_time_boottime, .get_time = &efi_get_time_boottime,
.set_time = (void *)&efi_device_error, .set_time = &efi_set_time_boottime,
.get_wakeup_time = (void *)&efi_unimplemented, .get_wakeup_time = (void *)&efi_unimplemented,
.set_wakeup_time = (void *)&efi_unimplemented, .set_wakeup_time = (void *)&efi_unimplemented,
.set_virtual_address_map = &efi_set_virtual_address_map, .set_virtual_address_map = &efi_set_virtual_address_map,
......
...@@ -10,6 +10,7 @@ ...@@ -10,6 +10,7 @@
#include <efi_selftest.h> #include <efi_selftest.h>
#define EFI_ST_NO_RTC "Could not read real time clock\n" #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; static struct efi_runtime_services *runtime;
...@@ -30,17 +31,26 @@ static int setup(const efi_handle_t handle, ...@@ -30,17 +31,26 @@ static int setup(const efi_handle_t handle,
/* /*
* Execute unit test. * 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 * @return: EFI_ST_SUCCESS for success
*/ */
static int execute(void) static int execute(void)
{ {
efi_status_t ret; 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 */ /* Display current time */
ret = runtime->get_time(&tm, NULL); ret = runtime->get_time(&tm_old, NULL);
if (ret != EFI_SUCCESS) { if (ret != EFI_SUCCESS) {
#ifdef CONFIG_CMD_DATE #ifdef CONFIG_CMD_DATE
efi_st_error(EFI_ST_NO_RTC); efi_st_error(EFI_ST_NO_RTC);
...@@ -49,11 +59,41 @@ static int execute(void) ...@@ -49,11 +59,41 @@ static int execute(void)
efi_st_todo(EFI_ST_NO_RTC); efi_st_todo(EFI_ST_NO_RTC);
return EFI_ST_SUCCESS; return EFI_ST_SUCCESS;
#endif #endif
} else { }
efi_st_printf("Time according to real time clock: " efi_st_printf("Time according to real time clock: "
"%.4u-%.2u-%.2u %.2u:%.2u:%.2u\n", "%.4u-%.2u-%.2u %.2u:%.2u:%.2u\n",
tm.year, tm.month, tm.day, tm_old.year, tm_old.month, tm_old.day,
tm.hour, tm.minute, tm.second); 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; return EFI_ST_SUCCESS;
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册