From nobody Sun Feb 8 11:40:39 2026 Delivered-To: importer@patchew.org Received-SPF: pass (zohomail.com: domain of groups.io designates 66.175.222.108 as permitted sender) client-ip=66.175.222.108; envelope-from=bounce+27952+112765+1787277+3901457@groups.io; helo=mail02.groups.io; Authentication-Results: mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of groups.io designates 66.175.222.108 as permitted sender) smtp.mailfrom=bounce+27952+112765+1787277+3901457@groups.io; dmarc=fail(p=none dis=none) header.from=intel.com ARC-Seal: i=1; a=rsa-sha256; t=1703091720; cv=none; d=zohomail.com; s=zohoarc; b=Bn26l7W2imr/05WhclTr3VGZ+qGe24aFbUOVkjxoiaCBCD/q7Pyqt8x3LmkBLm4J/p1X4lkbYKzEb4rvImQfBOmwdWG2I3cDMRAAGe+j0WICeWedz2NZBRAeXdgGbZdZnskvmVhdlpAQQzQOq5/XfKhPO/soMBEtW9K2iy7mR6I= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1703091720; h=Content-Transfer-Encoding:Cc:Cc:Date:Date:From:From:In-Reply-To:List-Subscribe:List-Id:List-Help:List-Unsubscribe:MIME-Version:Message-ID:Reply-To:Reply-To:References:Sender:Subject:Subject:To:To:Message-Id; bh=SwgukhD3q1D6GW4Iy/HtpZb9fgnMt/DN3+FM6Uzkzcw=; b=WT4ohDTbxJXPLDQy423XLINnrEwZPcFverju08UXhFRIHBnlY00dovlYvf85+/ykD/MHBubes4dUiVle2B6rBbAWh+brqvnXKDAsoRxfKUdgB2CorgMkugs2C83EDSL/sQqA0v9BkThs47AeKKGplaz3agUhOMNN5yNK/85Vudg= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of groups.io designates 66.175.222.108 as permitted sender) smtp.mailfrom=bounce+27952+112765+1787277+3901457@groups.io; dmarc=fail header.from= (p=none dis=none) Received: from mail02.groups.io (mail02.groups.io [66.175.222.108]) by mx.zohomail.com with SMTPS id 1703091720168807.0217960416842; Wed, 20 Dec 2023 09:02:00 -0800 (PST) Return-Path: DKIM-Signature: a=rsa-sha256; bh=g5i3VD64jax1zwFSuOU10+VHT7yf5b0szXEM/l+5P4o=; c=relaxed/simple; d=groups.io; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References:MIME-Version:Precedence:List-Subscribe:List-Help:Sender:List-Id:Mailing-List:Delivered-To:Reply-To:List-Unsubscribe-Post:List-Unsubscribe:Content-Transfer-Encoding; s=20140610; t=1703091719; v=1; b=b2/s6NhOcGotmtBarurYLpvfFZ2rkQGt43FFhlUIn3K5AciariRwzsZ8x3sCXMeKPO9ZKWmL bKpp7l+Vk28uBcyCXnWTt8Rn8C+x/IaGr4i9aMlrBAQxhU4qXaxawO3FrIZoUo3XRnLU2IXtSNw /ND83yT5iVoOcCvw6Wo298PM= X-Received: by 127.0.0.2 with SMTP id mMt7YY1788612x1bQhSmcHnJ; Wed, 20 Dec 2023 09:01:59 -0800 X-Received: from mgamail.intel.com (mgamail.intel.com [192.198.163.11]) by mx.groups.io with SMTP id smtpd.web10.26890.1703091715141496173 for ; Wed, 20 Dec 2023 09:01:59 -0800 X-IronPort-AV: E=McAfee;i="6600,9927,10930"; a="2671090" X-IronPort-AV: E=Sophos;i="6.04,291,1695711600"; d="scan'208";a="2671090" X-Received: from fmsmga001.fm.intel.com ([10.253.24.23]) by fmvoesa105.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 20 Dec 2023 09:01:59 -0800 X-ExtLoop1: 1 X-IronPort-AV: E=McAfee;i="6600,9927,10930"; a="920029629" X-IronPort-AV: E=Sophos;i="6.04,291,1695711600"; d="scan'208";a="920029629" X-Received: from shpfwdbuild003.ccr.corp.intel.com ([10.239.56.82]) by fmsmga001.fm.intel.com with ESMTP; 20 Dec 2023 09:01:56 -0800 From: "Xu, Wei6" To: devel@edk2.groups.io Cc: Wei6 Xu , Abner Chang , Nate DeSimone Subject: [edk2-devel] [PATCH edk2-platforms 1/4] IpmiFeaturePkg/ServerManagementLib: Support Standalone MM Date: Thu, 21 Dec 2023 01:01:42 +0800 Message-Id: <515f4567b0cd26ec94069a4cae367c86e59554cf.1703090380.git.wei6.xu@intel.com> In-Reply-To: References: MIME-Version: 1.0 Precedence: Bulk List-Subscribe: List-Help: Sender: devel@edk2.groups.io List-Id: Mailing-List: list devel@edk2.groups.io; contact devel+owner@edk2.groups.io Reply-To: devel@edk2.groups.io,wei6.xu@intel.com List-Unsubscribe-Post: List-Unsubscribe=One-Click List-Unsubscribe: X-Gm-Message-State: BaPr5wXapT8nZ2d3HlpNzVhTx1787277AA= Content-Transfer-Encoding: quoted-printable X-ZohoMail-DKIM: pass (identity @groups.io) X-ZM-MESSAGEID: 1703091721128100001 Content-Type: text/plain; charset="utf-8" Split the ServerManagementLib.c into two source files: - ServerManagementELog.c to support Event Log functions. - ServerManagementTime.c to support GetTimeStamp function. - Replace gBS->Stall() with MicroSecondDelay() in TimerLib to remove dependency on gBS. Base Lib includes both of the two source files, StandaloneMm Lib only includes the ServerManagementTime.c Cc: Abner Chang Cc: Nate DeSimone Signed-off-by: Wei6 Xu --- .../IpmiFeaturePkg/Include/IpmiFeature.dsc | 3 + .../ServerManagementElog.c | 235 ++++ .../ServerManagementLib.inf | 4 +- ...ManagementLib.c =3D> ServerManagementTime.c} | 1175 +++++++---------- .../StandaloneMmServerManagementLib.inf | 29 + 5 files changed, 749 insertions(+), 697 deletions(-) create mode 100644 Features/Intel/OutOfBandManagement/IpmiFeaturePkg/Libra= ry/ServerManagementLib/ServerManagementElog.c rename Features/Intel/OutOfBandManagement/IpmiFeaturePkg/Library/ServerMan= agementLib/{ServerManagementLib.c =3D> ServerManagementTime.c} (55%) create mode 100644 Features/Intel/OutOfBandManagement/IpmiFeaturePkg/Libra= ry/ServerManagementLib/StandaloneMmServerManagementLib.inf diff --git a/Features/Intel/OutOfBandManagement/IpmiFeaturePkg/Include/Ipmi= Feature.dsc b/Features/Intel/OutOfBandManagement/IpmiFeaturePkg/Include/Ipm= iFeature.dsc index c9c76565c672..45439f92eaac 100644 --- a/Features/Intel/OutOfBandManagement/IpmiFeaturePkg/Include/IpmiFeature= .dsc +++ b/Features/Intel/OutOfBandManagement/IpmiFeaturePkg/Include/IpmiFeature= .dsc @@ -62,6 +62,9 @@ SsifInterfaceLib|IpmiFeaturePkg/Library/BmcInterfaceCommonAccess/SsifInt= erfaceLib/SmmSsifInterfaceLib.inf IpmbInterfaceLib|IpmiFeaturePkg/Library/BmcInterfaceCommonAccess/IpmbInt= erfaceLib/SmmIpmbInterfaceLib.inf =20 +[LibraryClasses.common.MM_STANDALONE] + ServerManagementLib|IpmiFeaturePkg/Library/ServerManagementLib/Standalon= eMmServerManagementLib.inf + ##########################################################################= ###### # # Component section - list of all components that need built for this feat= ure. diff --git a/Features/Intel/OutOfBandManagement/IpmiFeaturePkg/Library/Serv= erManagementLib/ServerManagementElog.c b/Features/Intel/OutOfBandManagement= /IpmiFeaturePkg/Library/ServerManagementLib/ServerManagementElog.c new file mode 100644 index 000000000000..eddc8350188d --- /dev/null +++ b/Features/Intel/OutOfBandManagement/IpmiFeaturePkg/Library/ServerManag= ementLib/ServerManagementElog.c @@ -0,0 +1,235 @@ +/** @file + Lightweight lib to support EFI Server Management drivers. + This source file provides Event Log support. + +Copyright (c) 2023, Intel Corporation. All rights reserved.
+SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include +#include +#include +#include + +#include + +// +// Module Globals +// +EFI_SM_ELOG_PROTOCOL *mGenericElogProtocol =3D NULL; +VOID *mGenericElogRegistration =3D NULL; + +/** + This function is called whenever an instance of ELOG protocol is created= . When the function is notified + it initializes the module global data. + + @param Event This is used only for EFI compatibility. + @param Context This is used only for EFI compatibility. + +**/ +VOID +EFIAPI +GenericElogNotificationFunction ( + IN EFI_EVENT Event, + IN VOID *Context + ) +{ + EFI_STATUS Status; + + Status =3D gBS->LocateProtocol (&gEfiGenericElogProtocolGuid, NULL, (VOI= D **)&mGenericElogProtocol); + if (EFI_ERROR (Status)) { + mGenericElogProtocol =3D NULL; + } +} + +/** + The function will set up a notification on the ELOG protocol. This func= tion is required to be called prior + to utilizing the ELOG protocol from within this library. + + @retval EFI_SUCCESS after the notification has been setup. +**/ +EFI_STATUS +EfiInitializeGenericElog ( + VOID + ) +{ + EFI_EVENT Event; + EFI_STATUS Status; + + Status =3D gBS->CreateEvent (EVT_NOTIFY_SIGNAL, TPL_CALLBACK, GenericElo= gNotificationFunction, NULL, &Event); + ASSERT_EFI_ERROR (Status); + if (Status !=3D EFI_SUCCESS) { + return Status; + } + + Status =3D gBS->RegisterProtocolNotify (&gEfiGenericElogProtocolGuid, Ev= ent, &mGenericElogRegistration); + ASSERT_EFI_ERROR (Status); + if (Status !=3D EFI_SUCCESS) { + return Status; + } + + gBS->SignalEvent (Event); + + return EFI_SUCCESS; +} + +/** + This function sends event log data to the destination such as LAN, ICMB,= BMC etc. + + @param ElogData is a pointer to the event log data that needs to be = recorded + @param DataType type of Elog data that is being recorded. The Elog = is redirected based on this parameter. + @param AlertEvent is an indication that the input data type is an aler= t. The underlying + drivers need to decide if they need to listen to the= DataType and send it on + an appropriate channel as an alert use of the inform= ation. + @param DataSize is the size of the data to be logged + @param RecordId is the array of record IDs sent by the target. This= can be used to retrieve the + records or erase the records. + @retval EFI_SUCCESS - if the data was logged. + @retval EFI_INVALID_PARAMETER - if the DataType is >=3D EfiSmElogMax + @retval EFI_NOT_FOUND - the event log target was not found + @retval EFI_PROTOCOL_ERROR - there was a data formatting error + +**/ +EFI_STATUS +EfiSmSetEventLogData ( + IN UINT8 *ElogData, + IN EFI_SM_ELOG_TYPE DataType, + IN BOOLEAN AlertEvent, + IN UINTN DataSize, + OUT UINT64 *RecordId + ) +{ + // + // If the protocol is not found return EFI_NOT_FOUND + // + if (mGenericElogProtocol =3D=3D NULL) { + return EFI_NOT_FOUND; + } + + return mGenericElogProtocol->SetEventLogData ( + mGenericElogProtocol, + ElogData, + DataType, + AlertEvent, + DataSize, + RecordId + ); +} + +/** + This function gets event log data from the destination dependent on the = DataType. The destination + can be a remote target such as LAN, ICMB, IPMI, or a FV. The ELOG redir= driver will resolve the + destination. + + @param ElogData - pointer to the event log data buffer to contain the da= ta to be retrieved. + @param DataType - this is the type of Elog data to be gotten. Elog is r= edirected based upon this + information. + @param DataSize - this is the size of the data to be retrieved. + @param RecordId - the RecordId of the next record. If ElogData is NULL,= this gives the RecordId of the first + record available in the database with the correct Data= Size. A value of 0 on return indicates + that it was last record if the Status is EFI_SUCCESS. + + @retval EFI_SUCCESS - if the event log was retrieved successfully. + @retval EFI_NOT_FOUND - if the event log target was not found. + @retval EFI_NO_RESPONSE - if the event log target is not responding. Th= is is done by the redir driver. + @retval EFI_INVALID_PARAMETER - DataType or another parameter was invali= d. + @retval EFI_BUFFER_TOO_SMALL -the ElogData buffer is too small to be fil= led with the requested data. + +**/ +EFI_STATUS +EfiSmGetEventLogData ( + IN UINT8 *ElogData, + IN EFI_SM_ELOG_TYPE DataType, + IN OUT UINTN *DataSize, + IN OUT UINT64 *RecordId + ) +{ + // + // If the protocol is not found return EFI_NOT_FOUND + // + if (mGenericElogProtocol =3D=3D NULL) { + return EFI_NOT_FOUND; + } + + return mGenericElogProtocol->GetEventLogData ( + mGenericElogProtocol, + ElogData, + DataType, + DataSize, + RecordId + ); +} + +/** + This function erases the event log data defined by the DataType. The re= dir driver associated with + the DataType resolves the path to the record. + + @param DataType - the type of Elog data that is to be erased. + @param RecordId - the RecordId of the data to be erased. If RecordId is= NULL, all records in the + database are erased if permitted by the target. Recor= dId will contain the deleted + RecordId on return. + + @retval EFI_SUCCESS - the record or collection of records were erased. + @retval EFI_NOT_FOUND - the event log target was not found. + @retval EFI_NO_RESPONSE - the event log target was found but did not res= pond. + @retval EFI_INVALID_PARAMETER - one of the parameters was invalid. + +**/ +EFI_STATUS +EfiSmEraseEventlogData ( + IN EFI_SM_ELOG_TYPE DataType, + IN OUT UINT64 *RecordId + ) +{ + // + // If the protocol is not found return EFI_NOT_FOUND + // + if (mGenericElogProtocol =3D=3D NULL) { + return EFI_NOT_FOUND; + } + + return mGenericElogProtocol->EraseEventlogData ( + mGenericElogProtocol, + DataType, + RecordId + ); +} + +/** + This function enables or disables the event log defined by the DataType. + + + @param DataType - the type of Elog data that is being activated. + @param EnableElog - enables or disables the event log defined by the Dat= aType. If it is NULL + it returns the current status of the DataType log. + @param ElogStatus - is the current status of the Event log defined by th= e DataType. Enabled is + TRUE and Disabled is FALSE. + + @retval EFI_SUCCESS - if the event log was successfully enabled or disab= led. + @retval EFI_NOT_FOUND - the event log target was not found. + @retval EFI_NO_RESPONSE - the event log target was found but did not res= pond. + @retval EFI_INVALID_PARAMETER - one of the parameters was invalid. + +**/ +EFI_STATUS +EfiSmActivateEventLog ( + IN EFI_SM_ELOG_TYPE DataType, + IN BOOLEAN *EnableElog, + OUT BOOLEAN *ElogStatus + ) +{ + // + // If the protocol is not found return EFI_NOT_FOUND + // + if (mGenericElogProtocol =3D=3D NULL) { + return EFI_NOT_FOUND; + } + + return mGenericElogProtocol->ActivateEventLog ( + mGenericElogProtocol, + DataType, + EnableElog, + ElogStatus + ); +} diff --git a/Features/Intel/OutOfBandManagement/IpmiFeaturePkg/Library/Serv= erManagementLib/ServerManagementLib.inf b/Features/Intel/OutOfBandManagemen= t/IpmiFeaturePkg/Library/ServerManagementLib/ServerManagementLib.inf index 25a3a7540762..6e7702e0db33 100644 --- a/Features/Intel/OutOfBandManagement/IpmiFeaturePkg/Library/ServerManag= ementLib/ServerManagementLib.inf +++ b/Features/Intel/OutOfBandManagement/IpmiFeaturePkg/Library/ServerManag= ementLib/ServerManagementLib.inf @@ -17,7 +17,8 @@ LIBRARY_CLASS =3D ServerManagementLib =20 [Sources] - ServerManagementLib.c + ServerManagementELog.c + ServerManagementTime.c =20 [Packages] IpmiFeaturePkg/IpmiFeaturePkg.dec @@ -27,6 +28,7 @@ IoLib DebugLib UefiBootServicesTableLib + TimerLib =20 [Protocols] gEfiGenericElogProtocolGuid diff --git a/Features/Intel/OutOfBandManagement/IpmiFeaturePkg/Library/Serv= erManagementLib/ServerManagementLib.c b/Features/Intel/OutOfBandManagement/= IpmiFeaturePkg/Library/ServerManagementLib/ServerManagementTime.c similarity index 55% rename from Features/Intel/OutOfBandManagement/IpmiFeaturePkg/Library/Serve= rManagementLib/ServerManagementLib.c rename to Features/Intel/OutOfBandManagement/IpmiFeaturePkg/Library/ServerM= anagementLib/ServerManagementTime.c index 66a481fa57b4..ad7ac0b87054 100644 --- a/Features/Intel/OutOfBandManagement/IpmiFeaturePkg/Library/ServerManag= ementLib/ServerManagementLib.c +++ b/Features/Intel/OutOfBandManagement/IpmiFeaturePkg/Library/ServerManag= ementLib/ServerManagementTime.c @@ -1,696 +1,479 @@ -/** @file - Lightweight lib to support EFI Server Management drivers. - -Copyright (c) 2023, Intel Corporation. All rights reserved.
-SPDX-License-Identifier: BSD-2-Clause-Patent - -**/ - -#include -#include -#include -#include -#include - -#include - -// #include EFI_PROTOCOL_DEPENDENCY (CpuIo) - -#define PCAT_RTC_ADDRESS_REGISTER 0x70 -#define PCAT_RTC_DATA_REGISTER 0x71 - -#define RTC_ADDRESS_SECONDS 0 // R/W Range 0..59 -#define RTC_ADDRESS_MINUTES 2 // R/W Range 0..59 -#define RTC_ADDRESS_HOURS 4 // R/W Range 1..12 or 0..23 Bit= 7 is AM/PM -#define RTC_ADDRESS_DAY_OF_THE_MONTH 7 // R/W Range 1..31 -#define RTC_ADDRESS_MONTH 8 // R/W Range 1..12 -#define RTC_ADDRESS_YEAR 9 // R/W Range 0..99 -#define RTC_ADDRESS_REGISTER_A 10 // R/W[0..6] R0[7] -#define RTC_ADDRESS_REGISTER_B 11 // R/W -#define RTC_ADDRESS_REGISTER_C 12 // RO -#define RTC_ADDRESS_REGISTER_D 13 // RO -#define RTC_ADDRESS_CENTURY 50 // R/W Range 19..20 Bit 8 is R/W - -// -// Register A -// -typedef struct { - UINT8 RS : 4; // Rate Selection Bits - UINT8 DV : 3; // Divisor - UINT8 UIP : 1; // Update in progress -} RTC_REGISTER_A_BITS; - -typedef union { - RTC_REGISTER_A_BITS Bits; - UINT8 Data; -} RTC_REGISTER_A; - -// -// Register B -// -typedef struct { - UINT8 DSE : 1; // 0 - Daylight saving disabled 1 - Daylight savings= enabled - UINT8 MIL : 1; // 0 - 12 hour mode 1 - 24 hour mode - UINT8 DM : 1; // 0 - BCD Format 1 - Binary Format - UINT8 SQWE : 1; // 0 - Disable SQWE output 1 - Enable SQWE outp= ut - UINT8 UIE : 1; // 0 - Update INT disabled 1 - Update INT enabl= ed - UINT8 AIE : 1; // 0 - Alarm INT disabled 1 - Alarm INT Enabled - UINT8 PIE : 1; // 0 - Periodic INT disabled 1 - Periodic INT Ena= bled - UINT8 SET : 1; // 0 - Normal operation. 1 - Updates inhibited -} RTC_REGISTER_B_BITS; - -typedef union { - RTC_REGISTER_B_BITS Bits; - UINT8 Data; -} RTC_REGISTER_B; - -// -// Register D -// -typedef struct { - UINT8 Reserved : 7; // Read as zero. Can not be written. - UINT8 VRT : 1; // Valid RAM and Time -} RTC_REGISTER_D_BITS; - -typedef union { - RTC_REGISTER_D_BITS Bits; - UINT8 Data; -} RTC_REGISTER_D; - -// -// Module Globals -// -EFI_SM_ELOG_PROTOCOL *mGenericElogProtocol =3D NULL; -VOID *mGenericElogRegistration =3D NULL; - -INTN DaysOfMonth[12] =3D { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31= }; - -/** - This function is called whenever an instance of ELOG protocol is created= . When the function is notified - it initializes the module global data. - - @param Event This is used only for EFI compatibility. - @param Context This is used only for EFI compatibility. - -**/ -VOID -EFIAPI -GenericElogNotificationFunction ( - IN EFI_EVENT Event, - IN VOID *Context - ) -{ - EFI_STATUS Status; - - Status =3D gBS->LocateProtocol (&gEfiGenericElogProtocolGuid, NULL, (VOI= D **)&mGenericElogProtocol); - if (EFI_ERROR (Status)) { - mGenericElogProtocol =3D NULL; - } -} - -/** - The function will set up a notification on the ELOG protocol. This func= tion is required to be called prior - to utilizing the ELOG protocol from within this library. - - @retval EFI_SUCCESS after the notification has been setup. -**/ -EFI_STATUS -EfiInitializeGenericElog ( - VOID - ) -{ - EFI_EVENT Event; - EFI_STATUS Status; - - Status =3D gBS->CreateEvent (EVT_NOTIFY_SIGNAL, TPL_CALLBACK, GenericElo= gNotificationFunction, NULL, &Event); - ASSERT_EFI_ERROR (Status); - if (Status !=3D EFI_SUCCESS) { - return Status; - } - - Status =3D gBS->RegisterProtocolNotify (&gEfiGenericElogProtocolGuid, Ev= ent, &mGenericElogRegistration); - ASSERT_EFI_ERROR (Status); - if (Status !=3D EFI_SUCCESS) { - return Status; - } - - gBS->SignalEvent (Event); - - return EFI_SUCCESS; -} - -/** - This function sends event log data to the destination such as LAN, ICMB,= BMC etc. - - @param ElogData is a pointer to the event log data that needs to be = recorded - @param DataType type of Elog data that is being recorded. The Elog = is redirected based on this parameter. - @param AlertEvent is an indication that the input data type is an aler= t. The underlying - drivers need to decide if they need to listen to the= DataType and send it on - an appropriate channel as an alert use of the inform= ation. - @param DataSize is the size of the data to be logged - @param RecordId is the array of record IDs sent by the target. This= can be used to retrieve the - records or erase the records. - @retval EFI_SUCCESS - if the data was logged. - @retval EFI_INVALID_PARAMETER - if the DataType is >=3D EfiSmElogMax - @retval EFI_NOT_FOUND - the event log target was not found - @retval EFI_PROTOCOL_ERROR - there was a data formatting error - -**/ -EFI_STATUS -EfiSmSetEventLogData ( - IN UINT8 *ElogData, - IN EFI_SM_ELOG_TYPE DataType, - IN BOOLEAN AlertEvent, - IN UINTN DataSize, - OUT UINT64 *RecordId - ) -{ - // - // If the protocol is not found return EFI_NOT_FOUND - // - if (mGenericElogProtocol =3D=3D NULL) { - return EFI_NOT_FOUND; - } - - return mGenericElogProtocol->SetEventLogData ( - mGenericElogProtocol, - ElogData, - DataType, - AlertEvent, - DataSize, - RecordId - ); -} - -/** - This function gets event log data from the destination dependent on the = DataType. The destination - can be a remote target such as LAN, ICMB, IPMI, or a FV. The ELOG redir= driver will resolve the - destination. - - @param ElogData - pointer to the event log data buffer to contain the da= ta to be retrieved. - @param DataType - this is the type of Elog data to be gotten. Elog is r= edirected based upon this - information. - @param DataSize - this is the size of the data to be retrieved. - @param RecordId - the RecordId of the next record. If ElogData is NULL,= this gives the RecordId of the first - record available in the database with the correct Data= Size. A value of 0 on return indicates - that it was last record if the Status is EFI_SUCCESS. - - @retval EFI_SUCCESS - if the event log was retrieved successfully. - @retval EFI_NOT_FOUND - if the event log target was not found. - @retval EFI_NO_RESPONSE - if the event log target is not responding. Th= is is done by the redir driver. - @retval EFI_INVALID_PARAMETER - DataType or another parameter was invali= d. - @retval EFI_BUFFER_TOO_SMALL -the ElogData buffer is too small to be fil= led with the requested data. - -**/ -EFI_STATUS -EfiSmGetEventLogData ( - IN UINT8 *ElogData, - IN EFI_SM_ELOG_TYPE DataType, - IN OUT UINTN *DataSize, - IN OUT UINT64 *RecordId - ) -{ - // - // If the protocol is not found return EFI_NOT_FOUND - // - if (mGenericElogProtocol =3D=3D NULL) { - return EFI_NOT_FOUND; - } - - return mGenericElogProtocol->GetEventLogData ( - mGenericElogProtocol, - ElogData, - DataType, - DataSize, - RecordId - ); -} - -/** - This function erases the event log data defined by the DataType. The re= dir driver associated with - the DataType resolves the path to the record. - - @param DataType - the type of Elog data that is to be erased. - @param RecordId - the RecordId of the data to be erased. If RecordId is= NULL, all records in the - database are erased if permitted by the target. Recor= dId will contain the deleted - RecordId on return. - - @retval EFI_SUCCESS - the record or collection of records were erased. - @retval EFI_NOT_FOUND - the event log target was not found. - @retval EFI_NO_RESPONSE - the event log target was found but did not res= pond. - @retval EFI_INVALID_PARAMETER - one of the parameters was invalid. - -**/ -EFI_STATUS -EfiSmEraseEventlogData ( - IN EFI_SM_ELOG_TYPE DataType, - IN OUT UINT64 *RecordId - ) -{ - // - // If the protocol is not found return EFI_NOT_FOUND - // - if (mGenericElogProtocol =3D=3D NULL) { - return EFI_NOT_FOUND; - } - - return mGenericElogProtocol->EraseEventlogData ( - mGenericElogProtocol, - DataType, - RecordId - ); -} - -/** - This function enables or disables the event log defined by the DataType. - - - @param DataType - the type of Elog data that is being activated. - @param EnableElog - enables or disables the event log defined by the Dat= aType. If it is NULL - it returns the current status of the DataType log. - @param ElogStatus - is the current status of the Event log defined by th= e DataType. Enabled is - TRUE and Disabled is FALSE. - - @retval EFI_SUCCESS - if the event log was successfully enabled or disab= led. - @retval EFI_NOT_FOUND - the event log target was not found. - @retval EFI_NO_RESPONSE - the event log target was found but did not res= pond. - @retval EFI_INVALID_PARAMETER - one of the parameters was invalid. - -**/ -EFI_STATUS -EfiSmActivateEventLog ( - IN EFI_SM_ELOG_TYPE DataType, - IN BOOLEAN *EnableElog, - OUT BOOLEAN *ElogStatus - ) -{ - // - // If the protocol is not found return EFI_NOT_FOUND - // - if (mGenericElogProtocol =3D=3D NULL) { - return EFI_NOT_FOUND; - } - - return mGenericElogProtocol->ActivateEventLog ( - mGenericElogProtocol, - DataType, - EnableElog, - ElogStatus - ); -} - -/** - This function verifies the leap year - - @param Year year in YYYY format. - - @retval TRUE if the year is a leap year - -**/ -STATIC -BOOLEAN -IsLeapYear ( - IN UINT16 Year - ) -{ - if (Year % 4 =3D=3D 0) { - if (Year % 100 =3D=3D 0) { - if (Year % 400 =3D=3D 0) { - return TRUE; - } else { - return FALSE; - } - } else { - return TRUE; - } - } else { - return FALSE; - } -} - -/** - This function calculates the total number leap days from 1970 to the cur= rent year - - @param Time - Current Time - - @retval Returns the number of leap days since the base year, 1970. - -**/ -STATIC -UINTN -CountNumOfLeapDays ( - IN EFI_TIME *Time - ) -{ - UINT16 NumOfYear; - UINT16 BaseYear; - UINT16 Index; - UINTN Count; - - Count =3D 0; - BaseYear =3D 1970; - NumOfYear =3D Time->Year - 1970; - - for (Index =3D 0; Index <=3D NumOfYear; Index++) { - if (IsLeapYear (BaseYear + Index)) { - Count++; - } - } - - // - // If the current year is a leap year but the month is January or Februa= ry, - // then the leap day has not occurred and should not be counted. If it is - // February 29, the leap day is accounted for in CalculateNumOfDayPassed= ThisYear( ) - // - if (IsLeapYear (Time->Year)) { - if ((Count > 0) && (Time->Month < 3)) { - Count--; - } - } - - return Count; -} - -/** - This function calculates the total number of days passed till the day in= a year. - If the year is a leap year, an extra day is not added since the number o= f leap - days is calculated in CountNumOfLeapDays. - - @param Time This structure contains detailed information about date = and time - - @retval Returns the number of days passed until the input day. - -**/ -STATIC -UINTN -CalculateNumOfDayPassedThisYear ( - IN EFI_TIME Time - ) -{ - UINTN Index; - UINTN NumOfDays; - - NumOfDays =3D 0; - for (Index =3D 1; Index < Time.Month; Index++) { - NumOfDays +=3D DaysOfMonth[Index - 1]; - } - - NumOfDays +=3D Time.Day; - return NumOfDays; -} - -/** - Function converts a BCD to a decimal value. - - @param[in] BcdValue An 8 bit BCD value - - @return The decimal value of the BcdValue -**/ -STATIC -UINT8 -BcdToDecimal ( - IN UINT8 BcdValue - ) -{ - UINTN High; - UINTN Low; - - High =3D BcdValue >> 4; - Low =3D BcdValue - (High << 4); - - return (UINT8)(Low + (High * 10)); -} - -// -// RTC read functions were copied here since we need to get the time -// in both DXE and runtime code. The PcRtc driver is not currently a -// dual mode driver, this is more efficient since making PcRtc dual mode -// would unnecessarily bloat the SMM code space. -// - -/** - Read data register and return contents. - - @param Address - Register address to read - - @retval Value of data register contents - -**/ -STATIC -UINT8 -RtcRead ( - IN UINT8 Address - ) -{ - IoWrite8 (PCAT_RTC_ADDRESS_REGISTER, (UINT8)(Address | (UINT8)(IoRead8 (= PCAT_RTC_ADDRESS_REGISTER) & 0x80))); - return IoRead8 (PCAT_RTC_DATA_REGISTER); -} - -/** - Write data to register address. - - @param Address - Register address to write - @param Data - Data to write to register - -**/ -STATIC -VOID -RtcWrite ( - IN UINT8 Address, - IN UINT8 Data - ) -{ - IoWrite8 (PCAT_RTC_ADDRESS_REGISTER, (UINT8)(Address | (UINT8)(IoRead8 (= PCAT_RTC_ADDRESS_REGISTER) & 0x80))); - IoWrite8 (PCAT_RTC_DATA_REGISTER, Data); -} - -/** - Convert Rtc Time To Efi Time. - - @param Time - @param RegisterB - -**/ -STATIC -VOID -ConvertRtcTimeToEfiTime ( - IN EFI_TIME *Time, - IN RTC_REGISTER_B RegisterB - ) -{ - BOOLEAN Pm; - - if ((Time->Hour) & 0x80) { - Pm =3D TRUE; - } else { - Pm =3D FALSE; - } - - Time->Hour =3D (UINT8)(Time->Hour & 0x7f); - - if (RegisterB.Bits.DM =3D=3D 0) { - Time->Year =3D BcdToDecimal ((UINT8)Time->Year); - Time->Month =3D BcdToDecimal (Time->Month); - Time->Day =3D BcdToDecimal (Time->Day); - Time->Hour =3D BcdToDecimal (Time->Hour); - Time->Minute =3D BcdToDecimal (Time->Minute); - Time->Second =3D BcdToDecimal (Time->Second); - } - - // - // If time is in 12 hour format, convert it to 24 hour format - // - if (RegisterB.Bits.MIL =3D=3D 0) { - if (Pm && (Time->Hour < 12)) { - Time->Hour =3D (UINT8)(Time->Hour + 12); - } - - if (!Pm && (Time->Hour =3D=3D 12)) { - Time->Hour =3D 0; - } - } - - Time->Nanosecond =3D 0; - Time->TimeZone =3D EFI_UNSPECIFIED_TIMEZONE; - Time->Daylight =3D 0; -} - -/** - Test Century Register. - - @retval EFI_SUCCESS - @retval EFI_DEVICE_ERROR - -**/ -STATIC -EFI_STATUS -RtcTestCenturyRegister ( - VOID - ) -{ - UINT8 Century; - UINT8 Temp; - - Century =3D RtcRead (RTC_ADDRESS_CENTURY); - - // - // Always sync-up the Bit7 "semaphore"...this maintains - // consistency across the different chips/implementations of - // the RTC... - // - RtcWrite (RTC_ADDRESS_CENTURY, 0x00); - Temp =3D (UINT8)(RtcRead (RTC_ADDRESS_CENTURY) & 0x7f); - RtcWrite (RTC_ADDRESS_CENTURY, Century); - if ((Temp =3D=3D 0x19) || (Temp =3D=3D 0x20)) { - return EFI_SUCCESS; - } - - return EFI_DEVICE_ERROR; -} - -/** - Waits until RTC register A and D show data is valid. - - @param Timeout - Maximum time to wait - - @retval EFI_DEVICE_ERROR - @retval EFI_SUCCESS - -**/ -STATIC -EFI_STATUS -RtcWaitToUpdate ( - UINTN Timeout - ) -{ - RTC_REGISTER_A RegisterA; - RTC_REGISTER_D RegisterD; - - // - // See if the RTC is functioning correctly - // - RegisterD.Data =3D RtcRead (RTC_ADDRESS_REGISTER_D); - - if (RegisterD.Bits.VRT =3D=3D 0) { - return EFI_DEVICE_ERROR; - } - - // - // Wait for up to 0.1 seconds for the RTC to be ready. - // - Timeout =3D (Timeout / 10) + 1; - RegisterA.Data =3D RtcRead (RTC_ADDRESS_REGISTER_A); - while (RegisterA.Bits.UIP =3D=3D 1 && Timeout > 0) { - gBS->Stall (10); - RegisterA.Data =3D RtcRead (RTC_ADDRESS_REGISTER_A); - Timeout--; - } - - RegisterD.Data =3D RtcRead (RTC_ADDRESS_REGISTER_D); - if ((Timeout =3D=3D 0) || (RegisterD.Bits.VRT =3D=3D 0)) { - return EFI_DEVICE_ERROR; - } - - return EFI_SUCCESS; -} - -/** - Get time from RTC. - - @param Time - pointer to time structure - - @retval EFI_INVALID_PARAMETER - @retval EFI_SUCCESS - -**/ -STATIC -EFI_STATUS -RtcGetTime ( - OUT EFI_TIME *Time - ) -{ - RTC_REGISTER_B RegisterB; - UINT8 Century; - EFI_STATUS Status; - - // - // Check parameters for null pointer - // - if (Time =3D=3D NULL) { - return EFI_INVALID_PARAMETER; - } - - // - // Wait for up to 0.1 seconds for the RTC to be updated - // - Status =3D RtcWaitToUpdate (100000); - if (EFI_ERROR (Status)) { - return Status; - } - - // - // Read Register B - // - RegisterB.Data =3D RtcRead (RTC_ADDRESS_REGISTER_B); - - // - // Get the Time/Date/Daylight Savings values. - // - Time->Second =3D RtcRead (RTC_ADDRESS_SECONDS); - Time->Minute =3D RtcRead (RTC_ADDRESS_MINUTES); - Time->Hour =3D RtcRead (RTC_ADDRESS_HOURS); - Time->Day =3D RtcRead (RTC_ADDRESS_DAY_OF_THE_MONTH); - Time->Month =3D RtcRead (RTC_ADDRESS_MONTH); - Time->Year =3D RtcRead (RTC_ADDRESS_YEAR); - - ConvertRtcTimeToEfiTime (Time, RegisterB); - - if (RtcTestCenturyRegister () =3D=3D EFI_SUCCESS) { - Century =3D BcdToDecimal ((UINT8)(RtcRead (RTC_ADDRESS_CENTURY) & 0x7f= )); - } else { - Century =3D BcdToDecimal (RtcRead (RTC_ADDRESS_CENTURY)); - } - - Time->Year =3D (UINT16)(Century * 100 + Time->Year); - - return EFI_SUCCESS; -} - -/** - Return Date and Time from RTC in Unix format which fits in 32 bit format. - - @param NumOfSeconds - pointer to return calculated time - - @retval EFI_SUCCESS - @retval EFI status if error occurred - -**/ -EFI_STATUS -EfiSmGetTimeStamp ( - OUT UINT32 *NumOfSeconds - ) -{ - UINT16 NumOfYears; - UINTN NumOfLeapDays; - UINTN NumOfDays; - EFI_TIME Time; - EFI_STATUS Status; - - Status =3D RtcGetTime (&Time); - if (EFI_ERROR (Status)) { - return Status; - } - - NumOfYears =3D Time.Year - 1970; - NumOfLeapDays =3D CountNumOfLeapDays (&Time); - NumOfDays =3D CalculateNumOfDayPassedThisYear (Time); - - // - // Add 365 days for all years. Add additional days for Leap Years. Subtr= act off current day. - // - NumOfDays +=3D (NumOfLeapDays + (365 * NumOfYears) - 1); - - *NumOfSeconds =3D (UINT32)(3600 * 24 * NumOfDays + (Time.Hour * 3600) + = (60 * Time.Minute) + Time.Second); - - return EFI_SUCCESS; -} +/** @file + Lightweight lib to support EFI Server Management drivers. + This source file provides EfiSmGetTimeStamp support. + +Copyright (c) 2023, Intel Corporation. All rights reserved.
+SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include +#include +#include +#include + +#include + +// #include EFI_PROTOCOL_DEPENDENCY (CpuIo) + +#define PCAT_RTC_ADDRESS_REGISTER 0x70 +#define PCAT_RTC_DATA_REGISTER 0x71 + +#define RTC_ADDRESS_SECONDS 0 // R/W Range 0..59 +#define RTC_ADDRESS_MINUTES 2 // R/W Range 0..59 +#define RTC_ADDRESS_HOURS 4 // R/W Range 1..12 or 0..23 Bit= 7 is AM/PM +#define RTC_ADDRESS_DAY_OF_THE_MONTH 7 // R/W Range 1..31 +#define RTC_ADDRESS_MONTH 8 // R/W Range 1..12 +#define RTC_ADDRESS_YEAR 9 // R/W Range 0..99 +#define RTC_ADDRESS_REGISTER_A 10 // R/W[0..6] R0[7] +#define RTC_ADDRESS_REGISTER_B 11 // R/W +#define RTC_ADDRESS_REGISTER_C 12 // RO +#define RTC_ADDRESS_REGISTER_D 13 // RO +#define RTC_ADDRESS_CENTURY 50 // R/W Range 19..20 Bit 8 is R/W + +// +// Register A +// +typedef struct { + UINT8 RS : 4; // Rate Selection Bits + UINT8 DV : 3; // Divisor + UINT8 UIP : 1; // Update in progress +} RTC_REGISTER_A_BITS; + +typedef union { + RTC_REGISTER_A_BITS Bits; + UINT8 Data; +} RTC_REGISTER_A; + +// +// Register B +// +typedef struct { + UINT8 DSE : 1; // 0 - Daylight saving disabled 1 - Daylight savings= enabled + UINT8 MIL : 1; // 0 - 12 hour mode 1 - 24 hour mode + UINT8 DM : 1; // 0 - BCD Format 1 - Binary Format + UINT8 SQWE : 1; // 0 - Disable SQWE output 1 - Enable SQWE outp= ut + UINT8 UIE : 1; // 0 - Update INT disabled 1 - Update INT enabl= ed + UINT8 AIE : 1; // 0 - Alarm INT disabled 1 - Alarm INT Enabled + UINT8 PIE : 1; // 0 - Periodic INT disabled 1 - Periodic INT Ena= bled + UINT8 SET : 1; // 0 - Normal operation. 1 - Updates inhibited +} RTC_REGISTER_B_BITS; + +typedef union { + RTC_REGISTER_B_BITS Bits; + UINT8 Data; +} RTC_REGISTER_B; + +// +// Register D +// +typedef struct { + UINT8 Reserved : 7; // Read as zero. Can not be written. + UINT8 VRT : 1; // Valid RAM and Time +} RTC_REGISTER_D_BITS; + +typedef union { + RTC_REGISTER_D_BITS Bits; + UINT8 Data; +} RTC_REGISTER_D; + +// +// Module Globals +// +INTN DaysOfMonth[12] =3D { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31= }; + +/** + This function verifies the leap year + + @param Year year in YYYY format. + + @retval TRUE if the year is a leap year + +**/ +STATIC +BOOLEAN +IsLeapYear ( + IN UINT16 Year + ) +{ + if (Year % 4 =3D=3D 0) { + if (Year % 100 =3D=3D 0) { + if (Year % 400 =3D=3D 0) { + return TRUE; + } else { + return FALSE; + } + } else { + return TRUE; + } + } else { + return FALSE; + } +} + +/** + This function calculates the total number leap days from 1970 to the cur= rent year + + @param Time - Current Time + + @retval Returns the number of leap days since the base year, 1970. + +**/ +STATIC +UINTN +CountNumOfLeapDays ( + IN EFI_TIME *Time + ) +{ + UINT16 NumOfYear; + UINT16 BaseYear; + UINT16 Index; + UINTN Count; + + Count =3D 0; + BaseYear =3D 1970; + NumOfYear =3D Time->Year - 1970; + + for (Index =3D 0; Index <=3D NumOfYear; Index++) { + if (IsLeapYear (BaseYear + Index)) { + Count++; + } + } + + // + // If the current year is a leap year but the month is January or Februa= ry, + // then the leap day has not occurred and should not be counted. If it is + // February 29, the leap day is accounted for in CalculateNumOfDayPassed= ThisYear( ) + // + if (IsLeapYear (Time->Year)) { + if ((Count > 0) && (Time->Month < 3)) { + Count--; + } + } + + return Count; +} + +/** + This function calculates the total number of days passed till the day in= a year. + If the year is a leap year, an extra day is not added since the number o= f leap + days is calculated in CountNumOfLeapDays. + + @param Time This structure contains detailed information about date = and time + + @retval Returns the number of days passed until the input day. + +**/ +STATIC +UINTN +CalculateNumOfDayPassedThisYear ( + IN EFI_TIME Time + ) +{ + UINTN Index; + UINTN NumOfDays; + + NumOfDays =3D 0; + for (Index =3D 1; Index < Time.Month; Index++) { + NumOfDays +=3D DaysOfMonth[Index - 1]; + } + + NumOfDays +=3D Time.Day; + return NumOfDays; +} + +/** + Function converts a BCD to a decimal value. + + @param[in] BcdValue An 8 bit BCD value + + @return The decimal value of the BcdValue +**/ +STATIC +UINT8 +BcdToDecimal ( + IN UINT8 BcdValue + ) +{ + UINTN High; + UINTN Low; + + High =3D BcdValue >> 4; + Low =3D BcdValue - (High << 4); + + return (UINT8)(Low + (High * 10)); +} + +// +// RTC read functions were copied here since we need to get the time +// in both DXE and runtime code. The PcRtc driver is not currently a +// dual mode driver, this is more efficient since making PcRtc dual mode +// would unnecessarily bloat the SMM code space. +// + +/** + Read data register and return contents. + + @param Address - Register address to read + + @retval Value of data register contents + +**/ +STATIC +UINT8 +RtcRead ( + IN UINT8 Address + ) +{ + IoWrite8 (PCAT_RTC_ADDRESS_REGISTER, (UINT8)(Address | (UINT8)(IoRead8 (= PCAT_RTC_ADDRESS_REGISTER) & 0x80))); + return IoRead8 (PCAT_RTC_DATA_REGISTER); +} + +/** + Write data to register address. + + @param Address - Register address to write + @param Data - Data to write to register + +**/ +STATIC +VOID +RtcWrite ( + IN UINT8 Address, + IN UINT8 Data + ) +{ + IoWrite8 (PCAT_RTC_ADDRESS_REGISTER, (UINT8)(Address | (UINT8)(IoRead8 (= PCAT_RTC_ADDRESS_REGISTER) & 0x80))); + IoWrite8 (PCAT_RTC_DATA_REGISTER, Data); +} + +/** + Convert Rtc Time To Efi Time. + + @param Time + @param RegisterB + +**/ +STATIC +VOID +ConvertRtcTimeToEfiTime ( + IN EFI_TIME *Time, + IN RTC_REGISTER_B RegisterB + ) +{ + BOOLEAN Pm; + + if ((Time->Hour) & 0x80) { + Pm =3D TRUE; + } else { + Pm =3D FALSE; + } + + Time->Hour =3D (UINT8)(Time->Hour & 0x7f); + + if (RegisterB.Bits.DM =3D=3D 0) { + Time->Year =3D BcdToDecimal ((UINT8)Time->Year); + Time->Month =3D BcdToDecimal (Time->Month); + Time->Day =3D BcdToDecimal (Time->Day); + Time->Hour =3D BcdToDecimal (Time->Hour); + Time->Minute =3D BcdToDecimal (Time->Minute); + Time->Second =3D BcdToDecimal (Time->Second); + } + + // + // If time is in 12 hour format, convert it to 24 hour format + // + if (RegisterB.Bits.MIL =3D=3D 0) { + if (Pm && (Time->Hour < 12)) { + Time->Hour =3D (UINT8)(Time->Hour + 12); + } + + if (!Pm && (Time->Hour =3D=3D 12)) { + Time->Hour =3D 0; + } + } + + Time->Nanosecond =3D 0; + Time->TimeZone =3D EFI_UNSPECIFIED_TIMEZONE; + Time->Daylight =3D 0; +} + +/** + Test Century Register. + + @retval EFI_SUCCESS + @retval EFI_DEVICE_ERROR + +**/ +STATIC +EFI_STATUS +RtcTestCenturyRegister ( + VOID + ) +{ + UINT8 Century; + UINT8 Temp; + + Century =3D RtcRead (RTC_ADDRESS_CENTURY); + + // + // Always sync-up the Bit7 "semaphore"...this maintains + // consistency across the different chips/implementations of + // the RTC... + // + RtcWrite (RTC_ADDRESS_CENTURY, 0x00); + Temp =3D (UINT8)(RtcRead (RTC_ADDRESS_CENTURY) & 0x7f); + RtcWrite (RTC_ADDRESS_CENTURY, Century); + if ((Temp =3D=3D 0x19) || (Temp =3D=3D 0x20)) { + return EFI_SUCCESS; + } + + return EFI_DEVICE_ERROR; +} + +/** + Waits until RTC register A and D show data is valid. + + @param Timeout - Maximum time to wait + + @retval EFI_DEVICE_ERROR + @retval EFI_SUCCESS + +**/ +STATIC +EFI_STATUS +RtcWaitToUpdate ( + UINTN Timeout + ) +{ + RTC_REGISTER_A RegisterA; + RTC_REGISTER_D RegisterD; + + // + // See if the RTC is functioning correctly + // + RegisterD.Data =3D RtcRead (RTC_ADDRESS_REGISTER_D); + + if (RegisterD.Bits.VRT =3D=3D 0) { + return EFI_DEVICE_ERROR; + } + + // + // Wait for up to 0.1 seconds for the RTC to be ready. + // + Timeout =3D (Timeout / 10) + 1; + RegisterA.Data =3D RtcRead (RTC_ADDRESS_REGISTER_A); + while (RegisterA.Bits.UIP =3D=3D 1 && Timeout > 0) { + MicroSecondDelay (10); + RegisterA.Data =3D RtcRead (RTC_ADDRESS_REGISTER_A); + Timeout--; + } + + RegisterD.Data =3D RtcRead (RTC_ADDRESS_REGISTER_D); + if ((Timeout =3D=3D 0) || (RegisterD.Bits.VRT =3D=3D 0)) { + return EFI_DEVICE_ERROR; + } + + return EFI_SUCCESS; +} + +/** + Get time from RTC. + + @param Time - pointer to time structure + + @retval EFI_INVALID_PARAMETER + @retval EFI_SUCCESS + +**/ +STATIC +EFI_STATUS +RtcGetTime ( + OUT EFI_TIME *Time + ) +{ + RTC_REGISTER_B RegisterB; + UINT8 Century; + EFI_STATUS Status; + + // + // Check parameters for null pointer + // + if (Time =3D=3D NULL) { + return EFI_INVALID_PARAMETER; + } + + // + // Wait for up to 0.1 seconds for the RTC to be updated + // + Status =3D RtcWaitToUpdate (100000); + if (EFI_ERROR (Status)) { + return Status; + } + + // + // Read Register B + // + RegisterB.Data =3D RtcRead (RTC_ADDRESS_REGISTER_B); + + // + // Get the Time/Date/Daylight Savings values. + // + Time->Second =3D RtcRead (RTC_ADDRESS_SECONDS); + Time->Minute =3D RtcRead (RTC_ADDRESS_MINUTES); + Time->Hour =3D RtcRead (RTC_ADDRESS_HOURS); + Time->Day =3D RtcRead (RTC_ADDRESS_DAY_OF_THE_MONTH); + Time->Month =3D RtcRead (RTC_ADDRESS_MONTH); + Time->Year =3D RtcRead (RTC_ADDRESS_YEAR); + + ConvertRtcTimeToEfiTime (Time, RegisterB); + + if (RtcTestCenturyRegister () =3D=3D EFI_SUCCESS) { + Century =3D BcdToDecimal ((UINT8)(RtcRead (RTC_ADDRESS_CENTURY) & 0x7f= )); + } else { + Century =3D BcdToDecimal (RtcRead (RTC_ADDRESS_CENTURY)); + } + + Time->Year =3D (UINT16)(Century * 100 + Time->Year); + + return EFI_SUCCESS; +} + +/** + Return Date and Time from RTC in Unix format which fits in 32 bit format. + + @param NumOfSeconds - pointer to return calculated time + + @retval EFI_SUCCESS + @retval EFI status if error occurred + +**/ +EFI_STATUS +EfiSmGetTimeStamp ( + OUT UINT32 *NumOfSeconds + ) +{ + UINT16 NumOfYears; + UINTN NumOfLeapDays; + UINTN NumOfDays; + EFI_TIME Time; + EFI_STATUS Status; + + Status =3D RtcGetTime (&Time); + if (EFI_ERROR (Status)) { + return Status; + } + + NumOfYears =3D Time.Year - 1970; + NumOfLeapDays =3D CountNumOfLeapDays (&Time); + NumOfDays =3D CalculateNumOfDayPassedThisYear (Time); + + // + // Add 365 days for all years. Add additional days for Leap Years. Subtr= act off current day. + // + NumOfDays +=3D (NumOfLeapDays + (365 * NumOfYears) - 1); + + *NumOfSeconds =3D (UINT32)(3600 * 24 * NumOfDays + (Time.Hour * 3600) + = (60 * Time.Minute) + Time.Second); + + return EFI_SUCCESS; +} diff --git a/Features/Intel/OutOfBandManagement/IpmiFeaturePkg/Library/Serv= erManagementLib/StandaloneMmServerManagementLib.inf b/Features/Intel/OutOfB= andManagement/IpmiFeaturePkg/Library/ServerManagementLib/StandaloneMmServer= ManagementLib.inf new file mode 100644 index 000000000000..e44a1624d0eb --- /dev/null +++ b/Features/Intel/OutOfBandManagement/IpmiFeaturePkg/Library/ServerManag= ementLib/StandaloneMmServerManagementLib.inf @@ -0,0 +1,29 @@ +### @file +# +# Copyright (c) 2023, Intel Corporation. All rights reserved.
+# +# SPDX-License-Identifier: BSD-2-Clause-Patent +# +### + + +[Defines] + INF_VERSION =3D 0x00010005 + BASE_NAME =3D StandaloneMmServerManagementLib + FILE_GUID =3D b2740ad0-c15e-43a5-a13a-c8e078cc83ee + MODULE_TYPE =3D MM_STANDALONE + VERSION_STRING =3D 1.0 + PI_SPECIFICATION_VERSION =3D 0x00010032 + LIBRARY_CLASS =3D ServerManagementLib + +[Sources] + ServerManagementTime.c + +[Packages] + IpmiFeaturePkg/IpmiFeaturePkg.dec + MdePkg/MdePkg.dec + +[LibraryClasses] + IoLib + DebugLib + TimerLib --=20 2.29.2.windows.2 -=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D- Groups.io Links: You receive all messages sent to this group. View/Reply Online (#112765): https://edk2.groups.io/g/devel/message/112765 Mute This Topic: https://groups.io/mt/103284558/1787277 Group Owner: devel+owner@edk2.groups.io Unsubscribe: https://edk2.groups.io/g/devel/unsub [importer@patchew.org] -=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-