|
@@ -24,10 +24,6 @@
|
|
|
#include <linux/efi.h>
|
|
|
|
|
|
#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]
|
|
@@ -38,31 +34,24 @@ 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, 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 < EFI_RTC_EPOCH) {
|
|
|
- pr_err("EFI year < " __stringify(EFI_RTC_EPOCH) ", 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
|
|
@@ -103,16 +92,16 @@ convert_from_efi_time(efi_time_t *eft, struct rtc_time *wtime)
|
|
|
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 (wtime->tm_wday < 0)
|
|
|
+ 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:
|