2 RTC Architectural Protocol GUID as defined in DxeCis 0.96.
4 Copyright (c) 2006 - 2007, Intel Corporation
5 All rights reserved. This program and the accompanying materials
6 are licensed and made available under the terms and conditions of the BSD License
7 which accompanies this distribution. The full text of the license may be found at
8 http://opensource.org/licenses/bsd-license.php
10 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
11 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
18 Compare the Hour, Minute and Second of the From time and the To time.
20 Only compare H/M/S in EFI_TIME and ignore other fields here.
22 @param From the first time
23 @param To the second time
25 @return >0 The H/M/S of the From time is later than those of To time
26 @return ==0 The H/M/S of the From time is same as those of To time
27 @return <0 The H/M/S of the From time is earlier than those of To time
36 To check if second date is later than first date within 24 hours.
38 @param From the first date
39 @param To the second date
41 @retval TRUE From is previous to To within 24 hours.
42 @retval FALSE From is later, or it is previous to To more than 24 hours.
51 Read RTC content through its registers.
53 @param Address Address offset of RTC. It is recommended to use macros such as
56 @return The data of UINT8 type read from RTC.
63 IoWrite8 (PCAT_RTC_ADDRESS_REGISTER
, (UINT8
) (Address
| (UINT8
) (IoRead8 (PCAT_RTC_ADDRESS_REGISTER
) & 0x80)));
64 return IoRead8 (PCAT_RTC_DATA_REGISTER
);
68 Write RTC through its registers.
70 @param Address Address offset of RTC. It is recommended to use macros such as
72 @param Data The content you want to write into RTC.
81 IoWrite8 (PCAT_RTC_ADDRESS_REGISTER
, (UINT8
) (Address
| (UINT8
) (IoRead8 (PCAT_RTC_ADDRESS_REGISTER
) & 0x80)));
82 IoWrite8 (PCAT_RTC_DATA_REGISTER
, Data
);
88 @param Global For global use inside this module.
90 @retval EFI_DEVICE_ERROR Initialization failed due to device error.
91 @retval EFI_SUCCESS Initialization successful.
96 IN PC_RTC_MODULE_GLOBALS
*Global
100 RTC_REGISTER_A RegisterA
;
101 RTC_REGISTER_B RegisterB
;
102 RTC_REGISTER_D RegisterD
;
109 // Acquire RTC Lock to make access to RTC atomic
111 //Code here doesn't consider the runtime environment.
112 if (!EfiAtRuntime ()) {
113 EfiAcquireLock (&Global
->RtcLock
);
116 // Initialize RTC Register
118 // Make sure Division Chain is properly configured,
119 // or RTC clock won't "tick" -- time won't increment
121 RegisterA
.Data
= RTC_INIT_REGISTER_A
;
122 RtcWrite (RTC_ADDRESS_REGISTER_A
, RegisterA
.Data
);
127 RegisterB
.Data
= RtcRead (RTC_ADDRESS_REGISTER_B
);
130 // Clear RTC flag register
132 RtcRead (RTC_ADDRESS_REGISTER_C
);
135 // Clear RTC register D
137 RegisterD
.Data
= RTC_INIT_REGISTER_D
;
138 RtcWrite (RTC_ADDRESS_REGISTER_D
, RegisterD
.Data
);
141 // Wait for up to 0.1 seconds for the RTC to be updated
143 Status
= RtcWaitToUpdate (PcdGet32 (PcdRealTimeClockUpdateTimeout
));
144 if (EFI_ERROR (Status
)) {
145 //Code here doesn't consider the runtime environment.
146 if (!EfiAtRuntime ()) {
147 EfiReleaseLock (&Global
->RtcLock
);
149 return EFI_DEVICE_ERROR
;
152 // Get the Time/Date/Daylight Savings values.
154 Time
.Second
= RtcRead (RTC_ADDRESS_SECONDS
);
155 Time
.Minute
= RtcRead (RTC_ADDRESS_MINUTES
);
156 Time
.Hour
= RtcRead (RTC_ADDRESS_HOURS
);
157 Time
.Day
= RtcRead (RTC_ADDRESS_DAY_OF_THE_MONTH
);
158 Time
.Month
= RtcRead (RTC_ADDRESS_MONTH
);
159 Time
.Year
= RtcRead (RTC_ADDRESS_YEAR
);
161 if (RtcTestCenturyRegister () == EFI_SUCCESS
) {
162 Century
= (UINT8
) (RtcRead (RTC_ADDRESS_CENTURY
) & 0x7f);
164 Century
= RtcRead (RTC_ADDRESS_CENTURY
);
168 // Set RTC configuration after get original time
169 // The value of bit AIE should be reserved.
171 RtcWrite (RTC_ADDRESS_REGISTER_B
, (UINT8
)(RTC_INIT_REGISTER_B
| (RegisterB
.Data
& BIT5
)));
176 //Code here doesn't consider the runtime environment.
177 if (!EfiAtRuntime ()) {
178 EfiReleaseLock (&Global
->RtcLock
);
182 // Validate time fields
184 Status
= ConvertRtcTimeToEfiTime (&Time
, Century
, RegisterB
);
185 if (!EFI_ERROR (Status
)) {
186 Status
= RtcTimeFieldsValid (&Time
);
188 if (EFI_ERROR (Status
)) {
189 Time
.Second
= RTC_INIT_SECOND
;
190 Time
.Minute
= RTC_INIT_MINUTE
;
191 Time
.Hour
= RTC_INIT_HOUR
;
192 Time
.Day
= RTC_INIT_DAY
;
193 Time
.Month
= RTC_INIT_MONTH
;
194 Time
.Year
= RTC_INIT_YEAR
;
197 // Get the data of Daylight saving and time zone, if they have been
198 // stored in NV variable during previous boot.
200 DataSize
= sizeof (UINT32
);
201 Status
= EfiGetVariable (
208 if (!EFI_ERROR (Status
)) {
209 Global
->SavedTimeZone
= (INT16
) TimerVar
;
210 Global
->Daylight
= (UINT8
) (TimerVar
>> 16);
212 Time
.TimeZone
= Global
->SavedTimeZone
;
213 Time
.Daylight
= Global
->Daylight
;
216 // Reset time value according to new RTC configuration
218 PcRtcSetTime (&Time
, Global
);
224 Returns the current time and date information, and the time-keeping capabilities
225 of the hardware platform.
227 @param Time A pointer to storage to receive a snapshot of the current time.
228 @param Capabilities An optional pointer to a buffer to receive the real time clock
229 device's capabilities.
230 @param Global For global use inside this module.
232 @retval EFI_SUCCESS The operation completed successfully.
233 @retval EFI_INVALID_PARAMETER Time is NULL.
234 @retval EFI_DEVICE_ERROR The time could not be retrieved due to hardware error.
240 OUT EFI_TIME_CAPABILITIES
*Capabilities
, OPTIONAL
241 IN PC_RTC_MODULE_GLOBALS
*Global
245 RTC_REGISTER_B RegisterB
;
249 // Check parameters for null pointer
252 return EFI_INVALID_PARAMETER
;
256 // Acquire RTC Lock to make access to RTC atomic
258 //Code here doesn't consider the runtime environment.
259 if (!EfiAtRuntime ()) {
260 EfiAcquireLock (&Global
->RtcLock
);
263 // Wait for up to 0.1 seconds for the RTC to be updated
265 Status
= RtcWaitToUpdate (PcdGet32 (PcdRealTimeClockUpdateTimeout
));
266 if (EFI_ERROR (Status
)) {
267 //Code here doesn't consider the runtime environment.
268 if (!EfiAtRuntime ()) {
269 EfiReleaseLock (&Global
->RtcLock
);
276 RegisterB
.Data
= RtcRead (RTC_ADDRESS_REGISTER_B
);
279 // Get the Time/Date/Daylight Savings values.
281 Time
->Second
= RtcRead (RTC_ADDRESS_SECONDS
);
282 Time
->Minute
= RtcRead (RTC_ADDRESS_MINUTES
);
283 Time
->Hour
= RtcRead (RTC_ADDRESS_HOURS
);
284 Time
->Day
= RtcRead (RTC_ADDRESS_DAY_OF_THE_MONTH
);
285 Time
->Month
= RtcRead (RTC_ADDRESS_MONTH
);
286 Time
->Year
= RtcRead (RTC_ADDRESS_YEAR
);
288 if (RtcTestCenturyRegister () == EFI_SUCCESS
) {
289 Century
= (UINT8
) (RtcRead (RTC_ADDRESS_CENTURY
) & 0x7f);
291 Century
= RtcRead (RTC_ADDRESS_CENTURY
);
297 //Code here doesn't consider the runtime environment.
298 if (!EfiAtRuntime ()) {
299 EfiReleaseLock (&Global
->RtcLock
);
302 // Get the variable that contains the TimeZone and Daylight fields
304 Time
->TimeZone
= Global
->SavedTimeZone
;
305 Time
->Daylight
= Global
->Daylight
;
308 // Make sure all field values are in correct range
310 Status
= ConvertRtcTimeToEfiTime (Time
, Century
, RegisterB
);
311 if (!EFI_ERROR (Status
)) {
312 Status
= RtcTimeFieldsValid (Time
);
314 if (EFI_ERROR (Status
)) {
315 return EFI_DEVICE_ERROR
;
318 // Fill in Capabilities if it was passed in
320 if (Capabilities
!= NULL
) {
321 Capabilities
->Resolution
= 1;
325 Capabilities
->Accuracy
= 50000000;
329 Capabilities
->SetsToZero
= FALSE
;
336 Sets the current local time and date information.
338 @param Time A pointer to the current time.
339 @param Global For global use inside this module.
341 @retval EFI_SUCCESS The operation completed successfully.
342 @retval EFI_INVALID_PARAMETER A time field is out of range.
343 @retval EFI_DEVICE_ERROR The time could not be set due due to hardware error.
349 IN PC_RTC_MODULE_GLOBALS
*Global
354 RTC_REGISTER_B RegisterB
;
359 return EFI_INVALID_PARAMETER
;
362 // Make sure that the time fields are valid
364 Status
= RtcTimeFieldsValid (Time
);
365 if (EFI_ERROR (Status
)) {
369 CopyMem (&RtcTime
, Time
, sizeof (EFI_TIME
));
372 // Acquire RTC Lock to make access to RTC atomic
374 //Code here doesn't consider the runtime environment.
375 if (!EfiAtRuntime ()) {
376 EfiAcquireLock (&Global
->RtcLock
);
379 // Wait for up to 0.1 seconds for the RTC to be updated
381 Status
= RtcWaitToUpdate (PcdGet32 (PcdRealTimeClockUpdateTimeout
));
382 if (EFI_ERROR (Status
)) {
383 //Code here doesn't consider the runtime environment.
384 if (!EfiAtRuntime ()) {
385 EfiReleaseLock (&Global
->RtcLock
);
390 // Read Register B, and inhibit updates of the RTC
392 RegisterB
.Data
= RtcRead (RTC_ADDRESS_REGISTER_B
);
393 RegisterB
.Bits
.SET
= 1;
394 RtcWrite (RTC_ADDRESS_REGISTER_B
, RegisterB
.Data
);
396 ConvertEfiTimeToRtcTime (&RtcTime
, RegisterB
, &Century
);
398 RtcWrite (RTC_ADDRESS_SECONDS
, RtcTime
.Second
);
399 RtcWrite (RTC_ADDRESS_MINUTES
, RtcTime
.Minute
);
400 RtcWrite (RTC_ADDRESS_HOURS
, RtcTime
.Hour
);
401 RtcWrite (RTC_ADDRESS_DAY_OF_THE_MONTH
, RtcTime
.Day
);
402 RtcWrite (RTC_ADDRESS_MONTH
, RtcTime
.Month
);
403 RtcWrite (RTC_ADDRESS_YEAR
, (UINT8
) RtcTime
.Year
);
404 if (RtcTestCenturyRegister () == EFI_SUCCESS
) {
405 Century
= (UINT8
) ((Century
& 0x7f) | (RtcRead (RTC_ADDRESS_CENTURY
) & 0x80));
408 RtcWrite (RTC_ADDRESS_CENTURY
, Century
);
411 // Allow updates of the RTC registers
413 RegisterB
.Bits
.SET
= 0;
414 RtcWrite (RTC_ADDRESS_REGISTER_B
, RegisterB
.Data
);
419 //Code here doesn't consider the runtime environment.
420 if (!EfiAtRuntime ()) {
421 EfiReleaseLock (&Global
->RtcLock
);
424 // Set the variable that contains the TimeZone and Daylight fields
426 Global
->SavedTimeZone
= Time
->TimeZone
;
427 Global
->Daylight
= Time
->Daylight
;
429 TimerVar
= Time
->Daylight
;
430 TimerVar
= (UINT32
) ((TimerVar
<< 16) | Time
->TimeZone
);
431 Status
= EfiSetVariable (
434 EFI_VARIABLE_BOOTSERVICE_ACCESS
| EFI_VARIABLE_RUNTIME_ACCESS
| EFI_VARIABLE_NON_VOLATILE
,
438 ASSERT_EFI_ERROR (Status
);
444 Returns the current wakeup alarm clock setting.
446 @param Enabled Indicates if the alarm is currently enabled or disabled.
447 @param Pending Indicates if the alarm signal is pending and requires acknowledgment.
448 @param Time The current alarm setting.
449 @param Global For global use inside this module.
451 @retval EFI_SUCCESS The alarm settings were returned.
452 @retval EFI_INVALID_PARAMETER Enabled is NULL.
453 @retval EFI_INVALID_PARAMETER Pending is NULL.
454 @retval EFI_INVALID_PARAMETER Time is NULL.
455 @retval EFI_DEVICE_ERROR The wakeup time could not be retrieved due to a hardware error.
456 @retval EFI_UNSUPPORTED A wakeup timer is not supported on this platform.
461 OUT BOOLEAN
*Enabled
,
462 OUT BOOLEAN
*Pending
,
464 IN PC_RTC_MODULE_GLOBALS
*Global
468 RTC_REGISTER_B RegisterB
;
469 RTC_REGISTER_C RegisterC
;
473 // Check parameters for null pointers
475 if ((Enabled
== NULL
) || (Pending
== NULL
) || (Time
== NULL
)) {
476 return EFI_INVALID_PARAMETER
;
480 // Acquire RTC Lock to make access to RTC atomic
482 //Code here doesn't consider the runtime environment.
483 if (!EfiAtRuntime ()) {
484 EfiAcquireLock (&Global
->RtcLock
);
487 // Wait for up to 0.1 seconds for the RTC to be updated
489 Status
= RtcWaitToUpdate (PcdGet32 (PcdRealTimeClockUpdateTimeout
));
490 if (EFI_ERROR (Status
)) {
491 //Code here doesn't consider the runtime environment.
492 if (!EfiAtRuntime ()) {
493 EfiReleaseLock (&Global
->RtcLock
);
495 return EFI_DEVICE_ERROR
;
498 // Read Register B and Register C
500 RegisterB
.Data
= RtcRead (RTC_ADDRESS_REGISTER_B
);
501 RegisterC
.Data
= RtcRead (RTC_ADDRESS_REGISTER_C
);
504 // Get the Time/Date/Daylight Savings values.
506 *Enabled
= RegisterB
.Bits
.AIE
;
508 Time
->Second
= RtcRead (RTC_ADDRESS_SECONDS_ALARM
);
509 Time
->Minute
= RtcRead (RTC_ADDRESS_MINUTES_ALARM
);
510 Time
->Hour
= RtcRead (RTC_ADDRESS_HOURS_ALARM
);
511 Time
->Day
= RtcRead (RTC_ADDRESS_DAY_OF_THE_MONTH
);
512 Time
->Month
= RtcRead (RTC_ADDRESS_MONTH
);
513 Time
->Year
= RtcRead (RTC_ADDRESS_YEAR
);
518 Time
->Day
= RtcRead (RTC_ADDRESS_DAY_OF_THE_MONTH
);
519 Time
->Month
= RtcRead (RTC_ADDRESS_MONTH
);
520 Time
->Year
= RtcRead (RTC_ADDRESS_YEAR
);
523 if (RtcTestCenturyRegister () == EFI_SUCCESS
) {
524 Century
= (UINT8
) (RtcRead (RTC_ADDRESS_CENTURY
) & 0x7f);
526 Century
= RtcRead (RTC_ADDRESS_CENTURY
);
532 //Code here doesn't consider the runtime environment.
533 if (!EfiAtRuntime ()) {
534 EfiReleaseLock (&Global
->RtcLock
);
537 // Make sure all field values are in correct range
539 Status
= ConvertRtcTimeToEfiTime (Time
, Century
, RegisterB
);
540 if (!EFI_ERROR (Status
)) {
541 Status
= RtcTimeFieldsValid (Time
);
543 if (EFI_ERROR (Status
)) {
544 return EFI_DEVICE_ERROR
;
547 *Pending
= RegisterC
.Bits
.AF
;
553 Sets the system wakeup alarm clock time.
555 @param Enabled Enable or disable the wakeup alarm.
556 @param Time If Enable is TRUE, the time to set the wakeup alarm for.
557 If Enable is FALSE, then this parameter is optional, and may be NULL.
558 @param Global For global use inside this module.
560 @retval EFI_SUCCESS If Enable is TRUE, then the wakeup alarm was enabled.
561 If Enable is FALSE, then the wakeup alarm was disabled.
562 @retval EFI_INVALID_PARAMETER A time field is out of range.
563 @retval EFI_DEVICE_ERROR The wakeup time could not be set due to a hardware error.
564 @retval EFI_UNSUPPORTED A wakeup timer is not supported on this platform.
570 IN EFI_TIME
*Time
, OPTIONAL
571 IN PC_RTC_MODULE_GLOBALS
*Global
576 RTC_REGISTER_B RegisterB
;
578 EFI_TIME_CAPABILITIES Capabilities
;
583 return EFI_INVALID_PARAMETER
;
586 // Make sure that the time fields are valid
588 Status
= RtcTimeFieldsValid (Time
);
589 if (EFI_ERROR (Status
)) {
590 return EFI_INVALID_PARAMETER
;
593 // Just support set alarm time within 24 hours
595 PcRtcGetTime (&RtcTime
, &Capabilities
, Global
);
596 Status
= RtcTimeFieldsValid (&RtcTime
);
597 if (EFI_ERROR (Status
)) {
598 return EFI_DEVICE_ERROR
;
600 if (!IsWithinOneDay (&RtcTime
, Time
)) {
601 return EFI_UNSUPPORTED
;
604 // Make a local copy of the time and date
606 CopyMem (&RtcTime
, Time
, sizeof (EFI_TIME
));
610 // Acquire RTC Lock to make access to RTC atomic
612 //Code here doesn't consider the runtime environment.
613 if (!EfiAtRuntime ()) {
614 EfiAcquireLock (&Global
->RtcLock
);
617 // Wait for up to 0.1 seconds for the RTC to be updated
619 Status
= RtcWaitToUpdate (PcdGet32 (PcdRealTimeClockUpdateTimeout
));
620 if (EFI_ERROR (Status
)) {
621 //Code here doesn't consider the runtime environment.
622 if (!EfiAtRuntime ()) {
623 EfiReleaseLock (&Global
->RtcLock
);
625 return EFI_DEVICE_ERROR
;
628 // Read Register B, and inhibit updates of the RTC
630 RegisterB
.Data
= RtcRead (RTC_ADDRESS_REGISTER_B
);
632 RegisterB
.Bits
.SET
= 1;
633 RtcWrite (RTC_ADDRESS_REGISTER_B
, RegisterB
.Data
);
636 ConvertEfiTimeToRtcTime (&RtcTime
, RegisterB
, &Century
);
639 // Set RTC alarm time
641 RtcWrite (RTC_ADDRESS_SECONDS_ALARM
, RtcTime
.Second
);
642 RtcWrite (RTC_ADDRESS_MINUTES_ALARM
, RtcTime
.Minute
);
643 RtcWrite (RTC_ADDRESS_HOURS_ALARM
, RtcTime
.Hour
);
645 RegisterB
.Bits
.AIE
= 1;
648 RegisterB
.Bits
.AIE
= 0;
651 // Allow updates of the RTC registers
653 RegisterB
.Bits
.SET
= 0;
654 RtcWrite (RTC_ADDRESS_REGISTER_B
, RegisterB
.Data
);
659 //Code here doesn't consider the runtime environment.
660 if (!EfiAtRuntime ()) {
661 EfiReleaseLock (&Global
->RtcLock
);
667 See if century register of RTC is valid.
669 @retval EFI_SUCCESS Century register is valid.
670 @retval EFI_DEVICE_ERROR Century register is NOT valid.
673 RtcTestCenturyRegister (
680 Century
= RtcRead (RTC_ADDRESS_CENTURY
);
681 Temp
= (UINT8
) (RtcRead (RTC_ADDRESS_CENTURY
) & 0x7f);
682 RtcWrite (RTC_ADDRESS_CENTURY
, Century
);
683 if (Temp
== 0x19 || Temp
== 0x20) {
687 return EFI_DEVICE_ERROR
;
691 Checks an 8-bit BCD value, and converts to an 8-bit value if valid.
693 This function checks the 8-bit BCD value specified by Value.
694 If valid, the function converts it to an 8-bit value and returns it.
695 Otherwise, return 0xff.
697 @param Value The 8-bit BCD value to check and convert
699 @return The 8-bit value converted. Or 0xff if Value is invalid.
703 CheckAndConvertBcd8ToDecimal8 (
707 if ((Value
< 0xa0) && ((Value
& 0xf) < 0xa)) {
708 return BcdToDecimal8 (Value
);
715 Converts time read from RTC to EFI_TIME format defined by UEFI spec.
717 This function converts raw time data read from RTC to the EFI_TIME format
718 defined by UEFI spec.
719 If data mode of RTC is BCD, then converts it to decimal,
720 If RTC is in 12-hour format, then converts it to 24-hour format.
722 @param Time On input, the time data read from RTC to convert
723 On output, the time converted to UEFI format
724 @param Century Value of century read from RTC.
725 @param RegisterB Value of Register B of RTC, indicating data mode
728 @retval EFI_INVALID_PARAMETER Parameters passed in are invalid.
729 @retval EFI_SUCCESS Convert RTC time to EFI time successfully.
733 ConvertRtcTimeToEfiTime (
734 IN OUT EFI_TIME
*Time
,
736 IN RTC_REGISTER_B RegisterB
741 if ((Time
->Hour
& 0x80) != 0) {
747 Time
->Hour
= (UINT8
) (Time
->Hour
& 0x7f);
749 if (RegisterB
.Bits
.DM
== 0) {
750 Time
->Year
= CheckAndConvertBcd8ToDecimal8 ((UINT8
) Time
->Year
);
751 Time
->Month
= CheckAndConvertBcd8ToDecimal8 (Time
->Month
);
752 Time
->Day
= CheckAndConvertBcd8ToDecimal8 (Time
->Day
);
753 Time
->Hour
= CheckAndConvertBcd8ToDecimal8 (Time
->Hour
);
754 Time
->Minute
= CheckAndConvertBcd8ToDecimal8 (Time
->Minute
);
755 Time
->Second
= CheckAndConvertBcd8ToDecimal8 (Time
->Second
);
756 Century
= CheckAndConvertBcd8ToDecimal8 (Century
);
759 if (Time
->Year
== 0xff || Time
->Month
== 0xff || Time
->Day
== 0xff ||
760 Time
->Hour
== 0xff || Time
->Minute
== 0xff || Time
->Second
== 0xff ||
762 return EFI_INVALID_PARAMETER
;
765 Time
->Year
= (UINT16
) (Century
* 100 + Time
->Year
);
768 // If time is in 12 hour format, convert it to 24 hour format
770 if (RegisterB
.Bits
.MIL
== 0) {
771 if (IsPM
&& Time
->Hour
< 12) {
772 Time
->Hour
= (UINT8
) (Time
->Hour
+ 12);
775 if (!IsPM
&& Time
->Hour
== 12) {
780 Time
->Nanosecond
= 0;
781 Time
->TimeZone
= EFI_UNSPECIFIED_TIMEZONE
;
788 Wait for a period for the RTC to be ready.
790 @param Timeout Tell how long it should take to wait.
792 @retval EFI_DEVICE_ERROR RTC device error.
793 @retval EFI_SUCCESS RTC is updated and ready.
800 RTC_REGISTER_A RegisterA
;
801 RTC_REGISTER_D RegisterD
;
804 // See if the RTC is functioning correctly
806 RegisterD
.Data
= RtcRead (RTC_ADDRESS_REGISTER_D
);
808 if (RegisterD
.Bits
.VRT
== 0) {
809 return EFI_DEVICE_ERROR
;
812 // Wait for up to 0.1 seconds for the RTC to be ready.
814 Timeout
= (Timeout
/ 10) + 1;
815 RegisterA
.Data
= RtcRead (RTC_ADDRESS_REGISTER_A
);
816 while (RegisterA
.Bits
.UIP
== 1 && Timeout
> 0) {
817 MicroSecondDelay (10);
818 RegisterA
.Data
= RtcRead (RTC_ADDRESS_REGISTER_A
);
822 RegisterD
.Data
= RtcRead (RTC_ADDRESS_REGISTER_D
);
823 if (Timeout
== 0 || RegisterD
.Bits
.VRT
== 0) {
824 return EFI_DEVICE_ERROR
;
831 See if all fields of a variable of EFI_TIME type is correct.
833 @param Time The time to be checked.
835 @retval EFI_INVALID_PARAMETER Some fields of Time are not correct.
836 @retval EFI_SUCCESS Time is a valid EFI_TIME variable.
844 if (Time
->Year
< 1998 ||
851 Time
->Nanosecond
> 999999999 ||
852 (!(Time
->TimeZone
== EFI_UNSPECIFIED_TIMEZONE
|| (Time
->TimeZone
>= -1440 && Time
->TimeZone
<= 1440))) ||
853 ((Time
->Daylight
& (~(EFI_TIME_ADJUST_DAYLIGHT
| EFI_TIME_IN_DAYLIGHT
))) != 0)
855 if (!DayValid (Time
)) {
856 return EFI_INVALID_PARAMETER
;
864 See if field Day of an EFI_TIME is correct.
866 @param Time Its Day field is to be checked.
868 @retval TRUE Day field of Time is correct.
869 @retval FALSE Day field of Time is NOT correct.
892 // The validity of Time->Month field should be checked before
894 ASSERT (Time
->Month
>=1);
895 ASSERT (Time
->Month
<=12);
897 Time
->Day
> DayOfMonth
[Time
->Month
- 1] ||
898 (Time
->Month
== 2 && (!IsLeapYear (Time
) && Time
->Day
> 28))
907 Check if it is a leap year.
909 @param Time The time to be checked.
911 @retval TRUE It is a leap year.
912 @retval FALSE It is NOT a leap year.
919 if (Time
->Year
% 4 == 0) {
920 if (Time
->Year
% 100 == 0) {
921 if (Time
->Year
% 400 == 0) {
935 Converts time from EFI_TIME format defined by UEFI spec to RTC's.
937 This function converts time from EFI_TIME format defined by UEFI spec to RTC's.
938 If data mode of RTC is BCD, then converts EFI_TIME to it.
939 If RTC is in 12-hour format, then converts EFI_TIME to it.
941 @param Time On input, the time data read from UEFI to convert
942 On output, the time converted to RTC format
943 @param RegisterB Value of Register B of RTC, indicating data mode
944 @param Century It is set according to EFI_TIME Time.
948 ConvertEfiTimeToRtcTime (
949 IN OUT EFI_TIME
*Time
,
950 IN RTC_REGISTER_B RegisterB
,
958 // Adjust hour field if RTC is in 12 hour mode
960 if (RegisterB
.Bits
.MIL
== 0) {
961 if (Time
->Hour
< 12) {
965 if (Time
->Hour
>= 13) {
966 Time
->Hour
= (UINT8
) (Time
->Hour
- 12);
967 } else if (Time
->Hour
== 0) {
972 // Set the Time/Date/Daylight Savings values.
974 *Century
= DecimalToBcd8 ((UINT8
) (Time
->Year
/ 100));
976 Time
->Year
= (UINT16
) (Time
->Year
% 100);
978 if (RegisterB
.Bits
.DM
== 0) {
979 Time
->Year
= DecimalToBcd8 ((UINT8
) Time
->Year
);
980 Time
->Month
= DecimalToBcd8 (Time
->Month
);
981 Time
->Day
= DecimalToBcd8 (Time
->Day
);
982 Time
->Hour
= DecimalToBcd8 (Time
->Hour
);
983 Time
->Minute
= DecimalToBcd8 (Time
->Minute
);
984 Time
->Second
= DecimalToBcd8 (Time
->Second
);
987 // If we are in 12 hour mode and PM is set, then set bit 7 of the Hour field.
989 if (RegisterB
.Bits
.MIL
== 0 && IsPM
) {
990 Time
->Hour
= (UINT8
) (Time
->Hour
| 0x80);
995 Compare the Hour, Minute and Second of the From time and the To time.
997 Only compare H/M/S in EFI_TIME and ignore other fields here.
999 @param From the first time
1000 @param To the second time
1002 @return >0 The H/M/S of the From time is later than those of To time
1003 @return ==0 The H/M/S of the From time is same as those of To time
1004 @return <0 The H/M/S of the From time is earlier than those of To time
1012 if ((From
->Hour
> To
->Hour
) ||
1013 ((From
->Hour
== To
->Hour
) && (From
->Minute
> To
->Minute
)) ||
1014 ((From
->Hour
== To
->Hour
) && (From
->Minute
== To
->Minute
) && (From
->Second
> To
->Second
))) {
1016 } else if ((From
->Hour
== To
->Hour
) && (From
->Minute
== To
->Minute
) && (From
->Second
== To
->Second
)) {
1024 To check if second date is later than first date within 24 hours.
1026 @param From the first date
1027 @param To the second date
1029 @retval TRUE From is previous to To within 24 hours.
1030 @retval FALSE From is later, or it is previous to To more than 24 hours.
1038 UINT8 DayOfMonth
[12];
1051 DayOfMonth
[10] = 30;
1052 DayOfMonth
[11] = 31;
1057 // The validity of From->Month field should be checked before
1059 ASSERT (From
->Month
>=1);
1060 ASSERT (From
->Month
<=12);
1062 if (From
->Year
== To
->Year
) {
1063 if (From
->Month
== To
->Month
) {
1064 if ((From
->Day
+ 1) == To
->Day
) {
1065 if ((CompareHMS(From
, To
) >= 0)) {
1068 } else if (From
->Day
== To
->Day
) {
1069 if ((CompareHMS(From
, To
) <= 0)) {
1073 } else if (((From
->Month
+ 1) == To
->Month
) && (To
->Day
== 1)) {
1074 if ((From
->Month
== 2) && !IsLeapYear(From
)) {
1075 if (From
->Day
== 28) {
1076 if ((CompareHMS(From
, To
) >= 0)) {
1080 } else if (From
->Day
== DayOfMonth
[From
->Month
- 1]) {
1081 if ((CompareHMS(From
, To
) >= 0)) {
1086 } else if (((From
->Year
+ 1) == To
->Year
) &&
1087 (From
->Month
== 12) &&
1088 (From
->Day
== 31) &&
1091 if ((CompareHMS(From
, To
) >= 0)) {