Skip to content

Commit 2839fed

Browse files
chenlin3mergify[bot]
authored andcommitted
PcAtChipsetPkg: Write RTC time in PcRtcInit() only when it is needed
In PcRtcInit(), it always read RTC time and then write it back. It could potentially cause two issues: 1) There is time gap between read RTC and write RTC, writing RTC time on every boot could cause RTC time drift after many reboot cycles 2) Writing RTC registers on every boot could cause some unnecessary delay, slightly impact the boot performance. The change is only writing RTC time when 1) the current RTC time is not valid or 2) the RegisterB value is changed. Signed-off-by: Chen Lin Z <lin.z.chen@intel.com>
1 parent df6b43f commit 2839fed

File tree

1 file changed

+81
-37
lines changed
  • PcAtChipsetPkg/PcatRealTimeClockRuntimeDxe

1 file changed

+81
-37
lines changed

PcAtChipsetPkg/PcatRealTimeClockRuntimeDxe/PcRtc.c

Lines changed: 81 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -188,6 +188,67 @@ RtcWrite (
188188
}
189189
}
190190

191+
/**
192+
Sets the current local timezone & daylight information.
193+
194+
@param TimeZone Timezone info.
195+
@param Daylight Daylight info.
196+
@param Global For global use inside this module.
197+
198+
@retval EFI_SUCCESS The operation completed successfully.
199+
@retval EFI_DEVICE_ERROR The variable could not be set due due to hardware error.
200+
201+
**/
202+
EFI_STATUS
203+
PcRtcSetTimeZone (
204+
IN INT16 TimeZone,
205+
IN UINT8 Daylight,
206+
IN PC_RTC_MODULE_GLOBALS *Global
207+
)
208+
{
209+
EFI_STATUS Status;
210+
UINT32 TimerVar;
211+
212+
ASSERT ((TimeZone == EFI_UNSPECIFIED_TIMEZONE) || ((TimeZone >= -1440) && (TimeZone <= 1440)));
213+
ASSERT ((Daylight & (~(EFI_TIME_ADJUST_DAYLIGHT | EFI_TIME_IN_DAYLIGHT))) == 0);
214+
215+
//
216+
// Write timezone and daylight to RTC variable
217+
//
218+
if ((TimeZone == EFI_UNSPECIFIED_TIMEZONE) && (Daylight == 0)) {
219+
Status = EfiSetVariable (
220+
mTimeZoneVariableName,
221+
&gEfiCallerIdGuid,
222+
0,
223+
0,
224+
NULL
225+
);
226+
if (Status == EFI_NOT_FOUND) {
227+
Status = EFI_SUCCESS;
228+
}
229+
} else {
230+
TimerVar = Daylight;
231+
TimerVar = (UINT32)((TimerVar << 16) | (UINT16)(TimeZone));
232+
Status = EfiSetVariable (
233+
mTimeZoneVariableName,
234+
&gEfiCallerIdGuid,
235+
EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_NON_VOLATILE,
236+
sizeof (TimerVar),
237+
&TimerVar
238+
);
239+
}
240+
241+
//
242+
// Set the variable that contains the TimeZone and Daylight fields
243+
//
244+
if (!EFI_ERROR (Status)) {
245+
Global->SavedTimeZone = TimeZone;
246+
Global->Daylight = Daylight;
247+
}
248+
249+
return Status;
250+
}
251+
191252
/**
192253
Initialize RTC.
193254
@@ -211,6 +272,9 @@ PcRtcInit (
211272
UINT32 TimerVar;
212273
BOOLEAN Enabled;
213274
BOOLEAN Pending;
275+
BOOLEAN NeedRtcUpdate;
276+
277+
NeedRtcUpdate = FALSE;
214278

215279
//
216280
// Acquire RTC Lock to make access to RTC atomic
@@ -324,21 +388,32 @@ PcRtcInit (
324388
Time.Nanosecond = 0;
325389
Time.TimeZone = EFI_UNSPECIFIED_TIMEZONE;
326390
Time.Daylight = 0;
391+
NeedRtcUpdate = TRUE;
327392
}
328393

329394
//
330395
// Set RTC configuration after get original time
331396
// The value of bit AIE should be reserved.
332397
//
333-
RegisterB.Data = FixedPcdGet8 (PcdInitialValueRtcRegisterB) | (RegisterB.Data & BIT5);
334-
RtcWrite (RTC_ADDRESS_REGISTER_B, RegisterB.Data);
398+
if ((RegisterB.Data | BIT5) != (FixedPcdGet8 (PcdInitialValueRtcRegisterB) | BIT5)) {
399+
RegisterB.Data = FixedPcdGet8 (PcdInitialValueRtcRegisterB) | (RegisterB.Data & BIT5);
400+
RtcWrite (RTC_ADDRESS_REGISTER_B, RegisterB.Data);
401+
NeedRtcUpdate = TRUE;
402+
}
335403

336404
//
337405
// Reset time value according to new RTC configuration
338406
//
339-
Status = PcRtcSetTime (&Time, Global);
340-
if (EFI_ERROR (Status)) {
341-
return EFI_DEVICE_ERROR;
407+
if (NeedRtcUpdate) {
408+
Status = PcRtcSetTime (&Time, Global);
409+
if (EFI_ERROR (Status)) {
410+
return EFI_DEVICE_ERROR;
411+
}
412+
} else {
413+
Status = PcRtcSetTimeZone (Time.TimeZone, Time.Daylight, Global);
414+
if (EFI_ERROR (Status)) {
415+
return EFI_DEVICE_ERROR;
416+
}
342417
}
343418

344419
//
@@ -563,7 +638,6 @@ PcRtcSetTime (
563638
EFI_TIME RtcTime;
564639
RTC_REGISTER_A RegisterA;
565640
RTC_REGISTER_B RegisterB;
566-
UINT32 TimerVar;
567641

568642
if (Time == NULL) {
569643
return EFI_INVALID_PARAMETER;
@@ -598,31 +672,7 @@ PcRtcSetTime (
598672
return Status;
599673
}
600674

601-
//
602-
// Write timezone and daylight to RTC variable
603-
//
604-
if ((Time->TimeZone == EFI_UNSPECIFIED_TIMEZONE) && (Time->Daylight == 0)) {
605-
Status = EfiSetVariable (
606-
mTimeZoneVariableName,
607-
&gEfiCallerIdGuid,
608-
0,
609-
0,
610-
NULL
611-
);
612-
if (Status == EFI_NOT_FOUND) {
613-
Status = EFI_SUCCESS;
614-
}
615-
} else {
616-
TimerVar = Time->Daylight;
617-
TimerVar = (UINT32)((TimerVar << 16) | (UINT16)(Time->TimeZone));
618-
Status = EfiSetVariable (
619-
mTimeZoneVariableName,
620-
&gEfiCallerIdGuid,
621-
EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_NON_VOLATILE,
622-
sizeof (TimerVar),
623-
&TimerVar
624-
);
625-
}
675+
Status = PcRtcSetTimeZone (Time->TimeZone, Time->Daylight, Global);
626676

627677
if (EFI_ERROR (Status)) {
628678
if (!EfiAtRuntime ()) {
@@ -677,12 +727,6 @@ PcRtcSetTime (
677727
EfiReleaseLock (&Global->RtcLock);
678728
}
679729

680-
//
681-
// Set the variable that contains the TimeZone and Daylight fields
682-
//
683-
Global->SavedTimeZone = Time->TimeZone;
684-
Global->Daylight = Time->Daylight;
685-
686730
return EFI_SUCCESS;
687731
}
688732

0 commit comments

Comments
 (0)