)\r
{\r
EFI_STATUS Status;\r
- UINT32 EpochSeconds;\r
INT16 TimeZone;\r
UINT8 Daylight;\r
UINT64 Freq;\r
UINT64 Counter;\r
UINT64 Remainder;\r
- UINTN ElapsedSeconds;\r
+ UINTN EpochSeconds;\r
UINTN Size;\r
\r
if (Time == NULL) {\r
\r
// Get the epoch time from non-volatile storage\r
Size = sizeof (UINTN);\r
- ElapsedSeconds = 0;\r
+ EpochSeconds = 0;\r
Status = EfiGetVariable (\r
(CHAR16 *)mEpochVariableName,\r
&gEfiCallerIdGuid,\r
NULL,\r
&Size,\r
- (VOID *)&ElapsedSeconds\r
+ (VOID *)&EpochSeconds\r
);\r
// Fall back to compilation-time epoch if not set\r
if (EFI_ERROR (Status)) {\r
// If you are attempting to use this library on such an environment, please\r
// contact the edk2 mailing list, so we can try to add support for it.\r
//\r
- ElapsedSeconds = BUILD_EPOCH;\r
+ EpochSeconds = BUILD_EPOCH;\r
DEBUG ((\r
DEBUG_INFO,\r
"LibGetTime: %s non volatile variable was not found - Using compilation time epoch.\n",\r
));\r
}\r
Counter = GetPerformanceCounter ();\r
- ElapsedSeconds += DivU64x64Remainder (Counter, Freq, &Remainder);\r
+ EpochSeconds += DivU64x64Remainder (Counter, Freq, &Remainder);\r
\r
// Get the current time zone information from non-volatile storage\r
Size = sizeof (TimeZone);\r
}\r
}\r
\r
- EpochToEfiTime (ElapsedSeconds, Time);\r
+ EpochToEfiTime (EpochSeconds, Time);\r
\r
// Because we use the performance counter, we can fill the Nanosecond attribute\r
// provided that the remainder doesn't overflow 64-bit during multiplication.\r
)\r
{\r
EFI_STATUS Status;\r
+ UINT64 Freq;\r
+ UINT64 Counter;\r
+ UINT64 Remainder;\r
UINTN EpochSeconds;\r
\r
if (!IsTimeValid (Time)) {\r
EpochSeconds = EfiTimeToEpoch (Time);\r
\r
// Adjust for the correct time zone, i.e. convert to UTC time zone\r
- if (Time->TimeZone != EFI_UNSPECIFIED_TIMEZONE) {\r
+ if ((Time->TimeZone != EFI_UNSPECIFIED_TIMEZONE)\r
+ && (EpochSeconds > Time->TimeZone * SEC_PER_MIN)) {\r
EpochSeconds -= Time->TimeZone * SEC_PER_MIN;\r
}\r
\r
// Adjust for the correct period\r
- if ((Time->Daylight & EFI_TIME_IN_DAYLIGHT) == EFI_TIME_IN_DAYLIGHT) {\r
+ if (((Time->Daylight & EFI_TIME_IN_DAYLIGHT) == EFI_TIME_IN_DAYLIGHT)\r
+ && (EpochSeconds > SEC_PER_HOUR)) {\r
// Convert to un-adjusted time, i.e. fall back one hour\r
EpochSeconds -= SEC_PER_HOUR;\r
}\r
\r
+ // Use the performance counter to subtract the number of seconds\r
+ // since platform reset. Without this, setting time from the shell\r
+ // and immediately reading it back would result in a forward time\r
+ // offset, of the duration during which the platform has been up.\r
+ Freq = GetPerformanceCounterProperties (NULL, NULL);\r
+ if (Freq != 0) {\r
+ Counter = GetPerformanceCounter ();\r
+ if (EpochSeconds > DivU64x64Remainder (Counter, Freq, &Remainder)) {\r
+ EpochSeconds -= DivU64x64Remainder (Counter, Freq, &Remainder);\r
+ }\r
+ }\r
+\r
// Save the current time zone information into non-volatile storage\r
Status = EfiSetVariable (\r
(CHAR16 *)mTimeZoneVariableName,\r