|
@@ -0,0 +1,389 @@
|
|
|
+/** @file
|
|
|
+
|
|
|
+ KCS instance of Manageability Transport Library
|
|
|
+
|
|
|
+ Copyright (C) 2023 Advanced Micro Devices, Inc. All rights reserved.<BR>
|
|
|
+ SPDX-License-Identifier: BSD-2-Clause-Patent
|
|
|
+
|
|
|
+*/
|
|
|
+
|
|
|
+#include <Uefi.h>
|
|
|
+#include <IndustryStandard/IpmiKcs.h>
|
|
|
+#include <Library/IoLib.h>
|
|
|
+#include <Library/DebugLib.h>
|
|
|
+#include <Library/MemoryAllocationLib.h>
|
|
|
+#include <Library/ManageabilityTransportLib.h>
|
|
|
+#include <Library/ManageabilityTransportIpmiLib.h>
|
|
|
+#include <Library/ManageabilityTransportHelperLib.h>
|
|
|
+
|
|
|
+#include "ManageabilityTransportKcs.h"
|
|
|
+
|
|
|
+MANAGEABILITY_TRANSPORT_KCS *mSingleSessionToken = NULL;
|
|
|
+
|
|
|
+EFI_GUID *SupportedManageabilityProtocol[] = {
|
|
|
+ &gManageabilityProtocolIpmiGuid,
|
|
|
+ &gManageabilityProtocolMctpGuid
|
|
|
+};
|
|
|
+
|
|
|
+UINT8 NumberOfSupportedProtocol = (sizeof (SupportedManageabilityProtocol)/sizeof (EFI_GUID *));
|
|
|
+
|
|
|
+MANAGEABILITY_TRANSPORT_KCS_HARDWARE_INFO mKcsHardwareInfo;
|
|
|
+
|
|
|
+/**
|
|
|
+ This function initializes the transport interface.
|
|
|
+
|
|
|
+ @param [in] TransportToken The transport token acquired through
|
|
|
+ AcquireTransportSession function.
|
|
|
+ @param [in] HardwareInfo The hardware information
|
|
|
+ assigned to KCS transport interface.
|
|
|
+
|
|
|
+ @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 problems.
|
|
|
+ @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 == NULL) {
|
|
|
+ DEBUG ((DEBUG_ERROR, "%a: Invalid transport token.\n", __FUNCTION__));
|
|
|
+ return EFI_INVALID_PARAMETER;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (HardwareInfo.Kcs == NULL) {
|
|
|
+ DEBUG ((DEBUG_INFO, "%a: Hardware information is not provided, use dfault settings.\n", __FUNCTION__));
|
|
|
+ mKcsHardwareInfo.MemoryMap = MANAGEABILITY_TRANSPORT_KCS_IO_MAP_IO;
|
|
|
+ mKcsHardwareInfo.IoBaseAddress.IoAddress16 = PcdGet16 (PcdIpmiKcsIoBaseAddress);
|
|
|
+ mKcsHardwareInfo.IoDataInAddress.IoAddress16 = mKcsHardwareInfo.IoBaseAddress.IoAddress16 + IPMI_KCS_DATA_IN_REGISTER_OFFSET;
|
|
|
+ mKcsHardwareInfo.IoDataOutAddress.IoAddress16 = mKcsHardwareInfo.IoBaseAddress.IoAddress16 + IPMI_KCS_DATA_OUT_REGISTER_OFFSET;
|
|
|
+ mKcsHardwareInfo.IoCommandAddress.IoAddress16 = mKcsHardwareInfo.IoBaseAddress.IoAddress16 + IPMI_KCS_COMMAND_REGISTER_OFFSET;
|
|
|
+ mKcsHardwareInfo.IoStatusAddress.IoAddress16 = mKcsHardwareInfo.IoBaseAddress.IoAddress16 + IPMI_KCS_STATUS_REGISTER_OFFSET;
|
|
|
+ } else {
|
|
|
+ mKcsHardwareInfo.MemoryMap = ((MANAGEABILITY_TRANSPORT_KCS_HARDWARE_INFO *)HardwareInfo.Kcs)->MemoryMap;
|
|
|
+ mKcsHardwareInfo.IoBaseAddress = ((MANAGEABILITY_TRANSPORT_KCS_HARDWARE_INFO *)HardwareInfo.Kcs)->IoBaseAddress;
|
|
|
+ mKcsHardwareInfo.IoDataInAddress = ((MANAGEABILITY_TRANSPORT_KCS_HARDWARE_INFO *)HardwareInfo.Kcs)->IoDataInAddress;
|
|
|
+ mKcsHardwareInfo.IoDataOutAddress = ((MANAGEABILITY_TRANSPORT_KCS_HARDWARE_INFO *)HardwareInfo.Kcs)->IoDataOutAddress;
|
|
|
+ mKcsHardwareInfo.IoCommandAddress = ((MANAGEABILITY_TRANSPORT_KCS_HARDWARE_INFO *)HardwareInfo.Kcs)->IoCommandAddress;
|
|
|
+ mKcsHardwareInfo.IoStatusAddress = ((MANAGEABILITY_TRANSPORT_KCS_HARDWARE_INFO *)HardwareInfo.Kcs)->IoStatusAddress;
|
|
|
+ }
|
|
|
+
|
|
|
+ // Get protocol specification name.
|
|
|
+ ManageabilityProtocolName = HelperManageabilitySpecName (TransportToken->ManageabilityProtocolSpecification);
|
|
|
+
|
|
|
+ DEBUG ((DEBUG_INFO, "%a: KCS transport hardware for %s is:\n", __FUNCTION__, 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.IoBaseAddress.IoAddress16));
|
|
|
+ DEBUG ((DEBUG_INFO, "Data in I/O port : 0x%04x\n", mKcsHardwareInfo.IoDataInAddress.IoAddress16));
|
|
|
+ DEBUG ((DEBUG_INFO, "Data out I/O port: 0x%04x\n", mKcsHardwareInfo.IoDataOutAddress.IoAddress16));
|
|
|
+ DEBUG ((DEBUG_INFO, "Command I/O port : 0x%04x\n", mKcsHardwareInfo.IoCommandAddress.IoAddress16));
|
|
|
+ DEBUG ((DEBUG_INFO, "Status I/O port : 0x%04x\n", mKcsHardwareInfo.IoStatusAddress.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 through
|
|
|
+ AcquireTransportSession function.
|
|
|
+ @param [out] TransportAdditionalStatus The additional status of transport
|
|
|
+ interface.
|
|
|
+ NULL means no additional status of this
|
|
|
+ transport interface.
|
|
|
+
|
|
|
+ @retval EFI_SUCCESS Transport interface status is returned.
|
|
|
+ @retval EFI_INVALID_PARAMETER The invalid transport token.
|
|
|
+ @retval EFI_DEVICE_ERROR The transport interface has problems to return
|
|
|
+ @retval EFI_UNSUPPORTED The transport interface doesn't have status report.
|
|
|
+ Otherwise Other errors.
|
|
|
+
|
|
|
+**/
|
|
|
+EFI_STATUS
|
|
|
+EFIAPI
|
|
|
+KcsTransportStatus (
|
|
|
+ IN MANAGEABILITY_TRANSPORT_TOKEN *TransportToken,
|
|
|
+ OUT MANAGEABILITY_TRANSPORT_ADDITIONAL_STATUS *TransportAdditionalStatus OPTIONAL
|
|
|
+ )
|
|
|
+{
|
|
|
+ UINT8 TransportStatus;
|
|
|
+
|
|
|
+ if (TransportToken == NULL) {
|
|
|
+ DEBUG ((DEBUG_ERROR, "%a: Invalid transport token.\n", __FUNCTION__));
|
|
|
+ return EFI_INVALID_PARAMETER;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (TransportAdditionalStatus == NULL) {
|
|
|
+ return EFI_SUCCESS;
|
|
|
+ }
|
|
|
+
|
|
|
+ TransportStatus = IPMI_KCS_GET_STATE (KcsRegisterRead8 (KCS_REG_STATUS));
|
|
|
+ *TransportAdditionalStatus = MANAGEABILITY_TRANSPORT_ADDITIONAL_STATUS_NO_ERRORS;
|
|
|
+ if (TransportStatus != IpmiKcsIdleState) {
|
|
|
+ if (TransportStatus == IpmiKcsReadState) {
|
|
|
+ //
|
|
|
+ // Transport is in read state.
|
|
|
+ *TransportAdditionalStatus |= MANAGEABILITY_TRANSPORT_ADDITIONAL_STATUS_BUSY_IN_READ;
|
|
|
+ return EFI_NOT_READY;
|
|
|
+ } else if (TransportStatus == IpmiKcsWriteState) {
|
|
|
+ //
|
|
|
+ // Transport is in read state.
|
|
|
+ *TransportAdditionalStatus |= MANAGEABILITY_TRANSPORT_ADDITIONAL_STATUS_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 transport
|
|
|
+ interface. 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_ADDITIONAL_STATUS.
|
|
|
+
|
|
|
+ @param [in] TransportToken The transport token acquired through
|
|
|
+ AcquireTransportSession function.
|
|
|
+ @param [out] TransportAdditionalStatus The additional status of specific transport
|
|
|
+ interface after the reset.
|
|
|
+ NULL means no additional status of this
|
|
|
+ transport interface.
|
|
|
+
|
|
|
+ @retval EFI_SUCCESS Transport interface status is returned.
|
|
|
+ @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 problems to return
|
|
|
+ status.
|
|
|
+ Otherwise Other errors.
|
|
|
+
|
|
|
+**/
|
|
|
+EFI_STATUS
|
|
|
+EFIAPI
|
|
|
+KcsTransportReset (
|
|
|
+ IN MANAGEABILITY_TRANSPORT_TOKEN *TransportToken,
|
|
|
+ OUT MANAGEABILITY_TRANSPORT_ADDITIONAL_STATUS *TransportAdditionalStatus OPTIONAL
|
|
|
+ )
|
|
|
+{
|
|
|
+ return EFI_UNSUPPORTED;
|
|
|
+}
|
|
|
+
|
|
|
+/**
|
|
|
+ This function transmit the request over target transport interface.
|
|
|
+ The generic EFI_STATUS is returned to caller directly after reseting transport
|
|
|
+ interface. 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_ADDITIONAL_STATUS.
|
|
|
+
|
|
|
+ @param [in] TransportToken The transport token acquired through
|
|
|
+ AcquireTransportSession function.
|
|
|
+ @param [in] TransferToken The transfer token, see the definition 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 == NULL || TransferToken == NULL) {
|
|
|
+ DEBUG ((DEBUG_ERROR, "%a: Invalid transport token or transfer token.\n", __FUNCTION__));
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ TransmitHeader = (MANAGEABILITY_IPMI_TRANSPORT_HEADER *)TransferToken->TransmitHeader;
|
|
|
+ if (TransmitHeader == NULL) {
|
|
|
+ TransferToken->TransferStatus = EFI_INVALID_PARAMETER;
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ Status = KcsTransportSendCommand (
|
|
|
+ TransmitHeader->NetFn,
|
|
|
+ TransmitHeader->Command,
|
|
|
+ TransferToken->TransmitPackage.TransmitPayload,
|
|
|
+ TransferToken->TransmitPackage.TransmitSizeInByte,
|
|
|
+ TransferToken->ReceivePackage.ReceiveBuffer,
|
|
|
+ &TransferToken->ReceivePackage.ReceiveSizeInByte
|
|
|
+ );
|
|
|
+
|
|
|
+ TransferToken->TransferStatus = Status;
|
|
|
+ KcsTransportStatus (TransportToken, &TransferToken->TransportAdditionalStatus);
|
|
|
+}
|
|
|
+
|
|
|
+/**
|
|
|
+ This function acquires to create a transport session to transmit manageability
|
|
|
+ packet. A transport token is returned to caller for the follow up operations.
|
|
|
+
|
|
|
+ @param [in] ManageabilityProtocolSpec The protocol spec the transport interface is acquired.
|
|
|
+ @param [out] TransportToken The pointer to receive the transport 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 this 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 == NULL) {
|
|
|
+ DEBUG ((DEBUG_ERROR, "%a: No Manageability protocol specification specified.\n", __FUNCTION__));
|
|
|
+ return EFI_INVALID_PARAMETER;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (TransportToken == NULL) {
|
|
|
+ DEBUG ((DEBUG_ERROR, "%a: TransportToken is NULL.\n", __FUNCTION__));
|
|
|
+ return EFI_INVALID_PARAMETER;
|
|
|
+ }
|
|
|
+
|
|
|
+ Status = 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 != NULL) {
|
|
|
+ DEBUG ((DEBUG_ERROR, "%a: This manageability transport library only supports one session transport token.\n", __FUNCTION__));
|
|
|
+ return EFI_OUT_OF_RESOURCES;
|
|
|
+ }
|
|
|
+
|
|
|
+ KcsTransportToken = AllocateZeroPool (sizeof (MANAGEABILITY_TRANSPORT_KCS));
|
|
|
+ if (KcsTransportToken == NULL) {
|
|
|
+ DEBUG ((DEBUG_ERROR, "%a: Fail to allocate memory for MANAGEABILITY_TRANSPORT_KCS\n", __FUNCTION__));
|
|
|
+ return EFI_OUT_OF_RESOURCES;
|
|
|
+ }
|
|
|
+ KcsTransportToken->Token.Transport = AllocateZeroPool (sizeof (MANAGEABILITY_TRANSPORT));
|
|
|
+ if (KcsTransportToken->Token.Transport == NULL) {
|
|
|
+ FreePool (KcsTransportToken);
|
|
|
+ DEBUG ((DEBUG_ERROR, "%a: Fail to allocate memory for MANAGEABILITY_TRANSPORT\n", __FUNCTION__));
|
|
|
+ return EFI_OUT_OF_RESOURCES;
|
|
|
+ }
|
|
|
+
|
|
|
+ KcsTransportToken->Signature = MANAGEABILITY_TRANSPORT_KCS_SIGNATURE;
|
|
|
+ KcsTransportToken->Token.ManageabilityProtocolSpecification = ManageabilityProtocolSpec;
|
|
|
+ KcsTransportToken->Token.Transport->TransportVersion = MANAGEABILITY_TRANSPORT_TOKEN_VERSION;
|
|
|
+ KcsTransportToken->Token.Transport->ManageabilityTransportSpecification = &gManageabilityTransportKcsGuid;
|
|
|
+ KcsTransportToken->Token.Transport->TransportName = L"KCS";
|
|
|
+ KcsTransportToken->Token.Transport->Function.Version1_0 = AllocateZeroPool (sizeof (MANAGEABILITY_TRANSPORT_FUNCTION_V1_0));
|
|
|
+ if (KcsTransportToken->Token.Transport->Function.Version1_0 == NULL) {
|
|
|
+ DEBUG ((DEBUG_ERROR, "%a: Fail to allocate memory for MANAGEABILITY_TRANSPORT_FUNCTION_V1_0\n", __FUNCTION__));
|
|
|
+ FreePool (KcsTransportToken);
|
|
|
+ FreePool (KcsTransportToken->Token.Transport);
|
|
|
+ return EFI_OUT_OF_RESOURCES;
|
|
|
+ }
|
|
|
+
|
|
|
+ KcsTransportToken->Token.Transport->Function.Version1_0->TransportInit = KcsTransportInit;
|
|
|
+ KcsTransportToken->Token.Transport->Function.Version1_0->TransportReset = KcsTransportReset;
|
|
|
+ KcsTransportToken->Token.Transport->Function.Version1_0->TransportStatus = KcsTransportStatus;
|
|
|
+ KcsTransportToken->Token.Transport->Function.Version1_0->TransportTransmitReceive = KcsTransportTransmitReceive;
|
|
|
+
|
|
|
+ mSingleSessionToken = KcsTransportToken;
|
|
|
+ *TransportToken = &KcsTransportToken->Token;
|
|
|
+ return EFI_SUCCESS;
|
|
|
+}
|
|
|
+
|
|
|
+/**
|
|
|
+ This function returns the transport capabilities.
|
|
|
+
|
|
|
+ @param [out] TransportFeature Pointer to receive transport capabilities.
|
|
|
+ See the definitions of
|
|
|
+ MANAGEABILITY_TRANSPORT_CAPABILITY.
|
|
|
+
|
|
|
+**/
|
|
|
+VOID
|
|
|
+GetTransportCapability (
|
|
|
+ OUT MANAGEABILITY_TRANSPORT_CAPABILITY *TransportCapability
|
|
|
+ )
|
|
|
+{
|
|
|
+ if (TransportCapability != NULL) {
|
|
|
+ *TransportCapability = 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 == NULL) {
|
|
|
+ Status = EFI_INVALID_PARAMETER;
|
|
|
+ }
|
|
|
+
|
|
|
+ KcsTransportToken = MANAGEABILITY_TRANSPORT_KCS_FROM_LINK (TransportToken);
|
|
|
+ if (mSingleSessionToken != KcsTransportToken) {
|
|
|
+ Status = EFI_INVALID_PARAMETER;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (KcsTransportToken != NULL) {
|
|
|
+ FreePool (KcsTransportToken->Token.Transport->Function.Version1_0);
|
|
|
+ FreePool (KcsTransportToken->Token.Transport);
|
|
|
+ FreePool (KcsTransportToken);
|
|
|
+ mSingleSessionToken = NULL;
|
|
|
+ Status = EFI_SUCCESS;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (EFI_ERROR (Status)) {
|
|
|
+ DEBUG ((DEBUG_ERROR, "%a: Fail to release KCS transport token (%r).\n", __FUNCTION__, Status));
|
|
|
+ }
|
|
|
+
|
|
|
+ return Status;
|
|
|
+}
|