From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from NAM12-MW2-obe.outbound.protection.outlook.com (NAM12-MW2-obe.outbound.protection.outlook.com [40.107.244.46]) by mx.groups.io with SMTP id smtpd.web10.4748.1679368946803110166 for ; Mon, 20 Mar 2023 20:22:27 -0700 Authentication-Results: mx.groups.io; dkim=fail reason="body hash did not verify" header.i=@amd.com header.s=selector1 header.b=DFbDfRMM; spf=permerror, err=parse error for token &{10 18 %{i}._ip.%{h}._ehlo.%{d}._spf.vali.email}: invalid domain name (domain: amd.com, ip: 40.107.244.46, mailfrom: abner.chang@amd.com) ARC-Seal: i=1; a=rsa-sha256; s=arcselector9901; d=microsoft.com; cv=none; b=d+ITgVXPBPCVSCLv5NxNrQEoshXuowsD4k/vK21lqQ5CX4pYh2a/urjzuVn63jSXJNhXxN5iEEvSMqfnjHogimqF0U0j6ILwqS24MKIK9nrYY927XbEmauqBJHaVB60eO8GTX4b5Cz6S2uh33iG8efQ0aPfP7DQdW1xRNh4vfjJ1mt22p4LV7zDi6aZzLq3aYDYdSgrJ8CX1rZEyvtBvybp1on58X+X1+eaeM1fU8xDqAmYOe2sUsgvbR7RLZvthel+mElkHSBfPzEfSaCKJP13vxalMKzAfDe5ZTaOZC51Bm9NxVY3MFnCnvKtlHG1xYL+mKdxefBlGaduoDSF0mA== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=microsoft.com; s=arcselector9901; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-AntiSpam-MessageData-ChunkCount:X-MS-Exchange-AntiSpam-MessageData-0:X-MS-Exchange-AntiSpam-MessageData-1; bh=9jUPRmh8ySU7l/sykwdfjz7wFVwhRVHqtjPHxeEGukc=; b=Ntex/dT5uIcPl6awC3+TXrN8VDQLA3QGaxXueDbXWD7knW2aRJ/PWFWpZSOB5Z+F5OmuVSld1vnb3DgMJ1mcvkqY8Z88FYBYcAwzazo/r7yJnQ0ZAy7fffybs4wXK/+4Z4X0E2kPhVNyCpTCDp2fI4QNZHaQSPFFy4SDwZGCC6u/Wb+nNsNoENNnWR7RWjV1Km+n4fLu6eJC1qgju4pSmVtDwLF9CnE4tOWAZuqzo86prqcBNwilyBm2TFdmZB1ZZYR6Md1APJxt0jdUf7rcElvcly5c6RRW80TQDQATRtZqQLJcRqsM7kqYD1OWoEtCVL4MMf+0lcEVsxzzmGDVAA== ARC-Authentication-Results: i=1; mx.microsoft.com 1; spf=pass (sender ip is 165.204.84.17) smtp.rcpttodomain=edk2.groups.io smtp.mailfrom=amd.com; dmarc=pass (p=quarantine sp=quarantine pct=100) action=none header.from=amd.com; dkim=none (message not signed); arc=none DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=amd.com; s=selector1; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-SenderADCheck; bh=9jUPRmh8ySU7l/sykwdfjz7wFVwhRVHqtjPHxeEGukc=; b=DFbDfRMMy3atCxgeOUEc+HJrDZmFqoiG0teXBz1RkCgI0P70VabSNIhOrQV5+6GS6TG4eQAhBoyoMtWT+uNp9FW+7d+q9WmDJpeWl3EsZrBHEkL4JasLkOheKrlT0Q174/jJ3p0PAM4LhF844NhhteSKBWaXlEhfrQOWLWRMdj0= Received: from MW4PR04CA0259.namprd04.prod.outlook.com (2603:10b6:303:88::24) by SN7PR12MB7203.namprd12.prod.outlook.com (2603:10b6:806:2aa::8) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.6178.37; Tue, 21 Mar 2023 03:22:23 +0000 Received: from CO1NAM11FT065.eop-nam11.prod.protection.outlook.com (2603:10b6:303:88:cafe::c5) by MW4PR04CA0259.outlook.office365.com (2603:10b6:303:88::24) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.6178.37 via Frontend Transport; Tue, 21 Mar 2023 03:22:23 +0000 X-MS-Exchange-Authentication-Results: spf=pass (sender IP is 165.204.84.17) smtp.mailfrom=amd.com; dkim=none (message not signed) header.d=none;dmarc=pass action=none header.from=amd.com; Received-SPF: Pass (protection.outlook.com: domain of amd.com designates 165.204.84.17 as permitted sender) receiver=protection.outlook.com; client-ip=165.204.84.17; helo=SATLEXMB04.amd.com; pr=C Received: from SATLEXMB04.amd.com (165.204.84.17) by CO1NAM11FT065.mail.protection.outlook.com (10.13.174.62) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256) id 15.20.6222.16 via Frontend Transport; Tue, 21 Mar 2023 03:22:23 +0000 Received: from TPE-L1-ABNCHANG.amd.com (10.180.168.240) by SATLEXMB04.amd.com (10.181.40.145) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256) id 15.1.2375.34; Mon, 20 Mar 2023 22:22:20 -0500 From: "Chang, Abner" To: CC: Liming Gao , Isaac Oram , Nate DeSimone , Abdul Lateef Attar , Nickle Wang , "Igor Kulchytskyy" Subject: [PATCH v3 5/8] ManageabilityPkg/ManageabilityTransportKcsLib Date: Tue, 21 Mar 2023 11:21:44 +0800 Message-ID: <20230321032147.1616-3-abner.chang@amd.com> X-Mailer: git-send-email 2.37.1.windows.1 In-Reply-To: <20230321032147.1616-1-abner.chang@amd.com> References: <20230321032147.1616-1-abner.chang@amd.com> MIME-Version: 1.0 Return-Path: Abner.Chang@amd.com X-Originating-IP: [10.180.168.240] X-ClientProxiedBy: SATLEXMB04.amd.com (10.181.40.145) To SATLEXMB04.amd.com (10.181.40.145) X-EOPAttributedMessage: 0 X-MS-PublicTrafficType: Email X-MS-TrafficTypeDiagnostic: CO1NAM11FT065:EE_|SN7PR12MB7203:EE_ X-MS-Office365-Filtering-Correlation-Id: cc2f9bb6-ec19-49f8-1cd0-08db29bb7cc9 X-MS-Exchange-SenderADCheck: 1 X-MS-Exchange-AntiSpam-Relay: 0 X-Microsoft-Antispam: BCL:0; X-Microsoft-Antispam-Message-Info: YvX/jOTEefIUJBCl7dgalNMmdtUK28EGJU1fie0QXPoAjZqsJYFBwvXHyM5sJUUsci+SU3aZXlyP5GGKsda2rMD9FoQeSVffcDuNYhd+BabTKX+EtIFM2rm8HhFttL6Eya/4xVTI8K3lYtQ9lVbLgmbQ5io4PWqw1CKrTFj0BcnL78Lz21A2mzEigL4aExhjS4qdHeCFqHbJTYLGEI/vif4xDb1yK2Kbo28RXYQ/jqqBGcbi/FQ2YnUQ2/UPCy+aHXigTz5ZV6jhF1lFz+7jHY8GmiGk8oNie7BQQC5Ottfy9r66xG2I3F4YoiDYo7eb0oejXpTWeTUMs8CvMcdz0XMjODhM9bWU4wieHKSFcKJGWx73EJz9rlvUz+ryvPAnKwDtLh6EAG3mTavoLd2TgygN2hytoK4dn6/T3TyFZvHHcWTk4HtnU5AD/25/Izn2zQ6JHlMJs6ovx5r0hwdfuAOAhnneApsWviGnfX+oF5owOU22Dffukc9vEeRevmo0TnnVWsdFss4JtGv1J6phPEUJztbS+P2Gj1SBdeHjawQJBOTbZL06EmzwkRceXKHpB+dCMaJLbu5PQYq6NwUrmXPliWSww2p0Ic1wllEkH3LgoOSkYB+UZzJG/EJA6erOuGgJzMzaszaCAn6x79DeSojcEjr39VrRreKgWKCk9sQJBvswEPYj8kwk4N5i8/bYmV7LvGBz5SiHF0T48gf2aOLJ+FfVgMLJ4t9f6rQW7d+WSOwlv2/9cGIXiGhI0+VKTppAF+xZe/XrMmcn2fbAFA== X-Forefront-Antispam-Report: CIP:165.204.84.17;CTRY:US;LANG:en;SCL:1;SRV:;IPV:CAL;SFV:NSPM;H:SATLEXMB04.amd.com;PTR:InfoDomainNonexistent;CAT:NONE;SFS:(13230025)(4636009)(39860400002)(376002)(396003)(346002)(136003)(451199018)(40470700004)(46966006)(36840700001)(47076005)(426003)(2616005)(7696005)(6666004)(1076003)(5660300002)(26005)(336012)(86362001)(70586007)(478600001)(40460700003)(316002)(16526019)(83380400001)(82310400005)(186003)(54906003)(36756003)(6916009)(4326008)(41300700001)(19627235002)(8676002)(36860700001)(356005)(70206006)(8936002)(30864003)(82740400003)(2876002)(40480700001)(81166007)(2906002)(36900700001)(579004)(44824005);DIR:OUT;SFP:1101; X-OriginatorOrg: amd.com X-MS-Exchange-CrossTenant-OriginalArrivalTime: 21 Mar 2023 03:22:23.0672 (UTC) X-MS-Exchange-CrossTenant-Network-Message-Id: cc2f9bb6-ec19-49f8-1cd0-08db29bb7cc9 X-MS-Exchange-CrossTenant-Id: 3dd8961f-e488-4e60-8e11-a82d994e183d X-MS-Exchange-CrossTenant-OriginalAttributedTenantConnectingIp: TenantId=3dd8961f-e488-4e60-8e11-a82d994e183d;Ip=[165.204.84.17];Helo=[SATLEXMB04.amd.com] X-MS-Exchange-CrossTenant-AuthSource: CO1NAM11FT065.eop-nam11.prod.protection.outlook.com X-MS-Exchange-CrossTenant-AuthAs: Anonymous X-MS-Exchange-CrossTenant-FromEntityHeader: HybridOnPrem X-MS-Exchange-Transport-CrossTenantHeadersStamped: SN7PR12MB7203 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain From: Abner Chang This is the KCS manageability transport library instance follows the design guidance described in Readme file under ManageabilityPkg. Signed-off-by: Abner Chang Cc: Liming Gao Cc: Isaac Oram Cc: Nate DeSimone Cc: Abdul Lateef Attar Cc: Nickle Wang Cc: Igor Kulchytskyy --- .../ManageabilityPkg/ManageabilityPkg.dsc | 3 + .../Dxe/DxeManageabilityTransportKcs.inf | 44 ++ .../Common/ManageabilityTransportKcs.h | 105 ++++ .../Common/KcsCommon.c | 502 ++++++++++++++++++ .../Dxe/ManageabilityTransportKcs.c | 389 ++++++++++++++ .../Dxe/ManageabilityTransportKcs.uni | 13 + 6 files changed, 1056 insertions(+) create mode 100644 Features/ManageabilityPkg/Library/ManageabilityTranspor= tKcsLib/Dxe/DxeManageabilityTransportKcs.inf create mode 100644 Features/ManageabilityPkg/Library/ManageabilityTranspor= tKcsLib/Common/ManageabilityTransportKcs.h create mode 100644 Features/ManageabilityPkg/Library/ManageabilityTranspor= tKcsLib/Common/KcsCommon.c create mode 100644 Features/ManageabilityPkg/Library/ManageabilityTranspor= tKcsLib/Dxe/ManageabilityTransportKcs.c create mode 100644 Features/ManageabilityPkg/Library/ManageabilityTranspor= tKcsLib/Dxe/ManageabilityTransportKcs.uni diff --git a/Features/ManageabilityPkg/ManageabilityPkg.dsc b/Features/Mana= geabilityPkg/ManageabilityPkg.dsc index 0dd0ab41fc..45e07ac34f 100644 --- a/Features/ManageabilityPkg/ManageabilityPkg.dsc +++ b/Features/ManageabilityPkg/ManageabilityPkg.dsc @@ -36,6 +36,9 @@ !include MinPlatformPkg/Include/Dsc/CorePeiLib.dsc !include MinPlatformPkg/Include/Dsc/CoreDxeLib.dsc =20 +[Components] + ManageabilityPkg/Library/ManageabilityTransportKcsLib/Dxe/DxeManageabili= tyTransportKcs.inf + [LibraryClasses] ManageabilityTransportLib|ManageabilityPkg/Library/BaseManageabilityTran= sportNullLib/BaseManageabilityTransportNull.inf =20 diff --git a/Features/ManageabilityPkg/Library/ManageabilityTransportKcsLib= /Dxe/DxeManageabilityTransportKcs.inf b/Features/ManageabilityPkg/Library/M= anageabilityTransportKcsLib/Dxe/DxeManageabilityTransportKcs.inf new file mode 100644 index 0000000000..f0a6afa074 --- /dev/null +++ b/Features/ManageabilityPkg/Library/ManageabilityTransportKcsLib/Dxe/Dx= eManageabilityTransportKcs.inf @@ -0,0 +1,44 @@ +## @file +# KCS instance of Manageability Transport Library +# +# Copyright (C) 2023 Advanced Micro Devices, Inc. All rights reserved.
+# SPDX-License-Identifier: BSD-2-Clause-Patent +# +## + +[Defines] + INF_VERSION =3D 0x0001001B + BASE_NAME =3D DxeManageabilityTransportKcs + MODULE_UNI_FILE =3D ManageabilityTransportKcs.uni + FILE_GUID =3D FCCC8B34-145A-4927-9F08-553ADC579AF7 + MODULE_TYPE =3D DXE_DRIVER + VERSION_STRING =3D 1.0 + LIBRARY_CLASS =3D ManageabilityTransportLib + +# +# VALID_ARCHITECTURES =3D IA32 X64 ARM AARCH64 +# + +[Sources] + ManageabilityTransportKcs.c + ../Common/KcsCommon.c + ../Common/ManageabilityTransportKcs.h + +[Packages] + ManageabilityPkg/ManageabilityPkg.dec + MdePkg/MdePkg.dec + +[LibraryClasses] + DebugLib + IoLib + TimerLib + MemoryAllocationLib + +[Guids] + gManageabilityTransportKcsGuid + gManageabilityProtocolMctpGuid + gManageabilityProtocolIpmiGuid + +[FixedPcd] + gEfiMdePkgTokenSpaceGuid.PcdIpmiKcsBaseAddress # Used as default KCS I= /O base adddress + diff --git a/Features/ManageabilityPkg/Library/ManageabilityTransportKcsLib= /Common/ManageabilityTransportKcs.h b/Features/ManageabilityPkg/Library/Man= ageabilityTransportKcsLib/Common/ManageabilityTransportKcs.h new file mode 100644 index 0000000000..f1758ffd8f --- /dev/null +++ b/Features/ManageabilityPkg/Library/ManageabilityTransportKcsLib/Common= /ManageabilityTransportKcs.h @@ -0,0 +1,105 @@ +/** @file + + Manageability transport KCS internal used definitions. + + Copyright (C) 2023 Advanced Micro Devices, Inc. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent +**/ + +#ifndef MANAGEABILITY_TRANSPORT_KCS_LIB_H_ +#define MANAGEABILITY_TRANSPORT_KCS_LIB_H_ + +#include + +#define MANAGEABILITY_TRANSPORT_KCS_SIGNATURE SIGNATURE_32 ('M', 'T', 'K'= , 'C') + +#define KCS_BASE_ADDRESS mKcsHardwareInfo.IoBaseAddress +#define KCS_REG_DATA_IN mKcsHardwareInfo.IoDataInAddress +#define KCS_REG_DATA_OUT mKcsHardwareInfo.IoDataOutAddress +#define KCS_REG_COMMAND mKcsHardwareInfo.IoCommandAddress +#define KCS_REG_STATUS mKcsHardwareInfo.IoStatusAddress + +/// +/// Manageability transport KCS internal data structure. +/// +typedef struct { + UINTN Signature; + MANAGEABILITY_TRANSPORT_TOKEN Token; +} MANAGEABILITY_TRANSPORT_KCS; + +#define MANAGEABILITY_TRANSPORT_KCS_FROM_LINK(a) CR (a, MANAGEABILITY_TRA= NSPORT_KCS, Token, MANAGEABILITY_TRANSPORT_KCS_SIGNATURE) + +#define IPMI_KCS_GET_STATE(s) (s >> 6) +#define IPMI_KCS_SET_STATE(s) (s << 6) + +/// 5 sec, according to IPMI spec +#define IPMI_KCS_TIMEOUT_5_SEC 5000*1000 +#define IPMI_KCS_TIMEOUT_1MS 1000 + +/** + This service communicates with BMC using KCS protocol. + + @param[in] NetFunction Net function of the command. + @param[in] Command IPMI Command. + @param[in] RequestData Command Request Data. + @param[in] RequestDataSize Size of Command Request Data. + @param[out] ResponseData Command Response Data. The complet= ion + code is the first byte of response + data. + @param[in, out] ResponseDataSize Size of Command Response Data. + + @retval EFI_SUCCESS The command byte stream was + successfully submit to the device = and a + response was successfully received= . + @retval EFI_NOT_FOUND The command was not successfully s= ent + to the device or a response was no= t + successfully received from the dev= ice. + @retval EFI_NOT_READY Ipmi Device is not ready for Ipmi + command access. + @retval EFI_DEVICE_ERROR Ipmi Device hardware error. + @retval EFI_TIMEOUT The command time out. + @retval EFI_UNSUPPORTED The command was not successfully s= ent to + the device. + @retval EFI_OUT_OF_RESOURCES The resource allocation is out of + resource or data size error. +**/ + +EFI_STATUS +EFIAPI +KcsTransportSendCommand ( + IN UINT8 NetFunction, + IN UINT8 Command, + IN UINT8 *RequestData OPTIONAL, + IN UINT32 RequestDataSize, + OUT UINT8 *ResponseData OPTIONAL, + IN OUT UINT32 *ResponseDataSize OPTIONAL + ); + +/** + This function reads 8-bit value from register address. + + @param[in] Address This represents either 16-bit IO a= ddress + or 32-bit memory mapped address. + + @retval UINT8 8-bit value. +**/ +UINT8 +KcsRegisterRead8 ( + MANAGEABILITY_TRANSPORT_HARDWARE_IO Address + ); + +/** + This function writes 8-bit value to register address. + + @param[in] Address This represents either 16-bit IO a= ddress + or 32-bit memory mapped address. + @param[in] Value 8-bit value write to register addr= ess + +**/ +VOID +KcsRegisterWrite8 ( + MANAGEABILITY_TRANSPORT_HARDWARE_IO Address, + UINT8 Value + ); + +#endif diff --git a/Features/ManageabilityPkg/Library/ManageabilityTransportKcsLib= /Common/KcsCommon.c b/Features/ManageabilityPkg/Library/ManageabilityTransp= ortKcsLib/Common/KcsCommon.c new file mode 100644 index 0000000000..b141c65381 --- /dev/null +++ b/Features/ManageabilityPkg/Library/ManageabilityTransportKcsLib/Common= /KcsCommon.c @@ -0,0 +1,502 @@ +/** @file + + KCS instance of Manageability Transport Library + + Copyright (C) 2023 Advanced Micro Devices, Inc. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ +#include +#include +#include +#include +#include +#include +#include + +#include "ManageabilityTransportKcs.h" + +extern MANAGEABILITY_TRANSPORT_KCS_HARDWARE_INFO mKcsHardwareInfo; + +/** + This function waits for parameter Flag to set. + Checks status flag in every 1ms internal till 5 seconds elapses. + + @param[in] Flag KCS Flag to test. + @retval EFI_SUCCESS The KCS flag under test is set. + @retval EFI_TIMEOUT The KCS flag didn't set in 5 second windows. +**/ +EFI_STATUS +WaitStatusSet ( + IN UINT8 Flag + ) +{ + UINT64 Timeout =3D 0; + + while (!(KcsRegisterRead8 (KCS_REG_STATUS) & Flag)) { + MicroSecondDelay (IPMI_KCS_TIMEOUT_1MS); + Timeout =3D Timeout + IPMI_KCS_TIMEOUT_1MS; + if (Timeout >=3D IPMI_KCS_TIMEOUT_5_SEC) { + return EFI_TIMEOUT; + } + } + + return EFI_SUCCESS; +} + +/** + This function waits for parameter Flag to get cleared. + Checks status flag in every 1ms internal till 5 seconds elapses. + + @param[in] Flag KCS Flag to test. + + @retval EFI_SUCCESS The KCS flag under test is clear. + @retval EFI_TIMEOUT The KCS flag didn't cleared in 5 second windows. +**/ +EFI_STATUS +WaitStatusClear ( + IN UINT8 Flag + ) +{ + UINT64 Timeout =3D 0; + + while (KcsRegisterRead8 (KCS_REG_STATUS) & Flag) { + MicroSecondDelay (IPMI_KCS_TIMEOUT_1MS); + Timeout =3D Timeout + IPMI_KCS_TIMEOUT_1MS; + if (Timeout >=3D IPMI_KCS_TIMEOUT_5_SEC) { + return EFI_TIMEOUT; + } + } + + return EFI_SUCCESS; +} + +/** + This function validates KCS OBF bit. + Checks whether OBF bit is set or not. + + @retval EFI_SUCCESS OBF bit is set. + @retval EFI_NOT_READY OBF bit is not set. +**/ +EFI_STATUS +ClearOBF ( + VOID + ) +{ + if (KcsRegisterRead8 (KCS_REG_STATUS) & IPMI_KCS_OBF) { + KcsRegisterRead8 (KCS_REG_DATA_IN); // read the data to clear the OBF + if (KcsRegisterRead8 (KCS_REG_STATUS) & IPMI_KCS_OBF) { + return EFI_NOT_READY; + } + } + + return EFI_SUCCESS; +} + +/** + This function writes/sends data to the KCS port. + Algorithm is based on flow chart provided in IPMI spec 2.0 + Figure 9-6, KCS Interface BMC to SMS Write Transfer Flow Chart + + @param[in] NetFunction Net function of the command. + @param[in] Command IPMI Command. + @param[in] RequestData Command Request Data, could be NULL. + RequestDataSize must be zero, if Reque= stData + is NULL. + @param[in] RequestDataSize Size of Command Request Data. + + @retval EFI_SUCCESS The command byte stream was successful= ly + submit to the device and a response wa= s + successfully received. + @retval EFI_NOT_FOUND The command was not successfully sent = to the + device or a response was not successfu= lly + received from the device. + @retval EFI_NOT_READY Ipmi Device is not ready for Ipmi comm= and + access. + @retval EFI_DEVICE_ERROR Ipmi Device hardware error. + @retval EFI_TIMEOUT The command time out. + @retval EFI_UNSUPPORTED The command was not successfully sent = to + the device. + @retval EFI_OUT_OF_RESOURCES The resource allocation is out of reso= urce or + data size error. +**/ +EFI_STATUS +KcsTransportWrite ( + IN UINT8 NetFunction, + IN UINT8 Command, + IN UINT8 *RequestData OPTIONAL, + IN UINT32 RequestDataSize + ) +{ + EFI_STATUS Status; + UINT32 Length; + UINT8 *Buffer; + UINT8 *BufferPtr; + + // Validation on RequestData and RequestDataSize. + if ((RequestData =3D=3D NULL && RequestDataSize !=3D 0) || + (RequestData !=3D NULL && RequestDataSize =3D=3D 0) + ) { + DEBUG ((DEBUG_ERROR, "%a: Mismatched values of RequestData or RequestD= ataSize.\n", __FUNCTION__)); + return EFI_INVALID_PARAMETER; + } + + Length =3D sizeof (NetFunction) + sizeof (Command); + if (RequestData !=3D NULL) { + Length =3D Length + RequestDataSize; + } + + Buffer =3D AllocateZeroPool (Length); + if (Buffer =3D=3D NULL) { + return EFI_OUT_OF_RESOURCES; + } + + // + // Buffer[0] =3D NetFunction + // Buffer[1] =3D Command + // Buffer [2..RequestDataSize] =3D RequestData + // + BufferPtr =3D Buffer; + CopyMem (BufferPtr, &NetFunction, sizeof (NetFunction)); + BufferPtr +=3D sizeof (NetFunction); + CopyMem (BufferPtr, &Command, sizeof (Command)); + BufferPtr +=3D sizeof (Command); + if (Length > (sizeof (NetFunction) + sizeof (Command))) { + CopyMem (BufferPtr, RequestData, RequestDataSize); + } + + BufferPtr =3D Buffer; + + // Step 1. wait for IBF to get clear + Status =3D WaitStatusClear (IPMI_KCS_IBF); + if (EFI_ERROR (Status)) { + FreePool (Buffer); + return Status; + } + + // Step 2. clear OBF + if (EFI_ERROR (ClearOBF ())) { + FreePool (Buffer); + return EFI_NOT_READY; + } + + // Step 3. WR_START to CMD, phase=3Dwr_start + KcsRegisterWrite8 (KCS_REG_COMMAND, IPMI_KCS_CONTROL_CODE_WRITE_START); + + // Step 4. wait for IBF to get clear + Status =3D WaitStatusClear (IPMI_KCS_IBF); + if (EFI_ERROR (Status)) { + FreePool (Buffer); + return Status; + } + + // Step 5. check state it should be WRITE_STATE, else exit with error + if (IPMI_KCS_GET_STATE (KcsRegisterRead8 (KCS_REG_STATUS)) !=3D IPMI_KCS= _WRITE_STATE) { + FreePool (Buffer); + return EFI_NOT_READY; + } + + // Step 6, Clear OBF + if (EFI_ERROR (ClearOBF ())) { + FreePool (Buffer); + return EFI_NOT_READY; + } + + while (Length > 1) { + // Step 7, phase wr_data, write one byte of Data + KcsRegisterWrite8 (KCS_REG_DATA_OUT, *BufferPtr); + Length--; + BufferPtr++; + + // Step 8. wait for IBF clear + Status =3D WaitStatusClear (IPMI_KCS_IBF); + if (EFI_ERROR (Status)) { + FreePool (Buffer); + return Status; + } + + // Step 9. check state it should be WRITE_STATE, else exit with error + if (IPMI_KCS_GET_STATE (KcsRegisterRead8 (KCS_REG_STATUS)) !=3D IPMI_K= CS_WRITE_STATE) { + FreePool (Buffer); + return EFI_NOT_READY; + } + + // Step 10 + if (EFI_ERROR (ClearOBF ())) { + FreePool (Buffer); + return EFI_NOT_READY; + } + + // + // Step 11, check for DATA completion if more than one byte; + // if still need to be transferred then go to step 7 and repeat + // + } + + // Step 12, WR_END to CMD + KcsRegisterWrite8 (KCS_REG_COMMAND, IPMI_KCS_CONTROL_CODE_WRITE_END); + + // Step 13. wait for IBF to get clear + Status =3D WaitStatusClear (IPMI_KCS_IBF); + if (EFI_ERROR (Status)) { + FreePool (Buffer); + return Status; + } + + // Step 14. check state it should be WRITE_STATE, else exit with error + if (IPMI_KCS_GET_STATE (KcsRegisterRead8 (KCS_REG_STATUS)) !=3D IPMI_KCS= _WRITE_STATE) { + FreePool (Buffer); + return EFI_NOT_READY; + } + + // Step 15 + if (EFI_ERROR (ClearOBF ())) { + FreePool (Buffer); + return EFI_NOT_READY; + } + + // Step 16, write the last byte + KcsRegisterWrite8 (KCS_REG_DATA_OUT, *BufferPtr); + FreePool (Buffer); + return EFI_SUCCESS; +} + +/** + This function sends/receives data from KCS port. + Algorithm is based on flow chart provided in IPMI spec 2.0 + Figure 9-7, KCS Interface BMC to SMS Read Transfer Flow Chart + + @param [in] DataBytes Buffer to hold the read Data. + @param [in, out] Length Number of Bytes read from KCS po= rt. + @retval EFI_SUCCESS The command byte stream was + successfully submit to the devic= e and + a response was successfully rece= ived. + @retval EFI_NOT_FOUND The command was not successfully= sent + to the device or a response was = not + successfully received from the + device. + @retval EFI_NOT_READY Ipmi Device is not ready for Ipm= i + command access. + @retval EFI_DEVICE_ERROR Ipmi Device hardware error. + @retval EFI_TIMEOUT The command time out. + @retval EFI_UNSUPPORTED The command was not successfully= set + to the device. + @retval EFI_OUT_OF_RESOURCES The resource allocation is out o= f + resource or data size error. +**/ +EFI_STATUS +KcsTransportRead ( + OUT UINT8 *DataByte, + IN OUT UINT32 *Length + ) +{ + EFI_STATUS Status; + UINT32 ReadLength; + + if (DataByte =3D=3D NULL || *Length =3D=3D 0) { + DEBUG ((DEBUG_ERROR, "%a: Either DataByte is NULL or Length is 0.\n", = __FUNCTION__)); + return EFI_INVALID_PARAMETER; + } + ReadLength =3D 0; + while (ReadLength < *Length) { + // Step 1. wait for IBF to get clear + Status =3D WaitStatusClear (IPMI_KCS_IBF); + if (EFI_ERROR (Status)) { + *Length =3D ReadLength; + return Status; + } + + // Step 2. check state it should be READ_STATE, else exit with error + if (IPMI_KCS_GET_STATE (KcsRegisterRead8 (KCS_REG_STATUS)) =3D=3D IPMI= _KCS_READ_STATE) { + // Step 2.1.1 check of OBF to get clear + Status =3D WaitStatusSet (IPMI_KCS_OBF); + if (EFI_ERROR (Status)) { + *Length =3D ReadLength; + return Status; + } + + // Step 2.1.2 read data from data out + DataByte[ReadLength++] =3D KcsRegisterRead8 (KCS_REG_DATA_IN); + Status =3D WaitStatusClear (IPMI_KCS_IBF); + if (EFI_ERROR (Status)) { + *Length =3D ReadLength; + return Status; + } + + // Step 2.1.3 Write READ byte to data in register. + KcsRegisterWrite8 (KCS_REG_DATA_OUT, IPMI_KCS_CONTROL_CODE_READ); + } else if (IPMI_KCS_GET_STATE (KcsRegisterRead8 (KCS_REG_STATUS)) =3D= =3D IPMI_KCS_IDLE_STATE) { + // Step 2.2.1 + Status =3D WaitStatusSet (IPMI_KCS_OBF); + if (EFI_ERROR (Status)) { + *Length =3D ReadLength; + return Status; + } + + // Step 2.2.2 read dummy data + KcsRegisterRead8 (KCS_REG_DATA_IN); // Dummy read as per IPMI spec + *Length =3D ReadLength; + return EFI_SUCCESS; + } else { + *Length =3D ReadLength; + return EFI_DEVICE_ERROR; + } + } + + *Length =3D ReadLength; + return EFI_SUCCESS; +} + +/** + This service communicates with BMC using KCS protocol. + + @param[in] NetFunction Net function of the command. + @param[in] Command IPMI Command. + @param[in] RequestData Command Request Data. + @param[in] RequestDataSize Size of Command Request Data. + @param[out] ResponseData Command Response Data. The complet= ion + code is the first byte of response + data. + @param[in, out] ResponseDataSize Size of Command Response Data. + When IN, it is the expected data s= ize + of response data. + When OUT, it is the data size of r= esponse + exactly returned. + @retval EFI_SUCCESS The command byte stream was + successfully submit to the device = and a + response was successfully received= . + @retval EFI_NOT_FOUND The command was not successfully s= ent + to the device or a response was no= t + successfully received from the dev= ice. + @retval EFI_NOT_READY Ipmi Device is not ready for Ipmi + command access. + @retval EFI_DEVICE_ERROR Ipmi Device hardware error. + @retval EFI_TIMEOUT The command time out. + @retval EFI_UNSUPPORTED The command was not successfully s= ent to + the device. + @retval EFI_OUT_OF_RESOURCES The resource allocation is out of + resource or data size error. +**/ +EFI_STATUS +EFIAPI +KcsTransportSendCommand ( + IN UINT8 NetFunction, + IN UINT8 Command, + IN UINT8 *RequestData OPTIONAL, + IN UINT32 RequestDataSize, + OUT UINT8 *ResponseData OPTIONAL, + IN OUT UINT32 *ResponseDataSize OPTIONAL + ) +{ + EFI_STATUS Status; + UINT32 RspHeaderSize; + IPMI_KCS_RESPONSE_HEADER RspHeader; + + if ((RequestData !=3D NULL) && (RequestDataSize =3D=3D 0)) { + DEBUG((DEBUG_ERROR, "%a: Mismatched values of RequestData and RequestD= ataSize\n", __FUNCTION__)); + return EFI_INVALID_PARAMETER; + } + + if ((ResponseData !=3D NULL) && ((ResponseDataSize !=3D NULL) && (*Respo= nseDataSize =3D=3D 0))) { + DEBUG((DEBUG_ERROR, "%a: Mismatched values of ResponseData and Respons= eDataSize\n", __FUNCTION__)); + return EFI_INVALID_PARAMETER; + } + + Status =3D KcsTransportWrite ( + (NetFunction << 2), + Command, + RequestData, + RequestDataSize + ); + if (EFI_ERROR (Status)) { + DEBUG (( + DEBUG_ERROR, + "IPMI KCS Write Failed with Status(%r) for NetFunction(0x%x)," \ + " Command(0x%x).\n", + Status, + NetFunction, + Command + )); + return Status; + } + + // + // Read the response header + RspHeaderSize =3D sizeof (IPMI_KCS_RESPONSE_HEADER); + Status =3D KcsTransportRead ((UINT8 *)&RspHeader, &RspHeaderSize)= ; + if (EFI_ERROR (Status)) { + DEBUG (( + DEBUG_ERROR, + "IPMI KCS read response header failed Status(%r), " \ + "RspNetFunctionLun =3D 0x%x, " \ + "Comamnd =3D 0x%x \n", + Status, + RspHeader.NetFunc, + RspHeader.Command + )); + return (Status); + } + + Status =3D KcsTransportRead ((UINT8 *)ResponseData, ResponseDataSize); + if (EFI_ERROR (Status)) { + DEBUG (( + DEBUG_ERROR, + "IPMI KCS response read Failed with Status(%r) for NetFunction(0x%x)= ," \ + " Command(0x%x).\n", + Status, + NetFunction, + Command + )); + } + + return Status; +} + +/** + This function reads 8-bit value from register address. + + @param[in] Address This represents either 16-bit IO a= ddress + or 32-bit memory mapped address. + + @retval UINT8 8-bit value. +**/ +UINT8 +KcsRegisterRead8 ( + MANAGEABILITY_TRANSPORT_HARDWARE_IO Address + ) +{ + UINT8 Value; + + if (mKcsHardwareInfo.MemoryMap =3D=3D MANAGEABILITY_TRANSPORT_KCS_MEMORY= _MAP_IO) { + // Read 8-bit value from 32-bit Memory mapped address. + Value =3D MmioRead8 ((UINTN)Address.IoAddress32); + } else { + // Read 8-bit value from 16-bit I/O address + Value =3D IoRead8 ((UINTN)Address.IoAddress16); + } + + return Value; +} + +/** + This function writes 8-bit value to register address. + + @param[in] Address This represents either 16-bit IO a= ddress + or 32-bit memory mapped address. + @param[in] Value 8-bit value write to register addr= ess + +**/ +VOID +KcsRegisterWrite8 ( + MANAGEABILITY_TRANSPORT_HARDWARE_IO Address, + UINT8 Value + ) +{ + if (mKcsHardwareInfo.MemoryMap =3D=3D MANAGEABILITY_TRANSPORT_KCS_MEMORY= _MAP_IO) { + // Write 8-bit value to 32-bit Memory mapped address. + MmioWrite8 ((UINTN)Address.IoAddress32, Value); + } else { + // Write 8-bit value to 16-bit I/O address + IoWrite8 ((UINTN)Address.IoAddress16, Value); + } +} diff --git a/Features/ManageabilityPkg/Library/ManageabilityTransportKcsLib= /Dxe/ManageabilityTransportKcs.c b/Features/ManageabilityPkg/Library/Manage= abilityTransportKcsLib/Dxe/ManageabilityTransportKcs.c new file mode 100644 index 0000000000..8101e63c22 --- /dev/null +++ b/Features/ManageabilityPkg/Library/ManageabilityTransportKcsLib/Dxe/Ma= nageabilityTransportKcs.c @@ -0,0 +1,389 @@ +/** @file + + KCS instance of Manageability Transport Library + + Copyright (C) 2023 Advanced Micro Devices, Inc. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent + +*/ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "ManageabilityTransportKcs.h" + +MANAGEABILITY_TRANSPORT_KCS *mSingleSessionToken =3D NULL; + +EFI_GUID *SupportedManageabilityProtocol[] =3D { + &gManageabilityProtocolIpmiGuid, + &gManageabilityProtocolMctpGuid +}; + +UINT8 NumberOfSupportedProtocol =3D (sizeof (SupportedManageabilityProtoc= ol)/sizeof (EFI_GUID *)); + +MANAGEABILITY_TRANSPORT_KCS_HARDWARE_INFO mKcsHardwareInfo; + +/** + This function initializes the transport interface. + + @param [in] TransportToken The transport token acquired throu= gh + AcquireTransportSession function. + @param [in] HardwareInfo The hardware information + assigned to KCS transport interfac= e. + + @retval EFI_SUCCESS Transport interface is initialized + successfully. + @retval EFI_INVALID_PARAMETER The invalid transport token. + @retval EFI_NOT_READY The transport interface works fine= but + @retval is not ready. + @retval EFI_DEVICE_ERROR The transport interface has proble= ms. + @retval EFI_ALREADY_STARTED Teh protocol interface has already= initialized. + @retval Otherwise Other errors. + +**/ +EFI_STATUS +EFIAPI +KcsTransportInit ( + IN MANAGEABILITY_TRANSPORT_TOKEN *TransportToken, + IN MANAGEABILITY_TRANSPORT_HARDWARE_INFORMATION HardwareInfo OPTIONAL + ) +{ + CHAR16 *ManageabilityProtocolName; + + if (TransportToken =3D=3D NULL) { + DEBUG ((DEBUG_ERROR, "%a: Invalid transport token.\n", __FUNCTION__)); + return EFI_INVALID_PARAMETER; + } + + if (HardwareInfo.Kcs =3D=3D NULL) { + DEBUG ((DEBUG_INFO, "%a: Hardware information is not provided, use dfa= ult settings.\n", __FUNCTION__)); + mKcsHardwareInfo.MemoryMap =3D MANAGEABILITY_TRANSP= ORT_KCS_IO_MAP_IO; + mKcsHardwareInfo.IoBaseAddress.IoAddress16 =3D PcdGet16 (PcdIpmiKcs= BaseAddress); + mKcsHardwareInfo.IoDataInAddress.IoAddress16 =3D mKcsHardwareInfo.IoB= aseAddress.IoAddress16 + IPMI_KCS_DATA_IN_REGISTER_OFFSET; + mKcsHardwareInfo.IoDataOutAddress.IoAddress16 =3D mKcsHardwareInfo.IoB= aseAddress.IoAddress16 + IPMI_KCS_DATA_OUT_REGISTER_OFFSET; + mKcsHardwareInfo.IoCommandAddress.IoAddress16 =3D mKcsHardwareInfo.IoB= aseAddress.IoAddress16 + IPMI_KCS_COMMAND_REGISTER_OFFSET; + mKcsHardwareInfo.IoStatusAddress.IoAddress16 =3D mKcsHardwareInfo.IoB= aseAddress.IoAddress16 + IPMI_KCS_STATUS_REGISTER_OFFSET; + } else { + mKcsHardwareInfo.MemoryMap =3D ((MANAGEABILITY_TRANSPORT_KCS_HA= RDWARE_INFO *)HardwareInfo.Kcs)->MemoryMap; + mKcsHardwareInfo.IoBaseAddress =3D ((MANAGEABILITY_TRANSPORT_KCS_HA= RDWARE_INFO *)HardwareInfo.Kcs)->IoBaseAddress; + mKcsHardwareInfo.IoDataInAddress =3D ((MANAGEABILITY_TRANSPORT_KCS_HA= RDWARE_INFO *)HardwareInfo.Kcs)->IoDataInAddress; + mKcsHardwareInfo.IoDataOutAddress =3D ((MANAGEABILITY_TRANSPORT_KCS_HA= RDWARE_INFO *)HardwareInfo.Kcs)->IoDataOutAddress; + mKcsHardwareInfo.IoCommandAddress =3D ((MANAGEABILITY_TRANSPORT_KCS_HA= RDWARE_INFO *)HardwareInfo.Kcs)->IoCommandAddress; + mKcsHardwareInfo.IoStatusAddress =3D ((MANAGEABILITY_TRANSPORT_KCS_HA= RDWARE_INFO *)HardwareInfo.Kcs)->IoStatusAddress; + } + + // Get protocol specification name. + ManageabilityProtocolName =3D HelperManageabilitySpecName (TransportToke= n->ManageabilityProtocolSpecification); + + DEBUG ((DEBUG_INFO, "%a: KCS transport hardware for %s is:\n", __FUNCTIO= N__, ManageabilityProtocolName)); + if (mKcsHardwareInfo.MemoryMap) { + DEBUG ((DEBUG_INFO, "Memory Map I/O\n", __FUNCTION__)); + DEBUG ((DEBUG_INFO, "Base Memory Address : 0x%08x\n", mKcsHardwareInfo= .IoBaseAddress.IoAddress32)); + DEBUG ((DEBUG_INFO, "Data in Address : 0x%08x\n", mKcsHardwareInfo= .IoDataInAddress.IoAddress32)); + DEBUG ((DEBUG_INFO, "Data out Address : 0x%08x\n", mKcsHardwareInfo= .IoDataOutAddress.IoAddress32)); + DEBUG ((DEBUG_INFO, "Command Address : 0x%08x\n", mKcsHardwareInfo= .IoCommandAddress.IoAddress32)); + DEBUG ((DEBUG_INFO, "Status Address : 0x%08x\n", mKcsHardwareInfo= .IoStatusAddress.IoAddress32)); + } else { + DEBUG ((DEBUG_INFO, "I/O Map I/O\n")); + DEBUG ((DEBUG_INFO, "Base I/O port : 0x%04x\n", mKcsHardwareInfo.Io= BaseAddress.IoAddress16)); + DEBUG ((DEBUG_INFO, "Data in I/O port : 0x%04x\n", mKcsHardwareInfo.Io= DataInAddress.IoAddress16)); + DEBUG ((DEBUG_INFO, "Data out I/O port: 0x%04x\n", mKcsHardwareInfo.Io= DataOutAddress.IoAddress16)); + DEBUG ((DEBUG_INFO, "Command I/O port : 0x%04x\n", mKcsHardwareInfo.Io= CommandAddress.IoAddress16)); + DEBUG ((DEBUG_INFO, "Status I/O port : 0x%04x\n", mKcsHardwareInfo.Io= StatusAddress.IoAddress16)); + } + + return EFI_SUCCESS; +} + +/** + This function returns the transport interface status. + The generic EFI_STATUS is returned to caller directly, The additional + information of transport interface could be optionally returned in + TransportAdditionalStatus to describes the status that can't be + described obviously through EFI_STATUS. + See the definition of MANAGEABILITY_TRANSPORT_STATUS. + + @param [in] TransportToken The transport token acquired th= rough + AcquireTransportSession functio= n. + @param [out] TransportAdditionalStatus The additional status of transp= ort + interface. + NULL means no additional status= of this + transport interface. + + @retval EFI_SUCCESS Transport interface status is retu= rned. + @retval EFI_INVALID_PARAMETER The invalid transport token. + @retval EFI_DEVICE_ERROR The transport interface has proble= ms to return + @retval EFI_UNSUPPORTED The transport interface doesn't ha= ve status report. + Otherwise Other errors. + +**/ +EFI_STATUS +EFIAPI +KcsTransportStatus ( + IN MANAGEABILITY_TRANSPORT_TOKEN *TransportToken, + OUT MANAGEABILITY_TRANSPORT_ADDITIONAL_STATUS *TransportAdditionalStatu= s OPTIONAL + ) +{ + UINT8 TransportStatus; + + if (TransportToken =3D=3D NULL) { + DEBUG ((DEBUG_ERROR, "%a: Invalid transport token.\n", __FUNCTION__)); + return EFI_INVALID_PARAMETER; + } + + if (TransportAdditionalStatus =3D=3D NULL) { + return EFI_SUCCESS; + } + + TransportStatus =3D IPMI_KCS_GET_STATE (KcsRegisterRead8 (KCS= _REG_STATUS)); + *TransportAdditionalStatus =3D MANAGEABILITY_TRANSPORT_ADDITIONAL_STATUS= _NO_ERRORS; + if (TransportStatus !=3D IPMI_KCS_IDLE_STATE) { + if (TransportStatus =3D=3D IPMI_KCS_READ_STATE) { + // + // Transport is in read state. + *TransportAdditionalStatus |=3D MANAGEABILITY_TRANSPORT_ADDITIONAL_S= TATUS_BUSY_IN_READ; + return EFI_NOT_READY; + } else if (TransportStatus =3D=3D IPMI_KCS_WRITE_STATE) { + // + // Transport is in read state. + *TransportAdditionalStatus |=3D MANAGEABILITY_TRANSPORT_ADDITIONAL_S= TATUS_BUSY_IN_WRITE; + return EFI_NOT_READY; + } else { + return EFI_DEVICE_ERROR; + } + } + + return EFI_SUCCESS; +} + +/** + This function resets the transport interface. + The generic EFI_STATUS is returned to caller directly after reseting tra= nsport + interface. The additional information of transport interface could be op= tionally + returned in TransportAdditionalStatus to describes the status that can't= be + described obviously through EFI_STATUS. + See the definition of MANAGEABILITY_TRANSPORT_ADDITIONAL_STATUS. + + @param [in] TransportToken The transport token acquired th= rough + AcquireTransportSession functio= n. + @param [out] TransportAdditionalStatus The additional status of specif= ic transport + interface after the reset. + NULL means no additional status= of this + transport interface. + + @retval EFI_SUCCESS Transport interface status is retu= rned. + @retval EFI_INVALID_PARAMETER The invalid transport token. + @retval EFI_TIMEOUT The reset process is time out. + @retval EFI_DEVICE_ERROR The transport interface has proble= ms to return + status. + Otherwise Other errors. + +**/ +EFI_STATUS +EFIAPI +KcsTransportReset ( + IN MANAGEABILITY_TRANSPORT_TOKEN *TransportToken, + OUT MANAGEABILITY_TRANSPORT_ADDITIONAL_STATUS *TransportAdditionalStatu= s OPTIONAL + ) +{ + return EFI_UNSUPPORTED; +} + +/** + This function transmit the request over target transport interface. + The generic EFI_STATUS is returned to caller directly after reseting tra= nsport + interface. The additional information of transport interface could be op= tionally + returned in TransportAdditionalStatus to describes the status that can't= be + described obviously through EFI_STATUS. + See the definition of MANAGEABILITY_TRANSPORT_ADDITIONAL_STATUS. + + @param [in] TransportToken The transport token acquired throu= gh + AcquireTransportSession function. + @param [in] TransferToken The transfer token, see the defini= tion of + MANAGEABILITY_TRANSFER_TOKEN. + + @retval The EFI status is returned in MANAGEABILITY_TRANSFER_TOKEN. + +**/ +VOID +EFIAPI +KcsTransportTransmitReceive ( + IN MANAGEABILITY_TRANSPORT_TOKEN *TransportToken, + IN MANAGEABILITY_TRANSFER_TOKEN *TransferToken + ) +{ + EFI_STATUS Status; + MANAGEABILITY_IPMI_TRANSPORT_HEADER *TransmitHeader; + + if (TransportToken =3D=3D NULL || TransferToken =3D=3D NULL) { + DEBUG ((DEBUG_ERROR, "%a: Invalid transport token or transfer token.\n= ", __FUNCTION__)); + return; + } + + TransmitHeader =3D (MANAGEABILITY_IPMI_TRANSPORT_HEADER *)TransferToken-= >TransmitHeader; + if (TransmitHeader =3D=3D NULL) { + TransferToken->TransferStatus =3D EFI_INVALID_PARAMETER; + return; + } + + Status =3D KcsTransportSendCommand ( + TransmitHeader->NetFn, + TransmitHeader->Command, + TransferToken->TransmitPackage.TransmitPayload, + TransferToken->TransmitPackage.TransmitSizeInByte, + TransferToken->ReceivePackage.ReceiveBuffer, + &TransferToken->ReceivePackage.ReceiveSizeInByte + ); + + TransferToken->TransferStatus =3D Status; + KcsTransportStatus (TransportToken, &TransferToken->TransportAdditionalS= tatus); +} + +/** + This function acquires to create a transport session to transmit managea= bility + packet. A transport token is returned to caller for the follow up operat= ions. + + @param [in] ManageabilityProtocolSpec The protocol spec the transport= interface is acquired. + @param [out] TransportToken The pointer to receive the tran= sport token created by + the target transport interface = library. + @retval EFI_SUCCESS Token is created successfully. + @retval EFI_OUT_OF_RESOURCES Out of resource to create a new= transport session. + @retval EFI_UNSUPPORTED Protocol is not supported on th= is transport interface. + @retval Otherwise Other errors. + +**/ +EFI_STATUS +AcquireTransportSession ( + IN EFI_GUID *ManageabilityProtocolSpec, + OUT MANAGEABILITY_TRANSPORT_TOKEN **TransportToken + ) +{ + EFI_STATUS Status; + MANAGEABILITY_TRANSPORT_KCS *KcsTransportToken; + + if (ManageabilityProtocolSpec =3D=3D NULL) { + DEBUG ((DEBUG_ERROR, "%a: No Manageability protocol specification spec= ified.\n", __FUNCTION__)); + return EFI_INVALID_PARAMETER; + } + + if (TransportToken =3D=3D NULL) { + DEBUG ((DEBUG_ERROR, "%a: TransportToken is NULL.\n", __FUNCTION__)); + return EFI_INVALID_PARAMETER; + } + + Status =3D HelperManageabilityCheckSupportedSpec ( + &gManageabilityTransportKcsGuid, + SupportedManageabilityProtocol, + NumberOfSupportedProtocol, + ManageabilityProtocolSpec + ); + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_ERROR, "%a: Protocol is not supported on this transport = interface.\n", __FUNCTION__)); + return EFI_UNSUPPORTED; + } + + if (mSingleSessionToken !=3D NULL) { + DEBUG ((DEBUG_ERROR, "%a: This manageability transport library only su= pports one session transport token.\n", __FUNCTION__)); + return EFI_OUT_OF_RESOURCES; + } + + KcsTransportToken =3D AllocateZeroPool (sizeof (MANAGEABILITY_TRANSPORT_= KCS)); + if (KcsTransportToken =3D=3D NULL) { + DEBUG ((DEBUG_ERROR, "%a: Fail to allocate memory for MANAGEABILITY_TR= ANSPORT_KCS\n", __FUNCTION__)); + return EFI_OUT_OF_RESOURCES; + } + KcsTransportToken->Token.Transport =3D AllocateZeroPool (sizeof (MANAGEA= BILITY_TRANSPORT)); + if (KcsTransportToken->Token.Transport =3D=3D NULL) { + FreePool (KcsTransportToken); + DEBUG ((DEBUG_ERROR, "%a: Fail to allocate memory for MANAGEABILITY_TR= ANSPORT\n", __FUNCTION__)); + return EFI_OUT_OF_RESOURCES; + } + + KcsTransportToken->Signature = =3D MANAGEABILITY_TRANSPORT_KCS_SIGNATURE; + KcsTransportToken->Token.ManageabilityProtocolSpecification = =3D ManageabilityProtocolSpec; + KcsTransportToken->Token.Transport->TransportVersion = =3D MANAGEABILITY_TRANSPORT_TOKEN_VERSION; + KcsTransportToken->Token.Transport->ManageabilityTransportSpecification = =3D &gManageabilityTransportKcsGuid; + KcsTransportToken->Token.Transport->TransportName = =3D L"KCS"; + KcsTransportToken->Token.Transport->Function.Version1_0 = =3D AllocateZeroPool (sizeof (MANAGEABILITY_TRANSPORT_FUNCTION_V1_0)); + if (KcsTransportToken->Token.Transport->Function.Version1_0 =3D=3D NULL)= { + DEBUG ((DEBUG_ERROR, "%a: Fail to allocate memory for MANAGEABILITY_TR= ANSPORT_FUNCTION_V1_0\n", __FUNCTION__)); + FreePool (KcsTransportToken); + FreePool (KcsTransportToken->Token.Transport); + return EFI_OUT_OF_RESOURCES; + } + + KcsTransportToken->Token.Transport->Function.Version1_0->TransportInit = =3D KcsTransportInit; + KcsTransportToken->Token.Transport->Function.Version1_0->TransportReset = =3D KcsTransportReset; + KcsTransportToken->Token.Transport->Function.Version1_0->TransportStatus= =3D KcsTransportStatus; + KcsTransportToken->Token.Transport->Function.Version1_0->TransportTransm= itReceive =3D KcsTransportTransmitReceive; + + mSingleSessionToken =3D KcsTransportToken; + *TransportToken =3D &KcsTransportToken->Token; + return EFI_SUCCESS; +} + +/** + This function returns the transport capabilities. + + @param [out] TransportFeature Pointer to receive transport capab= ilities. + See the definitions of + MANAGEABILITY_TRANSPORT_CAPABILITY= . + +**/ +VOID +GetTransportCapability ( + OUT MANAGEABILITY_TRANSPORT_CAPABILITY *TransportCapability + ) +{ + if (TransportCapability !=3D NULL) { + *TransportCapability =3D 0; + } +} + +/** + This function releases the manageability session. + + @param [in] TransportToken The transport token acquired through + AcquireTransportSession. + @retval EFI_SUCCESS Token is released successfully. + @retval EFI_INVALID_PARAMETER Invalid TransportToken. + @retval Otherwise Other errors. + +**/ +EFI_STATUS +ReleaseTransportSession ( + IN MANAGEABILITY_TRANSPORT_TOKEN *TransportToken + ) +{ + EFI_STATUS Status; + MANAGEABILITY_TRANSPORT_KCS *KcsTransportToken; + + if (TransportToken =3D=3D NULL) { + Status =3D EFI_INVALID_PARAMETER; + } + + KcsTransportToken =3D MANAGEABILITY_TRANSPORT_KCS_FROM_LINK (TransportTo= ken); + if (mSingleSessionToken !=3D KcsTransportToken) { + Status =3D EFI_INVALID_PARAMETER; + } + + if (KcsTransportToken !=3D NULL) { + FreePool (KcsTransportToken->Token.Transport->Function.Version1_0); + FreePool (KcsTransportToken->Token.Transport); + FreePool (KcsTransportToken); + mSingleSessionToken =3D NULL; + Status =3D EFI_SUCCESS; + } + + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_ERROR, "%a: Fail to release KCS transport token (%r).\n"= , __FUNCTION__, Status)); + } + + return Status; +} diff --git a/Features/ManageabilityPkg/Library/ManageabilityTransportKcsLib= /Dxe/ManageabilityTransportKcs.uni b/Features/ManageabilityPkg/Library/Mana= geabilityTransportKcsLib/Dxe/ManageabilityTransportKcs.uni new file mode 100644 index 0000000000..61a3e8b588 --- /dev/null +++ b/Features/ManageabilityPkg/Library/ManageabilityTransportKcsLib/Dxe/Ma= nageabilityTransportKcs.uni @@ -0,0 +1,13 @@ +// /** @file +// KCS instance of Manageability Transport Library +// +// Copyright (C) 2023 Advanced Micro Devices, Inc. All rights reserved. +// +// SPDX-License-Identifier: BSD-2-Clause-Patent +// +// **/ + +#string STR_MODULE_ABSTRACT #language en-US "KCS instance of M= anageability Transport Library" + +#string STR_MODULE_DESCRIPTION #language en-US "KCS Manageability= Transport library implementation." + --=20 2.37.1.windows.1