diff options
Diffstat (limited to 'lib/efi_loader/efi_runtime.c')
-rw-r--r-- | lib/efi_loader/efi_runtime.c | 120 |
1 files changed, 108 insertions, 12 deletions
diff --git a/lib/efi_loader/efi_runtime.c b/lib/efi_loader/efi_runtime.c index 636dfdab39d..9c50955c9bd 100644 --- a/lib/efi_loader/efi_runtime.c +++ b/lib/efi_loader/efi_runtime.c @@ -167,9 +167,8 @@ 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; - int r; struct rtc_time tm; struct udevice *dev; @@ -179,11 +178,12 @@ static efi_status_t EFIAPI efi_get_time_boottime( ret = EFI_INVALID_PARAMETER; goto out; } - - r = uclass_get_device(UCLASS_RTC, 0, &dev); - if (!r) - r = dm_rtc_get(dev, &tm); - if (r) { + if (uclass_get_device(UCLASS_RTC, 0, &dev) || + dm_rtc_get(dev, &tm)) { + ret = EFI_UNSUPPORTED; + goto out; + } + if (dm_rtc_get(dev, &tm)) { ret = EFI_DEVICE_ERROR; goto out; } @@ -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) { @@ -210,11 +210,86 @@ out: return EFI_EXIT(ret); #else EFI_ENTRY("%p %p", time, capabilities); - return EFI_EXIT(EFI_DEVICE_ERROR); + return EFI_EXIT(EFI_UNSUPPORTED); #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 + * + * 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_EFI_SET_TIME + efi_status_t ret = EFI_SUCCESS; + struct rtc_time tm; + struct udevice *dev; + + EFI_ENTRY("%p", time); + + if (efi_validate_time(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_ADJUST_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 +346,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; @@ -290,6 +383,9 @@ static const struct efi_runtime_detach_list_struct efi_runtime_detach_list[] = { .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, .patchto = NULL, @@ -697,7 +793,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, |