mirror of
https://github.com/tianocore/edk2
synced 2026-08-27 00:23:19 -04:00
GetTime()/GetWakeupTime() wait for the RTC Update-In-Progress (UIP) bit to clear, then read the time/date registers (offsets 0-9) back to back. A clear UIP bit only guarantees a documented minimum before the next update cycle begins, not that the whole read fits inside it. Where a single RTC access is slow the read overruns that window and picks up undefined data from registers the update cycle has disconnected from the bus; the corrupted field fails the range check and GetTime() returns EFI_DEVICE_ERROR, which intermittently fails OS boot and resume. Read the registers through RtcReadTimeDateOrFail(), which samples the Seconds register before the read and requires both UIP still clear and Seconds unchanged afterwards. The update cycle is specified to increment the stored time, so Seconds changes if and only if an update occurred, which detects a collision anywhere inside the read. RtcReadRegistersSafe() drives that with at most one retry and copies out only on success. The full reasoning, including why one retry is enough, is documented at those two functions. The four read paths (GetTime, Init, GetWakeupTime, SetWakeupTime disable-alarm) use the helper; write paths already inhibit updates via the Register B SET bit and are unchanged. The helper enters its own update-free window, so the up-front RtcWaitToUpdate() in PcRtcGetTime() and in the PcRtcInit() read path is now redundant and is removed. Signed-off-by: James Lu <james.lu@intel.com> |
||
|---|---|---|
| .. | ||
| Bus/Pci/IdeControllerDxe | ||
| HpetTimerDxe | ||
| Include | ||
| Library | ||
| PcatRealTimeClockRuntimeDxe | ||
| PcAtChipsetPkg.ci.yaml | ||
| PcAtChipsetPkg.dec | ||
| PcAtChipsetPkg.dsc | ||
| PcAtChipsetPkg.uni | ||
| PcAtChipsetPkgExtra.uni | ||