Reviewed-by: Nickle Wang <nick...@nvidia.com> Regards, Nickle
> -----Original Message----- > From: abner.ch...@amd.com <abner.ch...@amd.com> > Sent: Friday, April 21, 2023 1:23 PM > To: devel@edk2.groups.io > Cc: Isaac Oram <isaac.w.o...@intel.com>; Abdul Lateef Attar > <abdat...@amd.com>; Nickle Wang <nick...@nvidia.com>; Igor Kulchytskyy > <ig...@ami.com> > Subject: [edk2-platforms][PATCH V3 10/14] ManageabilityPkg: Add MCTP > transport interface > > External email: Use caution opening links or attachments > > > From: Abner Chang <abner.ch...@amd.com> > > Add MCTP manageability transport interface library. > > The functionality is verified by checking the binary > debug output of payload. > > Signed-off-by: Abner Chang <abner.ch...@amd.com> > Cc: Isaac Oram <isaac.w.o...@intel.com> > Cc: Abdul Lateef Attar <abdat...@amd.com> > Cc: Nickle Wang <nick...@nvidia.com> > Cc: Igor Kulchytskyy <ig...@ami.com> > --- > .../ManageabilityPkg/ManageabilityPkg.dsc | 1 + > .../Dxe/DxeManageabilityTransportMctp.inf | 44 +++ > .../Dxe/ManageabilityTransportMctp.h | 26 ++ > .../Dxe/ManageabilityTransportMctp.c | 367 ++++++++++++++++++ > .../Dxe/ManageabilityTransportMctp.uni | 13 + > 5 files changed, 451 insertions(+) > create mode 100644 > Features/ManageabilityPkg/Library/ManageabilityTransportMctpLib/Dxe/DxeM > anageabilityTransportMctp.inf > create mode 100644 > Features/ManageabilityPkg/Library/ManageabilityTransportMctpLib/Dxe/Mana > geabilityTransportMctp.h > create mode 100644 > Features/ManageabilityPkg/Library/ManageabilityTransportMctpLib/Dxe/Mana > geabilityTransportMctp.c > create mode 100644 > Features/ManageabilityPkg/Library/ManageabilityTransportMctpLib/Dxe/Mana > geabilityTransportMctp.uni > > diff --git a/Features/ManageabilityPkg/ManageabilityPkg.dsc > b/Features/ManageabilityPkg/ManageabilityPkg.dsc > index 412029ef6c..959b3eabd2 100644 > --- a/Features/ManageabilityPkg/ManageabilityPkg.dsc > +++ b/Features/ManageabilityPkg/ManageabilityPkg.dsc > @@ -37,6 +37,7 @@ > > [Components] > > ManageabilityPkg/Library/ManageabilityTransportKcsLib/Dxe/DxeManageability > TransportKcs.inf > + > ManageabilityPkg/Library/ManageabilityTransportMctpLib/Dxe/DxeManageabili > tyTransportMctp.inf > ManageabilityPkg/Library/PldmProtocolLibrary/Dxe/PldmProtocolLib.inf > > [LibraryClasses] > diff --git > a/Features/ManageabilityPkg/Library/ManageabilityTransportMctpLib/Dxe/Dxe > ManageabilityTransportMctp.inf > b/Features/ManageabilityPkg/Library/ManageabilityTransportMctpLib/Dxe/Dxe > ManageabilityTransportMctp.inf > new file mode 100644 > index 0000000000..22ea37c516 > --- /dev/null > +++ > b/Features/ManageabilityPkg/Library/ManageabilityTransportMctpLib/Dxe/Dxe > ManageabilityTransportMctp.inf > @@ -0,0 +1,44 @@ > +## @file > +# MCTP instance of Manageability Transport Library > +# > +# Copyright (C) 2023 Advanced Micro Devices, Inc. All rights reserved.<BR> > +# SPDX-License-Identifier: BSD-2-Clause-Patent > +# > +## > + > +[Defines] > + INF_VERSION = 0x0001001B > + BASE_NAME = DxeManageabilityTransportMctp > + MODULE_UNI_FILE = ManageabilityTransportMctp.uni > + FILE_GUID = 7770FA0F-4808-47BD-89F4-717185332486 > + MODULE_TYPE = DXE_DRIVER > + VERSION_STRING = 1.0 > + LIBRARY_CLASS = ManageabilityTransportLib > + > +# > +# VALID_ARCHITECTURES = IA32 X64 ARM AARCH64 > +# > + > +[Sources] > + ManageabilityTransportMctp.c > + ManageabilityTransportMctp.h > + > +[Packages] > + ManageabilityPkg/ManageabilityPkg.dec > + MdePkg/MdePkg.dec > + > +[LibraryClasses] > + DebugLib > + MemoryAllocationLib > + UefiBootServicesTableLib > + > +[Protocols] > + gEdkiiMctpProtocolGuid > + > +[Guids] > + gManageabilityProtocolPldmGuid > + gManageabilityTransportMctpGuid > + > +[Depex] > + gEdkiiMctpProtocolGuid ## ALWAYS_CONSUMES > + > diff --git > a/Features/ManageabilityPkg/Library/ManageabilityTransportMctpLib/Dxe/Ma > nageabilityTransportMctp.h > b/Features/ManageabilityPkg/Library/ManageabilityTransportMctpLib/Dxe/Ma > nageabilityTransportMctp.h > new file mode 100644 > index 0000000000..1ce0d3a8bc > --- /dev/null > +++ > b/Features/ManageabilityPkg/Library/ManageabilityTransportMctpLib/Dxe/Ma > nageabilityTransportMctp.h > @@ -0,0 +1,26 @@ > +/** @file > + > + Manageability transport MCTP internal used definitions. > + > + Copyright (C) 2023 Advanced Micro Devices, Inc. All rights reserved.<BR> > + SPDX-License-Identifier: BSD-2-Clause-Patent > +**/ > + > +#ifndef MANAGEABILITY_TRANSPORT_MCTP_LIB_INTERNAL_H_ > +#define MANAGEABILITY_TRANSPORT_MCTP_LIB_INTERNAL_H_ > + > +#include <Library/ManageabilityTransportLib.h> > + > +#define MANAGEABILITY_TRANSPORT_MCTP_SIGNATURE SIGNATURE_32 > ('M', 'T', 'M', 'C') > + > +/// > +/// Manageability transport KCS internal data structure. > +/// > +typedef struct { > + UINTN Signature; > + MANAGEABILITY_TRANSPORT_TOKEN Token; > +} MANAGEABILITY_TRANSPORT_MCTP; > + > +#define MANAGEABILITY_TRANSPORT_MCTP_FROM_LINK(a) CR (a, > MANAGEABILITY_TRANSPORT_MCTP, Token, > MANAGEABILITY_TRANSPORT_MCTP_SIGNATURE) > + > +#endif // MANAGEABILITY_TRANSPORT_MCTP_LIB_INTERNAL_H_ > diff --git > a/Features/ManageabilityPkg/Library/ManageabilityTransportMctpLib/Dxe/Ma > nageabilityTransportMctp.c > b/Features/ManageabilityPkg/Library/ManageabilityTransportMctpLib/Dxe/Ma > nageabilityTransportMctp.c > new file mode 100644 > index 0000000000..eaf02bbb0a > --- /dev/null > +++ > b/Features/ManageabilityPkg/Library/ManageabilityTransportMctpLib/Dxe/Ma > nageabilityTransportMctp.c > @@ -0,0 +1,367 @@ > +/** @file > + > + MCTP 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 <Library/IoLib.h> > +#include <Library/DebugLib.h> > +#include <Library/MemoryAllocationLib.h> > +#include <Library/ManageabilityTransportLib.h> > +#include <Library/ManageabilityTransportMctpLib.h> > +#include <Library/ManageabilityTransportHelperLib.h> > +#include <Library/UefiBootServicesTableLib.h> > +#include <Protocol/MctpProtocol.h> > + > +#include "ManageabilityTransportMctp.h" > + > +MANAGEABILITY_TRANSPORT_MCTP *mSingleSessionToken = NULL; > +EDKII_MCTP_PROTOCOL *mMctpProtocol = NULL; > + > +EFI_GUID *mSupportedManageabilityProtocol[] = { > + &gManageabilityProtocolPldmGuid > +}; > + > +UINT8 mNumberOfSupportedProtocol = (sizeof > (mSupportedManageabilityProtocol)/sizeof (EFI_GUID *)); > + > +/** > + This function initializes the transport interface. > + > + @param [in] TransportToken The transport token acquired through > + AcquireTransportSession function. > + @param [in] HardwareInfo The hardware information > + assigned to MCTP 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 > +MctpTransportInit ( > + IN MANAGEABILITY_TRANSPORT_TOKEN *TransportToken, > + IN MANAGEABILITY_TRANSPORT_HARDWARE_INFORMATION HardwareInfo > OPTIONAL > + ) > +{ > + 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 > +MctpTransportStatus ( > + IN MANAGEABILITY_TRANSPORT_TOKEN *TransportToken, > + OUT MANAGEABILITY_TRANSPORT_ADDITIONAL_STATUS > *TransportAdditionalStatus OPTIONAL > + ) > +{ > + if (TransportToken == NULL) { > + DEBUG ((DEBUG_ERROR, "%a: Invalid transport token.\n", __FUNCTION__)); > + return EFI_INVALID_PARAMETER; > + } > + > + if (TransportAdditionalStatus != NULL) { > + *TransportAdditionalStatus = > MANAGEABILITY_TRANSPORT_ADDITIONAL_STATUS_NO_ERRORS; > + } > + > + 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 > +MctpTransportReset ( > + IN MANAGEABILITY_TRANSPORT_TOKEN *TransportToken, > + OUT MANAGEABILITY_TRANSPORT_ADDITIONAL_STATUS > *TransportAdditionalStatus OPTIONAL > + ) > +{ > + if (TransportAdditionalStatus != NULL) { > + *TransportAdditionalStatus = > MANAGEABILITY_TRANSPORT_ADDITIONAL_STATUS_NOT_AVAILABLE; > + } > + > + 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 > +MctpTransportTransmitReceive ( > + IN MANAGEABILITY_TRANSPORT_TOKEN *TransportToken, > + IN MANAGEABILITY_TRANSFER_TOKEN *TransferToken > + ) > +{ > + EFI_STATUS Status; > + MANAGEABILITY_MCTP_TRANSPORT_HEADER *TransmitHeader; > + > + if (TransportToken == NULL) { > + DEBUG ((DEBUG_ERROR, "%a: Invalid transport token.\n", __FUNCTION__)); > + TransferToken->TransportAdditionalStatus = > MANAGEABILITY_TRANSPORT_ADDITIONAL_STATUS_NOT_AVAILABLE; > + return; > + } > + > + TransmitHeader = (MANAGEABILITY_MCTP_TRANSPORT_HEADER > *)TransferToken->TransmitHeader; > + if (TransmitHeader == NULL) { > + TransferToken->TransferStatus = EFI_INVALID_PARAMETER; > + TransferToken->TransportAdditionalStatus = > MANAGEABILITY_TRANSPORT_ADDITIONAL_STATUS_NOT_AVAILABLE; > + return; > + } > + > + if (mMctpProtocol == NULL) { > + Status = gBS->LocateProtocol ( > + &gEdkiiMctpProtocolGuid, > + NULL, > + (VOID **)&mMctpProtocol > + ); > + if (EFI_ERROR (Status)) { > + // > + // Dxe MCTP Protocol is not installed. > + // > + DEBUG ((DEBUG_ERROR, "%a: EDKII MCTP protocol is not found - %r\n", > __FUNCTION__, Status)); > + return; > + } > + } > + > + DEBUG (( > + DEBUG_MANAGEABILITY_INFO, > + "%a: MCTP message type: 0x%x, SourceEndpointId: 0x%x, > DestinationEndpointId: 0x%x\n", > + __FUNCTION__, > + TransmitHeader->MessageHeader.MessageType, > + TransmitHeader->SourceEndpointId, > + TransmitHeader->DestinationEndpointId > + )); > + DEBUG (( > + DEBUG_MANAGEABILITY_INFO, > + " - Request message size: 0x%x, Response message size: %x\n", > + TransferToken->TransmitPackage.TransmitSizeInByte, > + TransferToken->ReceivePackage.ReceiveSizeInByte > + )); > + Status = mMctpProtocol->Functions.Version1_0->MctpSubmitCommand ( > + mMctpProtocol, > + > TransmitHeader->MessageHeader.MessageType, > + > TransmitHeader->SourceEndpointId, > + > TransmitHeader->DestinationEndpointId, > + (BOOLEAN)TransmitHeader- > >MessageHeader.IntegrityCheck, > + > TransferToken->TransmitPackage.TransmitPayload, > + TransferToken- > >TransmitPackage.TransmitSizeInByte, > + TransferToken- > >TransmitPackage.TransmitTimeoutInMillisecond, > + > TransferToken->ReceivePackage.ReceiveBuffer, > + &TransferToken- > >ReceivePackage.ReceiveSizeInByte, > + TransferToken- > >ReceivePackage.TransmitTimeoutInMillisecond, > + > &TransferToken->TransportAdditionalStatus > + ); > + TransferToken->TransferStatus = Status; > +} > + > +/** > + 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_MCTP *MctpTransportToken; > + > + if (ManageabilityProtocolSpec == NULL) { > + DEBUG ((DEBUG_ERROR, "%a: No Manageability protocol specification > specified.\n", __FUNCTION__)); > + return EFI_INVALID_PARAMETER; > + } > + > + Status = HelperManageabilityCheckSupportedSpec ( > + &gManageabilityTransportMctpGuid, > + mSupportedManageabilityProtocol, > + mNumberOfSupportedProtocol, > + 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; > + } > + > + MctpTransportToken = (MANAGEABILITY_TRANSPORT_MCTP > *)AllocateZeroPool (sizeof (MANAGEABILITY_TRANSPORT_MCTP)); > + if (MctpTransportToken == NULL) { > + DEBUG ((DEBUG_ERROR, "%a: Fail to allocate memory for > MANAGEABILITY_TRANSPORT_MCTP\n", __FUNCTION__)); > + return EFI_OUT_OF_RESOURCES; > + } > + > + MctpTransportToken->Token.Transport = AllocateZeroPool (sizeof > (MANAGEABILITY_TRANSPORT)); > + if (MctpTransportToken->Token.Transport == NULL) { > + FreePool (MctpTransportToken); > + DEBUG ((DEBUG_ERROR, "%a: Fail to allocate memory for > MANAGEABILITY_TRANSPORT\n", __FUNCTION__)); > + return EFI_OUT_OF_RESOURCES; > + } > + > + MctpTransportToken->Signature = > MANAGEABILITY_TRANSPORT_MCTP_SIGNATURE; > + MctpTransportToken->Token.ManageabilityProtocolSpecification = > ManageabilityProtocolSpec; > + MctpTransportToken->Token.Transport->TransportVersion = > MANAGEABILITY_TRANSPORT_TOKEN_VERSION; > + MctpTransportToken->Token.Transport- > >ManageabilityTransportSpecification = &gManageabilityTransportMctpGuid; > + MctpTransportToken->Token.Transport->TransportName = > L"MCTP"; > + MctpTransportToken->Token.Transport->Function.Version1_0 = > AllocateZeroPool (sizeof (MANAGEABILITY_TRANSPORT_FUNCTION_V1_0)); > + if (MctpTransportToken->Token.Transport->Function.Version1_0 == NULL) { > + DEBUG ((DEBUG_ERROR, "%a: Fail to allocate memory for > MANAGEABILITY_TRANSPORT_FUNCTION_V1_0\n", __FUNCTION__)); > + FreePool (MctpTransportToken); > + FreePool (MctpTransportToken->Token.Transport); > + return EFI_OUT_OF_RESOURCES; > + } > + > + MctpTransportToken->Token.Transport->Function.Version1_0->TransportInit > = MctpTransportInit; > + MctpTransportToken->Token.Transport->Function.Version1_0- > >TransportReset = MctpTransportReset; > + MctpTransportToken->Token.Transport->Function.Version1_0- > >TransportStatus = MctpTransportStatus; > + MctpTransportToken->Token.Transport->Function.Version1_0- > >TransportTransmitReceive = MctpTransportTransmitReceive; > + > + mSingleSessionToken = MctpTransportToken; > + *TransportToken = &MctpTransportToken->Token; > + return EFI_SUCCESS; > +} > + > +/** > + This function returns the transport capabilities according to > + the manageability protocol. > + > + @param [in] TransportToken Transport token acquired from > manageability > + transport library. > + @param [out] TransportFeature Pointer to receive transport > capabilities. > + See the definitions of > + > MANAGEABILITY_TRANSPORT_CAPABILITY. > + @retval EFI_SUCCESS TransportCapability is returned > successfully. > + @retval EFI_INVALID_PARAMETER TransportToken is not a valid > token. > +**/ > +EFI_STATUS > +GetTransportCapability ( > + IN MANAGEABILITY_TRANSPORT_TOKEN *TransportToken, > + OUT MANAGEABILITY_TRANSPORT_CAPABILITY *TransportCapability > + ) > +{ > + if ((TransportToken == NULL) || (TransportCapability == NULL)) { > + return EFI_INVALID_PARAMETER; > + } > + > + *TransportCapability = 0; > + return EFI_SUCCESS; > +} > + > +/** > + 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_MCTP *MctpTransportToken; > + > + if (TransportToken == NULL) { > + Status = EFI_INVALID_PARAMETER; > + } > + > + MctpTransportToken = MANAGEABILITY_TRANSPORT_MCTP_FROM_LINK > (TransportToken); > + if (mSingleSessionToken != MctpTransportToken) { > + Status = EFI_INVALID_PARAMETER; > + } > + > + if (MctpTransportToken != NULL) { > + FreePool (MctpTransportToken->Token.Transport->Function.Version1_0); > + FreePool (MctpTransportToken->Token.Transport); > + FreePool (MctpTransportToken); > + mSingleSessionToken = NULL; > + Status = EFI_SUCCESS; > + } > + > + if (EFI_ERROR (Status)) { > + DEBUG ((DEBUG_ERROR, "%a: Fail to release MCTP transport token (%r).\n", > __FUNCTION__, Status)); > + } > + > + return Status; > +} > diff --git > a/Features/ManageabilityPkg/Library/ManageabilityTransportMctpLib/Dxe/Ma > nageabilityTransportMctp.uni > b/Features/ManageabilityPkg/Library/ManageabilityTransportMctpLib/Dxe/Ma > nageabilityTransportMctp.uni > new file mode 100644 > index 0000000000..ca8125a4a7 > --- /dev/null > +++ > b/Features/ManageabilityPkg/Library/ManageabilityTransportMctpLib/Dxe/Ma > nageabilityTransportMctp.uni > @@ -0,0 +1,13 @@ > +// /** @file > +// MCTP instance of Manageability Transport Library > +// > +// Copyright (C) 2023 Advanced Micro Devices, Inc. All rights reserved.<BR> > +// > +// SPDX-License-Identifier: BSD-2-Clause-Patent > +// > +// **/ > + > +#string STR_MODULE_ABSTRACT #language en-US "MCTP instance of > Manageability Transport Library" > + > +#string STR_MODULE_DESCRIPTION #language en-US "MCTP > Manageability Transport library implementation." > + > -- > 2.37.1.windows.1 -=-=-=-=-=-=-=-=-=-=-=- Groups.io Links: You receive all messages sent to this group. View/Reply Online (#103504): https://edk2.groups.io/g/devel/message/103504 Mute This Topic: https://groups.io/mt/98404964/21656 Group Owner: devel+ow...@edk2.groups.io Unsubscribe: https://edk2.groups.io/g/devel/unsub [arch...@mail-archive.com] -=-=-=-=-=-=-=-=-=-=-=-