--- zzzz-none-000/linux-3.10.107/drivers/rtc/rtc-efi.c 2017-06-27 09:49:32.000000000 +0000 +++ scorpion-7490-727/linux-3.10.107/drivers/rtc/rtc-efi.c 2021-02-04 17:41:59.000000000 +0000 @@ -3,7 +3,7 @@ * * Copyright (C) 2009 Hewlett-Packard Development Company, L.P. * - * Author: dann frazier + * Author: dann frazier * Based on efirtc.c by Stephane Eranian * * This program is free software; you can redistribute it and/or modify it @@ -17,16 +17,13 @@ #include #include +#include #include #include #include #include #define EFI_ISDST (EFI_TIME_ADJUST_DAYLIGHT|EFI_TIME_IN_DAYLIGHT) -/* - * EFI Epoch is 1/1/1998 - */ -#define EFI_RTC_EPOCH 1998 /* * returns day of the year [0-365] @@ -35,33 +32,26 @@ compute_yday(efi_time_t *eft) { /* efi_time_t.month is in the [1-12] so, we need -1 */ - return rtc_year_days(eft->day - 1, eft->month - 1, eft->year); + return rtc_year_days(eft->day, eft->month - 1, eft->year); } + /* * returns day of the week [0-6] 0=Sunday - * - * Don't try to provide a year that's before 1998, please ! */ static int -compute_wday(efi_time_t *eft) +compute_wday(efi_time_t *eft, int yday) { - int y; - int ndays = 0; - - if (eft->year < 1998) { - pr_err("EFI year < 1998, invalid date\n"); - return -1; - } - - for (y = EFI_RTC_EPOCH; y < eft->year; y++) - ndays += 365 + (is_leap_year(y) ? 1 : 0); - - ndays += compute_yday(eft); + int ndays = eft->year * (365 % 7) + + (eft->year - 1) / 4 + - (eft->year - 1) / 100 + + (eft->year - 1) / 400 + + yday; /* - * 4=1/1/1998 was a Thursday + * 1/1/0000 may or may not have been a Sunday (if it ever existed at + * all) but assuming it was makes this calculation work correctly. */ - return (ndays + 4) % 7; + return ndays % 7; } static void @@ -78,23 +68,40 @@ eft->timezone = EFI_UNSPECIFIED_TIMEZONE; } -static void +static bool convert_from_efi_time(efi_time_t *eft, struct rtc_time *wtime) { memset(wtime, 0, sizeof(*wtime)); + + if (eft->second >= 60) + return false; wtime->tm_sec = eft->second; + + if (eft->minute >= 60) + return false; wtime->tm_min = eft->minute; + + if (eft->hour >= 24) + return false; wtime->tm_hour = eft->hour; + + if (!eft->day || eft->day > 31) + return false; wtime->tm_mday = eft->day; + + if (!eft->month || eft->month > 12) + return false; wtime->tm_mon = eft->month - 1; - wtime->tm_year = eft->year - 1900; - /* day of the week [0-6], Sunday=0 */ - wtime->tm_wday = compute_wday(eft); + if (eft->year < 1900 || eft->year > 9999) + return false; + wtime->tm_year = eft->year - 1900; /* day in the year [1-365]*/ wtime->tm_yday = compute_yday(eft); + /* day of the week [0-6], Sunday=0 */ + wtime->tm_wday = compute_wday(eft, wtime->tm_yday); switch (eft->daylight & EFI_ISDST) { case EFI_ISDST: @@ -106,6 +113,8 @@ default: wtime->tm_isdst = -1; } + + return true; } static int efi_read_alarm(struct device *dev, struct rtc_wkalrm *wkalrm) @@ -122,7 +131,8 @@ if (status != EFI_SUCCESS) return -EINVAL; - convert_from_efi_time(&eft, &wkalrm->time); + if (!convert_from_efi_time(&eft, &wkalrm->time)) + return -EIO; return rtc_valid_tm(&wkalrm->time); } @@ -163,7 +173,8 @@ return -EINVAL; } - convert_from_efi_time(&eft, tm); + if (!convert_from_efi_time(&eft, tm)) + return -EIO; return rtc_valid_tm(tm); } @@ -196,26 +207,22 @@ if (IS_ERR(rtc)) return PTR_ERR(rtc); + rtc->uie_unsupported = 1; platform_set_drvdata(dev, rtc); return 0; } -static int __exit efi_rtc_remove(struct platform_device *dev) -{ - return 0; -} - static struct platform_driver efi_rtc_driver = { .driver = { .name = "rtc-efi", - .owner = THIS_MODULE, }, - .remove = __exit_p(efi_rtc_remove), }; module_platform_driver_probe(efi_rtc_driver, efi_rtc_probe); -MODULE_AUTHOR("dann frazier "); +MODULE_ALIAS("platform:rtc-efi"); +MODULE_AUTHOR("dann frazier "); MODULE_LICENSE("GPL"); MODULE_DESCRIPTION("EFI RTC driver"); +MODULE_ALIAS("platform:rtc-efi");