alder_lake_bios/Lcfc/LfcPkg/RemoveRtcBattery/RemoveRtcBatteryDxe/RemoveRtcBatteryDxe.c

240 lines
6.1 KiB
C

/** @file
;******************************************************************************
;*
;* Copyright (c) 2012 - 2020, Hefei LCFC Information Technology Co.Ltd.
;* And/or its affiliates. All rights reserved.
;* Hefei LCFC Information Technology Co.Ltd. PROPRIETARY/CONFIDENTIAL.
;* Use is subject to license terms.
;*
;******************************************************************************
*/
#include <Library/UefiRuntimeServicesTableLib.h>
#include <Library/BaseLib.h>
#include <Library/IoLib.h>
#include <Library/UefiLib.h>
#include <Library/DebugLib.h>
#include <Protocol/LenovoVariable.h>
#include <Guid/LfcVariableGuid.h>
#include <Library/LfcEcLib.h>
/**
Check if it is a leap year.
@param[in] Time The time to be checked.
@retval TRUE It is a leap year.
@retval FALSE It is NOT a leap year.
**/
BOOLEAN
IsItLeapYear (
IN EFI_TIME *Time
)
{
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;
}
}
EFI_STATUS
TimeAddHours (
IN OUT EFI_TIME *Time,
IN UINT16 AddHours
)
{
EFI_TIME TheTime;
UINT8 MonthDays[13];
UINT8 MonthDaysLeapYear[13] = { 0, 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
UINT8 MonthDaysNoLeapYear[13] = { 0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
UINT16 MonthDaysSum[13];
UINT16 MonthDaysSumLeapYear[13] = { 0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335, 366 };
UINT16 MonthDaysSumNoLeapYear[13] = { 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365 };
UINTN Index;
UINTN Days = 0;
UINTN Hours = 0;
TheTime = *Time;
//Based on beginning of saved time year, get saved time hours sum.
if (IsItLeapYear(&TheTime)) {
for (Index = 0; Index < 13; Index++) {
MonthDays[Index] = MonthDaysLeapYear[Index];
}
} else {
for (Index = 0; Index < 13; Index++) {
MonthDays[Index] = MonthDaysNoLeapYear[Index];
}
}
for (Index = 0; Index < TheTime.Month; Index++) {
Days += MonthDays[Index];
}
Days += TheTime.Day;
Hours = (Days - 1) * 24 + TheTime.Hour;
//Add parameter AddHours
Hours += AddHours;
//Get wanted time
Days = (Hours / 24) + 1;
TheTime.Hour = Hours % 24;
while (TRUE) {
if (IsItLeapYear(&TheTime)) {
for (Index = 0; Index < 13; Index++) {
MonthDaysSum[Index] = MonthDaysSumLeapYear[Index];
}
} else {
for (Index = 0; Index < 13; Index++) {
MonthDaysSum[Index] = MonthDaysSumNoLeapYear[Index];
}
}
if (Days > MonthDaysSum[12]) {
TheTime.Year++;
Days -= MonthDaysSum[12];
} else {
break;
}
}
for (Index = 0; Index < 13; Index++) {
if (Days <= MonthDaysSum[Index]) {
TheTime.Month = (UINT8) Index;
TheTime.Day = (UINT8) (Days - MonthDaysSum[Index-1]);
break;
}
}
if (TheTime.Year < 2099) {
*Time = TheTime;
return EFI_SUCCESS;
} else {
return EFI_UNSUPPORTED;
}
}
/**
Correct RTC time, year support to 2099.
**/
EFI_STATUS
RollbackRtcTimeCallBack (
IN EFI_EVENT Event,
IN VOID *Context
)
{
EFI_STATUS Status;
UINT8 SaveTime[6] = {0};
UINTN TempDataLength = sizeof (SaveTime);
EFI_TIME TheTime;
UINT16 BatteryTimerCount;
//Get saved time from variable - "SaveCurrentTime"
Status = gRT->GetVariable (
L"SaveCurrentTime",
&gLfcVariableGuid,
NULL,
&TempDataLength,
SaveTime
);
if (EFI_ERROR (Status)) {
return Status;
}
//Get system default time format
Status = gRT->GetTime (&TheTime, NULL);
if (EFI_ERROR (Status)) {
return Status;
}
TheTime.Second = BcdToDecimal8(SaveTime[0]);
TheTime.Minute = BcdToDecimal8(SaveTime[1]);
TheTime.Hour = BcdToDecimal8(SaveTime[2]);
TheTime.Day = BcdToDecimal8(SaveTime[3]);
TheTime.Month = BcdToDecimal8(SaveTime[4]);
TheTime.Year = 2000 + BcdToDecimal8(SaveTime[5]);
TheTime.TimeZone = EFI_UNSPECIFIED_TIMEZONE;
TheTime.Daylight = 0;
//Get battery timer count from EC - hours.
Status = LfcEcLibGetBatteryTimerCount(&BatteryTimerCount);
if (EFI_ERROR (Status)) {
return Status;
}
//Time add battery timer count (hours)
Status = TimeAddHours(&TheTime, BatteryTimerCount);
if (EFI_ERROR (Status)) {
return Status;
}
//Set new Time
Status = gRT->SetTime(&TheTime);
if (EFI_ERROR (Status)) {
return Status;
}
//Delete variable - "SaveCurrentTime"
Status = gRT->SetVariable (
L"SaveCurrentTime",
&gLfcVariableGuid,
EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_NON_VOLATILE,
0,
SaveTime
);
if (EFI_ERROR (Status)) {
return Status;
}
// Add battery first use data
Status = LfcEcLibGetBatteryFirstUsedDate();
return EFI_SUCCESS;
}
/**
Remove RTC Battery DXE entry.
Remove RTC battery then ship support, RTC time will lost.
This solution will save current RTC time, then add battery count, generate new time and set it.
@param ImageHandle The firmware allocated handle for the UEFI image.
@param SystemTable A pointer to the EFI System Table.
@retval EFI_SUCCESS The operation completed successfully.
@retval Others An unexpected error occurred.
**/
EFI_STATUS
L05RemoveRtcBatteryDxeEntry (
IN EFI_HANDLE ImageHandle,
IN EFI_SYSTEM_TABLE *SystemTable
)
{
EFI_STATUS Status;
EFI_EVENT Event;
Status = EfiCreateEventReadyToBootEx (
TPL_CALLBACK,
RollbackRtcTimeCallBack,
NULL,
&Event
);
if (EFI_ERROR (Status)) {
return Status;
}
return EFI_SUCCESS;
}