From nobody Tue May 14 15:37:46 2024 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+110326+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+110326+1787277+3901457@groups.io; dmarc=fail(p=none dis=none) header.from=intel.com ARC-Seal: i=1; a=rsa-sha256; t=1698686019; cv=none; d=zohomail.com; s=zohoarc; b=S8jJJMa1B5AFeCqCGdh/vcnTKWL51CAN+fPveXzWMKg5mZ+Y6nughPSAphcKNdLGE9GnS8OMNV7xvt4wME7mGpOsoz7AiOl8Xar/95voc7h05EJLCIMe8s5oJmTUkNQQvb3+N5VYThilMiJdkWlIxkP1jrMpfpmJKyPqAqMruxU= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1698686019; 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=PBx3uRPs437JD3nwQUxvEk3MB5OuU5iLSOWR9FLec7A=; b=aKSDV32M3qu7qRQDS9wRJS9fje73QxTHgtovEugJdtx1TyLQV/7wgm3iDzF2l0I1TiJFG5Ku/4C1ZpF/novdxXsVDnmhZ8sAJjfHPISftuU45cwf1Sk+vwAJZpChqm20xF/gUsiEWwMdy16Jo+cZCBY/t8N/8Ye0Jw0vRXjwzcs= 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+110326+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 1698686019351867.3592792806921; Mon, 30 Oct 2023 10:13:39 -0700 (PDT) Return-Path: DKIM-Signature: a=rsa-sha256; bh=oYaWsWpiyW7e2Ru6Y+f3BMYRCdoSKdll+zQN4g2EKW4=; 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=1698686018; v=1; b=kMCzJzkfFxDwvJ2cfBUnGb3vevU58diSZZjaD/gq9QChBksglJdkzc/zabtISQFGqMuthwxt BUyCDJnTmflxFI6IfnbDC+ilaa/JV/nSy72ChSy5D7FuYJyw5n9VIH5dWyPvQ0LjE0xBLygUw4d 8Ilo61JVG1AQP7qIfqn92ZB8= X-Received: by 127.0.0.2 with SMTP id pklzYY1788612xL3imSLjuP3; Mon, 30 Oct 2023 10:13:38 -0700 X-Received: from mgamail.intel.com (mgamail.intel.com [134.134.136.24]) by mx.groups.io with SMTP id smtpd.web10.80041.1698611264012724787 for ; Sun, 29 Oct 2023 13:27:49 -0700 X-IronPort-AV: E=McAfee;i="6600,9927,10878"; a="390840888" X-IronPort-AV: E=Sophos;i="6.03,261,1694761200"; d="scan'208";a="390840888" X-Received: from orsmga001.jf.intel.com ([10.7.209.18]) by orsmga102.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 29 Oct 2023 13:27:48 -0700 X-ExtLoop1: 1 X-IronPort-AV: E=McAfee;i="6600,9927,10878"; a="795098438" X-IronPort-AV: E=Sophos;i="6.03,261,1694761200"; d="scan'208";a="795098438" X-Received: from scsrds0181.amr.corp.intel.com ([10.116.50.7]) by orsmga001.jf.intel.com with ESMTP; 29 Oct 2023 13:27:48 -0700 From: "Zhen Gong" To: devel@edk2.groups.io Cc: Zhen Gong Subject: [edk2-devel] [PATCH edk2-platforms v2 1/4] IpmiFeaturePkg: Add Elog drivers Date: Sun, 29 Oct 2023 13:27:37 -0700 Message-Id: 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,zhen.gong@intel.com List-Unsubscribe-Post: List-Unsubscribe=One-Click List-Unsubscribe: X-Gm-Message-State: Nz88rytTKOk99MPKQliROua3x1787277AA= Content-Transfer-Encoding: quoted-printable X-ZohoMail-DKIM: pass (identity @groups.io) X-ZM-MESSAGEID: 1698686020250100006 Content-Type: text/plain; charset="utf-8" Add generic Elog driver and support BMC Elog operations. Signed-off-by: Zhen Gong --- .../IpmiFeaturePkg/IpmiFeaturePkg.dec | 5 + .../IpmiFeaturePkg/Include/IpmiFeature.dsc | 7 +- .../IpmiFeaturePkg/Include/PostMemory.fdf | 5 +- .../IpmiFeaturePkg/Include/PreMemory.fdf | 1 + .../BmcElog/{BmcElog.inf =3D> DxeBmcElog.inf} | 19 +- .../IpmiFeaturePkg/BmcElog/PeiBmcElog.inf | 43 ++ .../IpmiFeaturePkg/BmcElog/SmmBmcElog.inf | 44 ++ .../GenericElog/Dxe/GenericElog.inf | 38 ++ .../GenericElog/Smm/GenericElog.inf | 38 ++ .../BmcElog/Common/BmcElogCommon.h | 144 +++++ .../IpmiFeaturePkg/BmcElog/Dxe/BmcElog.h | 42 ++ .../IpmiFeaturePkg/BmcElog/Pei/BmcElog.h | 44 ++ .../IpmiFeaturePkg/BmcElog/Smm/BmcElog.h | 43 ++ .../GenericElog/Dxe/GenericElog.h | 194 ++++++ .../GenericElog/Smm/GenericElog.h | 216 +++++++ .../IpmiFeaturePkg/Include/Ppi/GenericElog.h | 84 +++ .../Include/Protocol/GenericElog.h | 99 +++ .../IpmiFeaturePkg/BmcElog/BmcElog.c | 236 ------- .../BmcElog/Common/BmcElogCommon.c | 465 ++++++++++++++ .../IpmiFeaturePkg/BmcElog/Dxe/BmcElog.c | 287 +++++++++ .../IpmiFeaturePkg/BmcElog/Pei/BmcElog.c | 297 +++++++++ .../IpmiFeaturePkg/BmcElog/Smm/BmcElog.c | 288 +++++++++ .../GenericElog/Dxe/GenericElog.c | 576 ++++++++++++++++++ .../GenericElog/Smm/GenericElog.c | 558 +++++++++++++++++ 24 files changed, 3530 insertions(+), 243 deletions(-) rename Features/Intel/OutOfBandManagement/IpmiFeaturePkg/BmcElog/{BmcElog.= inf =3D> DxeBmcElog.inf} (60%) create mode 100644 Features/Intel/OutOfBandManagement/IpmiFeaturePkg/BmcEl= og/PeiBmcElog.inf create mode 100644 Features/Intel/OutOfBandManagement/IpmiFeaturePkg/BmcEl= og/SmmBmcElog.inf create mode 100644 Features/Intel/OutOfBandManagement/IpmiFeaturePkg/Gener= icElog/Dxe/GenericElog.inf create mode 100644 Features/Intel/OutOfBandManagement/IpmiFeaturePkg/Gener= icElog/Smm/GenericElog.inf create mode 100644 Features/Intel/OutOfBandManagement/IpmiFeaturePkg/BmcEl= og/Common/BmcElogCommon.h create mode 100644 Features/Intel/OutOfBandManagement/IpmiFeaturePkg/BmcEl= og/Dxe/BmcElog.h create mode 100644 Features/Intel/OutOfBandManagement/IpmiFeaturePkg/BmcEl= og/Pei/BmcElog.h create mode 100644 Features/Intel/OutOfBandManagement/IpmiFeaturePkg/BmcEl= og/Smm/BmcElog.h create mode 100644 Features/Intel/OutOfBandManagement/IpmiFeaturePkg/Gener= icElog/Dxe/GenericElog.h create mode 100644 Features/Intel/OutOfBandManagement/IpmiFeaturePkg/Gener= icElog/Smm/GenericElog.h create mode 100644 Features/Intel/OutOfBandManagement/IpmiFeaturePkg/Inclu= de/Ppi/GenericElog.h create mode 100644 Features/Intel/OutOfBandManagement/IpmiFeaturePkg/Inclu= de/Protocol/GenericElog.h delete mode 100644 Features/Intel/OutOfBandManagement/IpmiFeaturePkg/BmcEl= og/BmcElog.c create mode 100644 Features/Intel/OutOfBandManagement/IpmiFeaturePkg/BmcEl= og/Common/BmcElogCommon.c create mode 100644 Features/Intel/OutOfBandManagement/IpmiFeaturePkg/BmcEl= og/Dxe/BmcElog.c create mode 100644 Features/Intel/OutOfBandManagement/IpmiFeaturePkg/BmcEl= og/Pei/BmcElog.c create mode 100644 Features/Intel/OutOfBandManagement/IpmiFeaturePkg/BmcEl= og/Smm/BmcElog.c create mode 100644 Features/Intel/OutOfBandManagement/IpmiFeaturePkg/Gener= icElog/Dxe/GenericElog.c create mode 100644 Features/Intel/OutOfBandManagement/IpmiFeaturePkg/Gener= icElog/Smm/GenericElog.c diff --git a/Features/Intel/OutOfBandManagement/IpmiFeaturePkg/IpmiFeatureP= kg.dec b/Features/Intel/OutOfBandManagement/IpmiFeaturePkg/IpmiFeaturePkg.d= ec index 5df71300cbd1..22bc4e69be8a 100644 --- a/Features/Intel/OutOfBandManagement/IpmiFeaturePkg/IpmiFeaturePkg.dec +++ b/Features/Intel/OutOfBandManagement/IpmiFeaturePkg/IpmiFeaturePkg.dec @@ -67,6 +67,7 @@ [Guids] [Ppis] gPeiIpmiTransportPpiGuid =3D {0x7bf5fecc, 0xc5b5, 0x4b25, {0x81, 0x1b, 0= xb4, 0xb5, 0xb, 0x28, 0x79, 0xf7}} gPeiIpmiTransport2PpiGuid =3D {0x8122CEBD, 0xF4FD, 0x4EA8, { 0x97, 0x6C,= 0xF0, 0x30, 0xAD, 0xDC, 0x4C, 0xB4 }} + gPeiRedirElogPpiGuid =3D { 0x7a7c1591, 0xfc67, 0x4f69, { 0xa3, 0x78, 0xf= c, 0x3d, 0x4a, 0xd7, 0x92, 0xf7 } } =20 [Protocols] gIpmiTransportProtocolGuid =3D {0x6bb945e8, 0x3743, 0x433e, {0xb9, 0x0e= , 0x29, 0xb3, 0x0d, 0x5d, 0xc6, 0x30}} @@ -74,6 +75,10 @@ [Protocols] gEfiVideoPrintProtocolGuid =3D {0x3dbf3e06, 0x9d0c, 0x40d3, {0xb2, 0= x17, 0x45, 0x5f, 0x33, 0x9e, 0x29, 0x09}} gIpmiTransport2ProtocolGuid =3D { 0x4A1D0E66, 0x5271, 0x4E22, { 0x83, 0x= FE, 0x90, 0x92, 0x1B, 0x74, 0x82, 0x13 }} gSmmIpmiTransport2ProtocolGuid =3D { 0x1DBD1503, 0x0A60, 0x4230, { 0xAA,= 0xA3, 0x80, 0x16, 0xD8, 0xC3, 0xDE, 0x2F }} + gEfiGenericElogProtocolGuid =3D { 0x59d02fcd, 0x9233, 0x4d34, { 0xbc, 0x= fe, 0x87, 0xca, 0x81, 0xd3, 0xdd, 0xa7 } } + gSmmGenericElogProtocolGuid =3D { 0x664ef1f6, 0x19bf, 0x4498, { 0xab, 0x= 6a, 0xfc, 0x05, 0x72, 0xfb, 0x98, 0x51 } } + gEfiRedirElogProtocolGuid =3D { 0x16d11030, 0x71ba, 0x4e5e, { 0xa9, 0xf9= , 0xb4, 0x75, 0xa5, 0x49, 0x4, 0x8a } } + gSmmRedirElogProtocolGuid =3D { 0x79ac2d9c, 0x9216, 0x43c5, { 0xa0, 0x74= , 0x0b, 0x45, 0xc7, 0x64, 0x22, 0xc1 } } =20 [PcdsFeatureFlag] gIpmiFeaturePkgTokenSpaceGuid.PcdIpmiFeatureEnable|FALSE|BOOLEAN|0xA0000= 001 diff --git a/Features/Intel/OutOfBandManagement/IpmiFeaturePkg/Include/Ipmi= Feature.dsc b/Features/Intel/OutOfBandManagement/IpmiFeaturePkg/Include/Ipm= iFeature.dsc index 0401974b82e2..fa98e5672d83 100644 --- a/Features/Intel/OutOfBandManagement/IpmiFeaturePkg/Include/IpmiFeature= .dsc +++ b/Features/Intel/OutOfBandManagement/IpmiFeaturePkg/Include/IpmiFeature= .dsc @@ -57,6 +57,7 @@ [LibraryClasses.common.DXE_RUNTIME_DRIVER, LibraryClasses= .common.DXE_DRIVER] IpmbInterfaceLib|IpmiFeaturePkg/Library/BmcInterfaceCommonAccess/IpmbInt= erfaceLib/DxeIpmbInterfaceLib.inf =20 [LibraryClasses.common.DXE_SMM_DRIVER] + IpmiBaseLib|IpmiFeaturePkg/Library/SmmIpmiBaseLib/SmmIpmiBaseLib.inf SsifInterfaceLib|IpmiFeaturePkg/Library/BmcInterfaceCommonAccess/SsifInt= erfaceLib/SmmSsifInterfaceLib.inf IpmbInterfaceLib|IpmiFeaturePkg/Library/BmcInterfaceCommonAccess/IpmbInt= erfaceLib/SmmIpmbInterfaceLib.inf =20 @@ -96,6 +97,7 @@ [Components.IA32] IpmiFeaturePkg/GenericIpmi/Pei/PeiGenericIpmi.inf IpmiFeaturePkg/Frb/FrbPei.inf IpmiFeaturePkg/IpmiInit/PeiIpmiInit.inf + IpmiFeaturePkg/BmcElog/PeiBmcElog.inf =20 # # Feature DXE Components @@ -119,7 +121,10 @@ [Components.X64] IpmiFeaturePkg/GenericIpmi/Dxe/GenericIpmi.inf IpmiFeaturePkg/Library/SmmIpmiBaseLib/SmmIpmiBaseLib.inf IpmiFeaturePkg/BmcAcpi/BmcAcpi.inf - IpmiFeaturePkg/BmcElog/BmcElog.inf + IpmiFeaturePkg/BmcElog/DxeBmcElog.inf + IpmiFeaturePkg/BmcElog/SmmBmcElog.inf + IpmiFeaturePkg/GenericElog/Dxe/GenericElog.inf + IpmiFeaturePkg/GenericElog/Smm/GenericElog.inf IpmiFeaturePkg/Frb/FrbDxe.inf IpmiFeaturePkg/IpmiFru/IpmiFru.inf IpmiFeaturePkg/IpmiInit/DxeIpmiInit.inf diff --git a/Features/Intel/OutOfBandManagement/IpmiFeaturePkg/Include/Post= Memory.fdf b/Features/Intel/OutOfBandManagement/IpmiFeaturePkg/Include/Post= Memory.fdf index e0f3bbe158d9..f29810bc0b34 100644 --- a/Features/Intel/OutOfBandManagement/IpmiFeaturePkg/Include/PostMemory.= fdf +++ b/Features/Intel/OutOfBandManagement/IpmiFeaturePkg/Include/PostMemory.= fdf @@ -10,8 +10,11 @@ INF IpmiFeaturePkg/GenericIpmi/Dxe/GenericIpmi.inf INF IpmiFeaturePkg/IpmiInit/DxeIpmiInit.inf INF RuleOverride =3D DRIVER_ACPITABLE IpmiFeaturePkg/BmcAcpi/BmcAcpi.inf -INF IpmiFeaturePkg/BmcElog/BmcElog.inf +INF IpmiFeaturePkg/BmcElog/DxeBmcElog.inf +INF IpmiFeaturePkg/BmcElog/SmmBmcElog.inf INF IpmiFeaturePkg/Frb/FrbDxe.inf INF IpmiFeaturePkg/IpmiFru/IpmiFru.inf +INF IpmiFeaturePkg/GenericElog/Dxe/GenericElog.inf +INF IpmiFeaturePkg/GenericElog/Smm/GenericElog.inf INF IpmiFeaturePkg/OsWdt/OsWdt.inf INF IpmiFeaturePkg/SolStatus/SolStatus.inf diff --git a/Features/Intel/OutOfBandManagement/IpmiFeaturePkg/Include/PreM= emory.fdf b/Features/Intel/OutOfBandManagement/IpmiFeaturePkg/Include/PreMe= mory.fdf index d214988bd141..ca20546e9aa8 100644 --- a/Features/Intel/OutOfBandManagement/IpmiFeaturePkg/Include/PreMemory.f= df +++ b/Features/Intel/OutOfBandManagement/IpmiFeaturePkg/Include/PreMemory.f= df @@ -10,3 +10,4 @@ INF IpmiFeaturePkg/GenericIpmi/Pei/PeiGenericIpmi.inf INF IpmiFeaturePkg/IpmiInit/PeiIpmiInit.inf INF IpmiFeaturePkg/Frb/FrbPei.inf +INF IpmiFeaturePkg/BmcElog/PeiBmcElog.inf diff --git a/Features/Intel/OutOfBandManagement/IpmiFeaturePkg/BmcElog/BmcE= log.inf b/Features/Intel/OutOfBandManagement/IpmiFeaturePkg/BmcElog/DxeBmcE= log.inf similarity index 60% rename from Features/Intel/OutOfBandManagement/IpmiFeaturePkg/BmcElog/BmcEl= og.inf rename to Features/Intel/OutOfBandManagement/IpmiFeaturePkg/BmcElog/DxeBmcE= log.inf index 1e7a7658b7b0..7d8db9b633de 100644 --- a/Features/Intel/OutOfBandManagement/IpmiFeaturePkg/BmcElog/BmcElog.inf +++ b/Features/Intel/OutOfBandManagement/IpmiFeaturePkg/BmcElog/DxeBmcElog.= inf @@ -1,12 +1,12 @@ ### @file -# Component description file for BMC ELOG. # -# Copyright (c) 2018 - 2019, Intel Corporation. All rights reserved.
+# Copyright (c) 2023, Intel Corporation. All rights reserved.
# # SPDX-License-Identifier: BSD-2-Clause-Patent # ### =20 + [Defines] INF_VERSION =3D 0x00010005 BASE_NAME =3D BmcElog @@ -17,7 +17,10 @@ [Defines] ENTRY_POINT =3D InitializeBmcElogLayer =20 [Sources] - BmcElog.c + Dxe/BmcElog.c + Dxe/BmcElog.h + Common/BmcElogCommon.h + Common/BmcElogCommon.c =20 [Packages] MdePkg/MdePkg.dec @@ -28,7 +31,13 @@ [LibraryClasses] UefiDriverEntryPoint DebugLib UefiBootServicesTableLib - IpmiCommandLib + ReportStatusCodeLib + MemoryAllocationLib + IpmiBaseLib + +[Protocols] + gEfiRedirElogProtocolGuid # PROTOCOL ALWAYS_PRODUCED =20 [Depex] - TRUE + gEfiLoadedImageProtocolGuid AND + gIpmiTransportProtocolGuid diff --git a/Features/Intel/OutOfBandManagement/IpmiFeaturePkg/BmcElog/PeiB= mcElog.inf b/Features/Intel/OutOfBandManagement/IpmiFeaturePkg/BmcElog/PeiB= mcElog.inf new file mode 100644 index 000000000000..8274033e42e6 --- /dev/null +++ b/Features/Intel/OutOfBandManagement/IpmiFeaturePkg/BmcElog/PeiBmcElog.= inf @@ -0,0 +1,43 @@ +### @file +# +# Copyright (c) 2023, Intel Corporation. All rights reserved.
+# +# SPDX-License-Identifier: BSD-2-Clause-Patent +# +### + + +[Defines] + INF_VERSION =3D 0x00010005 + BASE_NAME =3D BmcElog + FILE_GUID =3D FD2A000E-09EA-4899-B40E-32BE30A58EBD + MODULE_TYPE =3D PEIM + VERSION_STRING =3D 1.0 + ENTRY_POINT =3D InitializeBmcElogLayer + +[Sources] + Pei/BmcElog.c + Pei/BmcElog.h + Common/BmcElogCommon.h + Common/BmcElogCommon.c + +[Packages] + IpmiFeaturePkg/IpmiFeaturePkg.dec + MdePkg/MdePkg.dec + MdeModulePkg/MdeModulePkg.dec + +[LibraryClasses] + DebugLib + ReportStatusCodeLib + MemoryAllocationLib + PeiServicesLib + PeimEntryPoint + IpmiBaseLib + +[Ppis] + gPeiRedirElogPpiGuid # PPI ALWAYS_PRODUCED + gPeiIpmiTransportPpiGuid + +[Depex] + TRUE + diff --git a/Features/Intel/OutOfBandManagement/IpmiFeaturePkg/BmcElog/SmmB= mcElog.inf b/Features/Intel/OutOfBandManagement/IpmiFeaturePkg/BmcElog/SmmB= mcElog.inf new file mode 100644 index 000000000000..d6880f8baa1b --- /dev/null +++ b/Features/Intel/OutOfBandManagement/IpmiFeaturePkg/BmcElog/SmmBmcElog.= inf @@ -0,0 +1,44 @@ +### @file +# +# Copyright (c) 2023, Intel Corporation. All rights reserved.
+# +# SPDX-License-Identifier: BSD-2-Clause-Patent +# +### + + +[Defines] + INF_VERSION =3D 0x00010005 + BASE_NAME =3D SmBmcElog + FILE_GUID =3D BE29A700-9D5A-4bb9-86B1-D1DB7A05D594 + MODULE_TYPE =3D DXE_SMM_DRIVER + PI_SPECIFICATION_VERSION =3D 0x0001000A + VERSION_STRING =3D 1.0 + ENTRY_POINT =3D InitializeSmBmcElogLayer + +[Sources] + Smm/BmcElog.c + Smm/BmcElog.h + Common/BmcElogCommon.h + Common/BmcElogCommon.c + +[Packages] + IpmiFeaturePkg/IpmiFeaturePkg.dec + MdePkg/MdePkg.dec + MdeModulePkg/MdeModulePkg.dec + +[LibraryClasses] + UefiDriverEntryPoint + DebugLib + UefiBootServicesTableLib + ReportStatusCodeLib + SmmServicesTableLib + IpmiBaseLib + +[Protocols] + gSmmRedirElogProtocolGuid # PROTOCOL ALWAYS_PRODUCED + +[Depex] + gEfiLoadedImageProtocolGuid AND + gSmmIpmiTransportProtocolGuid + diff --git a/Features/Intel/OutOfBandManagement/IpmiFeaturePkg/GenericElog/= Dxe/GenericElog.inf b/Features/Intel/OutOfBandManagement/IpmiFeaturePkg/Gen= ericElog/Dxe/GenericElog.inf new file mode 100644 index 000000000000..1073d3687d38 --- /dev/null +++ b/Features/Intel/OutOfBandManagement/IpmiFeaturePkg/GenericElog/Dxe/Gen= ericElog.inf @@ -0,0 +1,38 @@ +### @file +# +# Copyright (c) 2023, Intel Corporation. All rights reserved.
+# +# SPDX-License-Identifier: BSD-2-Clause-Patent +# +### + + +[Defines] + INF_VERSION =3D 0x00010005 + BASE_NAME =3D GenericElog + FILE_GUID =3D FD2D7E66-C5A7-47de-BDCC-4F1B5DC6ADA8 + MODULE_TYPE =3D DXE_DRIVER + VERSION_STRING =3D 1.0 + ENTRY_POINT =3D InitializeElogLayer + +[Sources] + GenericElog.c + GenericElog.h + +[Packages] + IpmiFeaturePkg/IpmiFeaturePkg.dec + MdePkg/MdePkg.dec + +[LibraryClasses] + UefiDriverEntryPoint + BaseMemoryLib + DebugLib + UefiBootServicesTableLib + MemoryAllocationLib + +[Protocols] + gEfiGenericElogProtocolGuid # PROTOCOL ALWAYS_PRODUCED + gEfiRedirElogProtocolGuid #PROTOCOL ALWAYS_COMSUMED + +[Depex] + gEfiRedirElogProtocolGuid diff --git a/Features/Intel/OutOfBandManagement/IpmiFeaturePkg/GenericElog/= Smm/GenericElog.inf b/Features/Intel/OutOfBandManagement/IpmiFeaturePkg/Gen= ericElog/Smm/GenericElog.inf new file mode 100644 index 000000000000..00f4154cdd39 --- /dev/null +++ b/Features/Intel/OutOfBandManagement/IpmiFeaturePkg/GenericElog/Smm/Gen= ericElog.inf @@ -0,0 +1,38 @@ +### @file +# +# Copyright (c) 2023, Intel Corporation. All rights reserved.
+# +# SPDX-License-Identifier: BSD-2-Clause-Patent +# +### + + +[Defines] + INF_VERSION =3D 0x00010005 + BASE_NAME =3D SmGenericElog + FILE_GUID =3D 870B000E-D3AD-4fb2-B846-AB0ADE8799CB + MODULE_TYPE =3D DXE_SMM_DRIVER + PI_SPECIFICATION_VERSION =3D 0x0001000A + VERSION_STRING =3D 1.0 + ENTRY_POINT =3D InitializeSmElogLayer + +[Sources] + GenericElog.c + GenericElog.h + +[Packages] + IpmiFeaturePkg/IpmiFeaturePkg.dec + MdePkg/MdePkg.dec + +[LibraryClasses] + UefiDriverEntryPoint + DebugLib + SmmServicesTableLib + +[Protocols] + gSmmGenericElogProtocolGuid # PROTOCOL ALWAYS_PRODUCED + gSmmRedirElogProtocolGuid #PROTOCOL ALWAYS_COMSUMED + +[Depex] + gSmmRedirElogProtocolGuid AND + gSmmIpmiTransportProtocolGuid diff --git a/Features/Intel/OutOfBandManagement/IpmiFeaturePkg/BmcElog/Comm= on/BmcElogCommon.h b/Features/Intel/OutOfBandManagement/IpmiFeaturePkg/BmcE= log/Common/BmcElogCommon.h new file mode 100644 index 000000000000..23c535d1dd6c --- /dev/null +++ b/Features/Intel/OutOfBandManagement/IpmiFeaturePkg/BmcElog/Common/BmcE= logCommon.h @@ -0,0 +1,144 @@ +/** @file + BMC Event Log functions. + +Copyright (c) 2023, Intel Corporation. All rights reserved.
+SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#ifndef _BMCELOG_COMMON_H_ +#define _BMCELOG_COMMON_H_ + +// +// Statements that include other files +// +#include +#include +#include +#include +#include +#include +#include "ServerManagement.h" +#include +#include +#include + +#define MAX_TEMP_DATA 160 +#define CLEAR_SEL_COUNTER 0x200 +#define SEL_RECORD_SIZE 0x10 // 16 bytes : Entire SEL Record size +#define SEL_RECORD_ID_SIZE 0x2 // 2 bytes : SEL Record-ID size + +#ifndef _EFI_SM_ELOG_TYPE +#define _EFI_SM_ELOG_TYPE +typedef enum { + EfiElogSmSMBIOS, + EfiElogSmIPMI, + EfiElogSmMachineCritical, + EfiElogSmASF, + EfiElogSmOEM, + EfiSmElogMax +} EFI_SM_ELOG_TYPE; +#endif + +/** + WaitTillClearSel. + + @param ResvId Reserved ID + + @retval EFI_SUCCESS + @retval EFI_NO_RESPONSE + +**/ +EFI_STATUS +WaitTillClearSel ( + UINT8 *ResvId + ); + +/** + Set Bmc Elog Data. + + + @param ElogData Buffer for log storage + @param DataType Event Log type + @param AlertEvent If it is an alert event + @param Size Log data size + @param RecordId Indicate which recorder it is + + @retval EFI_STATUS + +**/ +EFI_STATUS +SetBmcElogRecord ( + IN UINT8 *ElogData, + IN EFI_SM_ELOG_TYPE DataType, + IN BOOLEAN AlertEvent, + IN UINTN Size, + OUT UINT64 *RecordId + ); + +/** + Get Bmc Elog Data. + + @param ElogData Buffer for log data store + @param DataType Event log type + @param Size Size of log data + @param RecordId indicate which recorder it is + + @retval EFI_STATUS + +**/ +EFI_STATUS +GetBmcElogRecord ( + IN UINT8 *ElogData, + IN EFI_SM_ELOG_TYPE DataType, + IN OUT UINTN *Size, + IN OUT UINT64 *RecordId + ); + +/** + Erase Bmc Elog Data. + + @param This Protocol pointer + @param DataType Event log type + @param RecordId return which recorder it is + + @retval EFI_STATUS + +**/ +EFI_STATUS +EraseBmcElogRecord ( + IN EFI_SM_ELOG_TYPE DataType, + IN OUT UINT64 *RecordId + ); + +/** + Activate Bmc Elog. + + @param DataType indicate event log type + @param EnableElog Enable/Disable event log + @param ElogStatus return log status + + @retval EFI_STATUS + +**/ +EFI_STATUS +ActivateBmcElog ( + IN EFI_SM_ELOG_TYPE DataType, + IN BOOLEAN *EnableElog, + OUT BOOLEAN *ElogStatus + ); + +/** + This function verifies the BMC SEL is full and When it is reports the er= ror to the Error Manager. + + @retval EFI_SUCCESS + @retval EFI_DEVICE_ERROR + +**/ +EFI_STATUS +EFIAPI +CheckIfSelIsFull ( + VOID + ); + +#endif diff --git a/Features/Intel/OutOfBandManagement/IpmiFeaturePkg/BmcElog/Dxe/= BmcElog.h b/Features/Intel/OutOfBandManagement/IpmiFeaturePkg/BmcElog/Dxe/B= mcElog.h new file mode 100644 index 000000000000..d70261c7c537 --- /dev/null +++ b/Features/Intel/OutOfBandManagement/IpmiFeaturePkg/BmcElog/Dxe/BmcElog= .h @@ -0,0 +1,42 @@ +/** @file + BMC Event Log functions. + +Copyright (c) 2023, Intel Corporation. All rights reserved.
+SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#ifndef _EFI_BMCELOG_H_ +#define _EFI_BMCELOG_H_ + +// +// Statements that include other files +// + +#include +#include +#include +#include +#include "BmcElogCommon.h" + +// +// BMC Elog instance data +// +typedef struct { + UINTN Signature; + SM_COM_ADDRESS ControllerAddress; + SM_COM_ADDRESS TargetAddress; + UINT16 Instance; + EFI_SM_ELOG_TYPE DataType; + UINT8 TempData[MAX_TEMP_DATA + 1]; + EFI_SM_ELOG_REDIR_PROTOCOL BmcElog; +} EFI_BMC_ELOG_INSTANCE_DATA; + +// +// BMC Elog Instance signature +// +#define EFI_ELOG_REDIR_SIGNATURE SIGNATURE_32 ('e', 'e', 'l', 'g') + +#define INSTANCE_FROM_EFI_ELOG_REDIR_THIS(a) CR (a, EFI_BMC_ELOG_INSTANCE= _DATA, BmcElog, EFI_ELOG_REDIR_SIGNATURE) + +#endif diff --git a/Features/Intel/OutOfBandManagement/IpmiFeaturePkg/BmcElog/Pei/= BmcElog.h b/Features/Intel/OutOfBandManagement/IpmiFeaturePkg/BmcElog/Pei/B= mcElog.h new file mode 100644 index 000000000000..c1b53f3e468d --- /dev/null +++ b/Features/Intel/OutOfBandManagement/IpmiFeaturePkg/BmcElog/Pei/BmcElog= .h @@ -0,0 +1,44 @@ +/** @file + BMC Event Log functions. + +Copyright (c) 2023, Intel Corporation. All rights reserved.
+SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#ifndef _EFI_PEIBMCELOG_H_ +#define _EFI_PEIBMCELOG_H_ + +// +// Statements that include other files +// + +#include +#include +#include +#include +#include +#include "BmcElogCommon.h" + +// +// BMC Elog instance data +// +typedef struct { + UINTN Signature; + SM_COM_ADDRESS ControllerAddress; + SM_COM_ADDRESS TargetAddress; + UINT16 Instance; + EFI_SM_ELOG_TYPE DataType; + UINT8 TempData[MAX_TEMP_DATA + 1]; + EFI_SM_ELOG_REDIR_PPI BmcElogPpi; + EFI_PEI_PPI_DESCRIPTOR BmcElog; +} EFI_PEI_BMC_ELOG_INSTANCE_DATA; + +// +// BMC Elog Instance signature +// +#define EFI_PEI_ELOG_REDIR_SIGNATURE SIGNATURE_32 ('e', 'p', 'l', 'g') + +#define INSTANCE_FROM_EFI_PEI_ELOG_REDIR_THIS(a) CR (a, EFI_PEI_BMC_ELOG_= INSTANCE_DATA, BmcElogPpi, EFI_PEI_ELOG_REDIR_SIGNATURE) + +#endif diff --git a/Features/Intel/OutOfBandManagement/IpmiFeaturePkg/BmcElog/Smm/= BmcElog.h b/Features/Intel/OutOfBandManagement/IpmiFeaturePkg/BmcElog/Smm/B= mcElog.h new file mode 100644 index 000000000000..218af380a229 --- /dev/null +++ b/Features/Intel/OutOfBandManagement/IpmiFeaturePkg/BmcElog/Smm/BmcElog= .h @@ -0,0 +1,43 @@ +/** @file + BMC Event Log functions. + +Copyright (c) 2023, Intel Corporation. All rights reserved.
+SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#ifndef _SMM_BMCELOG_H_ +#define _SMM_BMCELOG_H_ + +// +// Statements that include other files +// + +#include +#include +#include +#include +#include +#include "BmcElogCommon.h" + +// +// BMC Elog instance data +// +typedef struct { + UINTN Signature; + SM_COM_ADDRESS ControllerAddress; + SM_COM_ADDRESS TargetAddress; + UINT16 Instance; + EFI_SM_ELOG_TYPE DataType; + UINT8 TempData[MAX_TEMP_DATA + 1]; + EFI_SM_ELOG_REDIR_PROTOCOL BmcElog; +} EFI_BMC_ELOG_INSTANCE_DATA; + +// +// BMC Elog Instance signature +// +#define SM_ELOG_REDIR_SIGNATURE SIGNATURE_32 ('e', 'l', 'o', 'f') + +#define INSTANCE_FROM_EFI_SM_ELOG_REDIR_THIS(a) CR (a, EFI_BMC_ELOG_INSTA= NCE_DATA, BmcElog, SM_ELOG_REDIR_SIGNATURE) + +#endif //_SMM_BMCELOG_H_ diff --git a/Features/Intel/OutOfBandManagement/IpmiFeaturePkg/GenericElog/= Dxe/GenericElog.h b/Features/Intel/OutOfBandManagement/IpmiFeaturePkg/Gener= icElog/Dxe/GenericElog.h new file mode 100644 index 000000000000..460185455648 --- /dev/null +++ b/Features/Intel/OutOfBandManagement/IpmiFeaturePkg/GenericElog/Dxe/Gen= ericElog.h @@ -0,0 +1,194 @@ +/** @file + Generic Event Log functions. + +Copyright (c) 2023, Intel Corporation. All rights reserved.
+SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#ifndef _EFI_GENELOG_H_ +#define _EFI_GENELOG_H_ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "ServerManagement.h" + +#include +#include + +#define EFI_ELOG_PHYSICAL 0 +#define EFI_ELOG_VIRTUAL 1 +#define MAX_REDIR_DESCRIPTOR 10 + +/// +/// A pointer to a function in IPF points to a plabel. +/// +typedef struct { + UINT64 EntryPoint; + UINT64 GP; +} EFI_PLABEL; + +typedef struct { + EFI_PLABEL *Function; + EFI_PLABEL Plabel; +} FUNCTION_PTR; + +typedef struct { + EFI_SM_ELOG_REDIR_PROTOCOL *This; + FUNCTION_PTR SetEventLogData; + FUNCTION_PTR GetEventLogData; + FUNCTION_PTR EraseEventLogData; + FUNCTION_PTR ActivateEventLog; +} REDIR_MODULE_PROC; + +typedef struct { + BOOLEAN Valid; + REDIR_MODULE_PROC Command[2]; +} REDIR_MODULES; + +typedef struct { + REDIR_MODULES Redir[MAX_REDIR_DESCRIPTOR]; + UINTN MaxDescriptors; +} ELOG_MODULE_GLOBAL; + +/** + Efi Convert Function. + + @param Function + + @retval EFI_SUCCESS +**/ +EFI_STATUS +EfiConvertFunction ( + IN FUNCTION_PTR *Function + ); + +/** + Efi Set Function Entry. + + @param FunctionPointer + @param Function + + @retval EFI_SUCCESS + +**/ +EFI_STATUS +EfiSetFunctionEntry ( + IN FUNCTION_PTR *FunctionPointer, + IN VOID *Function + ); + +/** + Elog Service Initialize. + + @param ImageHandle + @param SystemTable + + @retval EFI_SUCCESS + +**/ +EFI_STATUS +ElogServiceInitialize ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ); + +/** + Efi Lib Set Elog Data. + + @param ElogData + @param DataType + @param AlertEvent + @param DataSize + @param RecordId + @param Global + @param Virtual + + @retval EFI_SUCCESS + +**/ +EFI_STATUS +EfiLibSetElogData ( + IN UINT8 *ElogData, + IN EFI_SM_ELOG_TYPE DataType, + IN BOOLEAN AlertEvent, + IN UINTN DataSize, + OUT UINT64 *RecordId, + ELOG_MODULE_GLOBAL *Global, + BOOLEAN Virtual + ); + +/** + Efi Lib Get Elog Data. + + @param ElogData + @param DataType + @param DataSize + @param RecordId + @param Global + @param Virtual + + @retval EFI_SUCCESS + +**/ +EFI_STATUS +EfiLibGetElogData ( + IN UINT8 *ElogData, + IN EFI_SM_ELOG_TYPE DataType, + IN OUT UINTN *DataSize, + IN OUT UINT64 *RecordId, + ELOG_MODULE_GLOBAL *Global, + BOOLEAN Virtual + ); + +/** + Efi Lib Erase Elog Data. + + @param DataType + @param RecordId + @param Global + @param Virtual + + @retval EFI_SUCCESS + +**/ +EFI_STATUS +EfiLibEraseElogData ( + IN EFI_SM_ELOG_TYPE DataType, + IN OUT UINT64 *RecordId, + ELOG_MODULE_GLOBAL *Global, + BOOLEAN Virtual + ); + +/** + This API enables/Disables Event Log. + + @param DataType - Type of Elog Data that is being Activated. + @param EnableElog - Enables (TRUE) / Disables (FALSE) Event L= og. If NULL just returns the + Current ElogStatus. + @param ElogStatus - Current (New) Status of Event Log. Enable= d (TRUE), Disabled (FALSE). + @param Global - The module global variable pointer. + @param Virtual - If this function is called in virtual mod= e or physical mode + + @retval EFI_SUCCESS - Event-Log was recorded successfully + @retval EFI_UNSUPPORTED - The Data Type is unsupported + +**/ + +EFI_STATUS +EfiLibActivateElog ( + IN EFI_SM_ELOG_TYPE DataType, + IN BOOLEAN *EnableElog, + OUT BOOLEAN *ElogStatus, + ELOG_MODULE_GLOBAL *Global, + BOOLEAN Virtual + ); + +#endif //_EFI_GENELOG_H_ diff --git a/Features/Intel/OutOfBandManagement/IpmiFeaturePkg/GenericElog/= Smm/GenericElog.h b/Features/Intel/OutOfBandManagement/IpmiFeaturePkg/Gener= icElog/Smm/GenericElog.h new file mode 100644 index 000000000000..ad6530616309 --- /dev/null +++ b/Features/Intel/OutOfBandManagement/IpmiFeaturePkg/GenericElog/Smm/Gen= ericElog.h @@ -0,0 +1,216 @@ +/** @file + Generic Event Log functions. + +Copyright (c) 2023, Intel Corporation. All rights reserved.
+SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#ifndef _SMM_GENELOG_H_ +#define _SMM_GENELOG_H_ + +#include +#include +#include +#include + +#include +#include +#include + +#include "ServerManagement.h" +#include +#include + +#define EFI_ELOG_PHYSICAL 0 +#define EFI_ELOG_VIRTUAL 1 +#define MAX_REDIR_DESCRIPTOR 10 + +/// +/// A pointer to a function in IPF points to a plabel. +/// +typedef struct { + UINT64 EntryPoint; + UINT64 GP; +} EFI_PLABEL; + +typedef struct { + EFI_PLABEL *Function; + EFI_PLABEL Plabel; +} FUNCTION_PTR; + +typedef struct { + EFI_SM_ELOG_REDIR_PROTOCOL *This; + FUNCTION_PTR SetEventLogData; + FUNCTION_PTR GetEventLogData; + FUNCTION_PTR EraseEventLogData; + FUNCTION_PTR ActivateEventLog; +} REDIR_MODULE_PROC; + +typedef struct { + BOOLEAN Valid; + REDIR_MODULE_PROC Command[2]; +} REDIR_MODULES; + +typedef struct { + REDIR_MODULES Redir[MAX_REDIR_DESCRIPTOR]; + UINTN MaxDescriptors; +} ELOG_MODULE_GLOBAL; + +/** + Efi Convert Function. + + @param Function + + @retval EFI_SUCCESS +**/ +EFI_STATUS +EfiConvertFunction ( + IN FUNCTION_PTR *Function + ); + +/** + Set the function entry. + + @param FunctionPointer - The destination function pointer + @param Function - The source function pointer + + @retval EFI_SUCCESS - Set the function pointer successfully + +**/ +EFI_STATUS +EfiSetFunctionEntry ( + IN FUNCTION_PTR *FunctionPointer, + IN VOID *Function + ); + +/** + Entry point of SM Elog service Driver + + @param ImageHandle - The Image handle of this driver. + @param SystemTable - The pointer of EFI_SYSTEM_TABLE. + + @retval EFI_SUCCESS - The driver successfully initialized + +**/ +EFI_STATUS +SmElogServiceInitialize ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ); + +/** + Sm Redir Address Change Event. + + @param Event + @param Context + +**/ +VOID +SmRedirAddressChangeEvent ( + IN EFI_EVENT Event, + IN VOID *Context + ); + +/** + Sends the Event-Log data to the destination. + + @param ElogData - Pointer to the Event-Log data that needs = to be recorded. + @param DataType - Type of Elog Data that is being recorded. + @param AlertEvent - This is an indication that the input data= type is an Alert. + @param DataSize - Data Size. + @param RecordId - Record ID sent by the target. + @param Global - The module global variable pointer. + @param Virtual - If this function is called in virtual mod= e or physical mode + + @retval EFI_SUCCESS - Event-Log was recorded successfully. + @retval EFI_OUT_OF_RESOURCES - Not enough resources to record data. + @retval EFI_UNSUPPORTED - The Data Type is unsupported. + +**/ +EFI_STATUS +EfiLibSetElogData ( + IN UINT8 *ElogData, + IN EFI_SM_ELOG_TYPE DataType, + IN BOOLEAN AlertEvent, + IN UINTN DataSize, + OUT UINT64 *RecordId, + ELOG_MODULE_GLOBAL *Global, + BOOLEAN Virtual + ); + +/** + Gets the Event-Log data from the destination. + + @param ElogData - Pointer to the Event-Log data buffer that= will contain the data to be retrieved. + @param DataType - Type of Elog Data that is being recorded. + @param DataSize - Data Size. + @param RecordId - This is the RecordId of the next record. = If ElogData is NULL, + this gives the RecordId of the first recor= d available in the database with the correct DataSize. + A value of 0 on return indicates the last = record if the EFI_STATUS indicates a success + @param Global - The module global variable pointer. + @param Virtual - If this function is called in virtual mod= e or physical mode + + @retval EFI_SUCCESS - Event-Log was retrieved successfully. + @retval EFI_NOT_FOUND - Event-Log target not found. + @retval EFI_BUFFER_TOO_SMALL - Target buffer is too small to retrieve t= he data. + @retval EFI_UNSUPPORTED - The Data Type is unsupported + +**/ +EFI_STATUS +EfiLibGetElogData ( + IN UINT8 *ElogData, + IN EFI_SM_ELOG_TYPE DataType, + IN OUT UINTN *DataSize, + IN OUT UINT64 *RecordId, + ELOG_MODULE_GLOBAL *Global, + BOOLEAN Virtual + ); + +/** + Erases the Event-Log data from the destination. + + @param DataType - Type of Elog Data that is being Erased. + @param RecordId - This is the RecordId of the data to be er= ased. If RecordId is NULL, all + the records on the database are erased if= permitted by the target. + Contains the deleted RecordId on return + @param Global - The module global variable pointer. + @param Virtual - If this function is called in virtual mod= e or physical mode + + @retval EFI_SUCCESS - Event-Log was erased successfully + @retval EFI_UNSUPPORTED - The Data Type is unsupported + @retval EFI_NOT_FOUND - Event-Log target not found + +**/ +EFI_STATUS +EfiLibEraseElogData ( + IN EFI_SM_ELOG_TYPE DataType, + IN OUT UINT64 *RecordId, + ELOG_MODULE_GLOBAL *Global, + BOOLEAN Virtual + ); + +/** + This API enables/Disables Event Log. + + @param DataType - Type of Elog Data that is being Activated. + @param EnableElog - Enables (TRUE) / Disables (FALSE) Event L= og. If NULL just returns the + Current ElogStatus. + @param ElogStatus - Current (New) Status of Event Log. Enable= d (TRUE), Disabled (FALSE). + @param Global - The module global variable pointer. + @param Virtual - If this function is called in virtual mod= e or physical mode + + @retval EFI_SUCCESS - Event-Log was recorded successfully + @retval EFI_UNSUPPORTED - The Data Type is unsupported + +**/ +EFI_STATUS +EfiLibActivateElog ( + IN EFI_SM_ELOG_TYPE DataType, + IN BOOLEAN *EnableElog, + OUT BOOLEAN *ElogStatus, + ELOG_MODULE_GLOBAL *Global, + BOOLEAN Virtual + ); + +#endif //_SMM_GENELOG_H_ diff --git a/Features/Intel/OutOfBandManagement/IpmiFeaturePkg/Include/Ppi/= GenericElog.h b/Features/Intel/OutOfBandManagement/IpmiFeaturePkg/Include/P= pi/GenericElog.h new file mode 100644 index 000000000000..4b3b3ee2af33 --- /dev/null +++ b/Features/Intel/OutOfBandManagement/IpmiFeaturePkg/Include/Ppi/Generic= Elog.h @@ -0,0 +1,84 @@ +/** @file + This code abstracts the generic ELOG Protocol. + +Copyright (c) 2023, Intel Corporation. All rights reserved.
+SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#ifndef _GENERIC_ELOG_H_ +#define _GENERIC_ELOG_H_ + +#include "ServerManagement.h" + +typedef struct _EFI_SM_ELOG_PPI EFI_SM_ELOG_REDIR_PPI; + +// +// Common Defines +// +#ifndef _EFI_SM_ELOG_TYPE +#define _EFI_SM_ELOG_TYPE +typedef enum { + EfiElogSmSMBIOS, + EfiElogSmIPMI, + EfiElogSmMachineCritical, + EfiElogSmASF, + EfiElogSmOEM, + EfiSmElogMax +} EFI_SM_ELOG_TYPE; +#endif + +// +// Generic ELOG Function Prototypes +// +typedef +EFI_STATUS +(EFIAPI *EFI_SET_ELOG_DATA)( + IN EFI_SM_ELOG_REDIR_PPI *This, + IN UINT8 *ElogData, + IN EFI_SM_ELOG_TYPE DataType, + IN BOOLEAN AlertEvent, + IN UINTN DataSize, + OUT UINT64 *RecordId + ); + +typedef +EFI_STATUS +(EFIAPI *EFI_GET_ELOG_DATA)( + IN EFI_SM_ELOG_REDIR_PPI *This, + IN OUT UINT8 *ElogData, + IN EFI_SM_ELOG_TYPE DataType, + IN OUT UINTN *DataSize, + IN OUT UINT64 *RecordId + ); + +typedef +EFI_STATUS +(EFIAPI *EFI_ERASE_ELOG_DATA)( + IN EFI_SM_ELOG_REDIR_PPI *This, + IN EFI_SM_ELOG_TYPE DataType, + IN OUT UINT64 *RecordId + ); + +typedef +EFI_STATUS +(EFIAPI *EFI_ACTIVATE_ELOG)( + IN EFI_SM_ELOG_REDIR_PPI *This, + IN EFI_SM_ELOG_TYPE DataType, + IN BOOLEAN *EnableElog, + OUT BOOLEAN *ElogStatus + ); + +// +// IPMI TRANSPORT PPI +// +struct _EFI_SM_ELOG_PPI { + EFI_SET_ELOG_DATA SetEventLogData; + EFI_GET_ELOG_DATA GetEventLogData; + EFI_ERASE_ELOG_DATA EraseEventlogData; + EFI_ACTIVATE_ELOG ActivateEventLog; +}; + +extern EFI_GUID gPeiRedirElogPpiGuid; + +#endif diff --git a/Features/Intel/OutOfBandManagement/IpmiFeaturePkg/Include/Prot= ocol/GenericElog.h b/Features/Intel/OutOfBandManagement/IpmiFeaturePkg/Incl= ude/Protocol/GenericElog.h new file mode 100644 index 000000000000..19726ff58f0f --- /dev/null +++ b/Features/Intel/OutOfBandManagement/IpmiFeaturePkg/Include/Protocol/Ge= nericElog.h @@ -0,0 +1,99 @@ +/** @file + This code abstracts the generic ELOG Protocol. + +Copyright (c) 2023, Intel Corporation. All rights reserved.
+SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#ifndef _GENERIC_ELOG_H_ +#define _GENERIC_ELOG_H_ + +#include "ServerManagement.h" + +#define EFI_SM_ELOG_PROTOCOL_GUID \ + { \ + 0x59d02fcd, 0x9233, 0x4d34, 0xbc, 0xfe, 0x87, 0xca, 0x81, 0xd3, 0xdd, = 0xa7 \ + } + +#define EFI_SM_ELOG_REDIR_PROTOCOL_GUID \ + { \ + 0x16d11030, 0x71ba, 0x4e5e, 0xa9, 0xf9, 0xb4, 0x75, 0xa5, 0x49, 0x4, 0= x8a \ + } + +// +// Common Defines +// +#ifndef _EFI_SM_ELOG_TYPE +#define _EFI_SM_ELOG_TYPE +typedef enum { + EfiElogSmSMBIOS, + EfiElogSmIPMI, + EfiElogSmMachineCritical, + EfiElogSmASF, + EfiElogSmOEM, + EfiSmElogMax +} EFI_SM_ELOG_TYPE; +#endif + +typedef struct _EFI_SM_ELOG_PROTOCOL EFI_SM_ELOG_PROTOCOL; + +typedef struct _EFI_SM_ELOG_PROTOCOL EFI_SM_ELOG_REDIR_PROTOCOL; + +// +// Generic ELOG Function Prototypes +// +typedef +EFI_STATUS +(EFIAPI *EFI_SET_ELOG_DATA)( + IN EFI_SM_ELOG_PROTOCOL *This, + IN UINT8 *ElogData, + IN EFI_SM_ELOG_TYPE DataType, + IN BOOLEAN AlertEvent, + IN UINTN DataSize, + OUT UINT64 *RecordId + ); + +typedef +EFI_STATUS +(EFIAPI *EFI_GET_ELOG_DATA)( + IN EFI_SM_ELOG_PROTOCOL *This, + IN OUT UINT8 *ElogData, + IN EFI_SM_ELOG_TYPE DataType, + IN OUT UINTN *DataSize, + IN OUT UINT64 *RecordId + ); + +typedef +EFI_STATUS +(EFIAPI *EFI_ERASE_ELOG_DATA)( + IN EFI_SM_ELOG_PROTOCOL *This, + IN EFI_SM_ELOG_TYPE DataType, + IN OUT UINT64 *RecordId + ); + +typedef +EFI_STATUS +(EFIAPI *EFI_ACTIVATE_ELOG)( + IN EFI_SM_ELOG_PROTOCOL *This, + IN EFI_SM_ELOG_TYPE DataType, + IN BOOLEAN *EnableElog, + OUT BOOLEAN *ElogStatus + ); + +// +// IPMI TRANSPORT PROTOCOL +// +struct _EFI_SM_ELOG_PROTOCOL { + EFI_SET_ELOG_DATA SetEventLogData; + EFI_GET_ELOG_DATA GetEventLogData; + EFI_ERASE_ELOG_DATA EraseEventlogData; + EFI_ACTIVATE_ELOG ActivateEventLog; +}; + +extern EFI_GUID gEfiGenericElogProtocolGuid; +extern EFI_GUID gEfiRedirElogProtocolGuid; +extern EFI_GUID gSmmGenericElogProtocolGuid; +extern EFI_GUID gSmmRedirElogProtocolGuid; + +#endif diff --git a/Features/Intel/OutOfBandManagement/IpmiFeaturePkg/BmcElog/BmcE= log.c b/Features/Intel/OutOfBandManagement/IpmiFeaturePkg/BmcElog/BmcElog.c deleted file mode 100644 index a6d075b19c49..000000000000 --- a/Features/Intel/OutOfBandManagement/IpmiFeaturePkg/BmcElog/BmcElog.c +++ /dev/null @@ -1,236 +0,0 @@ -/** @file - BMC Event Log functions. - -Copyright (c) 2018 - 2019, Intel Corporation. All rights reserved.
-SPDX-License-Identifier: BSD-2-Clause-Patent - -**/ - -#include -#include -#include -#include -#include -#include -#include -#include - -EFI_STATUS -EFIAPI -CheckIfSelIsFull ( - VOID - ); - -/*++ - - Routine Description: - This function verifies the BMC SEL is full and When it is reports the = error to the Error Manager. - - Arguments: - None - - Returns: - EFI_SUCCESS - EFI_DEVICE_ERROR - ---*/ -EFI_STATUS -WaitTillErased ( - UINT8 *ResvId - ) -/*++ - -Routine Description: - -Arguments: - - BmcElogPrivateData - Bmc event log instance - ResvId - Reserved ID - -Returns: - - EFI_SUCCESS - EFI_NO_RESPONSE - ---*/ -{ - INTN Counter; - IPMI_CLEAR_SEL_REQUEST ClearSel; - IPMI_CLEAR_SEL_RESPONSE ClearSelResponse; - - Counter =3D 0x200; - ZeroMem (&ClearSelResponse, sizeof(ClearSelResponse)); - - while (TRUE) { - ZeroMem (&ClearSel, sizeof(ClearSel)); - ClearSel.Reserve[0] =3D ResvId[0]; - ClearSel.Reserve[1] =3D ResvId[1]; - ClearSel.AscC =3D 0x43; - ClearSel.AscL =3D 0x4C; - ClearSel.AscR =3D 0x52; - ClearSel.Erase =3D 0x00; - - IpmiClearSel ( - &ClearSel, - &ClearSelResponse - ); - - if ((ClearSelResponse.ErasureProgress & 0xf) =3D=3D 1) { - return EFI_SUCCESS; - } - // - // If there is not a response from the BMC controller we need to retu= rn and not hang. - // - --Counter; - if (Counter =3D=3D 0x0) { - return EFI_NO_RESPONSE; - } - } -} - -EFI_STATUS -EfiActivateBmcElog ( - IN BOOLEAN *EnableElog, - OUT BOOLEAN *ElogStatus - ) -/*++ - -Routine Description: - -Arguments: - - This - Protocol pointer - DataType - indicate event log type - EnableElog - Enable/Disable event log - ElogStatus - return log status - -Returns: - - EFI_STATUS - ---*/ -{ - EFI_STATUS Status; - UINT8 ElogStat; - IPMI_SET_BMC_GLOBAL_ENABLES_REQUEST SetBmcGlobalEnables; - IPMI_GET_BMC_GLOBAL_ENABLES_RESPONSE GetBmcGlobalEnables; - UINT8 CompletionCode; - - Status =3D EFI_SUCCESS; - ElogStat =3D 0; - - Status =3D IpmiGetBmcGlobalEnables (&GetBmcGlobalEnables); - if (EFI_ERROR(Status)) { - return Status; - } - - if (EnableElog =3D=3D NULL) { - *ElogStatus =3D GetBmcGlobalEnables.GetEnables.Bits.SystemEventLogging; - } else { - if (Status =3D=3D EFI_SUCCESS) { - if (*EnableElog) { - ElogStat =3D 1; - } - - CopyMem (&SetBmcGlobalEnables, (UINT8 *)&GetBmcGlobalEnables + 1, si= zeof(UINT8)); - SetBmcGlobalEnables.SetEnables.Bits.SystemEventLogging =3D ElogStat; - - Status =3D IpmiSetBmcGlobalEnables (&SetBmcGlobalEnables, &Completio= nCode); - } - } - - return Status; -} - -EFI_STATUS -SetElogRedirInstall ( - VOID - ) -/*++ - -Routine Description: - -Arguments: - - None - -Returns: - - EFI_SUCCESS - ---*/ -{ - BOOLEAN EnableElog; - BOOLEAN ElogStatus; - - // - // Activate the Event Log (This should depend upon Setup). - // - EfiActivateBmcElog (&EnableElog, &ElogStatus); - return EFI_SUCCESS; -} - -EFI_STATUS -EFIAPI -InitializeBmcElogLayer ( - IN EFI_HANDLE ImageHandle, - IN EFI_SYSTEM_TABLE *SystemTable - ) -/*++ - -Routine Description: - -Arguments: - - ImageHandle - ImageHandle of the loaded driver - SystemTable - Pointer to the System Table - -Returns: - - EFI_STATUS - ---*/ -{ - SetElogRedirInstall (); - - CheckIfSelIsFull (); - - return EFI_SUCCESS; -} - -EFI_STATUS -EFIAPI -CheckIfSelIsFull ( - VOID - ) -/*++ - - Routine Description: - This function verifies the BMC SEL is full and When it is reports the = error to the Error Manager. - - Arguments: - None - - Returns: - EFI_SUCCESS - EFI_DEVICE_ERROR - ---*/ -{ - EFI_STATUS Status; - UINT8 SelIsFull; - IPMI_GET_SEL_INFO_RESPONSE SelInfo; - - Status =3D IpmiGetSelInfo (&SelInfo); - if (EFI_ERROR (Status)) { - return EFI_DEVICE_ERROR; - } - - // - // Check the Bit7 of the OperationByte if SEL is OverFlow. - // - SelIsFull =3D (SelInfo.OperationSupport & 0x80); - DEBUG ((DEBUG_INFO, "SelIsFull - 0x%x\n", SelIsFull)); - - return EFI_SUCCESS; -} diff --git a/Features/Intel/OutOfBandManagement/IpmiFeaturePkg/BmcElog/Comm= on/BmcElogCommon.c b/Features/Intel/OutOfBandManagement/IpmiFeaturePkg/BmcE= log/Common/BmcElogCommon.c new file mode 100644 index 000000000000..b0688e3afb6c --- /dev/null +++ b/Features/Intel/OutOfBandManagement/IpmiFeaturePkg/BmcElog/Common/BmcE= logCommon.c @@ -0,0 +1,465 @@ +/** @file + BMC Event Log Common functions. + +Copyright (c) 2023, Intel Corporation. All rights reserved.
+SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include "BmcElogCommon.h" + +/** + WaitTillClearSel. + + @param ResvId - Reserved ID + + @retval EFI_SUCCESS + @retval EFI_NO_RESPONSE + +**/ +EFI_STATUS +WaitTillClearSel ( + UINT8 *ResvId + ) +{ + INTN Counter; + UINT32 ResponseDataSize; + IPMI_CLEAR_SEL_REQUEST ClearSelRequest; + IPMI_CLEAR_SEL_RESPONSE ClearSelResponse; + EFI_STATUS Status; + + Counter =3D 0x200; + Status =3D EFI_SUCCESS; + while (TRUE) { + ClearSelRequest.Reserve[0] =3D ResvId[0]; + ClearSelRequest.Reserve[1] =3D ResvId[1]; + ClearSelRequest.AscC =3D IPMI_CLEAR_SEL_REQUEST_C_CHAR_ASCII; + ClearSelRequest.AscL =3D IPMI_CLEAR_SEL_REQUEST_L_CHAR_ASCII; + ClearSelRequest.AscR =3D IPMI_CLEAR_SEL_REQUEST_R_CHAR_ASCII; + ClearSelRequest.Erase =3D IPMI_CLEAR_SEL_REQUEST_GET_ERASE_STATUS; + ResponseDataSize =3D sizeof (ClearSelResponse); + + Status =3D IpmiSubmitCommand ( + IPMI_NETFN_STORAGE, + IPMI_STORAGE_CLEAR_SEL, + (UINT8 *)&ClearSelRequest, + sizeof (ClearSelRequest), + (UINT8 *)&ClearSelResponse, + &ResponseDataSize + ); + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_ERROR, "IpmiSubmitCommand ClearSelRequest Failed %r\n"= , Status)); + } + + if ((ClearSelResponse.ErasureProgress & 0xf) =3D=3D IPMI_CLEAR_SEL_RES= PONSE_ERASURE_COMPLETED) { + return EFI_SUCCESS; + } + + // + // If there is not a response from the BMC controller we need to retu= rn and not hang. + // + --Counter; + if (Counter =3D=3D 0x0) { + return EFI_NO_RESPONSE; + } + } +} + +/** + Set Bmc Elog Data. + + + @param ElogData - Buffer for log storage + @param DataType - Event Log type + @param AlertEvent - If it is an alert event + @param Size - Log data size + @param RecordId - Indicate which recorder it is + + @retval EFI_STATUS + +**/ +EFI_STATUS +SetBmcElogRecord ( + IN UINT8 *ElogData, + IN EFI_SM_ELOG_TYPE DataType, + IN BOOLEAN AlertEvent, + IN UINTN Size, + OUT UINT64 *RecordId + ) +{ + EFI_STATUS Status; + UINT32 ResponseDataSize; + UINT8 EvntMsgResponse; + IPMI_PLATFORM_EVENT_MESSAGE_DATA_REQUEST EvntMsgRequest; + IPMI_ADD_SEL_ENTRY_REQUEST AddSelRequest; + IPMI_ADD_SEL_ENTRY_RESPONSE AddSelResponse; + + Status =3D EFI_SUCCESS; + CopyMem (&AddSelRequest.RecordData, ElogData, Size); + + *RecordId =3D 0; + + if (AlertEvent) { + EvntMsgRequest.GeneratorId =3D (UINT8)AddSelRequest.RecordData.Genera= torId; + EvntMsgRequest.EvMRevision =3D AddSelRequest.RecordData.EvMRevision; + EvntMsgRequest.SensorType =3D AddSelRequest.RecordData.SensorType; + EvntMsgRequest.SensorNumber =3D AddSelRequest.RecordData.SensorNumber; + EvntMsgRequest.EventDirType =3D AddSelRequest.RecordData.EventDirType; + EvntMsgRequest.OEMEvData1 =3D AddSelRequest.RecordData.OEMEvData1; + EvntMsgRequest.OEMEvData2 =3D AddSelRequest.RecordData.OEMEvData2; + EvntMsgRequest.OEMEvData3 =3D AddSelRequest.RecordData.OEMEvData3; + + ResponseDataSize =3D sizeof (EvntMsgResponse); + Status =3D IpmiSubmitCommand ( + IPMI_NETFN_SENSOR_EVENT, + IPMI_SENSOR_PLATFORM_EVENT_MESSAGE, + (UINT8 *)&EvntMsgRequest, + sizeof (EvntMsgRequest), + (UINT8 *)&EvntMsgResponse, + &ResponseDataSize + ); + } else { + ResponseDataSize =3D sizeof (AddSelResponse); + Status =3D IpmiSubmitCommand ( + IPMI_NETFN_STORAGE, + IPMI_STORAGE_ADD_SEL_ENTRY, + (UINT8 *)&AddSelRequest, + sizeof (AddSelRequest), + (UINT8 *)&AddSelResponse, + &ResponseDataSize + ); + + if (Status =3D=3D EFI_SUCCESS) { + *RecordId =3D AddSelResponse.RecordId; + } + } + + return Status; +} + +/** + Get Bmc Elog Data. + + @param ElogData - Buffer for log data store + @param DataType - Event log type + @param Size - Size of log data + @param RecordId - indicate which recorder it is + + @retval EFI_STATUS + +**/ +EFI_STATUS +GetBmcElogRecord ( + IN UINT8 *ElogData, + IN EFI_SM_ELOG_TYPE DataType, + IN OUT UINTN *Size, + IN OUT UINT64 *RecordId + ) +{ + UINT64 ReceiveKey; + EFI_STATUS Status; + IPMI_GET_SEL_ENTRY_REQUEST GetSelEntryRequest; + IPMI_GET_SEL_ENTRY_RESPONSE GetSelEntryResponse; + UINT32 ResponseDataSize; + + Status =3D EFI_SUCCESS; + ReceiveKey =3D *RecordId; + GetSelEntryRequest.ReserveId[0] =3D 0; + GetSelEntryRequest.ReserveId[1] =3D 0; + GetSelEntryRequest.SelRecID[0] =3D (UINT8)ReceiveKey; + ReceiveKey =3D DivU64x32 (ReceiveKey, (UINT32)(1 <<= 8)); + GetSelEntryRequest.SelRecID[1] =3D (UINT8)ReceiveKey; + GetSelEntryRequest.Offset =3D 0; + GetSelEntryRequest.BytesToRead =3D IPMI_COMPLETE_SEL_RECORD; + ResponseDataSize =3D sizeof (GetSelEntryResponse); + + Status =3D IpmiSubmitCommand ( + IPMI_NETFN_STORAGE, + IPMI_STORAGE_GET_SEL_ENTRY, + (UINT8 *)&GetSelEntryRequest, + sizeof (GetSelEntryRequest), + (UINT8 *)&GetSelEntryResponse, + &ResponseDataSize + ); + // + // Per IPMI spec, Entire Record is 16 Bytes + // If less than 16 bytes pointer is sent return buffer too small + // + if (Status =3D=3D EFI_SUCCESS) { + if (*Size < (SEL_RECORD_SIZE)) { + return EFI_BUFFER_TOO_SMALL; + } + + if (GetSelEntryResponse.NextSelRecordId =3D=3D 0xFFFF) { + return EFI_NOT_FOUND; + } + + *RecordId =3D GetSelEntryResponse.NextSelRecordId; + CopyMem (ElogData, &GetSelEntryResponse.RecordData, sizeof (GetSelEntr= yResponse.RecordData)); + *Size =3D SEL_RECORD_SIZE; + } + + return Status; +} + +/** + Erase Bmc Elog Data. + + @param DataType - Event log type + @param RecordId - return which recorder it is + + @retval EFI_STATUS + +**/ +EFI_STATUS +EraseBmcElogRecord ( + IN EFI_SM_ELOG_TYPE DataType, + IN OUT UINT64 *RecordId + ) +{ + EFI_STATUS Status; + UINT64 ReceiveKey; + UINT8 ResvId[2]; + BOOLEAN SelReserveIdIsSupported; + UINT8 OperationSupport; + UINT8 SelReserveIdvalue; + UINT32 ResponseDataSize; + IPMI_GET_SEL_INFO_RESPONSE GetSelInfoResponse; + IPMI_RESERVE_SEL_RESPONSE ReserveSelResponse; + IPMI_DELETE_SEL_ENTRY_REQUEST DeleteSelRequest; + IPMI_DELETE_SEL_ENTRY_RESPONSE DeleteSelResponse; + IPMI_CLEAR_SEL_REQUEST ClearSelRequest; + IPMI_CLEAR_SEL_RESPONSE ClearSelResponse; + + Status =3D EFI_SUCCESS; + + // + // Before issuing this SEL reservation ID, Check whether this command is= supported or not by issuing the + // GetSelInfoCommand. If it does not support ResvId should be 0000h + // + ResponseDataSize =3D sizeof (GetSelInfoResponse); + Status =3D IpmiSubmitCommand ( + IPMI_NETFN_STORAGE, + IPMI_STORAGE_GET_SEL_INFO, + NULL, + 0, + (UINT8 *)&GetSelInfoResponse, + &ResponseDataSize + ); + if (EFI_ERROR (Status)) { + return Status; + } + + OperationSupport =3D GetSelInfoResponse.OperationSupport; + SelReserveIdvalue =3D (OperationSupport & IPMI_GET_SEL_INFO_OPERATION_SU= PPORT_RESERVE_SEL_CMD); + if (SelReserveIdvalue =3D=3D IPMI_GET_SEL_INFO_OPERATION_SUPPORT_RESERVE= _SEL_CMD) { + SelReserveIdIsSupported =3D TRUE; + } else { + SelReserveIdIsSupported =3D FALSE; + } + + // + // if SelReserveIdcommand not supported do not issue the RESERVE_SEL_ENT= RY command, and set the ResvId value to 0000h + // + + // + // Get the SEL reservation ID + // + + if (SelReserveIdIsSupported) { + ResponseDataSize =3D sizeof (ReserveSelResponse); + Status =3D IpmiSubmitCommand ( + IPMI_NETFN_STORAGE, + IPMI_STORAGE_RESERVE_SEL, + NULL, + 0, + (UINT8 *)&ReserveSelResponse, + &ResponseDataSize + ); + + if (EFI_ERROR (Status)) { + return Status; + } + + ResvId[0] =3D ReserveSelResponse.ReservationId[0]; + ResvId[1] =3D ReserveSelResponse.ReservationId[1]; + } else { + ResvId[0] =3D 0x00; + ResvId[1] =3D 0x00; + } + + // + // Clear the SEL + // + if (RecordId !=3D NULL) { + ReceiveKey =3D *RecordId; + DeleteSelRequest.ReserveId[0] =3D ResvId[0]; + DeleteSelRequest.ReserveId[1] =3D ResvId[1]; + DeleteSelRequest.RecordToDelete[0] =3D (UINT8)ReceiveKey; + ReceiveKey =3D DivU64x32 (ReceiveKey, (UINT32)= (1 << 8)); + DeleteSelRequest.RecordToDelete[1] =3D (UINT8)ReceiveKey; + + ResponseDataSize =3D sizeof (DeleteSelResponse); + Status =3D IpmiSubmitCommand ( + IPMI_NETFN_STORAGE, + IPMI_STORAGE_DELETE_SEL_ENTRY, + (UINT8 *)&DeleteSelRequest, + sizeof (DeleteSelRequest), + (UINT8 *)&DeleteSelResponse, + &ResponseDataSize + ); + } else { + ClearSelRequest.Reserve[0] =3D ResvId[0]; + ClearSelRequest.Reserve[1] =3D ResvId[1]; + ClearSelRequest.AscC =3D IPMI_CLEAR_SEL_REQUEST_C_CHAR_ASCII; + ClearSelRequest.AscL =3D IPMI_CLEAR_SEL_REQUEST_L_CHAR_ASCII; + ClearSelRequest.AscR =3D IPMI_CLEAR_SEL_REQUEST_R_CHAR_ASCII; + ClearSelRequest.Erase =3D IPMI_CLEAR_SEL_REQUEST_INITIALIZE_ERASE; + ResponseDataSize =3D sizeof (ClearSelResponse); + + Status =3D IpmiSubmitCommand ( + IPMI_NETFN_STORAGE, + IPMI_STORAGE_CLEAR_SEL, + (UINT8 *)&ClearSelRequest, + sizeof (ClearSelRequest), + (UINT8 *)&ClearSelResponse, + &ResponseDataSize + ); + } + + if (Status =3D=3D EFI_SUCCESS) { + if (RecordId =3D=3D NULL) { + WaitTillClearSel (ResvId); + } + } + + return Status; +} + +/** + Activate Bmc Elog. + + @param DataType - indicate event log type + @param EnableElog - Enable/Disable event log + @param ElogStatus - return log status + + @retval EFI_STATUS + +**/ +EFI_STATUS +ActivateBmcElog ( + IN EFI_SM_ELOG_TYPE DataType, + IN BOOLEAN *EnableElog, + OUT BOOLEAN *ElogStatus + ) +{ + EFI_STATUS Status; + UINT8 ElogStat; + IPMI_GET_BMC_GLOBAL_ENABLES_RESPONSE GetBmcGlobalResponse; + IPMI_SET_BMC_GLOBAL_ENABLES_REQUEST SetBmcGlobalRequest; + UINT8 SetBmcGlobalResponse; + UINT32 ResponseDataSize; + + Status =3D EFI_SUCCESS; + ElogStat =3D 0; + + ResponseDataSize =3D sizeof (GetBmcGlobalResponse); + Status =3D IpmiSubmitCommand ( + IPMI_NETFN_APP, + IPMI_APP_GET_BMC_GLOBAL_ENABLES, + NULL, + 0, + (UINT8 *)&GetBmcGlobalResponse, + &ResponseDataSize + ); + + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_ERROR, "IpmiSubmitCommand App Get Bmc Global Enables Fai= led %r\n", Status)); + } + + if (EnableElog =3D=3D NULL) { + *ElogStatus =3D (UINT8)(GetBmcGlobalResponse.GetEnables.Bits.SystemEve= ntLogging); + } else { + if (Status =3D=3D EFI_SUCCESS) { + if (*EnableElog) { + ElogStat =3D 0x1; // Setting SystemEventLogging + } + + SetBmcGlobalRequest.SetEnables.Uint8 =3D GetBmcGlo= balResponse.GetEnables.Uint8; + SetBmcGlobalRequest.SetEnables.Bits.SystemEventLogging =3D ElogStat; + + ResponseDataSize =3D sizeof (SetBmcGlobalResponse); + Status =3D IpmiSubmitCommand ( + IPMI_NETFN_APP, + IPMI_APP_SET_BMC_GLOBAL_ENABLES, + (UINT8 *)&SetBmcGlobalRequest, + sizeof (SetBmcGlobalRequest), + (UINT8 *)&SetBmcGlobalResponse, + &ResponseDataSize + ); + + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_ERROR, "IpmiSubmitCommand App Set Bmc Global Enables= Failed %r\n", Status)); + } + } + } + + return Status; +} + +/** + This function checks the BMC SEL is full and whether to report the error. + + @retval EFI_SUCCESS + @retval EFI_DEVICE_ERROR + +**/ +EFI_STATUS +EFIAPI +CheckIfSelIsFull ( + VOID + ) +{ + EFI_STATUS Status; + UINT32 ResponseDataSize; + UINT8 OperationSupportByte; + UINT8 SelIsFull; + IPMI_GET_SEL_INFO_RESPONSE GetSelInfoResponse; + + OperationSupportByte =3D 0; + SelIsFull =3D 0; + + ResponseDataSize =3D sizeof (GetSelInfoResponse); + + Status =3D IpmiSubmitCommand ( + IPMI_NETFN_STORAGE, + IPMI_STORAGE_GET_SEL_INFO, + NULL, + 0, + (UINT8 *)&GetSelInfoResponse, + &ResponseDataSize + ); + + if (EFI_ERROR (Status)) { + return EFI_DEVICE_ERROR; + } + + OperationSupportByte =3D GetSelInfoResponse.OperationSupport; + + // + // Check the Bit7 of the OperationByte if SEL is OverFlow. + // + SelIsFull =3D (OperationSupportByte & IPMI_GET_SEL_INFO_OPERATION_SUPPOR= T_OVERFLOW_FLAG); + + if (SelIsFull =3D=3D IPMI_GET_SEL_INFO_OPERATION_SUPPORT_OVERFLOW_FLAG) { + // + // Report the Error code that SEL Log is full + // + ReportStatusCode ( + (EFI_ERROR_CODE | EFI_ERROR_MINOR), + (SOFTWARE_EFI_BMC | EFI_SW_EC_EVENT_LOG_FULL) + ); + } + + return EFI_SUCCESS; +} diff --git a/Features/Intel/OutOfBandManagement/IpmiFeaturePkg/BmcElog/Dxe/= BmcElog.c b/Features/Intel/OutOfBandManagement/IpmiFeaturePkg/BmcElog/Dxe/B= mcElog.c new file mode 100644 index 000000000000..0b1e2f5b1355 --- /dev/null +++ b/Features/Intel/OutOfBandManagement/IpmiFeaturePkg/BmcElog/Dxe/BmcElog= .c @@ -0,0 +1,287 @@ +/** @file + BMC Event Log functions. + +Copyright (c) 2023, Intel Corporation. All rights reserved.
+SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include "BmcElog.h" + +// +// Define module globals used to register for notification of when +// the ELOG REDIR protocol has been produced. +// +EFI_EVENT mEfiBmcTransEvent; +EFI_BMC_ELOG_INSTANCE_DATA *mRedirProtoPrivate; + +/** + WaitTillErased. + + @param BmcElogPrivateData - Bmc event log instance + @param ResvId - Reserved ID + + @retval EFI_SUCCESS + @retval EFI_NO_RESPONSE + +**/ +EFI_STATUS +WaitTillErased ( + EFI_BMC_ELOG_INSTANCE_DATA *BmcElogPrivateData, + UINT8 *ResvId + ) +{ + EFI_STATUS Status; + + Status =3D WaitTillClearSel (ResvId); + return Status; +} + +/** + Efi Set Bmc Elog Data. + + @param This - Protocol pointer + @param ElogData - Buffer for log storage + @param DataType - Event Log type + @param AlertEvent - If it is an alert event + @param Size - Log data size + @param RecordId - Indicate which recorder it is + + @retval EFI_STATUS + +**/ +EFI_STATUS +EfiSetBmcElogData ( + IN EFI_SM_ELOG_REDIR_PROTOCOL *This, + IN UINT8 *ElogData, + IN EFI_SM_ELOG_TYPE DataType, + IN BOOLEAN AlertEvent, + IN UINTN Size, + OUT UINT64 *RecordId + ) +{ + EFI_BMC_ELOG_INSTANCE_DATA *BmcElogPrivateData; + EFI_STATUS Status; + + Status =3D EFI_SUCCESS; + BmcElogPrivateData =3D INSTANCE_FROM_EFI_ELOG_REDIR_THIS (This); + + if (DataType >=3D EfiSmElogMax) { + return EFI_INVALID_PARAMETER; + } + + if (Size > SEL_RECORD_SIZE) { + return EFI_OUT_OF_RESOURCES; + } + + if (BmcElogPrivateData->DataType =3D=3D DataType) { + Status =3D SetBmcElogRecord (ElogData, DataType, AlertEvent, Size, Rec= ordId); + } + + return Status; +} + +/** + Efi Get Bmc Elog Data. + + @param This - Protocol pointer + @param ElogData - Buffer for log data store + @param DataType - Event log type + @param Size - Size of log data + @param RecordId - indicate which recorder it is + + @retval EFI_STATUS + +**/ +EFI_STATUS +EfiGetBmcElogData ( + IN EFI_SM_ELOG_REDIR_PROTOCOL *This, + IN OUT UINT8 *ElogData, + IN EFI_SM_ELOG_TYPE DataType, + IN OUT UINTN *Size, + IN OUT UINT64 *RecordId + ) +{ + EFI_BMC_ELOG_INSTANCE_DATA *BmcElogPrivateData; + EFI_STATUS Status; + + Status =3D EFI_SUCCESS; + BmcElogPrivateData =3D INSTANCE_FROM_EFI_ELOG_REDIR_THIS (This); + + if (DataType >=3D EfiSmElogMax) { + return EFI_INVALID_PARAMETER; + } + + if (BmcElogPrivateData->DataType =3D=3D DataType) { + Status =3D GetBmcElogRecord (ElogData, DataType, Size, RecordId); + } + + return Status; +} + +/** + Efi Erase Bmc Elog Data. + + @param This - Protocol pointer + @param DataType - Event log type + @param RecordId - return which recorder it is + + @retval EFI_STATUS + +**/ +EFI_STATUS +EfiEraseBmcElogData ( + IN EFI_SM_ELOG_REDIR_PROTOCOL *This, + IN EFI_SM_ELOG_TYPE DataType, + IN OUT UINT64 *RecordId + ) +{ + EFI_BMC_ELOG_INSTANCE_DATA *BmcElogPrivateData; + EFI_STATUS Status; + + Status =3D EFI_SUCCESS; + BmcElogPrivateData =3D INSTANCE_FROM_EFI_ELOG_REDIR_THIS (This); + + if (DataType >=3D EfiSmElogMax) { + return EFI_INVALID_PARAMETER; + } + + if (BmcElogPrivateData->DataType =3D=3D DataType) { + Status =3D EraseBmcElogRecord (DataType, RecordId); + + if (Status =3D=3D EFI_SUCCESS) { + if (RecordId !=3D NULL) { + *RecordId =3D (UINT16)(*((UINT16 *)&BmcElogPrivateData->TempData[0= ])); + } + } + } + + return EFI_SUCCESS; +} + +/** + Efi Activate Bmc Elog. + + @param This - Protocol pointer + @param DataType - indicate event log type + @param EnableElog - Enable/Disable event log + @param ElogStatus - return log status + + @retval EFI_STATUS + +**/ +EFI_STATUS +EfiActivateBmcElog ( + IN EFI_SM_ELOG_REDIR_PROTOCOL *This, + IN EFI_SM_ELOG_TYPE DataType, + IN BOOLEAN *EnableElog, + OUT BOOLEAN *ElogStatus + ) +{ + EFI_BMC_ELOG_INSTANCE_DATA *BmcElogPrivateData; + EFI_STATUS Status; + + Status =3D EFI_SUCCESS; + BmcElogPrivateData =3D INSTANCE_FROM_EFI_ELOG_REDIR_THIS (This); + + if (DataType >=3D EfiSmElogMax) { + return EFI_INVALID_PARAMETER; + } + + if (BmcElogPrivateData->DataType =3D=3D DataType) { + Status =3D ActivateBmcElog (DataType, EnableElog, ElogStatus); + } + + return Status; +} + +/** + Set Elog Redir Install. + + @retval EFI_SUCCESS + +**/ +EFI_STATUS +SetElogRedirInstall ( + VOID + ) +{ + EFI_HANDLE NewHandle; + EFI_STATUS Status; + BOOLEAN EnableElog; + BOOLEAN ElogStatus; + UINT16 Instance; + + Status =3D EFI_SUCCESS; + EnableElog =3D TRUE; + ElogStatus =3D TRUE; + Instance =3D 0; + + mRedirProtoPrivate->Signature =3D EFI_ELOG_REDIR_SIGNATU= RE; + mRedirProtoPrivate->DataType =3D EfiElogSmIPMI; + mRedirProtoPrivate->BmcElog.ActivateEventLog =3D EfiActivateBmcElog; + mRedirProtoPrivate->BmcElog.EraseEventlogData =3D EfiEraseBmcElogData; + mRedirProtoPrivate->BmcElog.GetEventLogData =3D EfiGetBmcElogData; + mRedirProtoPrivate->BmcElog.SetEventLogData =3D EfiSetBmcElogData; + mRedirProtoPrivate->Instance =3D Instance; + // + // Now install the Protocol + // + NewHandle =3D NULL; + + Status =3D gBS->InstallProtocolInterface ( + &NewHandle, + &gEfiRedirElogProtocolGuid, + EFI_NATIVE_INTERFACE, + &mRedirProtoPrivate->BmcElog + ); + ASSERT_EFI_ERROR (Status); + if (Status !=3D EFI_SUCCESS) { + return Status; + } + + // + // Activate the Event Log (This should depend upon Setup). + // + EfiActivateBmcElog (&mRedirProtoPrivate->BmcElog, EfiElogSmIPMI, &Enable= Elog, &ElogStatus); + + return EFI_SUCCESS; +} + +/** + InitializeBmcElogLayer. + + @param ImageHandle - ImageHandle of the loaded driver + @param SystemTable - Pointer to the System Table + + @retval EFI_STATUS + +**/ +EFI_STATUS +InitializeBmcElogLayer ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +{ + EFI_STATUS Status; + + Status =3D EFI_SUCCESS; + + InitializeIpmiBase (); + + mRedirProtoPrivate =3D AllocatePool (sizeof (EFI_BMC_ELOG_INSTANCE_DATA)= ); + ASSERT (mRedirProtoPrivate !=3D NULL); + if (mRedirProtoPrivate =3D=3D NULL) { + return EFI_OUT_OF_RESOURCES; + } + + SetElogRedirInstall (); + + // + // Check if the BMC System Event Log (SEL) is full and whether to report= the error. + // + + CheckIfSelIsFull (); + + return Status; +} diff --git a/Features/Intel/OutOfBandManagement/IpmiFeaturePkg/BmcElog/Pei/= BmcElog.c b/Features/Intel/OutOfBandManagement/IpmiFeaturePkg/BmcElog/Pei/B= mcElog.c new file mode 100644 index 000000000000..f791d872b7a1 --- /dev/null +++ b/Features/Intel/OutOfBandManagement/IpmiFeaturePkg/BmcElog/Pei/BmcElog= .c @@ -0,0 +1,297 @@ +/** @file + BMC Event Log functions. + +Copyright (c) 2023, Intel Corporation. All rights reserved.
+SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include "BmcElog.h" + +// +// Define module globals used to register for notification of when +// the ELOG REDIR protocol has been produced. +// + +EFI_STATUS +NotifyPeiBmcElogCallback ( + IN EFI_PEI_SERVICES **PeiServices, + IN EFI_PEI_NOTIFY_DESCRIPTOR *NotifyDescriptor, + IN VOID *Ppi + ); + +EFI_PEI_NOTIFY_DESCRIPTOR mNotifyList[] =3D { + { + EFI_PEI_PPI_DESCRIPTOR_NOTIFY_CALLBACK | EFI_PEI_PPI_DESCRIPTOR_TERMIN= ATE_LIST, + &gPeiIpmiTransportPpiGuid, + NotifyPeiBmcElogCallback + } +}; + +/** + Efi Set Bmc Elog Data. + + @param This - Protocol pointer + @param ElogData - Buffer for log storage + @param DataType - Event Log type + @param AlertEvent - If it is an alert event + @param Size - Log data size + @param RecordId - Indicate which recorder it is + + @retval EFI_STATUS + +**/ +EFI_STATUS +EfiSetBmcElogData ( + IN EFI_SM_ELOG_REDIR_PPI *This, + IN UINT8 *ElogData, + IN EFI_SM_ELOG_TYPE DataType, + IN BOOLEAN AlertEvent, + IN UINTN Size, + OUT UINT64 *RecordId + ) +{ + EFI_PEI_BMC_ELOG_INSTANCE_DATA *BmcElogPrivateData; + EFI_STATUS Status; + + Status =3D EFI_SUCCESS; + BmcElogPrivateData =3D INSTANCE_FROM_EFI_PEI_ELOG_REDIR_THIS (This); + + if (DataType >=3D EfiSmElogMax) { + return EFI_INVALID_PARAMETER; + } + + if (Size > SEL_RECORD_SIZE) { + return EFI_OUT_OF_RESOURCES; + } + + if (BmcElogPrivateData->DataType =3D=3D DataType) { + Status =3D SetBmcElogRecord (ElogData, DataType, AlertEvent, Size, Rec= ordId); + } + + return Status; +} + +/** + Efi Get Bmc Elog Data. + + @param This - Protocol pointer + @param ElogData - Buffer for log data store + @param DataType - Event log type + @param Size - Size of log data + @param RecordId - indicate which recorder it is + + @retval EFI_STATUS + +**/ +EFI_STATUS +EfiGetBmcElogData ( + IN EFI_SM_ELOG_REDIR_PPI *This, + IN OUT UINT8 *ElogData, + IN EFI_SM_ELOG_TYPE DataType, + IN OUT UINTN *Size, + IN OUT UINT64 *RecordId + ) +{ + EFI_PEI_BMC_ELOG_INSTANCE_DATA *BmcElogPrivateData; + EFI_STATUS Status; + + Status =3D EFI_SUCCESS; + BmcElogPrivateData =3D INSTANCE_FROM_EFI_PEI_ELOG_REDIR_THIS (This); + + if (DataType >=3D EfiSmElogMax) { + return EFI_INVALID_PARAMETER; + } + + if (BmcElogPrivateData->DataType =3D=3D DataType) { + Status =3D GetBmcElogRecord (ElogData, DataType, Size, RecordId); + } + + return Status; +} + +/** + Efi Erase Bmc Elog Data. + + @param This - Protocol pointer + @param DataType - Event log type + @param RecordId - return which recorder it is + + @retval EFI_STATUS + +**/ +EFI_STATUS +EfiEraseBmcElogData ( + IN EFI_SM_ELOG_REDIR_PPI *This, + IN EFI_SM_ELOG_TYPE DataType, + IN OUT UINT64 *RecordId + ) +{ + EFI_PEI_BMC_ELOG_INSTANCE_DATA *BmcElogPrivateData; + EFI_STATUS Status; + + Status =3D EFI_SUCCESS; + BmcElogPrivateData =3D INSTANCE_FROM_EFI_PEI_ELOG_REDIR_THIS (This); + + if (DataType >=3D EfiSmElogMax) { + return EFI_INVALID_PARAMETER; + } + + if (BmcElogPrivateData->DataType =3D=3D DataType) { + Status =3D EraseBmcElogRecord (DataType, RecordId); + + if (Status =3D=3D EFI_SUCCESS) { + if (RecordId !=3D NULL) { + *RecordId =3D (UINT16)(*((UINT16 *)&BmcElogPrivateData->TempData[0= ])); + } + } + } + + return EFI_SUCCESS; +} + +/** + Efi Activate Bmc Elog. + + @param This - Protocol pointer + @param DataType - indicate event log type + @param EnableElog - Enable/Disable event log + @param ElogStatus - return log status + + @retval EFI_STATUS + +**/ +EFI_STATUS +EfiActivateBmcElog ( + IN EFI_SM_ELOG_REDIR_PPI *This, + IN EFI_SM_ELOG_TYPE DataType, + IN BOOLEAN *EnableElog, + OUT BOOLEAN *ElogStatus + ) +{ + EFI_PEI_BMC_ELOG_INSTANCE_DATA *BmcElogPrivateData; + EFI_STATUS Status; + + Status =3D EFI_SUCCESS; + BmcElogPrivateData =3D INSTANCE_FROM_EFI_PEI_ELOG_REDIR_THIS (This); + + if (DataType >=3D EfiSmElogMax) { + return EFI_INVALID_PARAMETER; + } + + if (BmcElogPrivateData->DataType =3D=3D DataType) { + Status =3D ActivateBmcElog (DataType, EnableElog, ElogStatus); + } + + return Status; +} + +/** + Set Elog Redir Install. + + @retval EFI_SUCCESS + +**/ +EFI_STATUS +SetElogRedirInstall ( + EFI_PEI_BMC_ELOG_INSTANCE_DATA *mRedirPeiProtoPrivate + ) +{ + EFI_STATUS Status; + BOOLEAN EnableElog; + BOOLEAN ElogStatus; + UINT16 Instance; + + Status =3D EFI_SUCCESS; + EnableElog =3D TRUE; + ElogStatus =3D TRUE; + Instance =3D 0; + + mRedirPeiProtoPrivate->Signature =3D EFI_PEI_ELOG_RED= IR_SIGNATURE; + mRedirPeiProtoPrivate->DataType =3D EfiElogSmIPMI; + mRedirPeiProtoPrivate->BmcElogPpi.ActivateEventLog =3D EfiActivateBmcEl= og; + mRedirPeiProtoPrivate->BmcElogPpi.EraseEventlogData =3D EfiEraseBmcElogD= ata; + mRedirPeiProtoPrivate->BmcElogPpi.GetEventLogData =3D EfiGetBmcElogDat= a; + mRedirPeiProtoPrivate->BmcElogPpi.SetEventLogData =3D EfiSetBmcElogDat= a; + + mRedirPeiProtoPrivate->BmcElog.Guid =3D &gPeiRedirElogPpiGuid; + mRedirPeiProtoPrivate->BmcElog.Flags =3D EFI_PEI_PPI_DESCRIPTOR_PPI | EF= I_PEI_PPI_DESCRIPTOR_TERMINATE_LIST; + mRedirPeiProtoPrivate->BmcElog.Ppi =3D (VOID *)&mRedirPeiProtoPrivate-= >BmcElogPpi; + mRedirPeiProtoPrivate->Instance =3D Instance; + // + // Now install the Protocol + // + + Status =3D PeiServicesInstallPpi (&mRedirPeiProtoPrivate->BmcElog); + ASSERT_EFI_ERROR (Status); + if (Status !=3D EFI_SUCCESS) { + return Status; + } + + // + // Activate the Event Log (This should depend upon Setup). + // + EfiActivateBmcElog (&mRedirPeiProtoPrivate->BmcElogPpi, EfiElogSmIPMI, &= EnableElog, &ElogStatus); + + return EFI_SUCCESS; +} + +/** + InitializeBmcElogLayer. + + @param ImageHandle - ImageHandle of the loaded driver + @param SystemTable - Pointer to the System Table + + @retval EFI_STATUS + +**/ +EFI_STATUS +InitializeBmcElogLayer ( + IN EFI_PEI_FILE_HANDLE FileHandle, + IN CONST EFI_PEI_SERVICES **PeiServices + ) +{ + EFI_STATUS Status; + + Status =3D EFI_SUCCESS; + + Status =3D PeiServicesNotifyPpi (&mNotifyList[0]); + return Status; +} + +/** + NotifyPeiBmcElogCallback This notification function is invoked when an= instance of the + IPMI Transport layer at PEI is produced. + + @param PeiServices - Pointer to the PEI Services table + @param NotifyDescriptor - Pointer to the NotifyPpi Descriptor + @param Ppi - Pointer to the PPI passed during Notify + + @retval EFI_STATUS + +**/ +EFI_STATUS +NotifyPeiBmcElogCallback ( + IN EFI_PEI_SERVICES **PeiServices, + IN EFI_PEI_NOTIFY_DESCRIPTOR *NotifyDescriptor, + IN VOID *Ppi + ) +{ + EFI_STATUS Status; + EFI_PEI_BMC_ELOG_INSTANCE_DATA *mRedirPeiProtoPrivate; + + Status =3D EFI_SUCCESS; + + mRedirPeiProtoPrivate =3D AllocateZeroPool (sizeof (EFI_PEI_BMC_ELOG_INS= TANCE_DATA)); + + if (mRedirPeiProtoPrivate =3D=3D NULL) { + DEBUG ((DEBUG_ERROR, "IPMI BMCELog Peim:EFI_OUT_OF_RESOURCES of memory= allocation\n")); + return EFI_OUT_OF_RESOURCES; + } + + SetElogRedirInstall (mRedirPeiProtoPrivate); + + CheckIfSelIsFull (); + + return Status; +} diff --git a/Features/Intel/OutOfBandManagement/IpmiFeaturePkg/BmcElog/Smm/= BmcElog.c b/Features/Intel/OutOfBandManagement/IpmiFeaturePkg/BmcElog/Smm/B= mcElog.c new file mode 100644 index 000000000000..efaa61f43869 --- /dev/null +++ b/Features/Intel/OutOfBandManagement/IpmiFeaturePkg/BmcElog/Smm/BmcElog= .c @@ -0,0 +1,288 @@ +/** @file + BMC Event Log functions. + +Copyright (c) 2023, Intel Corporation. All rights reserved.
+SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include "BmcElog.h" + +// +// Define module globals used to register for notification of when +// the ELOG REDIR protocol has been produced. +// +EFI_EVENT mEfiBmcTransEvent; +EFI_BMC_ELOG_INSTANCE_DATA *mRedirProtoPrivate; + +/** + WaitTillErased. + + @param BmcElogPrivateData - Bmc event log instance + @param ResvId - Reserved ID + + @retval EFI_SUCCESS + @retval EFI_NO_RESPONSE + +**/ +EFI_STATUS +WaitTillErased ( + EFI_BMC_ELOG_INSTANCE_DATA *BmcElogPrivateData, + UINT8 *ResvId + ) +{ + EFI_STATUS Status; + + Status =3D WaitTillClearSel (ResvId); + return Status; +} + +/** + Efi Set Bmc Elog Data. + + @param This - Protocol pointer + @param ElogData - Buffer for log storage + @param DataType - Event Log type + @param AlertEvent - If it is an alert event + @param Size - Log data size + @param RecordId - Indicate which recorder it is + + @retval EFI_STATUS + +**/ +EFI_STATUS +EfiSetBmcElogData ( + IN EFI_SM_ELOG_REDIR_PROTOCOL *This, + IN UINT8 *ElogData, + IN EFI_SM_ELOG_TYPE DataType, + IN BOOLEAN AlertEvent, + IN UINTN Size, + OUT UINT64 *RecordId + ) +{ + EFI_BMC_ELOG_INSTANCE_DATA *BmcElogPrivateData; + EFI_STATUS Status; + + Status =3D EFI_SUCCESS; + BmcElogPrivateData =3D INSTANCE_FROM_EFI_SM_ELOG_REDIR_THIS (This); + + if (DataType >=3D EfiSmElogMax) { + return EFI_INVALID_PARAMETER; + } + + if (Size > SEL_RECORD_SIZE) { + return EFI_OUT_OF_RESOURCES; + } + + if (BmcElogPrivateData->DataType =3D=3D DataType) { + Status =3D SetBmcElogRecord (ElogData, DataType, AlertEvent, Size, Rec= ordId); + } + + return Status; +} + +/** + Efi Get Bmc Elog Data. + + @param This - Protocol pointer + @param ElogData - Buffer for log data store + @param DataType - Event log type + @param Size - Size of log data + @param RecordId - indicate which recorder it is + + @retval EFI_STATUS + +**/ +EFI_STATUS +EfiGetBmcElogData ( + IN EFI_SM_ELOG_REDIR_PROTOCOL *This, + IN OUT UINT8 *ElogData, + IN EFI_SM_ELOG_TYPE DataType, + IN OUT UINTN *Size, + IN OUT UINT64 *RecordId + ) +{ + EFI_BMC_ELOG_INSTANCE_DATA *BmcElogPrivateData; + EFI_STATUS Status; + + Status =3D EFI_SUCCESS; + BmcElogPrivateData =3D INSTANCE_FROM_EFI_SM_ELOG_REDIR_THIS (This); + + if (DataType >=3D EfiSmElogMax) { + return EFI_INVALID_PARAMETER; + } + + if (BmcElogPrivateData->DataType =3D=3D DataType) { + Status =3D GetBmcElogRecord (ElogData, DataType, Size, RecordId); + } + + return Status; +} + +/** + Efi Erase Bmc Elog Data. + + @param This - Protocol pointer + @param DataType - Event log type + @param RecordId - return which recorder it is + + @retval EFI_STATUS + +**/ +EFI_STATUS +EfiEraseBmcElogData ( + IN EFI_SM_ELOG_REDIR_PROTOCOL *This, + IN EFI_SM_ELOG_TYPE DataType, + IN OUT UINT64 *RecordId + ) +{ + EFI_BMC_ELOG_INSTANCE_DATA *BmcElogPrivateData; + EFI_STATUS Status; + + Status =3D EFI_SUCCESS; + BmcElogPrivateData =3D INSTANCE_FROM_EFI_SM_ELOG_REDIR_THIS (This); + + if (DataType >=3D EfiSmElogMax) { + return EFI_INVALID_PARAMETER; + } + + if (BmcElogPrivateData->DataType =3D=3D DataType) { + Status =3D EraseBmcElogRecord (DataType, RecordId); + + if (Status =3D=3D EFI_SUCCESS) { + if (RecordId !=3D NULL) { + *RecordId =3D (UINT16)(*((UINT16 *)&BmcElogPrivateData->TempData[0= ])); + } + } + } + + return EFI_SUCCESS; +} + +/** + Efi Activate Bmc Elog. + + @param This - Protocol pointer + @param DataType - indicate event log type + @param EnableElog - Enable/Disable event log + @param ElogStatus - return log status + + @retval EFI_STATUS + +**/ +EFI_STATUS +EfiActivateBmcElog ( + IN EFI_SM_ELOG_REDIR_PROTOCOL *This, + IN EFI_SM_ELOG_TYPE DataType, + IN BOOLEAN *EnableElog, + OUT BOOLEAN *ElogStatus + ) +{ + EFI_BMC_ELOG_INSTANCE_DATA *BmcElogPrivateData; + EFI_STATUS Status; + + Status =3D EFI_SUCCESS; + BmcElogPrivateData =3D INSTANCE_FROM_EFI_SM_ELOG_REDIR_THIS (This); + + if (DataType >=3D EfiSmElogMax) { + return EFI_INVALID_PARAMETER; + } + + if (BmcElogPrivateData->DataType =3D=3D DataType) { + Status =3D ActivateBmcElog (DataType, EnableElog, ElogStatus); + } + + return Status; +} + +/** + Set Elog Redir Install. + + @retval EFI_SUCCESS + +**/ +EFI_STATUS +SetElogRedirInstall ( + VOID + ) +{ + EFI_HANDLE NewHandle; + EFI_STATUS Status; + BOOLEAN EnableElog; + BOOLEAN ElogStatus; + UINT16 Instance; + + Status =3D EFI_SUCCESS; + EnableElog =3D TRUE; + ElogStatus =3D TRUE; + Instance =3D 0; + + mRedirProtoPrivate->Signature =3D SM_ELOG_REDIR_SIGNATUR= E; + mRedirProtoPrivate->DataType =3D EfiElogSmIPMI; + mRedirProtoPrivate->BmcElog.ActivateEventLog =3D (EFI_ACTIVATE_ELOG)Efi= ActivateBmcElog; + mRedirProtoPrivate->BmcElog.EraseEventlogData =3D (EFI_ERASE_ELOG_DATA)E= fiEraseBmcElogData; + mRedirProtoPrivate->BmcElog.GetEventLogData =3D (EFI_GET_ELOG_DATA)Efi= GetBmcElogData; + mRedirProtoPrivate->BmcElog.SetEventLogData =3D (EFI_SET_ELOG_DATA)Efi= SetBmcElogData; + mRedirProtoPrivate->Instance =3D Instance; + // + // Now install the Protocol + // + NewHandle =3D NULL; + Status =3D gSmst->SmmInstallProtocolInterface ( + &NewHandle, + &gSmmRedirElogProtocolGuid, + EFI_NATIVE_INTERFACE, + &mRedirProtoPrivate->BmcElog + ); + + ASSERT_EFI_ERROR (Status); + if (Status !=3D EFI_SUCCESS) { + return Status; + } + + // + // Activate the Event Log (This should depend upon Setup). + // + EfiActivateBmcElog (&mRedirProtoPrivate->BmcElog, EfiElogSmIPMI, &Enable= Elog, &ElogStatus); + + return EFI_SUCCESS; +} + +/** + InitializeBmcElogLayer. + + @param ImageHandle - ImageHandle of the loaded driver + @param SystemTable - Pointer to the System Table + + @retval EFI_STATUS + +**/ +EFI_STATUS +EFIAPI +InitializeSmBmcElogLayer ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +{ + EFI_STATUS Status; + + Status =3D EFI_SUCCESS; + + gST =3D SystemTable; + gBS =3D gST->BootServices; + + mRedirProtoPrivate =3D AllocatePool (sizeof (EFI_BMC_ELOG_INSTANCE_DATA)= ); + ASSERT (mRedirProtoPrivate !=3D NULL); + if (mRedirProtoPrivate =3D=3D NULL) { + return EFI_OUT_OF_RESOURCES; + } + + SetElogRedirInstall (); + // + // Check if the BMC System Event Log (SEL) is full and whether to report= the error. + // + + CheckIfSelIsFull (); + + return Status; +} diff --git a/Features/Intel/OutOfBandManagement/IpmiFeaturePkg/GenericElog/= Dxe/GenericElog.c b/Features/Intel/OutOfBandManagement/IpmiFeaturePkg/Gener= icElog/Dxe/GenericElog.c new file mode 100644 index 000000000000..d432b2151664 --- /dev/null +++ b/Features/Intel/OutOfBandManagement/IpmiFeaturePkg/GenericElog/Dxe/Gen= ericElog.c @@ -0,0 +1,576 @@ +/** @file + Generic Event Log functions of DXE driver. + +Copyright (c) 2023, Intel Corporation. All rights reserved.
+SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include "GenericElog.h" + +ELOG_MODULE_GLOBAL *mElogModuleGlobal; + +// +// Define module globals used to register for notification of when +// the ELOG REDIR protocol has been produced. +// +EFI_EVENT mEfiElogRedirProtocolEvent; + +/** + Sends the Event-Log data to the destination. + + @param[in] ElogData Pointer to the Event-Log data that needs to be recor= ded. + @param[in] DataType Type of Elog Data that is being recorded. + @param[in] AlertEvent This is an indication that the input data type is = an Alert. + @param[in] DataSize + @param[out] RecordId Record ID sent by the target. + @param[in] Global The module global variable pointer. + @param[in] Virtual If this function is called in virtual mode or physica= l mode + + @retval EFI_SUCCESS Event-Log was recorded successfully. + @retval EFI_OUT_OF_RESOURCES Not enough resources to record data. + @retval EFI_UNSUPPORTED The Data Type is unsupported. + +**/ +EFI_STATUS +EfiLibSetElogData ( + IN UINT8 *ElogData, + IN EFI_SM_ELOG_TYPE DataType, + IN BOOLEAN AlertEvent, + IN UINTN DataSize, + OUT UINT64 *RecordId, + IN ELOG_MODULE_GLOBAL *Global, + IN BOOLEAN Virtual + ) +{ + UINT8 Index; + VOID *ElogRedirCommand; + EFI_STATUS Status; + EFI_STATUS RetStatus; + + RetStatus =3D EFI_UNSUPPORTED; + + if (DataType >=3D EfiSmElogMax) { + RetStatus =3D EFI_INVALID_PARAMETER; + return RetStatus; + } + + for (Index =3D 0; Index < Global->MaxDescriptors; Index++) { + if (Global->Redir[Index].Valid) { + ElogRedirCommand =3D Global->Redir[Index].Command[Virtual].SetEventL= ogData.Function; + Status =3D (*((EFI_SET_ELOG_DATA *)&ElogRedirCommand))(Glo= bal->Redir[Index].Command[Virtual].This, ElogData, DataType, AlertEvent, Da= taSize, RecordId); + + if (!EFI_ERROR (Status)) { + RetStatus =3D EFI_SUCCESS; + break; + } else if (Status !=3D EFI_UNSUPPORTED) { + RetStatus =3D Status; + break; + } + } + } + + return RetStatus; +} + +/** + Add function description. + + @param This - add argument description + @param ElogData - add argument description + @param DataType - add argument description + @param AlertEvent - add argument description + @param DataSize - add argument description + @param RecordId - add argument description + + @retval EFI_SUCCESS + +**/ +EFI_STATUS +EfiSetElogData ( + IN EFI_SM_ELOG_PROTOCOL *This, + IN UINT8 *ElogData, + IN EFI_SM_ELOG_TYPE DataType, + IN BOOLEAN AlertEvent, + IN UINTN DataSize, + OUT UINT64 *RecordId + ) +{ + if (DataType >=3D EfiSmElogMax) { + return EFI_INVALID_PARAMETER; + } + + return EfiLibSetElogData ( + ElogData, + DataType, + AlertEvent, + DataSize, + RecordId, + mElogModuleGlobal, + FALSE + ); +} + +/** + Gets the Event-Log data from the destination. + + @param[in] ElogData Pointer to the Event-Log data buffer that will conta= in the data to be retrieved. + @param[in] DataType Type of Elog Data that is being recorded. + @param[in, out] DataSize + @param[in, out] RecordId This is the RecordId of the next record. If Elo= gData is NULL, + this gives the RecordId of the first record availab= le in the database with the correct DataSize. + A value of 0 on return indicates the last record i= f the EFI_STATUS indicates a success + @param[in] Global The module global variable pointer. + @param[in] Virtual If this function is called in virtual mode or physica= l mode + + @retval EFI_SUCCESS Event-Log was retrieved successfully. + @retval EFI_NOT_FOUND Event-Log target not found. + @retval EFI_BUFFER_TOO_SMALL Target buffer is too small to retrieve the = data. + @retval EFI_UNSUPPORTED The Data Type is unsupported + +**/ +EFI_STATUS +EfiLibGetElogData ( + IN UINT8 *ElogData, + IN EFI_SM_ELOG_TYPE DataType, + IN OUT UINTN *DataSize, + IN OUT UINT64 *RecordId, + IN ELOG_MODULE_GLOBAL *Global, + IN BOOLEAN Virtual + ) +{ + UINT8 Index; + VOID *ElogRedirCommand; + EFI_STATUS Status; + EFI_STATUS RetStatus; + + RetStatus =3D EFI_UNSUPPORTED; + + if (DataType >=3D EfiSmElogMax) { + RetStatus =3D EFI_INVALID_PARAMETER; + return RetStatus; + } + + for (Index =3D 0; Index < Global->MaxDescriptors; Index++) { + if (Global->Redir[Index].Valid) { + ElogRedirCommand =3D Global->Redir[Index].Command[Virtual].GetEventL= ogData.Function; + Status =3D (*((EFI_GET_ELOG_DATA *)&ElogRedirCommand))(Glo= bal->Redir[Index].Command[Virtual].This, ElogData, DataType, DataSize, Reco= rdId); + + if (!EFI_ERROR (Status)) { + RetStatus =3D EFI_SUCCESS; + break; + } else if (Status !=3D EFI_UNSUPPORTED) { + RetStatus =3D Status; + break; + } + } + } + + return RetStatus; +} + +/** + Add function description. + + @param This - Protocol instance pointer. + @param ElogData - Pointer to the Event-Log data buffer that will contai= n the data to be retrieved. + @param DataType - Type of Elog Data that is being recorded. + @param DataSize - Size of Elog Data in bytes. + @param RecordId - This is 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 the last record if t= he EFI_STATUS indicates a success + + @retval EFI_SUCCESS add return values + +**/ +EFI_STATUS +EfiGetElogData ( + IN EFI_SM_ELOG_PROTOCOL *This, + IN UINT8 *ElogData, + IN EFI_SM_ELOG_TYPE DataType, + IN OUT UINTN *DataSize, + IN OUT UINT64 *RecordId + ) +{ + if (DataType >=3D EfiSmElogMax) { + return EFI_INVALID_PARAMETER; + } + + return EfiLibGetElogData (ElogData, DataType, DataSize, RecordId, mElogM= oduleGlobal, FALSE); +} + +/** + Erases the Event-Log data from the destination. + + @param DataType - Type of Elog Data that is being Erased. + @param RecordId - This is the RecordId of the data to be er= ased. If RecordId is NULL, all + the records on the database are erased if= permitted by the target. + Contains the deleted RecordId on return + @param Global - The module global variable pointer. + @param Virtual - If this function is called in virtual mod= e or physical mode + + @retval EFI_SUCCESS - Event-Log was erased successfully + @retval EFI_UNSUPPORTED - The Data Type is unsupported + @retval EFI_NOT_FOUND - Event-Log target not found + +**/ +EFI_STATUS +EfiLibEraseElogData ( + IN EFI_SM_ELOG_TYPE DataType, + IN OUT UINT64 *RecordId, + IN ELOG_MODULE_GLOBAL *Global, + IN BOOLEAN Virtual + ) +{ + UINT8 Index; + VOID *ElogRedirCommand; + EFI_STATUS Status; + EFI_STATUS RetStatus; + + RetStatus =3D EFI_UNSUPPORTED; + + if (DataType >=3D EfiSmElogMax) { + RetStatus =3D EFI_INVALID_PARAMETER; + return RetStatus; + } + + for (Index =3D 0; Index < Global->MaxDescriptors; Index++) { + if (Global->Redir[Index].Valid) { + ElogRedirCommand =3D Global->Redir[Index].Command[Virtual].EraseEven= tLogData.Function; + Status =3D (*((EFI_ERASE_ELOG_DATA *)&ElogRedirCommand))(G= lobal->Redir[Index].Command[Virtual].This, DataType, RecordId); + + if (!EFI_ERROR (Status)) { + RetStatus =3D EFI_SUCCESS; + break; + } else if (Status !=3D EFI_UNSUPPORTED) { + RetStatus =3D Status; + break; + } + } + } + + return RetStatus; +} + +/** + Efi Erase Elog Data. + + @param This + @param DataType + @param RecordId + + @retval EFI_SUCCESS + +**/ +EFI_STATUS +EfiEraseElogData ( + IN EFI_SM_ELOG_PROTOCOL *This, + IN EFI_SM_ELOG_TYPE DataType, + IN OUT UINT64 *RecordId + ) +{ + return EfiLibEraseElogData (DataType, RecordId, mElogModuleGlobal, FALSE= ); +} + +/** + This API enables/Disables Event Log. + + @param DataType - Type of Elog Data that is being Activated. + @param EnableElog - Enables (TRUE) / Disables (FALSE) Event L= og. If NULL just returns the + Current ElogStatus. + @param ElogStatus - Current (New) Status of Event Log. Enable= d (TRUE), Disabled (FALSE). + @param Global - The module global variable pointer. + @param Virtual - If this function is called in virtual mod= e or physical mode + + @retval EFI_SUCCESS - Event-Log was recorded successfully + @retval EFI_UNSUPPORTED - The Data Type is unsupported + +**/ +EFI_STATUS +EfiLibActivateElog ( + IN EFI_SM_ELOG_TYPE DataType, + IN BOOLEAN *EnableElog, + OUT BOOLEAN *ElogStatus, + ELOG_MODULE_GLOBAL *Global, + BOOLEAN Virtual + ) +{ + UINT8 Index; + VOID *ElogRedirCommand; + EFI_STATUS Status; + EFI_STATUS RetStatus; + + RetStatus =3D EFI_UNSUPPORTED; + if (DataType >=3D EfiSmElogMax) { + RetStatus =3D EFI_INVALID_PARAMETER; + return RetStatus; + } + + for (Index =3D 0; Index < Global->MaxDescriptors; Index++) { + if (Global->Redir[Index].Valid) { + ElogRedirCommand =3D Global->Redir[Index].Command[Virtual].ActivateE= ventLog.Function; + Status =3D (*((EFI_ACTIVATE_ELOG *)&ElogRedirCommand))(Glo= bal->Redir[Index].Command[Virtual].This, DataType, EnableElog, ElogStatus); + + if (!EFI_ERROR (Status)) { + RetStatus =3D EFI_SUCCESS; + break; + } else if (Status !=3D EFI_UNSUPPORTED) { + RetStatus =3D Status; + break; + } + } + } + + return RetStatus; +} + +/** + Efi Activate Elog. + + @param This + @param DataType + @param EnableElog + @param ElogStatus + + @retval EFI_SUCCESS + +**/ +EFI_STATUS +EfiActivateElog ( + IN EFI_SM_ELOG_PROTOCOL *This, + IN EFI_SM_ELOG_TYPE DataType, + IN BOOLEAN *EnableElog, + OUT BOOLEAN *ElogStatus + ) +{ + if (DataType >=3D EfiSmElogMax) { + return EFI_INVALID_PARAMETER; + } + + return EfiLibActivateElog (DataType, EnableElog, ElogStatus, mElogModule= Global, FALSE); +} + +/** + SetElogRedirInstances. + + @retval EFI_SUCCESS - The Redir instances were successfully set. + @retval Other - Failed to set Redir instances. + +**/ +EFI_STATUS +SetElogRedirInstances ( + VOID + ) +{ + UINTN NumHandles; + UINTN Index; + UINTN Instance; + UINTN EmptyIndex; + EFI_HANDLE *Buffer; + EFI_STATUS Status; + EFI_SM_ELOG_REDIR_PROTOCOL *Redir; + REDIR_MODULE_PROC *RedirProc; + + Buffer =3D NULL; + + // + // Check for all IPMI Controllers + // + Status =3D gBS->LocateHandleBuffer ( + ByProtocol, + &gEfiRedirElogProtocolGuid, + NULL, + &NumHandles, + &Buffer + ); + + if (EFI_ERROR (Status) || (NumHandles =3D=3D 0)) { + return EFI_SUCCESS; + } + + for (Index =3D 0; ((Index < NumHandles) && (Index < mElogModuleGlobal->M= axDescriptors)); Index++) { + EmptyIndex =3D mElogModuleGlobal->MaxDescriptors; + + Status =3D gBS->HandleProtocol ( + Buffer[Index], + &gEfiRedirElogProtocolGuid, + (VOID *)&Redir + ); + if (EFI_ERROR (Status) || (Redir =3D=3D NULL)) { + continue; + } + + for (Instance =3D 0; Instance < mElogModuleGlobal->MaxDescriptors; Ins= tance++) { + if (mElogModuleGlobal->Redir[Instance].Valid =3D=3D FALSE) { + if (EmptyIndex >=3D mElogModuleGlobal->MaxDescriptors) { + EmptyIndex =3D Instance; + } + } else { + if (Redir =3D=3D mElogModuleGlobal->Redir[Instance].Command->This)= { + EmptyIndex =3D mElogModuleGlobal->MaxDescriptors; + break; + // + // FIX: changed continue to break. + // + } + } + } + + if (EmptyIndex < mElogModuleGlobal->MaxDescriptors) { + RedirProc =3D (REDIR_MODULE_PROC *)= mElogModuleGlobal->Redir[EmptyIndex].Command; + mElogModuleGlobal->Redir[EmptyIndex].Valid =3D TRUE; + + EfiSetFunctionEntry (&RedirProc->ActivateEventLog, *((VOID **)&Redir= ->ActivateEventLog)); + EfiSetFunctionEntry (&RedirProc->EraseEventLogData, *((VOID **)&Redi= r->EraseEventlogData)); + EfiSetFunctionEntry (&RedirProc->GetEventLogData, *((VOID **)&Redir-= >GetEventLogData)); + EfiSetFunctionEntry (&RedirProc->SetEventLogData, *((VOID **)&Redir-= >SetEventLogData)); + RedirProc->This =3D Redir; + + CopyMem (&RedirProc[EFI_ELOG_VIRTUAL], &RedirProc[EFI_ELOG_PHYSICAL]= , sizeof (REDIR_MODULE_PROC)); + } + } + + if (Buffer !=3D NULL) { + FreePool (Buffer); + } + + return EFI_SUCCESS; +} + +/** + This notification function is invoked when an instance of the + ELOG REDIR protocol is produced. + + @param Event - The event that occurred + @param Context - For EFI compatibility. Not used. + +**/ +VOID +EFIAPI +NotifyElogRedirEventCallback ( + IN EFI_EVENT Event, + IN VOID *Context + ) +{ + SetElogRedirInstances (); +} + +/** + Initialize the generic Elog driver of server management. + + @param ImageHandle - The image handle of this driver + @param SystemTable - The pointer of EFI_SYSTEM_TABLE + + @retval EFI_SUCCESS - The driver initialized successfully + +**/ +EFI_STATUS +EFIAPI +InitializeElogLayer ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +{ + EFI_HANDLE NewHandle; + EFI_STATUS Status; + EFI_SM_ELOG_PROTOCOL *ElogProtocol; + EFI_EVENT Event; + + mElogModuleGlobal =3D AllocateZeroPool (sizeof (ELOG_MODULE_GLOBAL)); + ASSERT (mElogModuleGlobal !=3D NULL); + if (mElogModuleGlobal =3D=3D NULL) { + return EFI_OUT_OF_RESOURCES; + } + + ElogServiceInitialize (ImageHandle, SystemTable); + + mElogModuleGlobal->MaxDescriptors =3D MAX_REDIR_DESCRIPTOR; + + // + // Check for all IPMI Controllers + // + SetElogRedirInstances (); + + ElogProtocol =3D AllocatePool (sizeof (EFI_SM_ELOG_PROTOCOL)); + ASSERT (ElogProtocol !=3D NULL); + if (ElogProtocol =3D=3D NULL) { + return EFI_OUT_OF_RESOURCES; + } + + ElogProtocol->ActivateEventLog =3D EfiActivateElog; + ElogProtocol->EraseEventlogData =3D EfiEraseElogData; + ElogProtocol->GetEventLogData =3D EfiGetElogData; + ElogProtocol->SetEventLogData =3D EfiSetElogData; + + NewHandle =3D NULL; + Status =3D gBS->InstallProtocolInterface ( + &NewHandle, + &gEfiGenericElogProtocolGuid, + EFI_NATIVE_INTERFACE, + ElogProtocol + ); + + ASSERT_EFI_ERROR (Status); + if (Status !=3D EFI_SUCCESS) { + return Status; + } + + // + // Register to be notified when the ELOG REDIR protocol has been + // produced. + // + Status =3D gBS->CreateEvent ( + EVT_NOTIFY_SIGNAL, + TPL_CALLBACK, + NotifyElogRedirEventCallback, + NULL, + &Event + ); + + if (!EFI_ERROR (Status)) { + Status =3D gBS->RegisterProtocolNotify ( + &gEfiRedirElogProtocolGuid, + Event, + &mEfiElogRedirProtocolEvent + ); + } + + return Status; +} + +/** + Set the function entry. + + @param FunctionPointer - The destination function pointer + @param Function - The source function pointer + + @retval EFI_SUCCESS - Set the function pointer successfully + +**/ +EFI_STATUS +EfiSetFunctionEntry ( + IN FUNCTION_PTR *FunctionPointer, + IN VOID *Function + ) +{ + FunctionPointer->Function =3D (EFI_PLABEL *)Function; + return EFI_SUCCESS; +} + +/** + Initialize Dxe generic event log. + + @param ImageHandle - The Image handle of this driver. + @param SystemTable - The pointer of EFI_SYSTEM_TABLE. + + @retval EFI_SUCCESS - The driver successfully initialized + +**/ +EFI_STATUS +ElogServiceInitialize ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +{ + return EFI_SUCCESS; +} diff --git a/Features/Intel/OutOfBandManagement/IpmiFeaturePkg/GenericElog/= Smm/GenericElog.c b/Features/Intel/OutOfBandManagement/IpmiFeaturePkg/Gener= icElog/Smm/GenericElog.c new file mode 100644 index 000000000000..d6a129a181fb --- /dev/null +++ b/Features/Intel/OutOfBandManagement/IpmiFeaturePkg/GenericElog/Smm/Gen= ericElog.c @@ -0,0 +1,558 @@ +/** @file + Generic Event Log functions of SMM driver. + +Copyright (c) 2023, Intel Corporation. All rights reserved.
+SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include "GenericElog.h" + +ELOG_MODULE_GLOBAL *mElogModuleGlobal; + +// +// Define module globals used to register for notification of when +// the ELOG REDIR protocol has been produced. +// +EFI_EVENT mEfiElogRedirProtocolEvent; + +/** + Sends the Event-Log data to the destination. + + @param ElogData - Pointer to the Event-Log data that needs = to be recorded. + @param DataType - Type of Elog Data that is being recorded. + @param AlertEvent - This is an indication that the input data= type is an Alert. + @param DataSize - Size of the data to be logged. + @param RecordId - Record ID sent by the target. + @param Global - The module global variable pointer. + @param Virtual - If this function is called in virtual mod= e or physical mode + + @retval EFI_SUCCESS - Event-Log was recorded successfully. + @retval EFI_OUT_OF_RESOURCES - Not enough resources to record data. + @retval EFI_UNSUPPORTED - The Data Type is unsupported. + +**/ +EFI_STATUS +EfiLibSetElogData ( + IN UINT8 *ElogData, + IN EFI_SM_ELOG_TYPE DataType, + IN BOOLEAN AlertEvent, + IN UINTN DataSize, + OUT UINT64 *RecordId, + IN ELOG_MODULE_GLOBAL *Global, + IN BOOLEAN Virtual + ) +{ + UINT8 Index; + VOID *ElogRedirCommand; + EFI_STATUS Status; + EFI_STATUS RetStatus; + + RetStatus =3D EFI_UNSUPPORTED; + + if (DataType >=3D EfiSmElogMax) { + RetStatus =3D EFI_INVALID_PARAMETER; + return RetStatus; + } + + for (Index =3D 0; Index < Global->MaxDescriptors; Index++) { + if (Global->Redir[Index].Valid) { + ElogRedirCommand =3D Global->Redir[Index].Command[Virtual].SetEventL= ogData.Function; + Status =3D (*((EFI_SET_ELOG_DATA *)&ElogRedirCommand))(Glo= bal->Redir[Index].Command[Virtual].This, ElogData, DataType, AlertEvent, Da= taSize, RecordId); + + if (!EFI_ERROR (Status)) { + RetStatus =3D EFI_SUCCESS; + break; + } else if (Status !=3D EFI_UNSUPPORTED) { + RetStatus =3D Status; + break; + } + } + } + + return RetStatus; +} + +/** + Efi Set Elog Data. + + @param This + @param ElogData + @param DataType + @param AlertEvent + @param DataSize + @param RecordId + + @retval EFI_SUCCESS + +**/ +EFI_STATUS +EfiSetElogData ( + IN EFI_SM_ELOG_PROTOCOL *This, + IN UINT8 *ElogData, + IN EFI_SM_ELOG_TYPE DataType, + IN BOOLEAN AlertEvent, + IN UINTN DataSize, + OUT UINT64 *RecordId + ) +{ + if (DataType >=3D EfiSmElogMax) { + return EFI_INVALID_PARAMETER; + } + + return EfiLibSetElogData ( + ElogData, + DataType, + AlertEvent, + DataSize, + RecordId, + mElogModuleGlobal, + FALSE + ); +} + +/** + Gets the Event-Log data from the destination. + + @param ElogData - Pointer to the Event-Log data buffer that= will contain the data to be retrieved. + @param DataType - Type of Elog Data that is being recorded. + @param DataSize - Size of the data to be retrieved. . + @param RecordId - This is the RecordId of the next record. = If ElogData is NULL, + this gives the RecordId of the first recor= d available in the database with the correct DataSize. + A value of 0 on return indicates the last = record if the EFI_STATUS indicates a success + @param Global - The module global variable pointer. + @param Virtual - If this function is called in virtual mod= e or physical mode + + @retval EFI_SUCCESS - Event-Log was retrieved successfully. + @retval EFI_NOT_FOUND - Event-Log target not found. + @retval EFI_BUFFER_TOO_SMALL - Target buffer is too small to retrieve t= he data. + @retval EFI_UNSUPPORTED - The Data Type is unsupported + +**/ +EFI_STATUS +EfiLibGetElogData ( + IN UINT8 *ElogData, + IN EFI_SM_ELOG_TYPE DataType, + IN OUT UINTN *DataSize, + IN OUT UINT64 *RecordId, + IN ELOG_MODULE_GLOBAL *Global, + IN BOOLEAN Virtual + ) +{ + UINT8 Index; + VOID *ElogRedirCommand; + EFI_STATUS Status; + EFI_STATUS RetStatus; + + RetStatus =3D EFI_UNSUPPORTED; + + if (DataType >=3D EfiSmElogMax) { + RetStatus =3D EFI_INVALID_PARAMETER; + return RetStatus; + } + + for (Index =3D 0; Index < Global->MaxDescriptors; Index++) { + if (Global->Redir[Index].Valid) { + ElogRedirCommand =3D Global->Redir[Index].Command[Virtual].GetEventL= ogData.Function; + Status =3D (*((EFI_GET_ELOG_DATA *)&ElogRedirCommand))(Glo= bal->Redir[Index].Command[Virtual].This, ElogData, DataType, DataSize, Reco= rdId); + + if (!EFI_ERROR (Status)) { + RetStatus =3D EFI_SUCCESS; + break; + } else if (Status !=3D EFI_UNSUPPORTED) { + RetStatus =3D Status; + break; + } + } + } + + return RetStatus; +} + +/** + Efi Get Elog Data. + + @param This + @param ElogData + @param DataType + @param DataSize + @param RecordId + + @retval EFI_SUCCESS + +**/ +EFI_STATUS +EfiGetElogData ( + IN EFI_SM_ELOG_PROTOCOL *This, + IN UINT8 *ElogData, + IN EFI_SM_ELOG_TYPE DataType, + IN OUT UINTN *DataSize, + IN OUT UINT64 *RecordId + ) +{ + if (DataType >=3D EfiSmElogMax) { + return EFI_INVALID_PARAMETER; + } + + return EfiLibGetElogData (ElogData, DataType, DataSize, RecordId, mElogM= oduleGlobal, FALSE); +} + +/** + Erases the Event-Log data from the destination. + + @param DataType - Type of Elog Data that is being Erased. + @param RecordId - This is the RecordId of the data to be er= ased. If RecordId is NULL, all + the records on the database are erased if= permitted by the target. + Contains the deleted RecordId on return + @param Global - The module global variable pointer. + @param Virtual - If this function is called in virtual mod= e or physical mode + + @retval EFI_SUCCESS - Event-Log was erased successfully + @retval EFI_UNSUPPORTED - The Data Type is unsupported + @retval EFI_NOT_FOUND - Event-Log target not found + +**/ +EFI_STATUS +EfiLibEraseElogData ( + IN EFI_SM_ELOG_TYPE DataType, + IN OUT UINT64 *RecordId, + IN ELOG_MODULE_GLOBAL *Global, + IN BOOLEAN Virtual + ) +{ + UINT8 Index; + VOID *ElogRedirCommand; + EFI_STATUS Status; + EFI_STATUS RetStatus; + + RetStatus =3D EFI_UNSUPPORTED; + + if (DataType >=3D EfiSmElogMax) { + RetStatus =3D EFI_INVALID_PARAMETER; + return RetStatus; + } + + for (Index =3D 0; Index < Global->MaxDescriptors; Index++) { + if (Global->Redir[Index].Valid) { + ElogRedirCommand =3D Global->Redir[Index].Command[Virtual].EraseEven= tLogData.Function; + Status =3D (*((EFI_ERASE_ELOG_DATA *)&ElogRedirCommand))(G= lobal->Redir[Index].Command[Virtual].This, DataType, RecordId); + + if (!EFI_ERROR (Status)) { + RetStatus =3D EFI_SUCCESS; + break; + } else if (Status !=3D EFI_UNSUPPORTED) { + RetStatus =3D Status; + break; + } + } + } + + return RetStatus; +} + +/** + Efi Erase Elog Data + + @param This + @param DataType + @param RecordId + + @retval EFI_SUCCESS + +**/ +EFI_STATUS +EfiEraseElogData ( + IN EFI_SM_ELOG_PROTOCOL *This, + IN EFI_SM_ELOG_TYPE DataType, + IN OUT UINT64 *RecordId + ) +{ + return EfiLibEraseElogData (DataType, RecordId, mElogModuleGlobal, FALSE= ); +} + +/** + This API enables/Disables Event Log. + + @param DataType - Type of Elog Data that is being Activated. + @param EnableElog - Enables (TRUE) / Disables (FALSE) Event L= og. If NULL just returns the + Current ElogStatus. + @param ElogStatus - Current (New) Status of Event Log. Enable= d (TRUE), Disabled (FALSE). + @param Global - The module global variable pointer. + @param Virtual - If this function is called in virtual mod= e or physical mode + + @retval EFI_SUCCESS - Event-Log was recorded successfully + @retval EFI_UNSUPPORTED - The Data Type is unsupported + +**/ +EFI_STATUS +EfiLibActivateElog ( + IN EFI_SM_ELOG_TYPE DataType, + IN BOOLEAN *EnableElog, + OUT BOOLEAN *ElogStatus, + ELOG_MODULE_GLOBAL *Global, + BOOLEAN Virtual + ) +{ + UINT8 Index; + VOID *ElogRedirCommand; + EFI_STATUS Status; + EFI_STATUS RetStatus; + + RetStatus =3D EFI_UNSUPPORTED; + if (DataType >=3D EfiSmElogMax) { + RetStatus =3D EFI_INVALID_PARAMETER; + return RetStatus; + } + + for (Index =3D 0; Index < Global->MaxDescriptors; Index++) { + if (Global->Redir[Index].Valid) { + ElogRedirCommand =3D Global->Redir[Index].Command[Virtual].ActivateE= ventLog.Function; + Status =3D (*((EFI_ACTIVATE_ELOG *)&ElogRedirCommand))(Glo= bal->Redir[Index].Command[Virtual].This, DataType, EnableElog, ElogStatus); + + if (!EFI_ERROR (Status)) { + RetStatus =3D EFI_SUCCESS; + break; + } else if (Status !=3D EFI_UNSUPPORTED) { + RetStatus =3D Status; + break; + } + } + } + + return RetStatus; +} + +/** + Efi Activate Elog. + + @param This + @param DataType + @param EnableElog + @param ElogStatus + + @retval EFI_SUCCESS + +**/ +EFI_STATUS +EfiActivateElog ( + IN EFI_SM_ELOG_PROTOCOL *This, + IN EFI_SM_ELOG_TYPE DataType, + IN BOOLEAN *EnableElog, + OUT BOOLEAN *ElogStatus + ) +{ + if (DataType >=3D EfiSmElogMax) { + return EFI_INVALID_PARAMETER; + } + + return EfiLibActivateElog (DataType, EnableElog, ElogStatus, mElogModule= Global, FALSE); +} + +/** + Set Elog Redir Instances. + + @retval EFI_SUCCESS - The Redir instances were successfully set. + @retval Other - Failed to set Redir instances. + +**/ +EFI_STATUS +SetElogRedirInstances ( + VOID + ) +{ + UINTN NumHandles; + UINTN Index; + UINTN Instance; + UINTN EmptyIndex; + EFI_HANDLE *Buffer; + EFI_STATUS Status; + EFI_SM_ELOG_REDIR_PROTOCOL *Redir; + REDIR_MODULE_PROC *RedirProc; + + Buffer =3D NULL; + + // + // Check for all IPMI Controllers + // + Status =3D gSmst->SmmLocateHandle ( + ByProtocol, + &gSmmRedirElogProtocolGuid, + NULL, + &NumHandles, + Buffer + ); + + if (EFI_ERROR (Status) || (NumHandles =3D=3D 0) || (Buffer =3D=3D NULL))= { + return Status; + } + + for (Index =3D 0; ((Index < NumHandles) && (Index < mElogModuleGlobal->M= axDescriptors)); Index++) { + EmptyIndex =3D mElogModuleGlobal->MaxDescriptors; + + Status =3D gSmst->SmmHandleProtocol ( + Buffer[Index], + &gSmmRedirElogProtocolGuid, + (VOID *)&Redir + ); + if (EFI_ERROR (Status) || (Redir =3D=3D NULL)) { + continue; + } + + for (Instance =3D 0; Instance < mElogModuleGlobal->MaxDescriptors; Ins= tance++) { + if (mElogModuleGlobal->Redir[Instance].Valid =3D=3D FALSE) { + if (EmptyIndex >=3D mElogModuleGlobal->MaxDescriptors) { + EmptyIndex =3D Instance; + } + } else { + if (Redir =3D=3D mElogModuleGlobal->Redir[Instance].Command->This)= { + EmptyIndex =3D mElogModuleGlobal->MaxDescriptors; + break; + // + // FIX: changed continue to break. + // + } + } + } + + if (EmptyIndex < mElogModuleGlobal->MaxDescriptors) { + RedirProc =3D (REDIR_MODULE_PROC *)= mElogModuleGlobal->Redir[EmptyIndex].Command; + mElogModuleGlobal->Redir[EmptyIndex].Valid =3D TRUE; + + EfiSetFunctionEntry (&RedirProc->ActivateEventLog, *((VOID **)&Redir= ->ActivateEventLog)); + EfiSetFunctionEntry (&RedirProc->EraseEventLogData, *((VOID **)&Redi= r->EraseEventlogData)); + EfiSetFunctionEntry (&RedirProc->GetEventLogData, *((VOID **)&Redir-= >GetEventLogData)); + EfiSetFunctionEntry (&RedirProc->SetEventLogData, *((VOID **)&Redir-= >SetEventLogData)); + RedirProc->This =3D Redir; + + CopyMem (&RedirProc[EFI_ELOG_VIRTUAL], &RedirProc[EFI_ELOG_PHYSICAL]= , sizeof (REDIR_MODULE_PROC)); + } + } + + return EFI_SUCCESS; +} + +/** + This notification function is invoked when an instance of the + ELOG REDIR protocol is produced. + + @param Event - The event that occurred + @param Context - For EFI compatibility. Not used. + +**/ +VOID +EFIAPI +NotifyElogRedirEventCallback ( + IN EFI_EVENT Event, + IN VOID *Context + ) +{ + SetElogRedirInstances (); +} + +/** + Initialize the generic Elog driver of server management. + + @param ImageHandle - The image handle of this driver + @param SystemTable - The pointer of EFI_SYSTEM_TABLE + + @retval EFI_SUCCESS - The driver initialized successfully + +**/ +EFI_STATUS +EFIAPI +InitializeSmElogLayer ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +{ + EFI_HANDLE NewHandle; + EFI_STATUS Status; + EFI_SM_ELOG_PROTOCOL *ElogProtocol; + + mElogModuleGlobal =3D AllocatePool (sizeof (ELOG_MODULE_GLOBAL)); + ASSERT (mElogModuleGlobal !=3D NULL); + if (mElogModuleGlobal =3D=3D NULL) { + return EFI_OUT_OF_RESOURCES; + } + + SmElogServiceInitialize (ImageHandle, SystemTable); + + mElogModuleGlobal->MaxDescriptors =3D MAX_REDIR_DESCRIPTOR; + + // + // Check for all IPMI Controllers + // + SetElogRedirInstances (); + + ElogProtocol =3D AllocatePool (sizeof (EFI_SM_ELOG_PROTOCOL)); + ASSERT (ElogProtocol !=3D NULL); + if (ElogProtocol =3D=3D NULL) { + return EFI_OUT_OF_RESOURCES; + } + + ElogProtocol->ActivateEventLog =3D (EFI_ACTIVATE_ELOG)EfiActivateElog; + ElogProtocol->EraseEventlogData =3D (EFI_ERASE_ELOG_DATA)EfiEraseElogDat= a; + ElogProtocol->GetEventLogData =3D (EFI_GET_ELOG_DATA)EfiGetElogData; + ElogProtocol->SetEventLogData =3D (EFI_SET_ELOG_DATA)EfiSetElogData; + + NewHandle =3D NULL; + Status =3D gSmst->SmmInstallProtocolInterface ( + &NewHandle, + &gSmmGenericElogProtocolGuid, + EFI_NATIVE_INTERFACE, + ElogProtocol + ); + + ASSERT_EFI_ERROR (Status); + if (Status !=3D EFI_SUCCESS) { + return Status; + } + + // + // Register to be notified when the ELOG REDIR protocol has been + // produced. + // + Status =3D gSmst->SmmRegisterProtocolNotify ( + &gSmmRedirElogProtocolGuid, + NULL, + &mEfiElogRedirProtocolEvent + ); + return Status; +} + +/** + Set the function entry. + + @param FunctionPointer - The destination function pointer + @param Function - The source function pointer + + @retval EFI_SUCCESS - Set the function pointer successfully + +**/ +EFI_STATUS +EfiSetFunctionEntry ( + IN FUNCTION_PTR *FunctionPointer, + IN VOID *Function + ) +{ + FunctionPointer->Function =3D (EFI_PLABEL *)Function; + return EFI_SUCCESS; +} + +/** + Entry point of SM Elog service Driver + + @param ImageHandle - The Image handle of this driver. + @param SystemTable - The pointer of EFI_SYSTEM_TABLE. + + @retval EFI_SUCCESS - The driver successfully initialized + +**/ +EFI_STATUS +SmElogServiceInitialize ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +{ + return EFI_SUCCESS; +} --=20 2.39.2.windows.1 -=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 (#110326): https://edk2.groups.io/g/devel/message/110326 Mute This Topic: https://groups.io/mt/102279905/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- From nobody Tue May 14 15:37:46 2024 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+110327+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+110327+1787277+3901457@groups.io; dmarc=fail(p=none dis=none) header.from=intel.com ARC-Seal: i=1; a=rsa-sha256; t=1698686018; cv=none; d=zohomail.com; s=zohoarc; b=JuB8KW9AvxvE4ZpyOOOkZ8pMHRVUgi4plBv4du3VN2G4NftRnvAYJqsO29JewjufpmBpF9JgWLTMCRkI+AFTiRoiLHYtuX/NDew+iQiFtPitM81EMlz7HLrWj8xRCFRSEqEvp6BdGwmEJfCpncRcFi7YPEjGgvK7ioeX/rEc5FI= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1698686018; 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=/UO2gOJH60ykgCdUv30fR5Mag9tJVQK6n2GhCqPUcBw=; b=aP4KEVem/8U3m1tWZxgRcPuYRRy9XdHmUKJRrkNDLiHNFdmfHOEqdC28glmKdwxuMV4IblDnLGDLG9NK9Mcdb8fVC+UK85n15rWLyGP/j70NTQtBkOSAj8wmkgRZi5WvBGBGGBriM/yp1hCW43Vr1Buj91R5WVHSFovSH4on+64= 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+110327+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 1698686018622166.5478837799269; Mon, 30 Oct 2023 10:13:38 -0700 (PDT) Return-Path: DKIM-Signature: a=rsa-sha256; bh=Ci8Jh5M7GNJmhMGsrGvTOH3SK1YiTQb4J7V/000rEDg=; 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=1698686018; v=1; b=JAUbTFOuBba4hrkw8lsDH4DzKxUr/cCd0W8hbj4oDHkY5mfQ2t3eafEDviBtyrmmHlvDcKoY bCPdiR6hbYIC2/23pyun7JmMU6OMlqjlQqJgjMP8TAZ1grCPQmoeZOmmHa3OgRUGvhhyJ7wa7VJ 14y8eYAlhZ/lhRE/yEcEEq50= X-Received: by 127.0.0.2 with SMTP id ODSdYY1788612xKtdEXICy1N; Mon, 30 Oct 2023 10:13:38 -0700 X-Received: from mgamail.intel.com (mgamail.intel.com [134.134.136.24]) by mx.groups.io with SMTP id smtpd.web10.80041.1698611264012724787 for ; Sun, 29 Oct 2023 13:27:49 -0700 X-IronPort-AV: E=McAfee;i="6600,9927,10878"; a="390840889" X-IronPort-AV: E=Sophos;i="6.03,261,1694761200"; d="scan'208";a="390840889" X-Received: from orsmga001.jf.intel.com ([10.7.209.18]) by orsmga102.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 29 Oct 2023 13:27:49 -0700 X-ExtLoop1: 1 X-IronPort-AV: E=McAfee;i="6600,9927,10878"; a="795098442" X-IronPort-AV: E=Sophos;i="6.03,261,1694761200"; d="scan'208";a="795098442" X-Received: from scsrds0181.amr.corp.intel.com ([10.116.50.7]) by orsmga001.jf.intel.com with ESMTP; 29 Oct 2023 13:27:48 -0700 From: "Zhen Gong" To: devel@edk2.groups.io Cc: Zhen Gong Subject: [edk2-devel] [PATCH edk2-platforms v2 2/4] IpmiFeaturePkg: Add ServerManagementLib Date: Sun, 29 Oct 2023 13:27:38 -0700 Message-Id: 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,zhen.gong@intel.com List-Unsubscribe-Post: List-Unsubscribe=One-Click List-Unsubscribe: X-Gm-Message-State: CvGviBfY1vsjFxznPANWguB7x1787277AA= Content-Transfer-Encoding: quoted-printable X-ZohoMail-DKIM: pass (identity @groups.io) X-ZM-MESSAGEID: 1698686019981100002 Content-Type: text/plain; charset="utf-8" Lightweight lib to support Server Management drivers. Signed-off-by: Zhen Gong --- .../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/Libra= ry/ServerManagementLib/ServerManagementLib.inf create mode 100644 Features/Intel/OutOfBandManagement/IpmiFeaturePkg/Libra= ry/ServerManagementLibNull/ServerManagementLibNull.inf create mode 100644 Features/Intel/OutOfBandManagement/IpmiFeaturePkg/Inclu= de/Library/ServerMgmtRtLib.h create mode 100644 Features/Intel/OutOfBandManagement/IpmiFeaturePkg/Libra= ry/ServerManagementLib/ServerManagementLib.c create mode 100644 Features/Intel/OutOfBandManagement/IpmiFeaturePkg/Libra= ry/ServerManagementLibNull/ServerManagementLibNull.c diff --git a/Features/Intel/OutOfBandManagement/IpmiFeaturePkg/Include/Ipmi= Feature.dsc b/Features/Intel/OutOfBandManagement/IpmiFeaturePkg/Include/Ipm= iFeature.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.U= EFI_DRIVER] [LibraryClasses.common] BmcCommonInterfaceLib|IpmiFeaturePkg/Library/BmcInterfaceCommonAccess/Bm= cCommonInterfaceLib.inf BtInterfaceLib|IpmiFeaturePkg/Library/BmcInterfaceCommonAccess/BtInterfa= ceLib/BtInterfaceLib.inf + ServerManagementLib|IpmiFeaturePkg/Library/ServerManagementLib/ServerMan= agementLib.inf =20 [LibraryClasses.common.DXE_RUNTIME_DRIVER, LibraryClasses.common.DXE_DRIVE= R] SsifInterfaceLib|IpmiFeaturePkg/Library/BmcInterfaceCommonAccess/SsifInt= erfaceLib/DxeSsifInterfaceLib.inf diff --git a/Features/Intel/OutOfBandManagement/IpmiFeaturePkg/Library/Serv= erManagementLib/ServerManagementLib.inf b/Features/Intel/OutOfBandManagemen= t/IpmiFeaturePkg/Library/ServerManagementLib/ServerManagementLib.inf new file mode 100644 index 000000000000..25a3a7540762 --- /dev/null +++ b/Features/Intel/OutOfBandManagement/IpmiFeaturePkg/Library/ServerManag= ementLib/ServerManagementLib.inf @@ -0,0 +1,35 @@ +### @file +# +# Copyright (c) 2023, Intel Corporation. All rights reserved.
+# +# SPDX-License-Identifier: BSD-2-Clause-Patent +# +### + + +[Defines] + INF_VERSION =3D 0x00010005 + BASE_NAME =3D ServerManagementLib + FILE_GUID =3D D43C86F0-7C8B-4992-9593-8CB6FBC66A0A + MODULE_TYPE =3D BASE + VERSION_STRING =3D 1.0 + PI_SPECIFICATION_VERSION =3D 0x0001000A + LIBRARY_CLASS =3D 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/Serv= erManagementLibNull/ServerManagementLibNull.inf b/Features/Intel/OutOfBandM= anagement/IpmiFeaturePkg/Library/ServerManagementLibNull/ServerManagementLi= bNull.inf new file mode 100644 index 000000000000..6b66b44857f3 --- /dev/null +++ b/Features/Intel/OutOfBandManagement/IpmiFeaturePkg/Library/ServerManag= ementLibNull/ServerManagementLibNull.inf @@ -0,0 +1,38 @@ +### @file +# +# Copyright (c) 2023, Intel Corporation. All rights reserved.
+# +# SPDX-License-Identifier: BSD-2-Clause-Patent +# +### + + +[Defines] + INF_VERSION =3D 0x00010005 + BASE_NAME =3D ServerManagementLibNull + FILE_GUID =3D 3AC01DE9-5A96-4df5-A645-ECD092C29AF9 + MODULE_TYPE =3D BASE + VERSION_STRING =3D 1.0 + PI_SPECIFICATION_VERSION =3D 0x0001000A + LIBRARY_CLASS =3D ServerManagementLib + +# +# The following information is for reference only and not required by the = build tools. +# +# VALID_ARCHITECTURES =3D IA32 X64 +# + +[Sources.common] + ServerManagementLibNull.c + + +[Packages] + MdePkg/MdePkg.dec + ServerPlatformPkg/PlatformPkg.dec + +[LibraryClasses] + DebugLib + +[Protocols] + + diff --git a/Features/Intel/OutOfBandManagement/IpmiFeaturePkg/Include/Libr= ary/ServerMgmtRtLib.h b/Features/Intel/OutOfBandManagement/IpmiFeaturePkg/I= nclude/Library/ServerMgmtRtLib.h new file mode 100644 index 000000000000..12b2e82f9e6e --- /dev/null +++ b/Features/Intel/OutOfBandManagement/IpmiFeaturePkg/Include/Library/Ser= verMgmtRtLib.h @@ -0,0 +1,147 @@ +/** @file + Server Management Driver Lib. + +Copyright (c) 2023, Intel Corporation. All rights reserved.
+SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#ifndef _SERVER_MGMT_LIB_H_ +#define _SERVER_MGMT_LIB_H_ + +#include + +/** + ELOG Library Initializer. +**/ + +/** + 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. + @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 rec= orded + @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 Data= Type 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 c= an 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_OUT_OF_RESOURCES If the DataSize is larger than the Elog tem= p 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 i= s NULL, this gives the RecordId of the first + record available in the database with the correct DataSi= ze. 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 fill= ed 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 re= dir 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 Reco= rdId is NULL, all records in the + database are erased if permitted by the target. RecordI= d 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 respo= nd. + @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 D= ataType. 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 disable= d. + @retval EFI_NOT_FOUND The event log target was not found. + @retval EFI_NO_RESPONSE The event log target was found but did not respo= nd. + @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/Serv= erManagementLib/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/ServerManag= ementLib/ServerManagementLib.c @@ -0,0 +1,696 @@ +/** @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; +} diff --git a/Features/Intel/OutOfBandManagement/IpmiFeaturePkg/Library/Serv= erManagementLibNull/ServerManagementLibNull.c b/Features/Intel/OutOfBandMan= agement/IpmiFeaturePkg/Library/ServerManagementLibNull/ServerManagementLibN= ull.c new file mode 100644 index 000000000000..7dd27f34878e --- /dev/null +++ b/Features/Intel/OutOfBandManagement/IpmiFeaturePkg/Library/ServerManag= ementLibNull/ServerManagementLibNull.c @@ -0,0 +1,144 @@ +/** @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 + +/** + 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 + ) +{ + 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 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_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 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_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 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 + ) +{ + 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 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_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 =3D 0; + + return EFI_NOT_FOUND; +} --=20 2.39.2.windows.1 -=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 (#110327): https://edk2.groups.io/g/devel/message/110327 Mute This Topic: https://groups.io/mt/102279906/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- From nobody Tue May 14 15:37:46 2024 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+110328+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+110328+1787277+3901457@groups.io; dmarc=fail(p=none dis=none) header.from=intel.com ARC-Seal: i=1; a=rsa-sha256; t=1698686019; cv=none; d=zohomail.com; s=zohoarc; b=FeAfMNxvQHUn0ggVSyj2WhOmwu9h3VQ5xl0GaS921UTv6KEhD1QYV29ANqXae0y7fw+kpQV0c11uWfUOUSw/ouaApeNgKufa1RF+6i0ydFZefzXzVgh3c8hH81zuUmXhMbqgmQNr/OAvaUkgP8bV3RqRXwuOdsl9a4oObrdnj5M= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1698686019; 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=WIAm5UKpKNXm8JHMk1auGurLk3z9B2V/6X3FTtLwVcs=; b=ArozrZs9WqbGDIrt/AYhy08WHNRP6bmDJJzo/AanOJGEkxLT4U/ircnHqiQO9EyEssTC2u8xpDfBp0l/PTP9LTRN+jP3bEvNnRB69WO58ad96ELdi+RwP903gP3rTmKddK3b5GanoXRf4q/9+fU3kj3cNx9xS6L1PRsN5uFxH6o= 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+110328+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 1698686019237642.2227603191194; Mon, 30 Oct 2023 10:13:39 -0700 (PDT) Return-Path: DKIM-Signature: a=rsa-sha256; bh=vGRSyI/7BVSARpRq7PRUUpVpGaVVR3w7SeGrvSQxt6k=; 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=1698686018; v=1; b=mUSBV3Tamp+WztprtmlIYw5Awwi25pShgqEi3Yi+joMMkV15Ms+pkitWhJSM+uF0s6gF4u5x ZvtGQbYuYYoq6RWsoaqnBZmpWDzm7ahS5fFkZYxMlB+mJxdCLm+O9iesilMdtzRhlBZVOBQdpPg HwRJqA/ZFOjk2j1R/0gXt1yk= X-Received: by 127.0.0.2 with SMTP id NYneYY1788612xqXjcLbEjWq; Mon, 30 Oct 2023 10:13:38 -0700 X-Received: from mgamail.intel.com (mgamail.intel.com [134.134.136.24]) by mx.groups.io with SMTP id smtpd.web11.80195.1698611269553056908 for ; Sun, 29 Oct 2023 13:27:49 -0700 X-IronPort-AV: E=McAfee;i="6600,9927,10878"; a="390840890" X-IronPort-AV: E=Sophos;i="6.03,261,1694761200"; d="scan'208";a="390840890" X-Received: from orsmga001.jf.intel.com ([10.7.209.18]) by orsmga102.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 29 Oct 2023 13:27:49 -0700 X-ExtLoop1: 1 X-IronPort-AV: E=McAfee;i="6600,9927,10878"; a="795098447" X-IronPort-AV: E=Sophos;i="6.03,261,1694761200"; d="scan'208";a="795098447" X-Received: from scsrds0181.amr.corp.intel.com ([10.116.50.7]) by orsmga001.jf.intel.com with ESMTP; 29 Oct 2023 13:27:48 -0700 From: "Zhen Gong" To: devel@edk2.groups.io Cc: Zhen Gong Subject: [edk2-devel] [PATCH edk2-platforms v2 3/4] IpmiFeaturePkg: Add ACPI power state drivers Date: Sun, 29 Oct 2023 13:27:39 -0700 Message-Id: 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,zhen.gong@intel.com List-Unsubscribe-Post: List-Unsubscribe=One-Click List-Unsubscribe: X-Gm-Message-State: cNnmLyuZV1CmoyrTLCca7bRUx1787277AA= Content-Transfer-Encoding: quoted-printable X-ZohoMail-DKIM: pass (identity @groups.io) X-ZM-MESSAGEID: 1698686019960100001 Content-Type: text/plain; charset="utf-8" Add DXE and SMM drivers that send "Set ACPI Power State" command to BMC. Signed-off-by: Zhen Gong --- .../IpmiFeaturePkg/IpmiFeaturePkg.dec | 1 + .../IpmiFeaturePkg/Include/IpmiFeature.dsc | 2 + .../IpmiFeaturePkg/Include/PostMemory.fdf | 2 + .../BmcAcpiState/BmcAcpiState.inf | 40 ++++ .../BmcAcpiSwChild/BmcAcpiSwChild.inf | 39 ++++ .../BmcAcpiState/BmcAcpiState.h | 26 +++ .../BmcAcpiSwChild/BmcAcpiSwChild.h | 82 ++++++++ .../Include/Protocol/BmcAcpiSwChildPolicy.h | 31 +++ .../BmcAcpiState/BmcAcpiState.c | 93 +++++++++ .../BmcAcpiSwChild/BmcAcpiSwChild.c | 189 ++++++++++++++++++ 10 files changed, 505 insertions(+) create mode 100644 Features/Intel/OutOfBandManagement/IpmiFeaturePkg/BmcAc= piState/BmcAcpiState.inf create mode 100644 Features/Intel/OutOfBandManagement/IpmiFeaturePkg/BmcAc= piSwChild/BmcAcpiSwChild.inf create mode 100644 Features/Intel/OutOfBandManagement/IpmiFeaturePkg/BmcAc= piState/BmcAcpiState.h create mode 100644 Features/Intel/OutOfBandManagement/IpmiFeaturePkg/BmcAc= piSwChild/BmcAcpiSwChild.h create mode 100644 Features/Intel/OutOfBandManagement/IpmiFeaturePkg/Inclu= de/Protocol/BmcAcpiSwChildPolicy.h create mode 100644 Features/Intel/OutOfBandManagement/IpmiFeaturePkg/BmcAc= piState/BmcAcpiState.c create mode 100644 Features/Intel/OutOfBandManagement/IpmiFeaturePkg/BmcAc= piSwChild/BmcAcpiSwChild.c diff --git a/Features/Intel/OutOfBandManagement/IpmiFeaturePkg/IpmiFeatureP= kg.dec b/Features/Intel/OutOfBandManagement/IpmiFeaturePkg/IpmiFeaturePkg.d= ec index 22bc4e69be8a..be0a11e2adb1 100644 --- a/Features/Intel/OutOfBandManagement/IpmiFeaturePkg/IpmiFeaturePkg.dec +++ b/Features/Intel/OutOfBandManagement/IpmiFeaturePkg/IpmiFeaturePkg.dec @@ -75,6 +75,7 @@ [Protocols] gEfiVideoPrintProtocolGuid =3D {0x3dbf3e06, 0x9d0c, 0x40d3, {0xb2, 0= x17, 0x45, 0x5f, 0x33, 0x9e, 0x29, 0x09}} gIpmiTransport2ProtocolGuid =3D { 0x4A1D0E66, 0x5271, 0x4E22, { 0x83, 0x= FE, 0x90, 0x92, 0x1B, 0x74, 0x82, 0x13 }} gSmmIpmiTransport2ProtocolGuid =3D { 0x1DBD1503, 0x0A60, 0x4230, { 0xAA,= 0xA3, 0x80, 0x16, 0xD8, 0xC3, 0xDE, 0x2F }} + gEfiBmcAcpiSwChildPolicyProtocolGuid =3D { 0x89843c0b, 0x5701, 0x4ff6, {= 0xa4, 0x73, 0x65, 0x75, 0x99, 0x04, 0xf7, 0x35 } } gEfiGenericElogProtocolGuid =3D { 0x59d02fcd, 0x9233, 0x4d34, { 0xbc, 0x= fe, 0x87, 0xca, 0x81, 0xd3, 0xdd, 0xa7 } } gSmmGenericElogProtocolGuid =3D { 0x664ef1f6, 0x19bf, 0x4498, { 0xab, 0x= 6a, 0xfc, 0x05, 0x72, 0xfb, 0x98, 0x51 } } gEfiRedirElogProtocolGuid =3D { 0x16d11030, 0x71ba, 0x4e5e, { 0xa9, 0xf9= , 0xb4, 0x75, 0xa5, 0x49, 0x4, 0x8a } } diff --git a/Features/Intel/OutOfBandManagement/IpmiFeaturePkg/Include/Ipmi= Feature.dsc b/Features/Intel/OutOfBandManagement/IpmiFeaturePkg/Include/Ipm= iFeature.dsc index fc9001e98473..7e663236d9a1 100644 --- a/Features/Intel/OutOfBandManagement/IpmiFeaturePkg/Include/IpmiFeature= .dsc +++ b/Features/Intel/OutOfBandManagement/IpmiFeaturePkg/Include/IpmiFeature= .dsc @@ -122,6 +122,8 @@ [Components.X64] IpmiFeaturePkg/GenericIpmi/Dxe/GenericIpmi.inf IpmiFeaturePkg/Library/SmmIpmiBaseLib/SmmIpmiBaseLib.inf IpmiFeaturePkg/BmcAcpi/BmcAcpi.inf + IpmiFeaturePkg/BmcAcpiState/BmcAcpiState.inf + IpmiFeaturePkg/BmcAcpiSwChild/BmcAcpiSwChild.inf IpmiFeaturePkg/BmcElog/DxeBmcElog.inf IpmiFeaturePkg/BmcElog/SmmBmcElog.inf IpmiFeaturePkg/GenericElog/Dxe/GenericElog.inf diff --git a/Features/Intel/OutOfBandManagement/IpmiFeaturePkg/Include/Post= Memory.fdf b/Features/Intel/OutOfBandManagement/IpmiFeaturePkg/Include/Post= Memory.fdf index f29810bc0b34..9b692f07dcd8 100644 --- a/Features/Intel/OutOfBandManagement/IpmiFeaturePkg/Include/PostMemory.= fdf +++ b/Features/Intel/OutOfBandManagement/IpmiFeaturePkg/Include/PostMemory.= fdf @@ -10,6 +10,8 @@ INF IpmiFeaturePkg/GenericIpmi/Dxe/GenericIpmi.inf INF IpmiFeaturePkg/IpmiInit/DxeIpmiInit.inf INF RuleOverride =3D DRIVER_ACPITABLE IpmiFeaturePkg/BmcAcpi/BmcAcpi.inf +INF IpmiFeaturePkg/BmcAcpiState/BmcAcpiState.inf +INF IpmiFeaturePkg/BmcAcpiSwChild/BmcAcpiSwChild.inf INF IpmiFeaturePkg/BmcElog/DxeBmcElog.inf INF IpmiFeaturePkg/BmcElog/SmmBmcElog.inf INF IpmiFeaturePkg/Frb/FrbDxe.inf diff --git a/Features/Intel/OutOfBandManagement/IpmiFeaturePkg/BmcAcpiState= /BmcAcpiState.inf b/Features/Intel/OutOfBandManagement/IpmiFeaturePkg/BmcAc= piState/BmcAcpiState.inf new file mode 100644 index 000000000000..f1b750d6a20a --- /dev/null +++ b/Features/Intel/OutOfBandManagement/IpmiFeaturePkg/BmcAcpiState/BmcAcp= iState.inf @@ -0,0 +1,40 @@ +### @file +# +# Copyright (c) 2023, Intel Corporation. All rights reserved.
+# +# SPDX-License-Identifier: BSD-2-Clause-Patent +# +### + + +[Defines] + INF_VERSION =3D 0x00010005 + BASE_NAME =3D BmcAcpiState + FILE_GUID =3D 04103e59-48cc-417a-baec-9929c69c20f6 + MODULE_TYPE =3D DXE_DRIVER + VERSION_STRING =3D 1.0 + ENTRY_POINT =3D BmcAcpiStateEntryPoint + +[Sources] + BmcAcpiState.c + BmcAcpiState.h + +[Packages] + IpmiFeaturePkg/IpmiFeaturePkg.dec + MdePkg/MdePkg.dec + MdeModulePkg/MdeModulePkg.dec + +[LibraryClasses] + DebugLib + UefiDriverEntryPoint + UefiBootServicesTableLib + IpmiBaseLib + +[Protocols] + gIpmiTransportProtocolGuid + +[Guids] + gEfiEventExitBootServicesGuid ## CONSUMES ## Event + +[Depex] + gIpmiTransportProtocolGuid diff --git a/Features/Intel/OutOfBandManagement/IpmiFeaturePkg/BmcAcpiSwChi= ld/BmcAcpiSwChild.inf b/Features/Intel/OutOfBandManagement/IpmiFeaturePkg/B= mcAcpiSwChild/BmcAcpiSwChild.inf new file mode 100644 index 000000000000..59a9f77d9f10 --- /dev/null +++ b/Features/Intel/OutOfBandManagement/IpmiFeaturePkg/BmcAcpiSwChild/BmcA= cpiSwChild.inf @@ -0,0 +1,39 @@ +### @file +# +# Copyright (c) 2023, Intel Corporation. All rights reserved.
+# +# SPDX-License-Identifier: BSD-2-Clause-Patent +# +### + + +[Defines] + INF_VERSION =3D 0x00010005 + BASE_NAME =3D BmcAcpiSwChild + FILE_GUID =3D BB5BEBD1-CE71-4cd0-9E2F-C07886502661 + MODULE_TYPE =3D DXE_SMM_DRIVER + PI_SPECIFICATION_VERSION =3D 0x0001000A + VERSION_STRING =3D 1.0 + ENTRY_POINT =3D InitializeBmcAcpiSwChild + +[Sources] + BmcAcpiSwChild.c + BmcAcpiSwChild.h + +[Packages] + IpmiFeaturePkg/IpmiFeaturePkg.dec + MdePkg/MdePkg.dec + MdeModulePkg/MdeModulePkg.dec + +[LibraryClasses] + UefiDriverEntryPoint + DebugLib + SmmServicesTableLib + ServerManagementLib + IpmiBaseLib + +[Protocols] + gEfiBmcAcpiSwChildPolicyProtocolGuid # PROTOCOL ALWAYS_PRODUCED + +[Depex] + gSmmIpmiTransportProtocolGuid diff --git a/Features/Intel/OutOfBandManagement/IpmiFeaturePkg/BmcAcpiState= /BmcAcpiState.h b/Features/Intel/OutOfBandManagement/IpmiFeaturePkg/BmcAcpi= State/BmcAcpiState.h new file mode 100644 index 000000000000..4352652a2bda --- /dev/null +++ b/Features/Intel/OutOfBandManagement/IpmiFeaturePkg/BmcAcpiState/BmcAcp= iState.h @@ -0,0 +1,26 @@ +/** @file + +Copyright (c) 2023, Intel Corporation. All rights reserved.
+SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#ifndef _ACPI_BMC_STATE_H_ +#define _ACPI_BMC_STATE_H_ + +// +// Statements that include other header files +// +#include +#include +#include +#include +#include +#include +#include +#include +#include + +EFI_EVENT mExitBootServicesEvent =3D NULL; + +#endif diff --git a/Features/Intel/OutOfBandManagement/IpmiFeaturePkg/BmcAcpiSwChi= ld/BmcAcpiSwChild.h b/Features/Intel/OutOfBandManagement/IpmiFeaturePkg/Bmc= AcpiSwChild/BmcAcpiSwChild.h new file mode 100644 index 000000000000..10d687ed2b84 --- /dev/null +++ b/Features/Intel/OutOfBandManagement/IpmiFeaturePkg/BmcAcpiSwChild/BmcA= cpiSwChild.h @@ -0,0 +1,82 @@ +/** @file + This driver produces the ACPI enable and disable SMI handlers. + +Copyright (c) 2023, Intel Corporation. All rights reserved.
+SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#ifndef _BMC_ACPI_SW_CHILD_H_ +#define _BMC_ACPI_SW_CHILD_H_ + +// +// Statements that include other files +// +#include +#include +#include +#include +#include +#include +#include + +#include "ServerManagement.h" + +#include +#include +#include +#include +#include + +// +// Module prototypes +// + +/** + This is the standard EFI driver entrypoint. This function initializes + the BMC ACPI SW Child protocol. + + @param ImageHandle - ImageHandle of the loaded driver + @param SystemTable - Pointer to the System Table + + @retval EFI_SUCCESS - If all services discovered. + @retval Other - Failure in constructor. + +**/ +EFI_STATUS +EFIAPI +InitializeBmcAcpiSwChild ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ); + +/** + Send the time to the BMC, in the UNIX 32 bit format. + + @retval Status - result of sending the time stamp + +**/ +EFI_STATUS +SyncTimeStamp ( + VOID + ); + +/** + Send a command to BMC to set the present power state. + + @param This + @param PowerState + @param DeviceState + + @retval EFI_SUCCESS if successful + @retval Other than EFI_SUCCESS if not successful + +**/ +EFI_STATUS +SetACPIPowerStateInBMC ( + IN EFI_BMC_ACPI_SW_CHILD_POLICY_PROTOCOL *This, + IN UINT8 PowerState, + IN UINT8 DeviceState + ); + +#endif diff --git a/Features/Intel/OutOfBandManagement/IpmiFeaturePkg/Include/Prot= ocol/BmcAcpiSwChildPolicy.h b/Features/Intel/OutOfBandManagement/IpmiFeatur= ePkg/Include/Protocol/BmcAcpiSwChildPolicy.h new file mode 100644 index 000000000000..7958f8c63899 --- /dev/null +++ b/Features/Intel/OutOfBandManagement/IpmiFeaturePkg/Include/Protocol/Bm= cAcpiSwChildPolicy.h @@ -0,0 +1,31 @@ +/** @file + This protocol produces BmcAcpiSwChildPolicy Protocol. + +Copyright (c) 2023, Intel Corporation. All rights reserved.
+SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#ifndef _BMC_ACPI_SW_CHILD_POLICY_H_ +#define _BMC_ACPI_SW_CHILD_POLICY_H_ + +typedef struct _EFI_BMC_ACPI_SW_CHILD_POLICY_PROTOCOL EFI_BMC_ACPI_SW_CHIL= D_POLICY_PROTOCOL; + +#define EFI_BMC_ACPI_SW_CHILD_POLICY_PROTOCOL_GUID \ + { 0x89843c0b, 0x5701, 0x4ff6, 0xa4, 0x73, 0x65, 0x75, 0x99, 0x04, 0xf7, = 0x35 } + +typedef +EFI_STATUS +(EFIAPI *EFI_SET_ACPI_POWER_STATE_IN_BMC)( + IN EFI_BMC_ACPI_SW_CHILD_POLICY_PROTOCOL *This, + IN UINT8 PowerState, + IN UINT8 DeviceState + ); + +struct _EFI_BMC_ACPI_SW_CHILD_POLICY_PROTOCOL { + EFI_SET_ACPI_POWER_STATE_IN_BMC SetACPIPowerStateInBMC; +}; + +extern EFI_GUID gEfiBmcAcpiSwChildPolicyProtocolGuid; + +#endif diff --git a/Features/Intel/OutOfBandManagement/IpmiFeaturePkg/BmcAcpiState= /BmcAcpiState.c b/Features/Intel/OutOfBandManagement/IpmiFeaturePkg/BmcAcpi= State/BmcAcpiState.c new file mode 100644 index 000000000000..04fe2d80307e --- /dev/null +++ b/Features/Intel/OutOfBandManagement/IpmiFeaturePkg/BmcAcpiState/BmcAcp= iState.c @@ -0,0 +1,93 @@ +/** @file + +Copyright (c) 2023, Intel Corporation. All rights reserved.
+SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include + +/** + Notification function of Exit Boot Services event group. + + Send a command to BMC to set power state to S0. + + @param Event Event whose notification function is being invoked. + @param Context Pointer to the notification function's context. + +**/ +VOID +EFIAPI +BmcAcpiPowerStateS0Notify ( + EFI_EVENT Event, + VOID *Context + ) +{ + EFI_STATUS Status =3D EFI_SUCCESS; + IPMI_SET_ACPI_POWER_STATE_REQUEST AcpiPowerStateRequest; + UINT8 AcpiPowerStateResponse; + UINT32 ResponseDataSize =3D 0; + + AcpiPowerStateRequest.SystemPowerState.Bits.PowerState =3D IPMI_SYSTEM_= POWER_STATE_S0_G0; // System Power State S0 + AcpiPowerStateRequest.SystemPowerState.Bits.StateChange =3D 1; + AcpiPowerStateRequest.DevicePowerState.Bits.PowerState =3D IPMI_DEVICE_= POWER_STATE_D0; // Device State State S0 + AcpiPowerStateRequest.DevicePowerState.Bits.StateChange =3D 1; + + ResponseDataSize =3D sizeof (AcpiPowerStateResponse); + + // + // Send a command to BMC to set power state to S0. + // + Status =3D IpmiSubmitCommand ( + IPMI_NETFN_APP, + IPMI_APP_SET_ACPI_POWERSTATE, + (UINT8 *)&AcpiPowerStateRequest, + sizeof (IPMI_SET_ACPI_POWER_STATE_REQUEST), + (UINT8 *)&AcpiPowerStateResponse, + &ResponseDataSize + ); + + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_ERROR, "IpmiSubmitCommand App Set Acpi Power State Faile= d %r\n", Status)); + } +} + +/** + + Entry point for the Bmc Acpi State Dxe driver. + Use this function to replace previous ACPI Enable SMM handler to set BMC= ACPI power state. + + @param ImageHandle - Image Handle. + @param SystemTable - EFI System Table. + + @retval EFI_SUCCESS - Function has completed successfully. + +**/ +EFI_STATUS +EFIAPI +BmcAcpiStateEntryPoint ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +{ + EFI_STATUS Status; + + // + // Create an Exit Boot Service to Send a command to BMC to set the prese= nt power state + // + Status =3D gBS->CreateEventEx ( + EVT_NOTIFY_SIGNAL, + TPL_NOTIFY, + BmcAcpiPowerStateS0Notify, + NULL, + &gEfiEventExitBootServicesGuid, + &mExitBootServicesEvent + ); + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_ERROR, "Create Exit Boot Services Event Failed\n")); + } else { + return EFI_SUCCESS; + } + + return EFI_UNSUPPORTED; +} diff --git a/Features/Intel/OutOfBandManagement/IpmiFeaturePkg/BmcAcpiSwChi= ld/BmcAcpiSwChild.c b/Features/Intel/OutOfBandManagement/IpmiFeaturePkg/Bmc= AcpiSwChild/BmcAcpiSwChild.c new file mode 100644 index 000000000000..ba134db8d50d --- /dev/null +++ b/Features/Intel/OutOfBandManagement/IpmiFeaturePkg/BmcAcpiSwChild/BmcA= cpiSwChild.c @@ -0,0 +1,189 @@ +/** @file + This driver publishes a protocol that is used by the ACPI SMM Platform + driver to notify the BMC of Power State transitions. + +Copyright (c) 2023, Intel Corporation. All rights reserved.
+SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include "BmcAcpiSwChild.h" + +// +// Global variables +// +EFI_BMC_ACPI_SW_CHILD_POLICY_PROTOCOL mBmcAcpiSwChild; + +/** + This is the standard EFI driver entrypoint. This function initializes + the BMC ACPI SW Child protocol. + + @param ImageHandle - ImageHandle of the loaded driver + @param SystemTable - Pointer to the System Table + + @retval EFI_SUCCESS - If all services discovered. + @retval Other - Failure in constructor. + +**/ +EFI_STATUS +EFIAPI +InitializeBmcAcpiSwChild ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +{ + EFI_STATUS Status; + EFI_HANDLE Handle; + + Status =3D EFI_SUCCESS; + + mBmcAcpiSwChild.SetACPIPowerStateInBMC =3D (EFI_SET_ACPI_POWER_STATE_IN_= BMC)SetACPIPowerStateInBMC; + + // + // Install protocol + // + Handle =3D NULL; + Status =3D gSmst->SmmInstallProtocolInterface ( + &Handle, + &gEfiBmcAcpiSwChildPolicyProtocolGuid, + EFI_NATIVE_INTERFACE, + &mBmcAcpiSwChild + ); + + return Status; +} + +/** + Send the time to the BMC, in the UNIX 32 bit format. + + @retval Status - result of sending the time stamp + +**/ +EFI_STATUS +SyncTimeStamp ( + VOID + ) +{ + EFI_STATUS Status; + UINT32 ResponseDataSize; + IPMI_ADD_SEL_ENTRY_REQUEST TimeStampEvtRecord; + IPMI_ADD_SEL_ENTRY_RESPONSE AddSelEntryResponse; + IPMI_SET_SEL_TIME_REQUEST SelTimeReq; + UINT8 SelTimeResponse; + + TimeStampEvtRecord.RecordData.RecordId =3D 0; = // Record Id + TimeStampEvtRecord.RecordData.RecordType =3D IPMI_SEL_SYSTEM_RECORD; = // Record Type + TimeStampEvtRecord.RecordData.TimeStamp =3D 0; = // Time stamp + TimeStampEvtRecord.RecordData.GeneratorId =3D 0x0003; = // GenID:BIOS + TimeStampEvtRecord.RecordData.EvMRevision =3D IPMI_EVM_REVISION; = // EVM REV + TimeStampEvtRecord.RecordData.SensorType =3D 0x12; = // Sensor Type + TimeStampEvtRecord.RecordData.SensorNumber =3D 0x83; = // Sensor No + TimeStampEvtRecord.RecordData.EventDirType =3D IPMI_SENSOR_TYPE_EVENT_CO= DE_DISCRETE; // Event Dir + TimeStampEvtRecord.RecordData.OEMEvData1 =3D 05; = // Sensor specific Offset for Timestamp Clock Synch Event. + TimeStampEvtRecord.RecordData.OEMEvData2 =3D 00; = // ED2 + TimeStampEvtRecord.RecordData.OEMEvData3 =3D 0xFF; = // ED3 + + // + // Log Timestamp Clock Synch Event 1st pair. + // + ResponseDataSize =3D sizeof (AddSelEntryResponse); + Status =3D IpmiSubmitCommand ( + IPMI_NETFN_STORAGE, + IPMI_STORAGE_ADD_SEL_ENTRY, + (UINT8 *)&TimeStampEvtRecord, + sizeof (TimeStampEvtRecord), + (UINT8 *)&AddSelEntryResponse, + &ResponseDataSize + ); + + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_ERROR, "IpmiSubmitCommand Storage Add SEL Entry Failed %= r\n", Status)); + return Status; + } + + Status =3D EfiSmGetTimeStamp (&SelTimeReq.Timestamp); + if (EFI_ERROR (Status)) { + return Status; + } + + ResponseDataSize =3D sizeof (SelTimeResponse); + Status =3D IpmiSubmitCommand ( + IPMI_NETFN_STORAGE, + IPMI_STORAGE_SET_SEL_TIME, + (UINT8 *)&SelTimeReq, + sizeof (SelTimeReq), + (UINT8 *)&SelTimeResponse, + &ResponseDataSize + ); + + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_ERROR, "IpmiSubmitCommand Storage Set SEL Time Failed %r= \n", Status)); + return Status; + } + + // + // Log Timestamp Clock Sync Event 2nd pair. + // + TimeStampEvtRecord.RecordData.OEMEvData2 =3D 0x80; + ResponseDataSize =3D sizeof (AddSelEntryResponse= ); + Status =3D IpmiSubmitCommand ( + IPMI_NETFN_STORAGE, + IPMI_STORAGE_ADD_SEL_ENTRY, + (UINT8 *)&TimeStampEvtRecor= d, + sizeof (TimeStampEvtRecord), + (UINT8 *)&AddSelEntryRespon= se, + &ResponseDataSize + ); + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_ERROR, "IpmiSubmitCommand Storage Add SEL Entry Failed %= r\n", Status)); + return Status; + } + + return EFI_SUCCESS; +} + +/** + Send a command to BMC to set the present power state. + + @param This + @param PowerState + @param DeviceState + + @retval EFI_SUCCESS if successful + @retval Other than EFI_SUCCESS if not successful + +**/ +EFI_STATUS +SetACPIPowerStateInBMC ( + IN EFI_BMC_ACPI_SW_CHILD_POLICY_PROTOCOL *This, + IN UINT8 PowerState, + IN UINT8 DeviceState + ) +{ + EFI_STATUS Status; + IPMI_SET_ACPI_POWER_STATE_REQUEST AcpiPowerStateRequest; + UINT8 AcpiPowerStateResponse; + UINT32 ResponseDataSize; + + AcpiPowerStateRequest.SystemPowerState.Bits.PowerState =3D PowerState; + AcpiPowerStateRequest.SystemPowerState.Bits.StateChange =3D 1; + AcpiPowerStateRequest.DevicePowerState.Bits.PowerState =3D DeviceState; + AcpiPowerStateRequest.DevicePowerState.Bits.StateChange =3D 1; + + ResponseDataSize =3D sizeof (AcpiPowerStateResponse); + + Status =3D IpmiSubmitCommand ( + IPMI_NETFN_APP, + IPMI_APP_SET_ACPI_POWERSTATE, + (UINT8 *)&AcpiPowerStateRequest, + sizeof (AcpiPowerStateRequest), + (UINT8 *)&AcpiPowerStateResponse, + &ResponseDataSize + ); + + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_ERROR, "IpmiSubmitCommand App Set Acpi Power State Faile= d %r\n", Status)); + } + + return Status; +} --=20 2.39.2.windows.1 -=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 (#110328): https://edk2.groups.io/g/devel/message/110328 Mute This Topic: https://groups.io/mt/102279907/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- From nobody Tue May 14 15:37:46 2024 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+110329+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+110329+1787277+3901457@groups.io; dmarc=fail(p=none dis=none) header.from=intel.com ARC-Seal: i=1; a=rsa-sha256; t=1698686020; cv=none; d=zohomail.com; s=zohoarc; b=LVilmuFpTFgcg1Rsid1bLRoBMSqQRFub/djipj+XzdVXXELw4DxVxpDDxN1JzHNTNxIDdxJJAN1FHPiFkkZwXawgEHu89PspPMUztseZ/GM8yrm3EO413sOPR51SvBAbltIaf/itb7m99cVBQ7ukwXieM+FLiOMWNeWwee+bUQw= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1698686020; 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=QelXBHbqfINeC6qH7J1Iy6Qwx0hhCzdKeE+Bu2bE7r4=; b=FWagacLfYXOcoL0hdSvpysglkx6lbQF/T9b3oghm8jtl/GFcgOYkHtoZkLGEGYKBNPXTB8/gm3VyfBBHO3IDFane2j3Lbv0udhRt2SNR4HkFY7rHP7pHJ3B6AYAA2nc05zRo4vv6v8SL6GoZ3iBdc/fDTe9PTvToUDlEPko9q7w= 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+110329+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 1698686020603362.10925605220973; Mon, 30 Oct 2023 10:13:40 -0700 (PDT) Return-Path: DKIM-Signature: a=rsa-sha256; bh=zYgW6ygbO3FtoJtyEGJ65dy1imETibRIkkWPQYTg2MY=; 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=1698686020; v=1; b=r3+E/yPmSsXjT/rWev8LnF+AfNWpvumu76cJ5wqmerYN62atV7nZMpzA12tJbAuWggbYJsAg MOxrzyoMAzMLAq9EvSLp28kjhn8r/6XJH6gmAzgXZ0ZRxpE50YcU/vdXu5XVNFQaVZQxyBjAMT0 WsmUmtxH8t7SmfKHkzxsnouc= X-Received: by 127.0.0.2 with SMTP id 2tUVYY1788612x8l7PO0Hk1P; Mon, 30 Oct 2023 10:13:40 -0700 X-Received: from mgamail.intel.com (mgamail.intel.com [134.134.136.24]) by mx.groups.io with SMTP id smtpd.web10.80044.1698611271237553030 for ; Sun, 29 Oct 2023 13:27:51 -0700 X-IronPort-AV: E=McAfee;i="6600,9927,10878"; a="390840891" X-IronPort-AV: E=Sophos;i="6.03,261,1694761200"; d="scan'208";a="390840891" X-Received: from orsmga001.jf.intel.com ([10.7.209.18]) by orsmga102.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 29 Oct 2023 13:27:50 -0700 X-ExtLoop1: 1 X-IronPort-AV: E=McAfee;i="6600,9927,10878"; a="795098455" X-IronPort-AV: E=Sophos;i="6.03,261,1694761200"; d="scan'208";a="795098455" X-Received: from scsrds0181.amr.corp.intel.com ([10.116.50.7]) by orsmga001.jf.intel.com with ESMTP; 29 Oct 2023 13:27:48 -0700 From: "Zhen Gong" To: devel@edk2.groups.io Cc: Zhen Gong Subject: [edk2-devel] [PATCH edk2-platforms v2 4/4] IpmiFeaturePkg: Add FRU drivers Date: Sun, 29 Oct 2023 13:27:40 -0700 Message-Id: <8d7ba08a231175486263cff47615fa81e76c0ce7.1698610713.git.zhen.gong@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,zhen.gong@intel.com List-Unsubscribe-Post: List-Unsubscribe=One-Click List-Unsubscribe: X-Gm-Message-State: Cdd9R0WFVdKcBiOlSqg7BpHgx1787277AA= Content-Transfer-Encoding: quoted-printable X-ZohoMail-DKIM: pass (identity @groups.io) X-ZM-MESSAGEID: 1698686021983100016 Content-Type: text/plain; charset="utf-8" Add GenericFruDriver and generate data based on SMBIOS data. Signed-off-by: Zhen Gong # Conflicts: # Features/Intel/OutOfBandManagement/IpmiFeaturePkg/IpmiFru/IpmiFru.inf --- .../IpmiFeaturePkg/IpmiFeaturePkg.dec | 4 + .../IpmiFeaturePkg/Include/IpmiFeature.dsc | 3 +- .../IpmiFeaturePkg/Include/PostMemory.fdf | 3 +- .../IpmiFeaturePkg/GenericFru/GenericFru.inf | 42 ++ .../IpmiFeaturePkg/IpmiFru/IpmiFru.inf | 36 -- .../IpmiRedirFru/IpmiRedirFru.inf | 51 ++ .../GenericFru/GenericFruDriver.h | 178 ++++++ .../Include/Protocol/GenericFru.h | 103 ++++ .../Include/Protocol/RedirFru.h | 81 +++ .../IpmiRedirFru/IpmiRedirFru.h | 149 +++++ .../IpmiFeaturePkg/GenericFru/GenericFru.c | 68 +++ .../GenericFru/GenericFruDriver.c | 513 ++++++++++++++++++ .../IpmiFeaturePkg/IpmiFru/IpmiFru.c | 67 --- .../IpmiFeaturePkg/IpmiRedirFru/FruSmbios.c | 469 ++++++++++++++++ .../IpmiRedirFru/IpmiRedirFru.c | 479 ++++++++++++++++ 15 files changed, 2141 insertions(+), 105 deletions(-) create mode 100644 Features/Intel/OutOfBandManagement/IpmiFeaturePkg/Gener= icFru/GenericFru.inf delete mode 100644 Features/Intel/OutOfBandManagement/IpmiFeaturePkg/IpmiF= ru/IpmiFru.inf create mode 100644 Features/Intel/OutOfBandManagement/IpmiFeaturePkg/IpmiR= edirFru/IpmiRedirFru.inf create mode 100644 Features/Intel/OutOfBandManagement/IpmiFeaturePkg/Gener= icFru/GenericFruDriver.h create mode 100644 Features/Intel/OutOfBandManagement/IpmiFeaturePkg/Inclu= de/Protocol/GenericFru.h create mode 100644 Features/Intel/OutOfBandManagement/IpmiFeaturePkg/Inclu= de/Protocol/RedirFru.h create mode 100644 Features/Intel/OutOfBandManagement/IpmiFeaturePkg/IpmiR= edirFru/IpmiRedirFru.h create mode 100644 Features/Intel/OutOfBandManagement/IpmiFeaturePkg/Gener= icFru/GenericFru.c create mode 100644 Features/Intel/OutOfBandManagement/IpmiFeaturePkg/Gener= icFru/GenericFruDriver.c delete mode 100644 Features/Intel/OutOfBandManagement/IpmiFeaturePkg/IpmiF= ru/IpmiFru.c create mode 100644 Features/Intel/OutOfBandManagement/IpmiFeaturePkg/IpmiR= edirFru/FruSmbios.c create mode 100644 Features/Intel/OutOfBandManagement/IpmiFeaturePkg/IpmiR= edirFru/IpmiRedirFru.c diff --git a/Features/Intel/OutOfBandManagement/IpmiFeaturePkg/IpmiFeatureP= kg.dec b/Features/Intel/OutOfBandManagement/IpmiFeaturePkg/IpmiFeaturePkg.d= ec index be0a11e2adb1..d586931a6d6f 100644 --- a/Features/Intel/OutOfBandManagement/IpmiFeaturePkg/IpmiFeaturePkg.dec +++ b/Features/Intel/OutOfBandManagement/IpmiFeaturePkg/IpmiFeaturePkg.dec @@ -63,6 +63,8 @@ [LibraryClasses] [Guids] gIpmiFeaturePkgTokenSpaceGuid =3D {0xc05283f6, 0xd6a8, 0x48f3, {0x9b, = 0x59, 0xfb, 0xca, 0x71, 0x32, 0x0f, 0x12}} gPeiIpmiHobGuid =3D {0xcb4d3e13, 0x1e34, 0x4373, {0x8a, 0= x81, 0xe9, 0x0, 0x10, 0xf1, 0xdb, 0xa4}} + gEfiIpmiFormatFruGuid =3D { 0x3531fdc6, 0xeae, 0x4cd2, { 0xb0,= 0xa6, 0x5f, 0x48, 0xa0, 0xdf, 0xe3, 0x8 } } + gEfiSystemTypeFruGuid =3D { 0xaab16018, 0x679d, 0x4461, { 0xba,= 0x20, 0xe7, 0xc, 0xf7, 0x86, 0x6a, 0x9b } } =20 [Ppis] gPeiIpmiTransportPpiGuid =3D {0x7bf5fecc, 0xc5b5, 0x4b25, {0x81, 0x1b, 0= xb4, 0xb5, 0xb, 0x28, 0x79, 0xf7}} @@ -80,6 +82,8 @@ [Protocols] gSmmGenericElogProtocolGuid =3D { 0x664ef1f6, 0x19bf, 0x4498, { 0xab, 0x= 6a, 0xfc, 0x05, 0x72, 0xfb, 0x98, 0x51 } } gEfiRedirElogProtocolGuid =3D { 0x16d11030, 0x71ba, 0x4e5e, { 0xa9, 0xf9= , 0xb4, 0x75, 0xa5, 0x49, 0x4, 0x8a } } gSmmRedirElogProtocolGuid =3D { 0x79ac2d9c, 0x9216, 0x43c5, { 0xa0, 0x74= , 0x0b, 0x45, 0xc7, 0x64, 0x22, 0xc1 } } + gEfiRedirFruProtocolGuid =3D { 0x28638cfa, 0xea88, 0x456c, { 0x92, 0xa5= , 0xf2, 0x49, 0xca, 0x48, 0x85, 0x35 } } + gEfiGenericFruProtocolGuid =3D { 0xc8eebf0e, 0x0e10, 0x47f7, { 0x81, 0xb= d, 0x39, 0xdb, 0x75, 0xca, 0x93, 0x9f } } =20 [PcdsFeatureFlag] gIpmiFeaturePkgTokenSpaceGuid.PcdIpmiFeatureEnable|FALSE|BOOLEAN|0xA0000= 001 diff --git a/Features/Intel/OutOfBandManagement/IpmiFeaturePkg/Include/Ipmi= Feature.dsc b/Features/Intel/OutOfBandManagement/IpmiFeaturePkg/Include/Ipm= iFeature.dsc index 7e663236d9a1..3ceedb2fa3c4 100644 --- a/Features/Intel/OutOfBandManagement/IpmiFeaturePkg/Include/IpmiFeature= .dsc +++ b/Features/Intel/OutOfBandManagement/IpmiFeaturePkg/Include/IpmiFeature= .dsc @@ -129,7 +129,8 @@ [Components.X64] IpmiFeaturePkg/GenericElog/Dxe/GenericElog.inf IpmiFeaturePkg/GenericElog/Smm/GenericElog.inf IpmiFeaturePkg/Frb/FrbDxe.inf - IpmiFeaturePkg/IpmiFru/IpmiFru.inf + IpmiFeaturePkg/IpmiRedirFru/IpmiRedirFru.inf + IpmiFeaturePkg/GenericFru/GenericFru.inf IpmiFeaturePkg/IpmiInit/DxeIpmiInit.inf IpmiFeaturePkg/OsWdt/OsWdt.inf IpmiFeaturePkg/SolStatus/SolStatus.inf diff --git a/Features/Intel/OutOfBandManagement/IpmiFeaturePkg/Include/Post= Memory.fdf b/Features/Intel/OutOfBandManagement/IpmiFeaturePkg/Include/Post= Memory.fdf index 9b692f07dcd8..810a041983c1 100644 --- a/Features/Intel/OutOfBandManagement/IpmiFeaturePkg/Include/PostMemory.= fdf +++ b/Features/Intel/OutOfBandManagement/IpmiFeaturePkg/Include/PostMemory.= fdf @@ -15,8 +15,9 @@ INF IpmiFeaturePkg/BmcElog/DxeBmcElog.inf INF IpmiFeaturePkg/BmcElog/SmmBmcElog.inf INF IpmiFeaturePkg/Frb/FrbDxe.inf -INF IpmiFeaturePkg/IpmiFru/IpmiFru.inf +INF IpmiFeaturePkg/IpmiRedirFru/IpmiRedirFru.inf INF IpmiFeaturePkg/GenericElog/Dxe/GenericElog.inf INF IpmiFeaturePkg/GenericElog/Smm/GenericElog.inf +INF IpmiFeaturePkg/GenericFru/GenericFru.inf INF IpmiFeaturePkg/OsWdt/OsWdt.inf INF IpmiFeaturePkg/SolStatus/SolStatus.inf diff --git a/Features/Intel/OutOfBandManagement/IpmiFeaturePkg/GenericFru/G= enericFru.inf b/Features/Intel/OutOfBandManagement/IpmiFeaturePkg/GenericFr= u/GenericFru.inf new file mode 100644 index 000000000000..f53642b1a476 --- /dev/null +++ b/Features/Intel/OutOfBandManagement/IpmiFeaturePkg/GenericFru/GenericF= ru.inf @@ -0,0 +1,42 @@ +### @file +# +# Copyright (c) 2023, Intel Corporation. All rights reserved.
+# +# SPDX-License-Identifier: BSD-2-Clause-Patent +# +### + + +[Defines] + INF_VERSION =3D 0x00010005 + BASE_NAME =3D GenericFru + FILE_GUID =3D 663FB335-25DE-45b0-A531-DF3627A13D29 + MODULE_TYPE =3D DXE_RUNTIME_DRIVER + ENTRY_POINT =3D InitializeSmFruLayer + +[Sources] + GenericFruDriver.h + GenericFruDriver.c + GenericFru.c + +[Packages] + IpmiFeaturePkg/IpmiFeaturePkg.dec + MdePkg/MdePkg.dec + MdeModulePkg/MdeModulePkg.dec + +[LibraryClasses] + UefiBootServicesTableLib + UefiRuntimeServicesTableLib + UefiRuntimeLib + UefiDriverEntryPoint + BaseMemoryLib + DebugLib + +[Protocols] + gEfiGenericFruProtocolGuid ##Produces + gEfiRedirFruProtocolGuid ##Consumes + +[Guids] + +[Depex] + gIpmiTransportProtocolGuid diff --git a/Features/Intel/OutOfBandManagement/IpmiFeaturePkg/IpmiFru/Ipmi= Fru.inf b/Features/Intel/OutOfBandManagement/IpmiFeaturePkg/IpmiFru/IpmiFru= .inf deleted file mode 100644 index f5778f3468df..000000000000 --- a/Features/Intel/OutOfBandManagement/IpmiFeaturePkg/IpmiFru/IpmiFru.inf +++ /dev/null @@ -1,36 +0,0 @@ -### @file -# Component description file for IPMI FRU. -# -# Copyright (c) 2018 - 2019, Intel Corporation. All rights reserved.
-# -# SPDX-License-Identifier: BSD-2-Clause-Patent -# -### - -[Defines] - INF_VERSION =3D 0x00010005 - BASE_NAME =3D IpmiFru - FILE_GUID =3D 3F1D6464-2B4C-4640-BAC4-3DD905D26CDA - MODULE_TYPE =3D DXE_DRIVER - PI_SPECIFICATION_VERSION =3D 0x0001000A - VERSION_STRING =3D 1.0 - ENTRY_POINT =3D InitializeFru - -[Sources] - IpmiFru.c - -[Packages] - MdePkg/MdePkg.dec - MdeModulePkg/MdeModulePkg.dec - IpmiFeaturePkg/IpmiFeaturePkg.dec - -[LibraryClasses] - UefiDriverEntryPoint - UefiLib - DebugLib - UefiBootServicesTableLib - BaseMemoryLib - IpmiCommandLib - -[Depex] - TRUE diff --git a/Features/Intel/OutOfBandManagement/IpmiFeaturePkg/IpmiRedirFru= /IpmiRedirFru.inf b/Features/Intel/OutOfBandManagement/IpmiFeaturePkg/IpmiR= edirFru/IpmiRedirFru.inf new file mode 100644 index 000000000000..24fbc94128da --- /dev/null +++ b/Features/Intel/OutOfBandManagement/IpmiFeaturePkg/IpmiRedirFru/IpmiRe= dirFru.inf @@ -0,0 +1,51 @@ +### @file +# +# Copyright (c) 2023, Intel Corporation. All rights reserved.
+# +# SPDX-License-Identifier: BSD-2-Clause-Patent +# +### + + +[Defines] + INF_VERSION =3D 0x00010005 + BASE_NAME =3D IpmiRedirFru + FILE_GUID =3D 3F1D6464-2B4C-4640-BAC4-3DD905D26CDA + MODULE_TYPE =3D DXE_DRIVER + PI_SPECIFICATION_VERSION =3D 0x0001000A + VERSION_STRING =3D 1.0 + ENTRY_POINT =3D InitializeSmRedirFruLayer + +[Sources] + FruSmbios.c + IpmiRedirFru.h + IpmiRedirFru.c + +[Packages] + IpmiFeaturePkg/IpmiFeaturePkg.dec + MdePkg/MdePkg.dec + MdeModulePkg/MdeModulePkg.dec + +[LibraryClasses] + UefiDriverEntryPoint + DebugLib + UefiBootServicesTableLib + BaseMemoryLib + MemoryAllocationLib + UefiLib + IpmiBaseLib + +[Guids] + gEfiIpmiFormatFruGuid + gEfiSystemTypeFruGuid + +[Protocols] + gEfiSmbiosProtocolGuid + gEfiRedirFruProtocolGuid # PROTOCOL ALWAYS_PRODUCED + gIpmiTransportProtocolGuid + +[Depex] + gIpmiTransportProtocolGuid AND + gEfiHiiDatabaseProtocolGuid AND + gEfiLoadedImageProtocolGuid + diff --git a/Features/Intel/OutOfBandManagement/IpmiFeaturePkg/GenericFru/G= enericFruDriver.h b/Features/Intel/OutOfBandManagement/IpmiFeaturePkg/Gener= icFru/GenericFruDriver.h new file mode 100644 index 000000000000..1761e52dc453 --- /dev/null +++ b/Features/Intel/OutOfBandManagement/IpmiFeaturePkg/GenericFru/GenericF= ruDriver.h @@ -0,0 +1,178 @@ +/** @file + Generic FRU functions. + +Copyright (c) 2023, Intel Corporation. All rights reserved.
+SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#ifndef _EFI_GENEFRU_H_ +#define _EFI_GENEFRU_H_ + +#include +#include +#include +#include +#include +#include +#include + +#include "Protocol/GenericFru.h" +#include "Protocol/RedirFru.h" + +#define EFI_FRU_PHYSICAL 0 +#define EFI_FRU_VIRTUAL 1 +#define MAX_REDIR_DESCRIPTOR 10 +// +// A pointer to a function in IPF points to a plabel. +// +typedef struct { + UINT64 EntryPoint; + UINT64 GP; +} EFI_PLABEL; + +typedef struct { + EFI_PLABEL *Function; + EFI_PLABEL Plabel; +} FUNCTION_PTR; + +typedef struct { + EFI_SM_FRU_REDIR_PROTOCOL *This; + FUNCTION_PTR GetFruRedirInfo; + FUNCTION_PTR GetFruSlotInfo; + FUNCTION_PTR GetFruRedirData; + FUNCTION_PTR SetFruRedirData; +} REDIR_FRU_MODULE_PROC; + +typedef struct { + BOOLEAN Valid; + EFI_GUID FruTypeGuid; + UINTN StartSlot; + UINTN EndSlot; + REDIR_FRU_MODULE_PROC Command[2]; +} FRU_REDIR_MODULES; + +typedef struct { + FRU_REDIR_MODULES Redir[MAX_REDIR_DESCRIPTOR]; + UINTN MaxDescriptors; +} FRU_MODULE_GLOBAL; + +/** + Efi Convert Function. + + @param Function + + @retval EFI_SUCCESS + +**/ +EFI_STATUS +EfiConvertFunction ( + IN FUNCTION_PTR *Function + ); + +/** + Efi Set Function Entry. + + @param FunctionPointer + @param Function + + @retval EFI_SUCCESS + +**/ +EFI_STATUS +EfiSetFunctionEntry ( + IN FUNCTION_PTR *FunctionPointer, + IN VOID *Function + ); + +/** + Sm Fru Service Initialize. + + @param ImageHandle + @param SystemTable + + @retval EFI_SUCCESS + +**/ +EFI_STATUS +SmFruServiceInitialize ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ); + +/** + Efi Lib Get Fru Info. + + @param FruTypeGuid + @param FruInstance + @param FruFormatGuid + @param DataAccessGranularity + @param FruInformationString + @param Global + @param Virtual + + @retval EFI_SUCCESS + +**/ +EFI_STATUS +EfiLibGetFruInfo ( + IN EFI_GUID *FruTypeGuid, + IN UINTN FruInstance, + OUT EFI_GUID *FruFormatGuid, + OUT UINTN *DataAccessGranularity, + OUT CHAR16 **FruInformationString, + IN FRU_MODULE_GLOBAL *Global, + IN BOOLEAN Virtual + ); + +/** + Efi Lib Get Fru Data. + + @param FruTypeGuid + @param FruInstance + @param FruDataOffset + @param FruDataSize + @param FruData + @param Global + @param Virtual + + @retval EFI_SUCCESS + +**/ +EFI_STATUS +EfiLibGetFruData ( + IN EFI_GUID *FruTypeGuid, + IN UINTN FruInstance, + IN UINTN FruDataOffset, + IN UINTN FruDataSize, + IN UINT8 *FruData, + IN FRU_MODULE_GLOBAL *Global, + IN BOOLEAN Virtual + ); + +/** + Efi Lib Set Fru Data. + + @param FruTypeGuid + @param FruInstance + @param FruDataOffset + @param FruDataSize + @param FruData + @param Global + @param Virtual + + @retval EFI_SUCCESS + +**/ +EFI_STATUS +EfiLibSetFruData ( + IN EFI_GUID *FruTypeGuid, + IN UINTN FruInstance, + IN UINTN FruDataOffset, + IN UINTN FruDataSize, + IN UINT8 *FruData, + IN FRU_MODULE_GLOBAL *Global, + IN BOOLEAN Virtual + ); + +#endif diff --git a/Features/Intel/OutOfBandManagement/IpmiFeaturePkg/Include/Prot= ocol/GenericFru.h b/Features/Intel/OutOfBandManagement/IpmiFeaturePkg/Inclu= de/Protocol/GenericFru.h new file mode 100644 index 000000000000..7fcc64ba5038 --- /dev/null +++ b/Features/Intel/OutOfBandManagement/IpmiFeaturePkg/Include/Protocol/Ge= nericFru.h @@ -0,0 +1,103 @@ +/** @file + Generic FRU Protocol as defined in Tiano + This code abstracts the generic FRU Protocol + +Copyright (c) 2023, Intel Corporation. All rights reserved.
+SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#ifndef _GENERIC_FRU_H_ +#define _GENERIC_FRU_H_ + +#define EFI_SM_FRU_PROTOCOL_GUID \ + { \ + 0xc8eebf0e, 0xe10, 0x47f7, 0x81, 0xbd, 0x39, 0xdb, 0x75, 0xca, 0x93, 0= x9f \ + } + +typedef struct _EFI_SM_FRU_PROTOCOL EFI_SM_FRU_PROTOCOL; + +// +// Common FRU Types +// +#define EFI_CPU_TYPE_FRU_GUID \ + { \ + 0xf064c91f, 0x188c, 0x4f56, 0xb7, 0xfd, 0x30, 0xa9, 0xb8, 0x6a, 0x29, = 0xf3 \ + } + +#define EFI_MEMORY_TYPE_FRU_GUID \ + { \ + 0xd50234f4, 0x6f4b, 0x43e8, 0xa0, 0x13, 0x3c, 0x1e, 0x33, 0xd9, 0xb9, = 0xb1 \ + } + +#define EFI_SYSTEM_TYPE_FRU_GUID \ + { \ + 0xaab16018, 0x679d, 0x4461, 0xba, 0x20, 0xe7, 0xc, 0xf7, 0x86, 0x6a, 0= x9b \ + } + +// +// Common FRU Formats. +// +#define EFI_IPMI_FORMAT_FRU_GUID \ + { \ + 0x3531fdc6, 0xeae, 0x4cd2, 0xb0, 0xa6, 0x5f, 0x48, 0xa0, 0xdf, 0xe3, 0= x8 \ + } + +#define EFI_DMI_FORMAT_FRU_GUID \ + { \ + 0x67ef7a73, 0x2594, 0x4a5e, 0x93, 0xa, 0xe1, 0x66, 0xfa, 0xbc, 0xd2, 0= xc8 \ + } + +#define EFI_INTEL_MFG_FORMAT_FRU_GUID \ + { \ + 0x79e8c9c7, 0x1152, 0x4f00, 0xb8, 0x31, 0x14, 0xf1, 0xc4, 0x4, 0x1a, 0= xe0 \ + } + +// +// Generic FRU Function Prototypes +// +typedef +EFI_STATUS +(EFIAPI *EFI_GET_FRU_INFO)( + IN EFI_SM_FRU_PROTOCOL *This, + IN EFI_GUID *FruTypeGuid, + IN UINTN FruInstance, + OUT EFI_GUID *FruFormatGuid, + OUT UINTN *DataAccessGranularity, + OUT CHAR16 **FruInformationString + ); + +typedef +EFI_STATUS +(EFIAPI *EFI_GET_FRU_DATA)( + IN EFI_SM_FRU_PROTOCOL *This, + IN EFI_GUID *FruTypeGuid, + IN UINTN FruInstance, + IN UINTN FruDataOffset, + IN UINTN FruDataSize, + IN UINT8 *FruData + ); + +typedef +EFI_STATUS +(EFIAPI *EFI_SET_FRU_DATA)( + IN EFI_SM_FRU_PROTOCOL *This, + IN EFI_GUID *FruTypeGuid, + IN UINTN FruInstance, + IN UINTN FruDataOffset, + IN UINTN FruDataSize, + IN UINT8 *FruData + ); + +// +// GENERIC FRU PROTOCOL +// +typedef struct _EFI_SM_FRU_PROTOCOL { + EFI_GET_FRU_INFO GetFruInfo; + EFI_GET_FRU_DATA GetFruData; + EFI_SET_FRU_DATA SetFruData; +} EFI_SM_FRU_PROTOCOL; + +extern EFI_GUID gEfiGenericFruProtocolGuid; + +#endif diff --git a/Features/Intel/OutOfBandManagement/IpmiFeaturePkg/Include/Prot= ocol/RedirFru.h b/Features/Intel/OutOfBandManagement/IpmiFeaturePkg/Include= /Protocol/RedirFru.h new file mode 100644 index 000000000000..30281ba9fa04 --- /dev/null +++ b/Features/Intel/OutOfBandManagement/IpmiFeaturePkg/Include/Protocol/Re= dirFru.h @@ -0,0 +1,81 @@ +/** @file + This code abstracts the generic FRU Protocol. + +Copyright (c) 2023, Intel Corporation. All rights reserved.
+SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#ifndef _REDIR_FRU_H_ +#define _REDIR_FRU_H_ + +typedef struct _EFI_SM_FRU_REDIR_PROTOCOL EFI_SM_FRU_REDIR_PROTOCOL; + +#define EFI_SM_FRU_REDIR_PROTOCOL_GUID \ + { \ + 0x28638cfa, 0xea88, 0x456c, 0x92, 0xa5, 0xf2, 0x49, 0xca, 0x48, 0x85, = 0x35 \ + } + +// {41F49AE4-7FB0-4c54-994E-EA199171B0AC} +#define EFI_PRE_FRU_SMBIOS_DATA_GUID \ + { \ + 0x41f49ae4, 0x7fb0, 0x4c54, 0x99, 0x4e, 0xea, 0x19, 0x91, 0x71, 0xb0, = 0xac \ + } + +#define EFI_SM_FRU_REDIR_SIGNATURE SIGNATURE_32 ('f', 'r', 'r', 'x') + +// +// Redir FRU Function Prototypes +// +typedef +EFI_STATUS +(EFIAPI *EFI_GET_FRU_REDIR_INFO)( + IN EFI_SM_FRU_REDIR_PROTOCOL *This, + IN UINTN FruSlotNumber, + OUT EFI_GUID *FruFormatGuid, + OUT UINTN *DataAccessGranularity, + OUT CHAR16 **FruInformationString + ); + +typedef +EFI_STATUS +(EFIAPI *EFI_GET_FRU_SLOT_INFO)( + IN EFI_SM_FRU_REDIR_PROTOCOL *This, + OUT EFI_GUID *FruTypeGuid, + OUT UINTN *StartFruSlotNumber, + OUT UINTN *NumSlots + ); + +typedef +EFI_STATUS +(EFIAPI *EFI_GET_FRU_REDIR_DATA)( + IN EFI_SM_FRU_REDIR_PROTOCOL *This, + IN UINTN FruSlotNumber, + IN UINTN FruDataOffset, + IN UINTN FruDataSize, + IN UINT8 *FruData + ); + +typedef +EFI_STATUS +(EFIAPI *EFI_SET_FRU_REDIR_DATA)( + IN EFI_SM_FRU_REDIR_PROTOCOL *This, + IN UINTN FruSlotNumber, + IN UINTN FruDataOffset, + IN UINTN FruDataSize, + IN UINT8 *FruData + ); + +// +// REDIR FRU PROTOCOL +// +struct _EFI_SM_FRU_REDIR_PROTOCOL { + EFI_GET_FRU_REDIR_INFO GetFruRedirInfo; + EFI_GET_FRU_SLOT_INFO GetFruSlotInfo; + EFI_GET_FRU_REDIR_DATA GetFruRedirData; + EFI_SET_FRU_REDIR_DATA SetFruRedirData; +}; + +extern EFI_GUID gEfiRedirFruProtocolGuid; + +#endif diff --git a/Features/Intel/OutOfBandManagement/IpmiFeaturePkg/IpmiRedirFru= /IpmiRedirFru.h b/Features/Intel/OutOfBandManagement/IpmiFeaturePkg/IpmiRed= irFru/IpmiRedirFru.h new file mode 100644 index 000000000000..9fd0067973a6 --- /dev/null +++ b/Features/Intel/OutOfBandManagement/IpmiFeaturePkg/IpmiRedirFru/IpmiRe= dirFru.h @@ -0,0 +1,149 @@ +/** @file + IPMI Redir Sensor functions. + +Copyright (c) 2023, Intel Corporation. All rights reserved.
+SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#ifndef _EFI_IPMI_REDIR_FRU_H_ +#define _EFI_IPMI_REDIR_FRU_H_ + +#include +#include +#include +#include + +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define MAX_FRU_SLOT 20 + +#define IPMI_RDWR_FRU_FRAGMENT_SIZE 0x10 + +#define CHASSIS_TYPE_LENGTH 1 +#define CHASSIS_TYPE_OFFSET 2 +#define CHASSIS_PART_NUMBER 3 + +#define PRODUCT_MFG_OFFSET 3 +#define BOARD_MFG_OFFSET 6 + +#define SMBIOSTYPE1 1 +#define SMBIOSTYPE2 2 +#define SMBIOSTYPE3 3 + +#define OFFSET0 0 +#define OFFSET1 1 +#define OFFSET2 2 +#define OFFSET3 3 +#define OFFSET4 4 +#define OFFSET5 5 +#define OFFSET6 6 +#define OFFSET7 7 +#define OFFSET8 8 +#define OFFSET9 9 + +#define STRING1 1 +#define STRING2 2 +#define STRING3 3 +#define STRING4 4 +#define STRING5 5 +#define STRING6 6 +#define STRING7 7 +#define STRING8 8 +#define STRING9 9 + +typedef struct { + BOOLEAN Valid; + IPMI_FRU_DATA_INFO FruDevice; +} EFI_FRU_DEVICE_INFO; + +typedef struct { + UINTN Signature; + UINT8 MaxFruSlots; + UINT8 NumSlots; + EFI_FRU_DEVICE_INFO FruDeviceInfo[MAX_FRU_SLOT]; + EFI_SM_FRU_REDIR_PROTOCOL IpmiRedirFruProtocol; +} EFI_IPMI_FRU_GLOBAL; + +/** + Get Fru Redir Data. + + @param This + @param FruSlotNumber + @param FruDataOffset + @param FruDataSize + @param FruData + + EFI_STATUS + +**/ +EFI_STATUS +EFIAPI +EfiGetFruRedirData ( + IN EFI_SM_FRU_REDIR_PROTOCOL *This, + IN UINTN FruSlotNumber, + IN UINTN FruDataOffset, + IN UINTN FruDataSize, + IN UINT8 *FruData + ); + +/** + This routine install a notify function listen to gEfiEventReadyToBootGui= d. + + @param This - SM Fru Redir protocol + +**/ +VOID +GenerateFruSmbiosData ( + IN EFI_SM_FRU_REDIR_PROTOCOL *This + ); + +#define INSTANCE_FROM_EFI_SM_IPMI_FRU_THIS(a) \ + CR (a, \ + EFI_IPMI_FRU_GLOBAL, \ + IpmiRedirFruProtocol, \ + EFI_SM_FRU_REDIR_SIGNATURE \ + ) + +/** + Do a one byte IO write. + + @param Address - IO address to write + @param Data - Data to write to Address + +Returns: + NONE + +**/ +VOID +IoWrite8 ( + IN UINT64 Address, + IN UINT8 Data + ); + +/** + Do a one byte IO read. + + @param Address - IO address to read + + @retval Data read + +**/ +UINT8 +IoRead8 ( + IN UINT64 Address + ); + +#endif diff --git a/Features/Intel/OutOfBandManagement/IpmiFeaturePkg/GenericFru/G= enericFru.c b/Features/Intel/OutOfBandManagement/IpmiFeaturePkg/GenericFru/= GenericFru.c new file mode 100644 index 000000000000..8b91a4dd05bc --- /dev/null +++ b/Features/Intel/OutOfBandManagement/IpmiFeaturePkg/GenericFru/GenericF= ru.c @@ -0,0 +1,68 @@ +/** @file + Hooks for Generic FRU. + +Copyright (c) 2023, Intel Corporation. All rights reserved.
+SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include "GenericFruDriver.h" + +// +// Don't use module globals after the SetVirtualAddress map is signaled +// +extern FRU_MODULE_GLOBAL *mFruModuleGlobal; + +/** + Efi Convert Function. + + @param Function + + @retval EFI_SUCCESS + +**/ +EFI_STATUS +EfiConvertFunction ( + IN FUNCTION_PTR *Function + ) +{ + gRT->ConvertPointer (0x02, (VOID **)&Function->Function); + return EFI_SUCCESS; +} + +/** + Efi Set Function Entry. + + @param FunctionPointer + @param Function + + @retval EFI_SUCCESS + +**/ +EFI_STATUS +EfiSetFunctionEntry ( + IN FUNCTION_PTR *FunctionPointer, + IN VOID *Function + ) +{ + FunctionPointer->Function =3D (EFI_PLABEL *)Function; + return EFI_SUCCESS; +} + +/** + SmFru Service Initialize. + + @param ImageHandle + @param SystemTable + + @retval EFI_SUCCESS + +**/ +EFI_STATUS +SmFruServiceInitialize ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +{ + return EFI_SUCCESS; +} diff --git a/Features/Intel/OutOfBandManagement/IpmiFeaturePkg/GenericFru/G= enericFruDriver.c b/Features/Intel/OutOfBandManagement/IpmiFeaturePkg/Gener= icFru/GenericFruDriver.c new file mode 100644 index 000000000000..523630d452f9 --- /dev/null +++ b/Features/Intel/OutOfBandManagement/IpmiFeaturePkg/GenericFru/GenericF= ruDriver.c @@ -0,0 +1,513 @@ +/** @file + Server Management Generic FRU Driver. Each FRU REDIR driver attaches + to the Generic FRU driver which is coded in this section. A Runtime + protocol will bind to this and be able to access all the FRU transports + as well as their physical layers. + +Copyright (c) 2023, Intel Corporation. All rights reserved.
+SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include "GenericFruDriver.h" + +FRU_MODULE_GLOBAL *mFruModuleGlobal; + +// +// Define module globals used to register for notification of when +// the FRU REDIR protocol has been produced. +// +VOID *mEfiFruRedirProtocolNotifyReg; +EFI_EVENT mEfiFruRedirProtocolEvent; + +/** + Efi Lib Get Fru Info. + + @param FruTypeGuid + @param FruInstance + @param FruFormatGuid + @param DataAccessGranularity + @param FruInformationString + @param Global + @param Virtual + + @retval EFI_SUCCESS + +**/ +EFI_STATUS +EfiLibGetFruInfo ( + IN EFI_GUID *FruTypeGuid, + IN UINTN FruInstance, + OUT EFI_GUID *FruFormatGuid, + OUT UINTN *DataAccessGranularity, + OUT CHAR16 **FruInformationString, + IN FRU_MODULE_GLOBAL *Global, + IN BOOLEAN Virtual + ) +{ + UINTN Index; + VOID *FruRedirCommand; + + // + // Get the FRU Type string first. + // + for (Index =3D 0; Index < Global->MaxDescriptors; Index++) { + if (Global->Redir[Index].Valid) { + if (CompareGuid (&Global->Redir[Index].FruTypeGuid, FruTypeGuid)) { + // + // We found our target, Now check the format it supports. + // + FruRedirCommand =3D Global->Redir[Index].Command[Virtual].GetFruRe= dirInfo.Function; + return (*((EFI_GET_FRU_REDIR_INFO *)&FruRedirCommand))( + Global->Redir[Index].Command[Virtual].This, + FruInstance, + FruFormatGuid, + DataAccessGranularity, + FruInformationString + ); + } + } + } + + return EFI_NOT_FOUND; +} + +/** + Efi Get Fru Info. + + @param This + @param FruTypeGuid + @param FruInstance + @param FruFormatGuid + @param DataAccessGranularity + @param FruInformationString + + @retval EFI_SUCCESS + +**/ +EFI_STATUS +EfiGetFruInfo ( + IN EFI_SM_FRU_PROTOCOL *This, + IN EFI_GUID *FruTypeGuid, + IN UINTN FruInstance, + OUT EFI_GUID *FruFormatGuid, + OUT UINTN *DataAccessGranularity, + OUT CHAR16 **FruInformationString + ) +{ + return EfiLibGetFruInfo ( + FruTypeGuid, + FruInstance, + FruFormatGuid, + DataAccessGranularity, + FruInformationString, + mFruModuleGlobal, + EfiGoneVirtual () + ); +} + +/** + Efi Lib Get Fru Data. + + @param FruTypeGuid + @param FruInstance + @param FruDataOffset + @param FruDataSize + @param FruData + @param Global + @param Virtual + + @retval EFI_SUCCESS + +**/ +EFI_STATUS +EfiLibGetFruData ( + IN EFI_GUID *FruTypeGuid, + IN UINTN FruInstance, + IN UINTN FruDataOffset, + IN UINTN FruDataSize, + IN UINT8 *FruData, + IN FRU_MODULE_GLOBAL *Global, + IN BOOLEAN Virtual + ) +{ + UINTN Index; + VOID *FruRedirCommand; + + // + // Get the FRU Type string first. + // + for (Index =3D 0; Index < Global->MaxDescriptors; Index++) { + if (Global->Redir[Index].Valid) { + if (CompareGuid (&Global->Redir[Index].FruTypeGuid, FruTypeGuid)) { + // + // We found our target, Now check the format it supports. + // + FruRedirCommand =3D Global->Redir[Index].Command[Virtual].GetFruRe= dirData.Function; + return (*((EFI_GET_FRU_REDIR_DATA *)&FruRedirCommand))( + Global->Redir[Index].Command[Virtual].This, + FruInstance, + FruDataOffset, + FruDataSize, + FruData + ); + } + } + } + + return EFI_NOT_FOUND; +} + +/** + Efi Get Fru Data. + + @param This + @param FruTypeGuid + @param FruInstance + @param FruDataOffset + @param FruDataSize + @param FruData + + @retval EFI_SUCCESS + +**/ +EFI_STATUS +EfiGetFruData ( + IN EFI_SM_FRU_PROTOCOL *This, + IN EFI_GUID *FruTypeGuid, + IN UINTN FruInstance, + IN UINTN FruDataOffset, + IN UINTN FruDataSize, + IN UINT8 *FruData + ) +{ + return EfiLibGetFruData ( + FruTypeGuid, + FruInstance, + FruDataOffset, + FruDataSize, + FruData, + mFruModuleGlobal, + EfiGoneVirtual () + ); +} + +/** + Efi Lib Set Fru Data. + + @param FruTypeGuid + @param FruInstance + @param FruDataOffset + @param FruDataSize + @param FruData + @param Global + @param Virtual + + @retval EFI_SUCCESS + +**/ +EFI_STATUS +EfiLibSetFruData ( + IN EFI_GUID *FruTypeGuid, + IN UINTN FruInstance, + IN UINTN FruDataOffset, + IN UINTN FruDataSize, + IN UINT8 *FruData, + IN FRU_MODULE_GLOBAL *Global, + IN BOOLEAN Virtual + ) +{ + UINTN Index; + VOID *FruRedirCommand; + + // + // Get the FRU Type string first. + // + for (Index =3D 0; Index < Global->MaxDescriptors; Index++) { + if (Global->Redir[Index].Valid) { + if (CompareGuid (&Global->Redir[Index].FruTypeGuid, FruTypeGuid)) { + // + // We found our target, Now check the format it supports. + // + FruRedirCommand =3D Global->Redir[Index].Command[Virtual].SetFruRe= dirData.Function; + return (*((EFI_SET_FRU_REDIR_DATA *)&FruRedirCommand))( + Global->Redir[Index].Command[Virtual].This, + FruInstance, + FruDataOffset, + FruDataSize, + FruData + ); + } + } + } + + return EFI_NOT_FOUND; +} + +/** + Efi Set Fru Data. + + @param This + @param FruTypeGuid + @param FruInstance + @param FruDataOffset + @param FruDataSize + @param FruData + + @retval EFI_SUCCESS + +**/ +EFI_STATUS +EfiSetFruData ( + IN EFI_SM_FRU_PROTOCOL *This, + IN EFI_GUID *FruTypeGuid, + IN UINTN FruInstance, + IN UINTN FruDataOffset, + IN UINTN FruDataSize, + IN UINT8 *FruData + ) +{ + return EfiLibSetFruData ( + FruTypeGuid, + FruInstance, + FruDataOffset, + FruDataSize, + FruData, + mFruModuleGlobal, + EfiGoneVirtual () + ); +} + +/** + Sm Fru Address Change Event. + + @param Event + @param Context +**/ +VOID +SmFruAddressChangeEvent ( + IN EFI_EVENT Event, + IN VOID *Context + ) +{ + UINTN Index; + REDIR_FRU_MODULE_PROC *RedirProc; + + // + // FRU REDIR Pointer Conversion + // + for (Index =3D 0; Index < mFruModuleGlobal->MaxDescriptors; Index++) { + if (mFruModuleGlobal->Redir[Index].Valid) { + RedirProc =3D (REDIR_FRU_MODULE_PROC *)&mFruModuleGlobal->Redir[Inde= x].Command[EFI_FRU_VIRTUAL]; + EfiConvertFunction (&RedirProc->GetFruRedirInfo); + EfiConvertFunction (&RedirProc->GetFruSlotInfo); + EfiConvertFunction (&RedirProc->GetFruRedirData); + EfiConvertFunction (&RedirProc->SetFruRedirData); + EfiConvertPointer (0x02, (VOID **)&RedirProc->This); + } + } +} + +/** + Set Fru Redir Instances. + + @retval EFI_SUCCESS + +**/ +EFI_STATUS +SetFruRedirInstances ( + VOID + ) +{ + UINTN NumHandles; + UINTN Index, Instance, EmptyIndex; + EFI_HANDLE *Buffer; + EFI_STATUS Status; + EFI_SM_FRU_REDIR_PROTOCOL *Redir; + REDIR_FRU_MODULE_PROC *RedirProc; + + // + // Check for all IPMI Controllers + // + Status =3D gBS->LocateHandleBuffer ( + ByProtocol, + &gEfiRedirFruProtocolGuid, + NULL, + &NumHandles, + &Buffer + ); + + if (EFI_ERROR (Status) || (NumHandles =3D=3D 0)) { + return EFI_SUCCESS; + } + + EmptyIndex =3D mFruModuleGlobal->MaxDescriptors; + + for (Index =3D 0; ((Index < NumHandles) && (Index < mFruModuleGlobal->Ma= xDescriptors)); Index++) { + Status =3D gBS->HandleProtocol ( + Buffer[Index], + &gEfiRedirFruProtocolGuid, + (VOID *)&Redir + ); + if (EFI_ERROR (Status) || (Redir =3D=3D NULL)) { + continue; + } + + for (Instance =3D 0; Instance < mFruModuleGlobal->MaxDescriptors; Inst= ance++) { + if (mFruModuleGlobal->Redir[Instance].Valid =3D=3D FALSE) { + if (EmptyIndex >=3D mFruModuleGlobal->MaxDescriptors) { + EmptyIndex =3D Instance; + } + } else { + if (Redir =3D=3D mFruModuleGlobal->Redir[Instance].Command->This) { + EmptyIndex =3D mFruModuleGlobal->MaxDescriptors; + continue; + } + } + } + + if (EmptyIndex < mFruModuleGlobal->MaxDescriptors) { + Redir->GetFruSlotInfo ( + Redir, + &mFruModuleGlobal->Redir[EmptyIndex].FruTypeGuid, + &mFruModuleGlobal->Redir[EmptyIndex].StartSlot, + &mFruModuleGlobal->Redir[EmptyIndex].EndSlot + ); + + mFruModuleGlobal->Redir[EmptyIndex].EndSlot +=3D mFruModuleGlobal->R= edir[EmptyIndex].StartSlot; + RedirProc =3D (REDIR_FRU_MODULE_P= ROC *)mFruModuleGlobal->Redir[EmptyIndex].Command; + mFruModuleGlobal->Redir[EmptyIndex].Valid =3D TRUE; + + EfiSetFunctionEntry (&RedirProc->GetFruRedirInfo, *((VOID **)&Redir-= >GetFruRedirInfo)); + EfiSetFunctionEntry (&RedirProc->GetFruSlotInfo, *((VOID **)&Redir->= GetFruSlotInfo)); + EfiSetFunctionEntry (&RedirProc->GetFruRedirData, *((VOID **)&Redir-= >GetFruRedirData)); + EfiSetFunctionEntry (&RedirProc->SetFruRedirData, *((VOID **)&Redir-= >SetFruRedirData)); + RedirProc->This =3D Redir; + + CopyMem (&RedirProc[EFI_FRU_VIRTUAL], &RedirProc[EFI_FRU_PHYSICAL], = sizeof (REDIR_FRU_MODULE_PROC)); + } + } + + if (Buffer !=3D NULL) { + gBS->FreePool (Buffer); + } + + return EFI_SUCCESS; +} + +/** + This notification function is invoked when an instance of the + FRU REDIR protocol is produced. + + @param Event - The event that occurred + @param Context - For EFI compatibility. Not used. + +**/ +VOID +EFIAPI +NotifyFruRedirEventCallback ( + EFI_EVENT Event, + VOID *Context + ) +{ + SetFruRedirInstances (); +} + +/** + Initialize Sm Fru Layer. + + @param ImageHandle + @param SystemTable + + @retval EFI_SUCCESS + +**/ +EFI_STATUS +EFIAPI +InitializeSmFruLayer ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +{ + EFI_HANDLE NewHandle; + EFI_STATUS Status; + EFI_SM_FRU_PROTOCOL *FruProtocol; + + Status =3D gBS->AllocatePool ( + EfiRuntimeServicesData, + sizeof (FRU_MODULE_GLOBAL), + (VOID **)&mFruModuleGlobal + ); + + ASSERT_EFI_ERROR (Status); + if (Status !=3D EFI_SUCCESS) { + return Status; + } + + ZeroMem (mFruModuleGlobal, sizeof (FRU_MODULE_GLOBAL)); + + SmFruServiceInitialize (ImageHandle, SystemTable); + + mFruModuleGlobal->MaxDescriptors =3D MAX_REDIR_DESCRIPTOR; + + // + // Check for all IPMI Controllers + // + SetFruRedirInstances (); + + Status =3D gBS->AllocatePool ( + EfiRuntimeServicesData, + sizeof (EFI_SM_FRU_PROTOCOL), + (VOID **)&FruProtocol + ); + ASSERT_EFI_ERROR (Status); + if (Status !=3D EFI_SUCCESS) { + return Status; + } + + ZeroMem (FruProtocol, sizeof (EFI_SM_FRU_PROTOCOL)); + + FruProtocol->GetFruInfo =3D (EFI_GET_FRU_INFO)EfiGetFruInfo; + FruProtocol->GetFruData =3D (EFI_GET_FRU_DATA)EfiGetFruData; + FruProtocol->SetFruData =3D (EFI_SET_FRU_DATA)EfiSetFruData; + + NewHandle =3D NULL; + Status =3D gBS->InstallProtocolInterface ( + &NewHandle, + &gEfiGenericFruProtocolGuid, + EFI_NATIVE_INTERFACE, + FruProtocol + ); + + ASSERT_EFI_ERROR (Status); + if (Status !=3D EFI_SUCCESS) { + return Status; + } + + // + // Register to be notified when the FRU REDIR protocol has been + // produced. + // + + Status =3D gBS->CreateEvent ( + EVT_NOTIFY_SIGNAL, + TPL_CALLBACK, + NotifyFruRedirEventCallback, + NULL, + &mEfiFruRedirProtocolEvent + ); + + ASSERT_EFI_ERROR (Status); + if (Status !=3D EFI_SUCCESS) { + return Status; + } + + Status =3D gBS->RegisterProtocolNotify ( + &gEfiRedirFruProtocolGuid, + mEfiFruRedirProtocolEvent, + &mEfiFruRedirProtocolNotifyReg + ); + ASSERT_EFI_ERROR (Status); + + return Status; +} diff --git a/Features/Intel/OutOfBandManagement/IpmiFeaturePkg/IpmiFru/Ipmi= Fru.c b/Features/Intel/OutOfBandManagement/IpmiFeaturePkg/IpmiFru/IpmiFru.c deleted file mode 100644 index 58e1fb4d7ef0..000000000000 --- a/Features/Intel/OutOfBandManagement/IpmiFeaturePkg/IpmiFru/IpmiFru.c +++ /dev/null @@ -1,67 +0,0 @@ -/** @file - IPMI FRU Driver. - -Copyright (c) 2018 - 2019, Intel Corporation. All rights reserved.
-SPDX-License-Identifier: BSD-2-Clause-Patent - -**/ - -#include -#include -#include -#include -#include -#include -#include - -EFI_STATUS -EFIAPI -InitializeFru ( - IN EFI_HANDLE ImageHandle, - IN EFI_SYSTEM_TABLE *SystemTable - ) -/*++ - -Routine Description: - - Initialize SM Redirection Fru Layer - -Arguments: - - ImageHandle - ImageHandle of the loaded driver - SystemTable - Pointer to the System Table - -Returns: - - EFI_STATUS - ---*/ -{ - EFI_STATUS Status; - IPMI_GET_DEVICE_ID_RESPONSE ControllerInfo; - IPMI_GET_FRU_INVENTORY_AREA_INFO_REQUEST GetFruInventoryAreaInfoReques= t; - IPMI_GET_FRU_INVENTORY_AREA_INFO_RESPONSE GetFruInventoryAreaInfoRespon= se; - - // - // Get all the SDR Records from BMC and retrieve the Record ID from the= structure for future use. - // - Status =3D IpmiGetDeviceId (&ControllerInfo); - if (EFI_ERROR (Status)) { - DEBUG((DEBUG_ERROR, "!!! IpmiFru IpmiGetDeviceId Status=3D%x\n", Stat= us)); - return Status; - } - - DEBUG((DEBUG_ERROR, "!!! IpmiFru FruInventorySupport %x\n", ControllerI= nfo.DeviceSupport.Bits.FruInventorySupport)); - - if (ControllerInfo.DeviceSupport.Bits.FruInventorySupport) { - GetFruInventoryAreaInfoRequest.DeviceId =3D 0; - Status =3D IpmiGetFruInventoryAreaInfo (&GetFruInventoryAreaInfoReques= t, &GetFruInventoryAreaInfoResponse); - if (EFI_ERROR (Status)) { - DEBUG((DEBUG_ERROR, "!!! IpmiFru IpmiGetFruInventoryAreaInfo Status= =3D%x\n", Status)); - return Status; - } - DEBUG((DEBUG_ERROR, "!!! IpmiFru InventoryAreaSize=3D%x\n", GetFruInv= entoryAreaInfoResponse.InventoryAreaSize)); - } - - return EFI_SUCCESS; -} diff --git a/Features/Intel/OutOfBandManagement/IpmiFeaturePkg/IpmiRedirFru= /FruSmbios.c b/Features/Intel/OutOfBandManagement/IpmiFeaturePkg/IpmiRedirF= ru/FruSmbios.c new file mode 100644 index 000000000000..bd4b35ba5793 --- /dev/null +++ b/Features/Intel/OutOfBandManagement/IpmiFeaturePkg/IpmiRedirFru/FruSmb= ios.c @@ -0,0 +1,469 @@ +/** @file + This code reads the FRU and publishes the data to SMBIOS Type 1,2,3 tabl= es. + +Copyright (c) 2023, Intel Corporation. All rights reserved.
+SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#ifndef FRUMAXSTRING +#define FRUMAXSTRING 128 +#endif + +#include "IpmiRedirFru.h" + +EFI_SM_FRU_REDIR_PROTOCOL *mFruRedirProtocol; +EFI_SMBIOS_PROTOCOL *mSmbiosProtocol; + +extern EFI_GUID gEfiSmbiosProtocolGuid; + +/** + Fru Str Len. + + @param Str. + + @retval Length. + +**/ +UINT8 +FruStrLen ( + IN CHAR8 *Str + ) +{ + UINT8 Length; + CHAR8 *Ptr; + + Length =3D 0; + + if (Str !=3D NULL) { + Ptr =3D Str; + while (*Ptr !=3D '\0') { + Length++; + Ptr++; + } + } + + return Length; +} + +/** + This routine attempts to get a string out of the FRU at the designated o= ffset in the + buffer pointed to by TempPtr. String type is ASCII. + + @param Offset - Offset of string in buffer pointed to by TempPtr, thi= s is updated to the next + offset. + @param TempPtr - Pointer to a buffer containing the FRU. + @param StrPtr - the pointer to a buffer for retrieve the string get f= rom FRU. + +**/ +VOID +GetStringFromFru ( + IN OUT UINTN *Offset, + IN UINT8 *TempPtr, + IN OUT UINT8 *StrPtr + ) +{ + UINTN Length; + UINT8 *SrcStrPtr; + + if ((Offset =3D=3D NULL) || (TempPtr =3D=3D NULL)) { + return; + } + + Length =3D 0x3F & TempPtr[*Offset]; + SrcStrPtr =3D &TempPtr[*Offset + 1]; + + ASSERT (Length < FRUMAXSTRING); + if (Length >=3D FRUMAXSTRING) { + return; + } + + if (StrPtr !=3D NULL) { + if (Length > 0) { + CopyMem (StrPtr, SrcStrPtr, Length); + StrPtr[Length] =3D '\0'; + } else { + StrPtr[0] =3D '\0'; + } + } + + *Offset =3D *Offset + Length + 1; + return; +} + +/** + This routine gets the FRU info area specified by the offset and returns = it in + an allocated buffer. It is the caller's responsibility to free the buff= er. + + @param This - SM Fru Redir protocol. + @param Offset - Info Area starting offset in multiples of 8 bytes. + + @retval Buffer with FruInfo data or NULL if not found. + +**/ +UINT8 * +GetFruInfoArea ( + IN EFI_SM_FRU_REDIR_PROTOCOL *This, + IN UINTN Offset + ) +{ + EFI_STATUS Status; + UINT8 *TempPtr; + UINTN Length; + + TempPtr =3D NULL; + + Offset =3D Offset * 8; + if (Offset > 0) { + // + // Get Info area length, which is in multiples of 8 bytes + // + Length =3D 0; + Status =3D EfiGetFruRedirData (This, 0, (Offset + 1), 1, (UINT8 *)&Len= gth); + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_ERROR, "EfiGetFruRedirData returned status %r\n", Stat= us)); + return NULL; + } + + Length =3D Length * 8; + + if (Length > 0) { + TempPtr =3D AllocateRuntimePool (Length); + ASSERT (TempPtr !=3D NULL); + if (TempPtr =3D=3D NULL) { + return NULL; + } + + Status =3D EfiGetFruRedirData (This, 0, Offset, Length, TempPtr); + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_ERROR, "EfiGetFruRedirData returned status %r\n", St= atus)); + return NULL; + } + } + } + + return TempPtr; +} + +/** + Type1,2,3 only has one instance in SMBIOS tables for each. + + @param TypeNo - The number of SMBIOS TYPE. + + @retval Record the pointer of SMBIOS TYPE structure. + +**/ +UINT8 * +GetStructureByTypeNo ( + IN UINT16 TypeNo + ) +{ + EFI_STATUS Status; + EFI_SMBIOS_HANDLE SmbiosHandle; + EFI_SMBIOS_TABLE_HEADER *Record; + + SmbiosHandle =3D 0; + + Status =3D mSmbiosProtocol->GetNext ( + mSmbiosProtocol, + &SmbiosHandle, + (EFI_SMBIOS_TYPE *)&TypeNo, + &Record, + NULL + ); + if (EFI_ERROR (Status)) { + return NULL; + } + + return (UINT8 *)Record; +} + +/** + Smbios Check Sum. + + @param ChecksumSrc. + @param length. + + @retval Record the pointer of SMBIOS TYPE structure. + +**/ +UINT8 +SmbiosCheckSum ( + IN UINT8 *ChecksumSrc, + IN UINT8 length + ) +{ + UINT8 Checksum; + UINT8 Num; + + Checksum =3D 0; + + for (Num =3D 0; Num < length; Num++) { + Checksum =3D Checksum + *ChecksumSrc++; + } + + return (0 - Checksum); +} + +/** + Dynamic Update Type. + + @param TypeNo. + @param StringNo. + @param Data. + +**/ +VOID +DynamicUpdateType ( + IN UINT16 TypeNo, + IN UINTN StringNo, + IN UINT8 *Data + ) +{ + EFI_STATUS Status; + EFI_SMBIOS_HANDLE SmbiosHandle; + EFI_SMBIOS_TABLE_HEADER *Record; + + SmbiosHandle =3D 0; + + Status =3D mSmbiosProtocol->GetNext ( + mSmbiosProtocol, + &SmbiosHandle, + (EFI_SMBIOS_TYPE *)&TypeNo, + &Record, + NULL + ); + if (EFI_ERROR (Status)) { + return; + } + + mSmbiosProtocol->UpdateString ( + mSmbiosProtocol, + &SmbiosHandle, + &StringNo, + (CHAR8 *)Data + ); +} + +/** + This routine is notified by protocol gEfiEventReadyToBootGuid, and reads + strings out of the FRU and populates them into the appropriate Smbios ta= bles. + + @param Event. + @param Context. + +**/ +VOID +EFIAPI +GenerateFruSmbiosType123DataNotified ( + IN EFI_EVENT Event, + IN VOID *Context + ) +{ + EFI_STATUS Status; + + UINT8 *FruHdrPtr; + UINT8 FruHdrChksum; + IPMI_FRU_COMMON_HEADER FruCommonHeader; + UINT8 Num; + UINTN Offset; + UINT8 *TempPtr; + UINT8 TempStr[FRUMAXSTRING]; + + UINT8 *TablePtr; + + DEBUG ((DEBUG_INFO, "[FRU SMBIOS]: Generate Fru Smbios Type 1,2,3 Data N= otified.\n")); + gBS->CloseEvent (Event); + + SetMem ((UINT8 *)(&FruCommonHeader), sizeof (IPMI_FRU_COMMON_HEADER), 0); + SetMem (TempStr, FRUMAXSTRING, 0); + + Status =3D gBS->LocateProtocol (&gEfiSmbiosProtocolGuid, NULL, (VOID **)= &mSmbiosProtocol); + ASSERT_EFI_ERROR (Status); + if (Status !=3D EFI_SUCCESS) { + return; + } + + Status =3D EfiGetFruRedirData (mFruRedirProtocol, 0, 0, sizeof (IPMI_FRU= _COMMON_HEADER), (UINT8 *)&FruCommonHeader); + + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_ERROR, "EfiGetFruRedirData returned status %r\n", Status= )); + return; + } else { + // + // Do a validity check on the FRU header, since it may be all 0xFF(s) = if + // there is no FRU programmed on the system. + // + FruHdrPtr =3D (UINT8 *)&FruCommonHeader; + for (Num =3D 0, FruHdrChksum =3D 0; Num < sizeof (FruCommonHeader); Nu= m++) { + FruHdrChksum =3D (UINT8)(FruHdrChksum +*FruHdrPtr++); + } + + if (FruHdrChksum !=3D 0) { + DEBUG ((DEBUG_ERROR, "FRU header invalid.\n")); + // + // The FRU information is bad so nothing need to do. + // + return; + } + } + + // + // SMBIOS Type 1, Product data + // + TempPtr =3D GetFruInfoArea (mFruRedirProtocol, FruCommonHeader.ProductIn= foStartingOffset); + if (TempPtr !=3D NULL) { + // + // Get the following fields in the specified order. DO NOT change thi= s order unless the FRU file definition + // changes. Offset is initialized and then is incremented to the next= field offset in GetStringFromFru. + // + // Product Manufacturer + // Product Name + // Product Model Number / System Part Number + // Product Version + // Product Serial Number + // Product Asset Tag + // + Offset =3D PRODUCT_MFG_OFFSET; + GetStringFromFru (&Offset, TempPtr, TempStr); // MiscSystemManufact= urer.SystemManufacturer + if (FruStrLen ((CHAR8 *)(TempStr)) !=3D 0) { + DynamicUpdateType (SMBIOSTYPE1, STRING1, TempStr); + } + + GetStringFromFru (&Offset, TempPtr, TempStr); // MiscSystemManufact= urer.SystemProductName + if (FruStrLen ((CHAR8 *)(TempStr)) !=3D 0) { + DynamicUpdateType (SMBIOSTYPE1, STRING2, TempStr); + } + + GetStringFromFru (&Offset, TempPtr, TempStr); // ******************= *****SystemPartNum + + GetStringFromFru (&Offset, TempPtr, TempStr); // MiscSystemManufact= urer.SystemVersion + if (FruStrLen ((CHAR8 *)(TempStr)) !=3D 0) { + DynamicUpdateType (SMBIOSTYPE1, STRING3, TempStr); + } + + GetStringFromFru (&Offset, TempPtr, TempStr); // MiscSystemManufact= urer.SystemSerialNumber + if (FruStrLen ((CHAR8 *)(TempStr)) !=3D 0) { + DynamicUpdateType (SMBIOSTYPE1, STRING4, TempStr); + } + + GetStringFromFru (&Offset, TempPtr, TempStr); // ******************= *****AssetTag + if (FruStrLen ((CHAR8 *)(TempStr)) !=3D 0) { + DynamicUpdateType (SMBIOSTYPE3, STRING4, TempStr); // NOTICE: this A= sset Tag can be used by type 3 table + } + + FreePool (TempPtr); + } + + // + // SMBIOS Type 2, Base Board data + // + TempPtr =3D GetFruInfoArea (mFruRedirProtocol, FruCommonHeader.BoardArea= StartingOffset); + if (TempPtr !=3D NULL) { + // + // Get the following fields in the specified order. DO NOT change thi= s order unless the FRU file definition + // changes. Offset is initialized and then is incremented to the next= field offset in GetStringFromFru. + // + // Board Manufacturer + // Board Product Name + // Board Serial Number + // Board Part Number + // FRU Version Number + // + Offset =3D BOARD_MFG_OFFSET; + GetStringFromFru (&Offset, TempPtr, TempStr); // MiscBaseBoardManufac= turer.BaseBoardManufacturer + if (FruStrLen ((CHAR8 *)(TempStr)) !=3D 0) { + DynamicUpdateType (SMBIOSTYPE2, STRING1, TempStr); + } + + GetStringFromFru (&Offset, TempPtr, TempStr); // MiscBaseBoardManufac= turer.BaseBoardProductName + if (FruStrLen ((CHAR8 *)(TempStr)) !=3D 0) { + DynamicUpdateType (SMBIOSTYPE2, STRING2, TempStr); + } + + GetStringFromFru (&Offset, TempPtr, TempStr); // MiscBaseBoardManufac= turer.BaseBoardSerialNumber + if (FruStrLen ((CHAR8 *)(TempStr)) !=3D 0) { + DynamicUpdateType (SMBIOSTYPE2, STRING4, TempStr); + } + + GetStringFromFru (&Offset, TempPtr, TempStr); // MiscBaseBoardManufac= turer.BoardPartNumber + if (FruStrLen ((CHAR8 *)(TempStr)) !=3D 0) { + DynamicUpdateType (SMBIOSTYPE2, STRING3, TempStr); + } + + GetStringFromFru (&Offset, TempPtr, TempStr); // ********************= ******FRU Version Number + if (FruStrLen ((CHAR8 *)(TempStr)) !=3D 0) { + DynamicUpdateType (SMBIOSTYPE2, STRING3, TempStr); + } + + FreePool (TempPtr); + } + + // + // SMBIOS Type 3, Chassis data + // + TempPtr =3D GetFruInfoArea (mFruRedirProtocol, FruCommonHeader.ChassisIn= foStartingOffset); + if (TempPtr !=3D NULL) { + // special process: + TablePtr =3D GetStructureByTypeNo (SMBIOSTYPE3); + ASSERT (TablePtr !=3D NULL); + if (TablePtr =3D=3D NULL) { + return; + } + + ((SMBIOS_TABLE_TYPE3 *)TablePtr)->Type =3D TempPtr[CHASSIS_TYPE_OFFSET= ]; + // + // Get the following fields in the specified order. DO NOT change thi= s order unless the FRU file definition + // changes. Offset is initialized and then is incremented to the next= field offset in GetStringFromFru. + // + Offset =3D CHASSIS_PART_NUMBER; + GetStringFromFru (&Offset, TempPtr, TempStr); // MiscChassisManufactu= rer.ChassisVersion + if (FruStrLen ((CHAR8 *)(TempStr)) !=3D 0) { + DynamicUpdateType (SMBIOSTYPE3, STRING2, TempStr); + } + + GetStringFromFru (&Offset, TempPtr, TempStr); // MiscChassisManufactu= rer.ChassisSerialNumber + if (FruStrLen ((CHAR8 *)(TempStr)) !=3D 0) { + DynamicUpdateType (SMBIOSTYPE3, STRING3, TempStr); + } + + GetStringFromFru (&Offset, TempPtr, TempStr); // MiscChassisManufactu= rer.ChassisManufacturer + if (FruStrLen ((CHAR8 *)(TempStr)) !=3D 0) { + DynamicUpdateType (SMBIOSTYPE3, STRING1, TempStr); + } + + FreePool (TempPtr); + } + + return; +} + +/** + This routine install a notify function listen to ReadyToBoot Event. + + @param This - SM Fru Redir protocol. + +**/ +VOID +GenerateFruSmbiosData ( + IN EFI_SM_FRU_REDIR_PROTOCOL *This + ) +{ + EFI_EVENT Event; + EFI_STATUS Status; + + mFruRedirProtocol =3D This; + + Status =3D EfiCreateEventReadyToBootEx ( + TPL_CALLBACK, + GenerateFruSmbiosType123DataNotified, + NULL, + &Event + ); + + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_ERROR, "GenerateFruSmbiosData(): EfiCreateEventReadyToBo= otEx failed with return value: %r\n", Status)); + } + + return; +} diff --git a/Features/Intel/OutOfBandManagement/IpmiFeaturePkg/IpmiRedirFru= /IpmiRedirFru.c b/Features/Intel/OutOfBandManagement/IpmiFeaturePkg/IpmiRed= irFru/IpmiRedirFru.c new file mode 100644 index 000000000000..ac3c8ca50022 --- /dev/null +++ b/Features/Intel/OutOfBandManagement/IpmiFeaturePkg/IpmiRedirFru/IpmiRe= dirFru.c @@ -0,0 +1,479 @@ +/** @file + Server Management IPMI Redir FRU Driver. This REDIR FRU driver attaches + to the Generic FRU driver. + +Copyright (c) 2023, Intel Corporation. All rights reserved.
+SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include "IpmiRedirFru.h" +#include + +EFI_IPMI_FRU_GLOBAL *mIpmiFruGlobal; + +/** + Get Empty Fru Slot. + + @retval UINT8 + +**/ +UINT8 +GetEmptyFruSlot ( + VOID + ) +{ + UINT8 Num; + + for (Num =3D 1; Num < mIpmiFruGlobal->MaxFruSlots; Num++) { + if (!mIpmiFruGlobal->FruDeviceInfo[Num].Valid) { + return Num; + } + } + + return 0xFF; +} + +/** + Get Fru Redir Info. + + @param This + @param FruSlotNumber + @param FruFormatGuid + @param DataAccessGranularity + @param FruInformationString + + @retval EFI_NO_MAPPING + @retval EFI_SUCCESS + +**/ +EFI_STATUS +EFIAPI +EfiGetFruRedirInfo ( + IN EFI_SM_FRU_REDIR_PROTOCOL *This, + IN UINTN FruSlotNumber, + OUT EFI_GUID *FruFormatGuid, + OUT UINTN *DataAccessGranularity, + OUT CHAR16 **FruInformationString + ) +{ + EFI_IPMI_FRU_GLOBAL *FruPrivate; + + FruPrivate =3D INSTANCE_FROM_EFI_SM_IPMI_FRU_THIS (This); + + if ((FruSlotNumber + 1) > FruPrivate->NumSlots) { + return EFI_NO_MAPPING; + } + + CopyMem (FruFormatGuid, &gEfiIpmiFormatFruGuid, sizeof (EFI_GUID)); + + *DataAccessGranularity =3D 0x1; + *FruInformationString =3D NULL; + + return EFI_SUCCESS; +} + +/** + Get Fru Slot Info. + + @param This + @param FruTypeGuid + @param StartFruSlotNumber + @param NumSlots + + @retval EFI_SUCCESS + +**/ +EFI_STATUS +EFIAPI +EfiGetFruSlotInfo ( + IN EFI_SM_FRU_REDIR_PROTOCOL *This, + OUT EFI_GUID *FruTypeGuid, + OUT UINTN *StartFruSlotNumber, + OUT UINTN *NumSlots + ) +{ + EFI_IPMI_FRU_GLOBAL *FruPrivate; + + FruPrivate =3D NULL; + + FruPrivate =3D INSTANCE_FROM_EFI_SM_IPMI_FRU_THIS (This); + + CopyMem (FruTypeGuid, &gEfiSystemTypeFruGuid, sizeof (EFI_GUID)); + *StartFruSlotNumber =3D 0; + *NumSlots =3D FruPrivate->NumSlots; + return EFI_SUCCESS; +} + +/** + Get Fru Redir Data. + + @param This + @param FruSlotNumber + @param FruDataOffset + @param FruDataSize + @param FruData + + EFI_STATUS + +**/ +EFI_STATUS +EFIAPI +EfiGetFruRedirData ( + IN EFI_SM_FRU_REDIR_PROTOCOL *This, + IN UINTN FruSlotNumber, + IN UINTN FruDataOffset, + IN UINTN FruDataSize, + IN UINT8 *FruData + ) +{ + EFI_IPMI_FRU_GLOBAL *FruPrivate; + UINT32 ResponseDataSize; + UINT8 BackupCount; + UINT8 PointerOffset; + UINT8 DataToCopySize; + EFI_STATUS Status =3D EFI_SUCCESS; + IPMI_READ_FRU_DATA_REQUEST ReadFruDataRequest; + IPMI_READ_FRU_DATA_RESPONSE *ReadFruDataResponse; + + FruPrivate =3D NULL; + PointerOffset =3D 0; + + FruPrivate =3D INSTANCE_FROM_EFI_SM_IPMI_FRU_THIS (This); + + if ((FruSlotNumber + 1) > FruPrivate->NumSlots) { + Status =3D EFI_NO_MAPPING; + return Status; + } + + if (FruSlotNumber >=3D sizeof (FruPrivate->FruDeviceInfo) / sizeof (EFI_= FRU_DEVICE_INFO)) { + Status =3D EFI_INVALID_PARAMETER; + return Status; + } + + if (FruPrivate->FruDeviceInfo[FruSlotNumber].FruDevice.Bits.LogicalFruDe= vice) { + // + // Create the FRU Read Command for the logical FRU Device. + // + ReadFruDataRequest.DeviceId =3D FruPrivate->FruDeviceInfo[FruSl= otNumber].FruDevice.Bits.FruDeviceId; + ReadFruDataRequest.InventoryOffset =3D (UINT16)FruDataOffset; + ReadFruDataRequest.CountToRead =3D (UINT8)FruDataSize; + + ReadFruDataResponse =3D AllocateZeroPool (sizeof (ReadFruDataResponse)= + IPMI_RDWR_FRU_FRAGMENT_SIZE); + + if (ReadFruDataResponse =3D=3D NULL) { + DEBUG ((DEBUG_ERROR, " Null Pointer returned by AllocateZeroPool to = Read Fru data\n")); + return EFI_OUT_OF_RESOURCES; + } + + // + // Collect the data till it is completely retrieved. + // + while (ReadFruDataRequest.CountToRead !=3D 0) { + // + // Backup the count, since we are going to perform fragmented reads + // + BackupCount =3D ReadFruDataRequest.CountToRead; + if (ReadFruDataRequest.CountToRead > IPMI_RDWR_FRU_FRAGMENT_SIZE) { + ReadFruDataRequest.CountToRead =3D IPMI_RDWR_FRU_FRAGMENT_SIZE; + } + + ResponseDataSize =3D sizeof (ReadFruDataResponse) + ReadFruDataReque= st.CountToRead; + + Status =3D IpmiSubmitCommand ( + IPMI_NETFN_STORAGE, + IPMI_STORAGE_READ_FRU_DATA, + (UINT8 *)&ReadFruDataRequest, + sizeof (ReadFruDataRequest), + (UINT8 *)ReadFruDataResponse, + &ResponseDataSize + ); + + if (Status =3D=3D EFI_BUFFER_TOO_SMALL) { + DEBUG ((DEBUG_WARN, "%a: WARNING:: IpmiSubmitCommand returned EFI_= BUFFER_TOO_SMALL \n", __func__)); + } + + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_ERROR, "%a: IpmiSubmitCommand returned status %r\n",= __func__, Status)); + FreePool (ReadFruDataResponse); + return Status; + } + + // + // If the read FRU command returns a count of 0, then no FRU data wa= s found, so exit. + // + if (ReadFruDataResponse->CountReturned =3D=3D 0x00) { + Status =3D EFI_NOT_FOUND; + DEBUG ((DEBUG_ERROR, "%a: IpmiSubmitCommand Response data size is = 0x0\n", __func__)); + FreePool (ReadFruDataResponse); + return Status; + } + + ReadFruDataRequest.CountToRead =3D BackupCount; + + // + // In case of partial retrieval; Data[0] contains the retrieved data= size; + // + if (ReadFruDataRequest.CountToRead >=3D ReadFruDataResponse->CountRe= turned) { + DataToCopySize =3D ReadFruDataResponse->CountRetur= ned; + ReadFruDataRequest.CountToRead =3D (UINT8)(ReadFruDataRequest.Coun= tToRead - ReadFruDataResponse->CountReturned); // Remaining Count + } else { + DEBUG (( + DEBUG_WARN, + "%a: WARNING Command.Count (%d) is less than response data size = (%d) received\n", + __func__, + ReadFruDataRequest.CountToRead, + ReadFruDataResponse->CountReturned + )); + DataToCopySize =3D ReadFruDataRequest.CountToRead; + ReadFruDataRequest.CountToRead =3D 0; // Remaining Count + } + + ReadFruDataRequest.InventoryOffset =3D (UINT16)(ReadFruDataRequest.I= nventoryOffset + DataToCopySize); // Next Offset to retrieve + + if (PointerOffset + DataToCopySize > FruDataSize) { + DEBUG (( + DEBUG_ERROR, + "Insufficient storage supplied to %a, need more than % bytes\n", + __func__, + PointerOffset + DataToCopySize + )); + Status =3D EFI_BUFFER_TOO_SMALL; + FreePool (ReadFruDataResponse); + return Status; + } + + ASSERT (PointerOffset < FruDataSize); + ASSERT (PointerOffset + DataToCopySize <=3D FruDataSize); + + CopyMem (&FruData[PointerOffset], &ReadFruDataResponse->Data[0], Dat= aToCopySize); // Copy the partial data + PointerOffset =3D (UINT8)(PointerOffset + DataToCopySize); = // Next offset to the iput pointer. + } + + FreePool (ReadFruDataResponse); + } else { + Status =3D EFI_UNSUPPORTED; + return Status; + } + + return Status; +} + +/** + Set Fru Redir Data. + + @retval This + @retval FruSlotNumber + @retval FruDataOffset + @retval FruDataSize + @retval FruData + + @retval EFI_STATUS + +**/ +EFI_STATUS +EFIAPI +EfiSetFruRedirData ( + IN EFI_SM_FRU_REDIR_PROTOCOL *This, + IN UINTN FruSlotNumber, + IN UINTN FruDataOffset, + IN UINTN FruDataSize, + IN UINT8 *FruData + ) +{ + EFI_IPMI_FRU_GLOBAL *FruPrivate; + UINT8 Count; + UINT8 BackupCount; + UINT32 ResponseDataSize; + UINT8 PointerOffset; + UINT8 DataToCopySize; + EFI_STATUS Status; + IPMI_WRITE_FRU_DATA_REQUEST *WriteFruDataRequest; + IPMI_WRITE_FRU_DATA_RESPONSE WriteFruDataResponse; + + FruPrivate =3D NULL; + PointerOffset =3D 0; + + FruPrivate =3D INSTANCE_FROM_EFI_SM_IPMI_FRU_THIS (This); + + if ((FruSlotNumber + 1) > FruPrivate->NumSlots) { + return EFI_NO_MAPPING; + } + + if (FruSlotNumber >=3D sizeof (FruPrivate->FruDeviceInfo) / sizeof (EFI_= FRU_DEVICE_INFO)) { + return EFI_INVALID_PARAMETER; + } + + if (FruPrivate->FruDeviceInfo[FruSlotNumber].FruDevice.Bits.LogicalFruDe= vice) { + WriteFruDataRequest =3D AllocateZeroPool (sizeof (IPMI_WRITE_FRU_DATA_= REQUEST) + IPMI_RDWR_FRU_FRAGMENT_SIZE); + + if (WriteFruDataRequest =3D=3D NULL) { + DEBUG ((DEBUG_ERROR, " Null Pointer returned by AllocateZeroPool to = Write Fru data\n")); + return EFI_OUT_OF_RESOURCES; + } + + // + // Create the FRU Write Command for the logical FRU Device. + // + WriteFruDataRequest->DeviceId =3D FruPrivate->FruDeviceInfo[Fru= SlotNumber].FruDevice.Bits.FruDeviceId; + WriteFruDataRequest->InventoryOffset =3D (UINT16)FruDataOffset; + Count =3D (UINT8)FruDataSize; + PointerOffset =3D 0; + + // + // Collect the data till it is completely retrieved. + // + while (Count !=3D 0) { + // + // Backup the count, since we are going to perform fragmented reads + // + BackupCount =3D Count; + if (Count > IPMI_RDWR_FRU_FRAGMENT_SIZE) { + Count =3D IPMI_RDWR_FRU_FRAGMENT_SIZE; + } + + CopyMem (&WriteFruDataRequest->Data[0], &FruData[PointerOffset], Cou= nt); + + ResponseDataSize =3D sizeof (WriteFruDataResponse); + Status =3D IpmiSubmitCommand ( + IPMI_NETFN_STORAGE, + IPMI_STORAGE_WRITE_FRU_DATA, + (UINT8 *)WriteFruDataRequest, + (sizeof (WriteFruDataRequest) + Count), + (UINT8 *)&WriteFruDataResponse, + &ResponseDataSize + ); + + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_ERROR, "%a: IpmiSubmitCommand returned status %r\n",= __func__, Status)); + FreePool (WriteFruDataRequest); + return Status; + } + + Count =3D BackupCount; + + if (Count >=3D WriteFruDataResponse.CountWritten) { + DataToCopySize =3D Count - WriteFruDataResponse.CountWritten; + Count =3D (UINT8)(Count - WriteFruDataResponse.CountWritt= en); // Remaining Count + } else { + DEBUG (( + DEBUG_WARN, + "%a: WARNING Count (%d) is less than response data size (%d) rec= eived\n", + __func__, + Count, + WriteFruDataResponse.CountWritten + )); + DataToCopySize =3D Count; + Count =3D 0; // Remaining Count + } + + // + // In case of partial retrieval; Data[0] contains the retrieved data= size; + // + WriteFruDataRequest->InventoryOffset =3D (UINT16)(WriteFruDataReques= t->InventoryOffset + DataToCopySize); // Next Offset to set + PointerOffset =3D (UINT8)(PointerOffset + Dat= aToCopySize); // Next offset to the iput pointer. + } + + FreePool (WriteFruDataRequest); + } else { + return EFI_UNSUPPORTED; + } + + return EFI_SUCCESS; +} + +/** + Initialize SM Redirection Fru Layer. + + @param ImageHandle - ImageHandle of the loaded driver + @param SystemTable - Pointer to the System Table + + @retval EFI_STATUS + +**/ +EFI_STATUS +EFIAPI +InitializeSmRedirFruLayer ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +{ + EFI_HANDLE NewHandle; + EFI_STATUS Status; + IPMI_GET_DEVICE_ID_RESPONSE GetDeviceIdResponse; + UINT32 ResponseDataSize; + + gST =3D SystemTable; + gBS =3D gST->BootServices; + + // + // Initialize Global memory + // + mIpmiFruGlobal =3D AllocateRuntimePool (sizeof (EFI_IPMI_FRU_GLOBAL)); + ASSERT (mIpmiFruGlobal !=3D NULL); + if (mIpmiFruGlobal =3D=3D NULL) { + return EFI_OUT_OF_RESOURCES; + } + + mIpmiFruGlobal->NumSlots =3D 0; + mIpmiFruGlobal->IpmiRedirFruProtocol.GetFruRedirInfo =3D (EFI_GET_FRU_RE= DIR_INFO)EfiGetFruRedirInfo; + mIpmiFruGlobal->IpmiRedirFruProtocol.GetFruSlotInfo =3D (EFI_GET_FRU_SL= OT_INFO)EfiGetFruSlotInfo; + mIpmiFruGlobal->IpmiRedirFruProtocol.GetFruRedirData =3D (EFI_GET_FRU_RE= DIR_DATA)EfiGetFruRedirData; + mIpmiFruGlobal->IpmiRedirFruProtocol.SetFruRedirData =3D (EFI_SET_FRU_RE= DIR_DATA)EfiSetFruRedirData; + mIpmiFruGlobal->Signature =3D EFI_SM_FRU_REDI= R_SIGNATURE; + mIpmiFruGlobal->MaxFruSlots =3D MAX_FRU_SLOT; + // + // Get all the SDR Records from BMC and retrieve the Record ID from the= structure for future use. + // + ResponseDataSize =3D sizeof (GetDeviceIdResponse); + Status =3D IpmiSubmitCommand ( + IPMI_NETFN_APP, + IPMI_APP_GET_DEVICE_ID, + (UINT8 *)NULL, + 0, + (UINT8 *)&GetDeviceIdResponse, + &ResponseDataSize + ); + + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_ERROR, "IpmiSubmitCommand Ipmi App Get DeviceId Failed %= r\n", Status)); + return Status; + } + + if (GetDeviceIdResponse.DeviceSupport.Bits.FruInventorySupport) { + // + // Initialize all FRU slots + // Add a mandatory FRU Inventory device attached to the controller. + // + for (mIpmiFruGlobal->NumSlots =3D 0; mIpmiFruGlobal->NumSlots < mIpmiF= ruGlobal->MaxFruSlots; mIpmiFruGlobal->NumSlots++) { + mIpmiFruGlobal->FruDeviceInfo[mIpmiFruGlobal->NumSlots].Valid =3D TR= UE; + ZeroMem (&mIpmiFruGlobal->FruDeviceInfo[mIpmiFruGlobal->NumSlots].Fr= uDevice, sizeof (IPMI_FRU_DATA_INFO)); + mIpmiFruGlobal->FruDeviceInfo[mIpmiFruGlobal->NumSlots].FruDevice.Bi= ts.LogicalFruDevice =3D 1; + mIpmiFruGlobal->FruDeviceInfo[mIpmiFruGlobal->NumSlots].FruDevice.Bi= ts.FruDeviceId =3D mIpmiFruGlobal->NumSlots; + } + } + + // + // Install callback for ReadyToBoot event to generate FRU SMBIOS Data + // + + GenerateFruSmbiosData (&mIpmiFruGlobal->IpmiRedirFruProtocol); + + // + // Install the FRU Ipmi Redir protocol. + // + NewHandle =3D NULL; + Status =3D gBS->InstallProtocolInterface ( + &NewHandle, + &gEfiRedirFruProtocolGuid, + EFI_NATIVE_INTERFACE, + &mIpmiFruGlobal->IpmiRedirFruProtocol + ); + + ASSERT_EFI_ERROR (Status); + if (Status !=3D EFI_SUCCESS) { + return Status; + } + + return EFI_SUCCESS; +} --=20 2.39.2.windows.1 -=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 (#110329): https://edk2.groups.io/g/devel/message/110329 Mute This Topic: https://groups.io/mt/102279908/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-