[edk2-devel] [PATCH edk2-platforms 2/4] IpmiFeaturePkg: Add ServerManagementLib

Zhen Gong zhen.gong at intel.com
Fri Oct 27 20:11:14 UTC 2023


Lightweight lib to support Server Management drivers.

Signed-off-by: Zhen Gong <zhen.gong at intel.com>
---
 .../IpmiFeaturePkg/Include/IpmiFeature.dsc    |   1 +
 .../ServerManagementLib.inf                   |  35 +
 .../ServerManagementLibNull.inf               |  38 +
 .../Include/Library/ServerMgmtRtLib.h         | 147 ++++
 .../ServerManagementLib/ServerManagementLib.c | 696 ++++++++++++++++++
 .../ServerManagementLibNull.c                 | 144 ++++
 6 files changed, 1061 insertions(+)
 create mode 100644 Features/Intel/OutOfBandManagement/IpmiFeaturePkg/Library/ServerManagementLib/ServerManagementLib.inf
 create mode 100644 Features/Intel/OutOfBandManagement/IpmiFeaturePkg/Library/ServerManagementLibNull/ServerManagementLibNull.inf
 create mode 100644 Features/Intel/OutOfBandManagement/IpmiFeaturePkg/Include/Library/ServerMgmtRtLib.h
 create mode 100644 Features/Intel/OutOfBandManagement/IpmiFeaturePkg/Library/ServerManagementLib/ServerManagementLib.c
 create mode 100644 Features/Intel/OutOfBandManagement/IpmiFeaturePkg/Library/ServerManagementLibNull/ServerManagementLibNull.c

diff --git a/Features/Intel/OutOfBandManagement/IpmiFeaturePkg/Include/IpmiFeature.dsc b/Features/Intel/OutOfBandManagement/IpmiFeaturePkg/Include/IpmiFeature.dsc
index fa98e5672d83..fc9001e98473 100644
--- a/Features/Intel/OutOfBandManagement/IpmiFeaturePkg/Include/IpmiFeature.dsc
+++ b/Features/Intel/OutOfBandManagement/IpmiFeaturePkg/Include/IpmiFeature.dsc
@@ -51,6 +51,7 @@ [LibraryClasses.common.DXE_DRIVER,LibraryClasses.common.UEFI_DRIVER]
 [LibraryClasses.common]
   BmcCommonInterfaceLib|IpmiFeaturePkg/Library/BmcInterfaceCommonAccess/BmcCommonInterfaceLib.inf
   BtInterfaceLib|IpmiFeaturePkg/Library/BmcInterfaceCommonAccess/BtInterfaceLib/BtInterfaceLib.inf
+  ServerManagementLib|IpmiFeaturePkg/Library/ServerManagementLib/ServerManagementLib.inf
 
 [LibraryClasses.common.DXE_RUNTIME_DRIVER, LibraryClasses.common.DXE_DRIVER]
   SsifInterfaceLib|IpmiFeaturePkg/Library/BmcInterfaceCommonAccess/SsifInterfaceLib/DxeSsifInterfaceLib.inf
diff --git a/Features/Intel/OutOfBandManagement/IpmiFeaturePkg/Library/ServerManagementLib/ServerManagementLib.inf b/Features/Intel/OutOfBandManagement/IpmiFeaturePkg/Library/ServerManagementLib/ServerManagementLib.inf
new file mode 100644
index 000000000000..25a3a7540762
--- /dev/null
+++ b/Features/Intel/OutOfBandManagement/IpmiFeaturePkg/Library/ServerManagementLib/ServerManagementLib.inf
@@ -0,0 +1,35 @@
+### @file
+#
+# Copyright (c) 2023, Intel Corporation. All rights reserved.<BR>
+#
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+###
+
+
+[Defines]
+  INF_VERSION                = 0x00010005
+  BASE_NAME                  = ServerManagementLib
+  FILE_GUID                  = D43C86F0-7C8B-4992-9593-8CB6FBC66A0A
+  MODULE_TYPE                = BASE
+  VERSION_STRING             = 1.0
+  PI_SPECIFICATION_VERSION   = 0x0001000A
+  LIBRARY_CLASS              = ServerManagementLib
+
+[Sources]
+  ServerManagementLib.c
+
+[Packages]
+  IpmiFeaturePkg/IpmiFeaturePkg.dec
+  MdePkg/MdePkg.dec
+
+[LibraryClasses]
+  IoLib
+  DebugLib
+  UefiBootServicesTableLib
+
+[Protocols]
+  gEfiGenericElogProtocolGuid
+
+
+
diff --git a/Features/Intel/OutOfBandManagement/IpmiFeaturePkg/Library/ServerManagementLibNull/ServerManagementLibNull.inf b/Features/Intel/OutOfBandManagement/IpmiFeaturePkg/Library/ServerManagementLibNull/ServerManagementLibNull.inf
new file mode 100644
index 000000000000..6b66b44857f3
--- /dev/null
+++ b/Features/Intel/OutOfBandManagement/IpmiFeaturePkg/Library/ServerManagementLibNull/ServerManagementLibNull.inf
@@ -0,0 +1,38 @@
+### @file
+#
+# Copyright (c) 2023, Intel Corporation. All rights reserved.<BR>
+#
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+###
+
+
+[Defines]
+  INF_VERSION                   = 0x00010005
+  BASE_NAME                     = ServerManagementLibNull
+  FILE_GUID                     = 3AC01DE9-5A96-4df5-A645-ECD092C29AF9
+  MODULE_TYPE                   = BASE
+  VERSION_STRING                = 1.0
+  PI_SPECIFICATION_VERSION      = 0x0001000A
+  LIBRARY_CLASS                 = ServerManagementLib
+
+#
+# The following information is for reference only and not required by the build tools.
+#
+#  VALID_ARCHITECTURES          = IA32 X64
+#
+
+[Sources.common]
+  ServerManagementLibNull.c
+
+
+[Packages]
+  MdePkg/MdePkg.dec
+  ServerPlatformPkg/PlatformPkg.dec
+
+[LibraryClasses]
+  DebugLib
+
+[Protocols]
+
+
diff --git a/Features/Intel/OutOfBandManagement/IpmiFeaturePkg/Include/Library/ServerMgmtRtLib.h b/Features/Intel/OutOfBandManagement/IpmiFeaturePkg/Include/Library/ServerMgmtRtLib.h
new file mode 100644
index 000000000000..12b2e82f9e6e
--- /dev/null
+++ b/Features/Intel/OutOfBandManagement/IpmiFeaturePkg/Include/Library/ServerMgmtRtLib.h
@@ -0,0 +1,147 @@
+/** @file
+  Server Management Driver Lib.
+
+Copyright (c) 2023, Intel Corporation. All rights reserved.<BR>
+SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#ifndef _SERVER_MGMT_LIB_H_
+#define _SERVER_MGMT_LIB_H_
+
+#include <Protocol/GenericElog.h>
+
+/**
+  ELOG Library Initializer.
+**/
+
+/**
+  The function will set up a notification on the ELOG protocol.  This function is required to be called prior
+  to utilizing the ELOG protocol from within this library.
+  @param None
+
+  @retval EFI_SUCCESS  After the notification has been setup.
+  @retval Other        Failure in constructor.
+
+**/
+EFI_STATUS
+EfiInitializeGenericElog (
+  VOID
+  );
+
+/**
+
+  This function sends event log data to the destination such as LAN, ICMB, BMC etc.
+  @param[in] ElogData A pointer to the event log data that needs to be recorded
+  @param[in] DataType Type of Elog data that is being recorded.  The Elog is redirected based on this
+               parameter.
+  @param[in] AlertEvent An indication that the input data type is an alert.  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 information.
+  @param[in] DataSize The size of the data to be logged
+  @param[out] RecordId 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 >= EfiSmElogMax
+  @retval EFI_OUT_OF_RESOURCES If the DataSize is larger than the Elog temp buffer and we cannot log the record
+  @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
+  );
+
+/**
+
+  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[in] ElogData Pointer to the event log data buffer to contain the data to be retrieved.
+  @param[in] DataType This is the type of Elog data to be gotten.  Elog is redirected based upon this
+             information.
+  @param[in, out] DataSize This is the size of the data to be retrieved.
+  @param[in, out] 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 DataSize.  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.  This is done by the redir driver.
+  @retval EFI_INVALID_PARAMETER DataType or another parameter was invalid.
+  @retval EFI_BUFFER_TOO_SMALL The ElogData buffer is too small to be filled with the requested data.
+
+**/
+EFI_STATUS
+EfiSmGetEventLogData (
+  IN  UINT8             *ElogData,
+  IN  EFI_SM_ELOG_TYPE  DataType,
+  IN  OUT UINTN         *DataSize,
+  IN OUT UINT64         *RecordId
+  );
+
+/**
+  This function erases the event log data defined by the DataType.  The redir driver associated with
+  the DataType resolves the path to the record.
+
+  @param[in] DataType The type of Elog data that is to be erased.
+  @param[in, out] 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.  RecordId 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 respond.
+  @retval EFI_INVALID_PARAMETER One of the parameters was invalid.
+
+**/
+EFI_STATUS
+EfiSmEraseEventlogData (
+  IN EFI_SM_ELOG_TYPE  DataType,
+  IN OUT UINT64        *RecordId
+  );
+
+/**
+
+  This function enables or disables the event log defined by the DataType.
+  @param[in] DataType The type of Elog data that is being activated.
+  @param[in] EnableElog Enables or disables the event log defined by the DataType.  If it is NULL
+             it returns the current status of the DataType log.
+  @param[out] ElogStatus Is the current status of the Event log defined by the DataType.  Enabled is
+              TRUE and Disabled is FALSE.
+
+  @retval EFI_SUCCESS If the event log was successfully enabled or disabled.
+  @retval EFI_NOT_FOUND The event log target was not found.
+  @retval EFI_NO_RESPONSE The event log target was found but did not respond.
+  @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
+  );
+
+/**
+
+  Return Date and Time from RTC in Unix format which fits in 32 bit format.
+
+  @param[out] NumOfSeconds Pointer to return calculated time.
+
+  @retval EFI_SUCCESS
+  @retval Other EFI status if error occurred.
+
+**/
+EFI_STATUS
+EfiSmGetTimeStamp (
+  OUT UINT32  *NumOfSeconds
+  );
+
+#endif // _SERVER_MGMT_LIB_H_
diff --git a/Features/Intel/OutOfBandManagement/IpmiFeaturePkg/Library/ServerManagementLib/ServerManagementLib.c b/Features/Intel/OutOfBandManagement/IpmiFeaturePkg/Library/ServerManagementLib/ServerManagementLib.c
new file mode 100644
index 000000000000..66a481fa57b4
--- /dev/null
+++ b/Features/Intel/OutOfBandManagement/IpmiFeaturePkg/Library/ServerManagementLib/ServerManagementLib.c
@@ -0,0 +1,696 @@
+/** @file
+  Lightweight lib to support EFI Server Management drivers.
+
+Copyright (c) 2023, Intel Corporation. All rights reserved.<BR>
+SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include <PiDxe.h>
+#include <Library/IoLib.h>
+#include <Library/DebugLib.h>
+#include <Library/UefiBootServicesTableLib.h>
+#include <Protocol/GenericElog.h>
+
+#include <Library/ServerMgmtRtLib.h>
+
+// #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 output
+  UINT8    UIE  : 1; // 0 - Update INT disabled       1 - Update INT enabled
+  UINT8    AIE  : 1; // 0 - Alarm INT disabled        1 - Alarm INT Enabled
+  UINT8    PIE  : 1; // 0 - Periodic INT disabled     1 - Periodic INT Enabled
+  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     = NULL;
+VOID                  *mGenericElogRegistration = NULL;
+
+INTN  DaysOfMonth[12] = { 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 = gBS->LocateProtocol (&gEfiGenericElogProtocolGuid, NULL, (VOID **)&mGenericElogProtocol);
+  if (EFI_ERROR (Status)) {
+    mGenericElogProtocol = NULL;
+  }
+}
+
+/**
+  The function will set up a notification on the ELOG protocol.  This function 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 = gBS->CreateEvent (EVT_NOTIFY_SIGNAL, TPL_CALLBACK, GenericElogNotificationFunction, NULL, &Event);
+  ASSERT_EFI_ERROR (Status);
+  if (Status != EFI_SUCCESS) {
+    return Status;
+  }
+
+  Status = gBS->RegisterProtocolNotify (&gEfiGenericElogProtocolGuid, Event, &mGenericElogRegistration);
+  ASSERT_EFI_ERROR (Status);
+  if (Status != 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 alert.  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 information.
+  @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 >= 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 == 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 data to be retrieved.
+  @param DataType - this is the type of Elog data to be gotten.  Elog is redirected 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 DataSize.  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.  This is done by the redir driver.
+  @retval EFI_INVALID_PARAMETER - DataType or another parameter was invalid.
+  @retval EFI_BUFFER_TOO_SMALL -the ElogData buffer is too small to be filled 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 == 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 redir 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.  RecordId 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 respond.
+  @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 == 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 DataType.  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 the DataType.  Enabled is
+                      TRUE and Disabled is FALSE.
+
+  @retval EFI_SUCCESS - if the event log was successfully enabled or disabled.
+  @retval EFI_NOT_FOUND - the event log target was not found.
+  @retval EFI_NO_RESPONSE - the event log target was found but did not respond.
+  @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 == 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 == 0) {
+    if (Year % 100 == 0) {
+      if (Year % 400 == 0) {
+        return TRUE;
+      } else {
+        return FALSE;
+      }
+    } else {
+      return TRUE;
+    }
+  } else {
+    return FALSE;
+  }
+}
+
+/**
+  This function calculates the total number leap days from 1970 to the current 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     = 0;
+  BaseYear  = 1970;
+  NumOfYear = Time->Year - 1970;
+
+  for (Index = 0; Index <= NumOfYear; Index++) {
+    if (IsLeapYear (BaseYear + Index)) {
+      Count++;
+    }
+  }
+
+  //
+  // If the current year is a leap year but the month is January or February,
+  // then the leap day has not occurred and should not be counted. If it is
+  // February 29, the leap day is accounted for in CalculateNumOfDayPassedThisYear( )
+  //
+  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 of 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 = 0;
+  for (Index = 1; Index < Time.Month; Index++) {
+    NumOfDays += DaysOfMonth[Index - 1];
+  }
+
+  NumOfDays += 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 = BcdValue >> 4;
+  Low  = 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 = 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;
+}
+
+/**
+  Test Century Register.
+
+  @retval EFI_SUCCESS
+  @retval EFI_DEVICE_ERROR
+
+**/
+STATIC
+EFI_STATUS
+RtcTestCenturyRegister (
+  VOID
+  )
+{
+  UINT8  Century;
+  UINT8  Temp;
+
+  Century = 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 = (UINT8)(RtcRead (RTC_ADDRESS_CENTURY) & 0x7f);
+  RtcWrite (RTC_ADDRESS_CENTURY, Century);
+  if ((Temp == 0x19) || (Temp == 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 = 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) {
+    gBS->Stall (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;
+}
+
+/**
+  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 == NULL) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  //
+  // Wait for up to 0.1 seconds for the RTC to be updated
+  //
+  Status = RtcWaitToUpdate (100000);
+  if (EFI_ERROR (Status)) {
+    return Status;
+  }
+
+  //
+  // Read Register B
+  //
+  RegisterB.Data = RtcRead (RTC_ADDRESS_REGISTER_B);
+
+  //
+  // Get the Time/Date/Daylight Savings values.
+  //
+  Time->Second = RtcRead (RTC_ADDRESS_SECONDS);
+  Time->Minute = RtcRead (RTC_ADDRESS_MINUTES);
+  Time->Hour   = RtcRead (RTC_ADDRESS_HOURS);
+  Time->Day    = RtcRead (RTC_ADDRESS_DAY_OF_THE_MONTH);
+  Time->Month  = RtcRead (RTC_ADDRESS_MONTH);
+  Time->Year   = RtcRead (RTC_ADDRESS_YEAR);
+
+  ConvertRtcTimeToEfiTime (Time, RegisterB);
+
+  if (RtcTestCenturyRegister () == EFI_SUCCESS) {
+    Century = BcdToDecimal ((UINT8)(RtcRead (RTC_ADDRESS_CENTURY) & 0x7f));
+  } else {
+    Century = BcdToDecimal (RtcRead (RTC_ADDRESS_CENTURY));
+  }
+
+  Time->Year = (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 = RtcGetTime (&Time);
+  if (EFI_ERROR (Status)) {
+    return Status;
+  }
+
+  NumOfYears    = Time.Year - 1970;
+  NumOfLeapDays = CountNumOfLeapDays (&Time);
+  NumOfDays     = CalculateNumOfDayPassedThisYear (Time);
+
+  //
+  // Add 365 days for all years. Add additional days for Leap Years. Subtract off current day.
+  //
+  NumOfDays += (NumOfLeapDays + (365 * NumOfYears) - 1);
+
+  *NumOfSeconds = (UINT32)(3600 * 24 * NumOfDays + (Time.Hour * 3600) + (60 * Time.Minute) + Time.Second);
+
+  return EFI_SUCCESS;
+}
diff --git a/Features/Intel/OutOfBandManagement/IpmiFeaturePkg/Library/ServerManagementLibNull/ServerManagementLibNull.c b/Features/Intel/OutOfBandManagement/IpmiFeaturePkg/Library/ServerManagementLibNull/ServerManagementLibNull.c
new file mode 100644
index 000000000000..7dd27f34878e
--- /dev/null
+++ b/Features/Intel/OutOfBandManagement/IpmiFeaturePkg/Library/ServerManagementLibNull/ServerManagementLibNull.c
@@ -0,0 +1,144 @@
+/** @file
+  Lightweight lib to support EFI Server Management drivers.
+
+Copyright (c) 2023, Intel Corporation. All rights reserved.<BR>
+SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include <PiDxe.h>
+#include <Library/DebugLib.h>
+#include <Library/ServerMgmtRtLib.h>
+
+/**
+  The function will set up a notification on the ELOG protocol.  This function 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
+  )
+{
+  return EFI_UNSUPPORTED;
+}
+
+/**
+  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 alert.  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 information.
+  @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_NOT_FOUND - the event log target was not found
+
+**/
+EFI_STATUS
+EfiSmSetEventLogData (
+  IN  UINT8             *ElogData,
+  IN  EFI_SM_ELOG_TYPE  DataType,
+  IN  BOOLEAN           AlertEvent,
+  IN  UINTN             DataSize,
+  OUT UINT64            *RecordId
+  )
+{
+  return EFI_NOT_FOUND;
+}
+
+/**
+  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 data to be retrieved.
+  @param DataType - this is the type of Elog data to be gotten.  Elog is redirected 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 DataSize.  A value of 0 on return indicates
+                    that it was last record if the Status is EFI_SUCCESS.
+
+  @retval EFI_NOT_FOUND - if the event log target was not found.
+
+**/
+EFI_STATUS
+EfiSmGetEventLogData (
+  IN  UINT8             *ElogData,
+  IN  EFI_SM_ELOG_TYPE  DataType,
+  IN  OUT UINTN         *DataSize,
+  IN OUT UINT64         *RecordId
+  )
+{
+  return EFI_NOT_FOUND;
+}
+
+/**
+  This function erases the event log data defined by the DataType.  The redir 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.  RecordId 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 respond.
+  @retval EFI_INVALID_PARAMETER - one of the parameters was invalid.
+
+**/
+EFI_STATUS
+EfiSmEraseEventlogData (
+  IN EFI_SM_ELOG_TYPE  DataType,
+  IN OUT UINT64        *RecordId
+  )
+{
+  return EFI_NOT_FOUND;
+}
+
+/**
+  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 DataType.  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 the DataType.  Enabled is
+                      TRUE and Disabled is FALSE.
+
+  @retval EFI_NOT_FOUND - the event log target was not found.
+
+**/
+EFI_STATUS
+EfiSmActivateEventLog (
+  IN EFI_SM_ELOG_TYPE  DataType,
+  IN BOOLEAN           *EnableElog,
+  OUT BOOLEAN          *ElogStatus
+  )
+{
+  return EFI_NOT_FOUND;
+}
+
+/**
+  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
+  )
+{
+  *NumOfSeconds = 0;
+
+  return EFI_NOT_FOUND;
+}
-- 
2.39.2.windows.1



-=-=-=-=-=-=-=-=-=-=-=-
Groups.io Links: You receive all messages sent to this group.
View/Reply Online (#110230): https://edk2.groups.io/g/devel/message/110230
Mute This Topic: https://groups.io/mt/102231767/1813853
Group Owner: devel+owner at edk2.groups.io
Unsubscribe: https://edk2.groups.io/g/devel/unsub [edk2-devel-archive at redhat.com]
-=-=-=-=-=-=-=-=-=-=-=-




More information about the edk2-devel-archive mailing list