BayTrail/AaeonCommonPkg/AaeonRunningTime/S5andPowerBtnSMI.c
2022-09-02 09:03:21 +08:00

205 lines
6.6 KiB
C

//;******************************************************************************
//;* Copyright (c) 2017, Aaeon Corporation. All Rights Reserved.
//;*
//;* You may not reproduce, distribute, publish, display, perform, modify, adapt,
//;* transmit, broadcast, present, recite, release, license or otherwise exploit
//;* any part of this publication in any form, by any means, without the prior
//;* written permission of Aaeon Corporation.
//;*
//;******************************************************************************
//; ModuleName:
//;
//; S5andPowerBtnSMI.c
//;
//;------------------------------------------------------------------------------
//;
//; Abstract:
//; This is a DXE SMM driver to register power button and S5 SMI handler.
//;
#include <Uefi.h>
#include <AmiDxeLib.h>
#include <AmiCspLib.h>
#include <Token.h>
#include <Setup.h>
#include <Protocol/SmmVariable.h>
#include <Library/BaseLib.h>
#include <Library/SmmServicesTableLib.h>
#include <Library/PrintLib.h>
#define IsLeap(y) (((y) % 4) == 0 && (((y) % 100) != 0 || ((y) % 400) == 0))
#define MINSPERHOUR (60)
#define MINSPERDAY (24 * MINSPERHOUR)
static EFI_GUID AaeonRunTimeleGuid = {0xCE066E0D, 0x1893, 0x4FF5, {0x81, 0x89, 0x0B, 0xF8, 0x8F, 0xF1, 0x6B, 0xCA}};
//
// The arrays give the cumulative number of days up to the first of the
// month number used as the index (1 -> 12) for regular and leap years.
// The value at index 13 is for the whole year.
//
static UINTN CumulativeDays[2][14] = {
{
0,
0,
31,
31 + 28,
31 + 28 + 31,
31 + 28 + 31 + 30,
31 + 28 + 31 + 30 + 31,
31 + 28 + 31 + 30 + 31 + 30,
31 + 28 + 31 + 30 + 31 + 30 + 31,
31 + 28 + 31 + 30 + 31 + 30 + 31 + 31,
31 + 28 + 31 + 30 + 31 + 30 + 31 + 31 + 30,
31 + 28 + 31 + 30 + 31 + 30 + 31 + 31 + 30 + 31,
31 + 28 + 31 + 30 + 31 + 30 + 31 + 31 + 30 + 31 + 30,
31 + 28 + 31 + 30 + 31 + 30 + 31 + 31 + 30 + 31 + 30 + 31
},
{
0,
0,
31,
31 + 29,
31 + 29 + 31,
31 + 29 + 31 + 30,
31 + 29 + 31 + 30 + 31,
31 + 29 + 31 + 30 + 31 + 30,
31 + 29 + 31 + 30 + 31 + 30 + 31,
31 + 29 + 31 + 30 + 31 + 30 + 31 + 31,
31 + 29 + 31 + 30 + 31 + 30 + 31 + 31 + 30,
31 + 29 + 31 + 30 + 31 + 30 + 31 + 31 + 30 + 31,
31 + 29 + 31 + 30 + 31 + 30 + 31 + 31 + 30 + 31 + 30,
31 + 29 + 31 + 30 + 31 + 30 + 31 + 31 + 30 + 31 + 30 + 31
}
};
static UINT64 TimeToMinute (EFI_TIME CurrentTime)
/*++
Routine Description:
A function to translate system time to number of minutes since year 1970.
--*/
{
UINT64 CalTimeInMinute = 0;
UINTN Year;
//
// Years Handling
// UTime should now be set to 00:00:00 on Jan 1 of the current year.
//
for (Year = 1970, CalTimeInMinute = 0; Year != CurrentTime.Year; Year++) {
CalTimeInMinute = CalTimeInMinute + (CumulativeDays[IsLeap(Year)][13] * MINSPERDAY);
}
//
// Add in number of seconds for current Month, Day, Hour, Minute and TimeZone adjustment
//
CalTimeInMinute = CalTimeInMinute +
(CumulativeDays[IsLeap(CurrentTime.Year)][CurrentTime.Month] * MINSPERDAY) +
(((CurrentTime.Day > 0) ? CurrentTime.Day - 1 : 0) * MINSPERDAY) +
(CurrentTime.Hour * MINSPERHOUR) +
(CurrentTime.Minute);
return CalTimeInMinute;
}
EFI_STATUS
EFIAPI
RunningTimePwrBtnSxHandler (SETUP_DATA *SetupData)
/*++
Routine Description:
SMI handler to store running time of this boot back to variable PreviousRunTime.
It's called when power button is pressed or S5 is executing.
--*/
{
EFI_STATUS Status;
EFI_SMM_VARIABLE_PROTOCOL *SmmVarProtocol = NULL;
EFI_TIME CurrentTime;
UINT64 CurrentTimeInMinute;
UINT64 ThisBootRunTimeInMinute;
UINT64 PreviousRunTimeInMinute;
UINT64 PowerOnTimeInMinute;
UINTN Size = sizeof(UINT64);
CurrentTimeInMinute = 0;
PowerOnTimeInMinute = 0;
PreviousRunTimeInMinute = 0;
Status = pSmst->SmmLocateProtocol(&gEfiSmmVariableProtocolGuid, NULL, &SmmVarProtocol);
if (EFI_ERROR(Status)) return Status;
//
// Get system time and translate to number of minutes since year 1970.
//
Status = pRS->GetTime (&CurrentTime, NULL);
if (EFI_ERROR(Status)) {
return Status;
}
// Do nothing if system time is invalid. The purpose is to fix potential issue that
// running time will increase abnormally after setting system time right after COMS load default.
if (CurrentTime.Year < 2017) {
return EFI_SUCCESS;
}
CurrentTimeInMinute = TimeToMinute (CurrentTime);
//
// Get power on time in minutes.
//
Status = SmmVarProtocol->SmmGetVariable(
L"PowerOnTime",
&AaeonRunTimeleGuid,
NULL,
&Size,
&PowerOnTimeInMinute
);
if (EFI_ERROR(Status)) {
return Status;
}
//
// If user set the system time to past time, then also sync system time to power on time.
// It's to prevent minus Running Time
//
if (CurrentTimeInMinute < PowerOnTimeInMinute) {
PowerOnTimeInMinute = CurrentTimeInMinute;
Status = pRS->SetVariable(
L"PowerOnTime",
&AaeonRunTimeleGuid,
EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_NON_VOLATILE,
Size,
&PowerOnTimeInMinute);
}
//
// Get PreviousRunTime in minutes.
//
Status = SmmVarProtocol->SmmGetVariable(
L"PreviousRunTime",
&AaeonRunTimeleGuid,
NULL,
&Size,
&PreviousRunTimeInMinute
);
if (EFI_ERROR(Status)) {
return Status;
}
//
// Store ruinning time of this boot to PreviousRunTimeInMinute.
//
ThisBootRunTimeInMinute = CurrentTimeInMinute - PowerOnTimeInMinute + PreviousRunTimeInMinute;
Status = SmmVarProtocol->SmmSetVariable (
L"PreviousRunTime",
&AaeonRunTimeleGuid,
EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_BOOTSERVICE_ACCESS,
Size,
&ThisBootRunTimeInMinute
);
Status = SmmVarProtocol->SmmSetVariable (
L"PowerOnTime",
&AaeonRunTimeleGuid,
0,
0,
NULL
);
return EFI_SUCCESS;
}