realtimeclock.c
来自「EFI BIOS是Intel提出的下一代的BIOS标准。这里上传的Edk源代码是」· C语言 代码 · 共 1,013 行 · 第 1/2 页
C
1,013 行
return EFI_SUCCESS;
}
EFI_STATUS
EFIAPI
PcRtcSetWakeupTime (
IN BOOLEAN Enable,
OUT EFI_TIME *Time,
IN PC_RTC_MODULE_GLOBALS *Global
)
/*++
Routine Description:
Arguments:
Returns:
--*/
// TODO: Enable - add argument and description to function comment
// TODO: Time - add argument and description to function comment
// TODO: Global - add argument and description to function comment
// TODO: EFI_INVALID_PARAMETER - add return value to function comment
// TODO: EFI_INVALID_PARAMETER - add return value to function comment
// TODO: EFI_UNSUPPORTED - add return value to function comment
// TODO: EFI_DEVICE_ERROR - add return value to function comment
// TODO: EFI_SUCCESS - add return value to function comment
{
EFI_STATUS Status;
EFI_TIME RtcTime;
RTC_REGISTER_B RegisterB;
UINT8 Century;
EFI_TIME_CAPABILITIES Capabilities;
if (Enable) {
if (Time == NULL) {
return EFI_INVALID_PARAMETER;
}
//
// Make sure that the time fields are valid
//
Status = RtcTimeFieldsValid (Time);
if (EFI_ERROR (Status)) {
return EFI_INVALID_PARAMETER;
}
//
// Just support set alarm time within 24 hours
//
PcRtcGetTime (&RtcTime, &Capabilities, Global);
if (!IsWithinOneDay (&RtcTime, Time)) {
return EFI_UNSUPPORTED;
}
//
// Make a local copy of the time and date
//
EfiCopyMem (&RtcTime, Time, sizeof (EFI_TIME));
}
//
// Acquire RTC Lock to make access to RTC atomic
//
EfiAcquireLock (&Global->RtcLock);
//
// Wait for up to 0.1 seconds for the RTC to be updated
//
Status = RtcWaitToUpdate (100000);
if (EFI_ERROR (Status)) {
EfiReleaseLock (&Global->RtcLock);
return EFI_DEVICE_ERROR;
}
//
// Read Register B, and inhibit updates of the RTC
//
RegisterB.Data = RtcRead (RTC_ADDRESS_REGISTER_B);
RegisterB.Bits.SET = 1;
RtcWrite (RTC_ADDRESS_REGISTER_B, RegisterB.Data);
if (Enable) {
ConvertEfiTimeToRtcTime (&RtcTime, RegisterB, &Century);
//
// Set RTC alarm time
//
RtcWrite (RTC_ADDRESS_SECONDS_ALARM, RtcTime.Second);
RtcWrite (RTC_ADDRESS_MINUTES_ALARM, RtcTime.Minute);
RtcWrite (RTC_ADDRESS_HOURS_ALARM, RtcTime.Hour);
RegisterB.Bits.AIE = 1;
} else {
RegisterB.Bits.AIE = 0;
}
//
// Allow updates of the RTC registers
//
RegisterB.Bits.SET = 0;
RtcWrite (RTC_ADDRESS_REGISTER_B, RegisterB.Data);
//
// Release RTC Lock.
//
EfiReleaseLock (&Global->RtcLock);
return EFI_SUCCESS;
}
UINT8
BcdToDecimal (
IN UINT8 BcdValue
)
/*++
Routine Description:
Arguments:
Returns:
--*/
// TODO: BcdValue - add argument and description to function comment
{
UINTN High;
UINTN Low;
High = BcdValue >> 4;
Low = BcdValue - (High << 4);
return (UINT8) (Low + (High * 10));
}
EFI_STATUS
RtcTestCenturyRegister (
VOID
)
/*++
Routine Description:
Arguments:
Returns:
--*/
// TODO: EFI_SUCCESS - add return value to function comment
// TODO: EFI_DEVICE_ERROR - add return value to function comment
{
UINT8 Century;
UINT8 Temp;
Century = RtcRead (RTC_ADDRESS_CENTURY);
//
// RtcWrite (RTC_ADDRESS_CENTURY, 0x00);
//
Temp = (UINT8) (RtcRead (RTC_ADDRESS_CENTURY) & 0x7f);
RtcWrite (RTC_ADDRESS_CENTURY, Century);
if (Temp == 0x19 || Temp == 0x20) {
return EFI_SUCCESS;
}
return EFI_DEVICE_ERROR;
}
VOID
ConvertRtcTimeToEfiTime (
IN EFI_TIME *Time,
IN RTC_REGISTER_B RegisterB
)
/*++
Routine Description:
Arguments:
Returns:
--*/
// TODO: Time - add argument and description to function comment
// TODO: RegisterB - add argument and description to function comment
{
BOOLEAN PM;
if ((Time->Hour) & 0x80) {
PM = TRUE;
} else {
PM = FALSE;
}
Time->Hour = (UINT8) (Time->Hour & 0x7f);
if (RegisterB.Bits.DM == 0) {
Time->Year = BcdToDecimal ((UINT8) Time->Year);
Time->Month = BcdToDecimal (Time->Month);
Time->Day = BcdToDecimal (Time->Day);
Time->Hour = BcdToDecimal (Time->Hour);
Time->Minute = BcdToDecimal (Time->Minute);
Time->Second = BcdToDecimal (Time->Second);
}
//
// If time is in 12 hour format, convert it to 24 hour format
//
if (RegisterB.Bits.MIL == 0) {
if (PM && Time->Hour < 12) {
Time->Hour = (UINT8) (Time->Hour + 12);
}
if (!PM && Time->Hour == 12) {
Time->Hour = 0;
}
}
Time->Nanosecond = 0;
Time->TimeZone = EFI_UNSPECIFIED_TIMEZONE;
Time->Daylight = 0;
}
EFI_STATUS
RtcWaitToUpdate (
UINTN Timeout
)
/*++
Routine Description:
Arguments:
Returns:
--*/
// TODO: Timeout - add argument and description to function comment
// TODO: EFI_DEVICE_ERROR - add return value to function comment
// TODO: EFI_DEVICE_ERROR - add return value to function comment
// TODO: EFI_SUCCESS - add return value to function comment
{
RTC_REGISTER_A RegisterA;
RTC_REGISTER_D RegisterD;
//
// See if the RTC is functioning correctly
//
RegisterD.Data = RtcRead (RTC_ADDRESS_REGISTER_D);
if (RegisterD.Bits.VRT == 0) {
return EFI_DEVICE_ERROR;
}
//
// Wait for up to 0.1 seconds for the RTC to be ready.
//
Timeout = (Timeout / 10) + 1;
RegisterA.Data = RtcRead (RTC_ADDRESS_REGISTER_A);
while (RegisterA.Bits.UIP == 1 && Timeout > 0) {
EfiStall (10);
RegisterA.Data = RtcRead (RTC_ADDRESS_REGISTER_A);
Timeout--;
}
RegisterD.Data = RtcRead (RTC_ADDRESS_REGISTER_D);
if (Timeout == 0 || RegisterD.Bits.VRT == 0) {
return EFI_DEVICE_ERROR;
}
return EFI_SUCCESS;
}
EFI_STATUS
RtcTimeFieldsValid (
IN EFI_TIME *Time
)
/*++
Routine Description:
Arguments:
Returns:
--*/
// TODO: Time - add argument and description to function comment
// TODO: EFI_INVALID_PARAMETER - add return value to function comment
// TODO: EFI_SUCCESS - add return value to function comment
{
if (Time->Year < 1998 ||
Time->Year > 2099 ||
Time->Month < 1 ||
Time->Month > 12 ||
(!DayValid (Time)) ||
Time->Hour > 23 ||
Time->Minute > 59 ||
Time->Second > 59 ||
Time->Nanosecond > 999999999 ||
(!(Time->TimeZone == EFI_UNSPECIFIED_TIMEZONE || (Time->TimeZone >= -1440 && Time->TimeZone <= 1440))) ||
(Time->Daylight & (~(EFI_TIME_ADJUST_DAYLIGHT | EFI_TIME_IN_DAYLIGHT)))
) {
return EFI_INVALID_PARAMETER;
}
return EFI_SUCCESS;
}
BOOLEAN
DayValid (
IN EFI_TIME *Time
)
/*++
Routine Description:
TODO: Add function description
Arguments:
Time - TODO: add argument description
Returns:
TODO: add return values
--*/
{
INTN DayOfMonth[12] = { 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
if (Time->Day < 1 ||
Time->Day > DayOfMonth[Time->Month - 1] ||
(Time->Month == 2 && (!IsLeapYear (Time) && Time->Day > 28))
) {
return FALSE;
}
return TRUE;
}
BOOLEAN
IsLeapYear (
IN EFI_TIME *Time
)
/*++
Routine Description:
TODO: Add function description
Arguments:
Time - TODO: add argument description
Returns:
TODO: add return values
--*/
{
if (Time->Year % 4 == 0) {
if (Time->Year % 100 == 0) {
if (Time->Year % 400 == 0) {
return TRUE;
} else {
return FALSE;
}
} else {
return TRUE;
}
} else {
return FALSE;
}
}
VOID
ConvertEfiTimeToRtcTime (
IN EFI_TIME *Time,
IN RTC_REGISTER_B RegisterB,
IN UINT8 *Century
)
/*++
Routine Description:
Arguments:
Returns:
--*/
// TODO: Time - add argument and description to function comment
// TODO: RegisterB - add argument and description to function comment
// TODO: Century - add argument and description to function comment
{
BOOLEAN PM;
PM = TRUE;
//
// Adjust hour field if RTC in in 12 hour mode
//
if (RegisterB.Bits.MIL == 0) {
if (Time->Hour < 12) {
PM = FALSE;
}
if (Time->Hour >= 13) {
Time->Hour = (UINT8) (Time->Hour - 12);
} else if (Time->Hour == 0) {
Time->Hour = 12;
}
}
//
// Set the Time/Date/Daylight Savings values.
//
*Century = DecimaltoBcd ((UINT8) (Time->Year / 100));
Time->Year = (UINT16) (Time->Year % 100);
if (RegisterB.Bits.DM == 0) {
Time->Year = DecimaltoBcd ((UINT8) Time->Year);
Time->Month = DecimaltoBcd (Time->Month);
Time->Day = DecimaltoBcd (Time->Day);
Time->Hour = DecimaltoBcd (Time->Hour);
Time->Minute = DecimaltoBcd (Time->Minute);
Time->Second = DecimaltoBcd (Time->Second);
}
//
// If we are in 12 hour mode and PM is set, then set bit 7 of the Hour field.
//
if (RegisterB.Bits.MIL == 0 && PM) {
Time->Hour = (UINT8) (Time->Hour | 0x80);
}
}
BOOLEAN
IsWithinOneDay (
IN EFI_TIME *From,
IN EFI_TIME *To
)
/*++
Routine Description:
Judge whether two days are adjacent.
Arguments:
From - the first day
To - the second day
Returns:
TRUE - The interval of two days are within one day.
FALSE - The interval of two days exceed ony day or parameter error.
--*/
{
UINT8 DayOfMonth[12] = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
BOOLEAN Adjacent = FALSE;
if (From->Year == To->Year) {
if (From->Month == To->Month) {
if ((From->Day + 1) == To->Day) {
Adjacent = TRUE;
}
} else if (((From->Month + 1) == To->Month) && (To->Day == 1)) {
if ((From->Month == 2) && IsLeapYear(From)) {
if (From->Day == 29) {
Adjacent = TRUE;
}
} else if (From->Day == DayOfMonth[From->Month - 1]) {
Adjacent = TRUE;
}
}
} else if (((From->Year + 1) == To->Year) &&
(From->Month == 12) &&
(From->Day == 31) &&
(To->Month == 1) &&
(To->Day == 1)) {
Adjacent = TRUE;
}
return Adjacent;
}
UINT8
DecimaltoBcd (
IN UINT8 DecValue
)
/*++
Routine Description:
Arguments:
Returns:
--*/
// TODO: DecValue - add argument and description to function comment
{
UINTN High;
UINTN Low;
High = DecValue / 10;
Low = DecValue - (High * 10);
return (UINT8) (Low + (High << 4));
}
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?