diff options
author | Pete Batard <pete@akeo.ie> | 2019-02-25 23:52:02 +0000 |
---|---|---|
committer | Ard Biesheuvel <ard.biesheuvel@linaro.org> | 2019-02-26 08:32:37 +0100 |
commit | 1342d7679e10b45f0702679b521513804205cdaf (patch) | |
tree | fb71ca1ac56371a78836d0e889fedac95a7e6dbe /EmbeddedPkg | |
parent | 9ab4ec5188824170af6b429e5a1c77a2f92fe2d2 (diff) | |
download | edk2-1342d7679e10b45f0702679b521513804205cdaf.tar.gz edk2-1342d7679e10b45f0702679b521513804205cdaf.tar.bz2 edk2-1342d7679e10b45f0702679b521513804205cdaf.zip |
EmbeddedPkg/VirtualRealTimeClockLib: Fix correctness issues
LibGetTime():
- Two variables were used for the epoch, where only one should have been [*].
- Also harmonize variable name to match the one used in LibSetTime.
LibSetTime():
- Address possible underflows if time is set to start of epoch.
- Ensure that time being read does actually match time that was manually
set (plus the time elapsed since), by subtracting number of seconds
since reset.
[*] This fixes a build breakage, since one of these variables was set but
never used, triggering a compiler diagnostic at some optimization levels.
Contributed-under: TianoCore Contribution Agreement 1.1
Signed-off-by: Pete Batard <pete@akeo.ie>
Reviewed-by: Ard Biesheuvel <ard.biesheuvel@linaro.org>
Diffstat (limited to 'EmbeddedPkg')
-rw-r--r-- | EmbeddedPkg/Library/VirtualRealTimeClockLib/VirtualRealTimeClockLib.c | 34 |
1 files changed, 25 insertions, 9 deletions
diff --git a/EmbeddedPkg/Library/VirtualRealTimeClockLib/VirtualRealTimeClockLib.c b/EmbeddedPkg/Library/VirtualRealTimeClockLib/VirtualRealTimeClockLib.c index 4c354730d0..8ad2df90e7 100644 --- a/EmbeddedPkg/Library/VirtualRealTimeClockLib/VirtualRealTimeClockLib.c +++ b/EmbeddedPkg/Library/VirtualRealTimeClockLib/VirtualRealTimeClockLib.c @@ -54,13 +54,12 @@ LibGetTime ( )
{
EFI_STATUS Status;
- UINT32 EpochSeconds;
INT16 TimeZone;
UINT8 Daylight;
UINT64 Freq;
UINT64 Counter;
UINT64 Remainder;
- UINTN ElapsedSeconds;
+ UINTN EpochSeconds;
UINTN Size;
if (Time == NULL) {
@@ -75,13 +74,13 @@ LibGetTime ( // Get the epoch time from non-volatile storage
Size = sizeof (UINTN);
- ElapsedSeconds = 0;
+ EpochSeconds = 0;
Status = EfiGetVariable (
(CHAR16 *)mEpochVariableName,
&gEfiCallerIdGuid,
NULL,
&Size,
- (VOID *)&ElapsedSeconds
+ (VOID *)&EpochSeconds
);
// Fall back to compilation-time epoch if not set
if (EFI_ERROR (Status)) {
@@ -93,7 +92,7 @@ LibGetTime ( // If you are attempting to use this library on such an environment, please
// contact the edk2 mailing list, so we can try to add support for it.
//
- ElapsedSeconds = BUILD_EPOCH;
+ EpochSeconds = BUILD_EPOCH;
DEBUG ((
DEBUG_INFO,
"LibGetTime: %s non volatile variable was not found - Using compilation time epoch.\n",
@@ -101,7 +100,7 @@ LibGetTime ( ));
}
Counter = GetPerformanceCounter ();
- ElapsedSeconds += DivU64x64Remainder (Counter, Freq, &Remainder);
+ EpochSeconds += DivU64x64Remainder (Counter, Freq, &Remainder);
// Get the current time zone information from non-volatile storage
Size = sizeof (TimeZone);
@@ -204,7 +203,7 @@ LibGetTime ( }
}
- EpochToEfiTime (ElapsedSeconds, Time);
+ EpochToEfiTime (EpochSeconds, Time);
// Because we use the performance counter, we can fill the Nanosecond attribute
// provided that the remainder doesn't overflow 64-bit during multiplication.
@@ -240,6 +239,9 @@ LibSetTime ( )
{
EFI_STATUS Status;
+ UINT64 Freq;
+ UINT64 Counter;
+ UINT64 Remainder;
UINTN EpochSeconds;
if (!IsTimeValid (Time)) {
@@ -249,16 +251,30 @@ LibSetTime ( EpochSeconds = EfiTimeToEpoch (Time);
// Adjust for the correct time zone, i.e. convert to UTC time zone
- if (Time->TimeZone != EFI_UNSPECIFIED_TIMEZONE) {
+ if ((Time->TimeZone != EFI_UNSPECIFIED_TIMEZONE)
+ && (EpochSeconds > Time->TimeZone * SEC_PER_MIN)) {
EpochSeconds -= Time->TimeZone * SEC_PER_MIN;
}
// Adjust for the correct period
- if ((Time->Daylight & EFI_TIME_IN_DAYLIGHT) == EFI_TIME_IN_DAYLIGHT) {
+ if (((Time->Daylight & EFI_TIME_IN_DAYLIGHT) == EFI_TIME_IN_DAYLIGHT)
+ && (EpochSeconds > SEC_PER_HOUR)) {
// Convert to un-adjusted time, i.e. fall back one hour
EpochSeconds -= SEC_PER_HOUR;
}
+ // Use the performance counter to subtract the number of seconds
+ // since platform reset. Without this, setting time from the shell
+ // and immediately reading it back would result in a forward time
+ // offset, of the duration during which the platform has been up.
+ Freq = GetPerformanceCounterProperties (NULL, NULL);
+ if (Freq != 0) {
+ Counter = GetPerformanceCounter ();
+ if (EpochSeconds > DivU64x64Remainder (Counter, Freq, &Remainder)) {
+ EpochSeconds -= DivU64x64Remainder (Counter, Freq, &Remainder);
+ }
+ }
+
// Save the current time zone information into non-volatile storage
Status = EfiSetVariable (
(CHAR16 *)mTimeZoneVariableName,
|