[AMD Official Use Only - General] Hi Nickle, Thanks for those good comments. V2 patch was just sent!
Abner > -----Original Message----- > From: Nickle Wang <nick...@nvidia.com> > Sent: Monday, March 20, 2023 11:13 AM > To: Chang, Abner <abner.ch...@amd.com>; devel@edk2.groups.io > Cc: Igor Kulchytskyy <ig...@ami.com> > Subject: RE: [PATCH 1/3] RedfishPkg/Library: Redfish BMC USBNIC Host > Interface > > Caution: This message originated from an External Source. Use proper > caution when opening attachments, clicking links, or responding. > > > Please find my comment inline below, thanks! > > Regards, > Nickle > > -----Original Message----- > From: abner.ch...@amd.com <abner.ch...@amd.com> > Sent: Thursday, March 9, 2023 11:41 PM > To: devel@edk2.groups.io > Cc: Nickle Wang <nick...@nvidia.com>; Igor Kulchytskyy <ig...@ami.com> > Subject: [PATCH 1/3] RedfishPkg/Library: Redfish BMC USBNIC Host Interface > > External email: Use caution opening links or attachments > > > From: Abner Chang <abner.ch...@amd.com> > > BMC exposed USB NIC platform Redfish Host Interface library > implementation. > > Signed-off-by: Abner Chang <abner.ch...@amd.com> > Cc: Nickle Wang <nick...@nvidia.com> > Cc: Igor Kulchytskyy <ig...@ami.com> > --- > RedfishPkg/RedfishPkg.dec | 10 + > .../PlatformHostInterfaceBmcUsbNicLib.inf | 48 + > RedfishPkg/Include/Library/RedfishDebugLib.h | 3 +- > .../PlatformHostInterfaceBmcUsbNicLib.h | 84 ++ > .../PlatformHostInterfaceBmcUsbNicLib.c | 1280 +++++++++++++++++ > 5 files changed, 1424 insertions(+), 1 deletion(-) create mode 100644 > RedfishPkg/Library/PlatformHostInterfaceBmcUsbNicLib/PlatformHostInterf > aceBmcUsbNicLib.inf > create mode 100644 > RedfishPkg/Library/PlatformHostInterfaceBmcUsbNicLib/PlatformHostInterf > aceBmcUsbNicLib.h > create mode 100644 > RedfishPkg/Library/PlatformHostInterfaceBmcUsbNicLib/PlatformHostInterf > aceBmcUsbNicLib.c > > diff --git a/RedfishPkg/RedfishPkg.dec b/RedfishPkg/RedfishPkg.dec index > 53e52c2b008..251aa5e2b76 100644 > --- a/RedfishPkg/RedfishPkg.dec > +++ b/RedfishPkg/RedfishPkg.dec > @@ -113,3 +113,13 @@ > # Default is set to not add. > # > > gEfiRedfishPkgTokenSpaceGuid.PcdRedfishRestExAddingExpect|FALSE|BOO > LEAN|0x00001004 > + # > + # Use PCD to declare the Redfish host nmae becasue there is no # > + specification for that. > + # > + > gEfiRedfishPkgTokenSpaceGuid.PcdRedfishHostName|""|VOID*|0x0000100 > 5 > + # > + # Use PCD to declare the Redfish service UUID becasue there is no # > + specification for that. > + # > + > + > gEfiRedfishPkgTokenSpaceGuid.PcdRedfishServiceUuid|L""|VOID*|0x00001 > 00 > + 6 > > Would it be good to provide dummy string for above PCDs? For example: > > gEfiRedfishPkgTokenSpaceGuid.PcdRedfishHostName|"edk2_redfishpkg"|V > OID*|0x00001005 > gEfiRedfishPkgTokenSpaceGuid.PcdRedfishServiceUuid|L"0000000000000000 > "|VOID*|0x0000100 > > diff --git > a/RedfishPkg/Library/PlatformHostInterfaceBmcUsbNicLib/PlatformHostInte > rfaceBmcUsbNicLib.inf > b/RedfishPkg/Library/PlatformHostInterfaceBmcUsbNicLib/PlatformHostInte > rfaceBmcUsbNicLib.inf > new file mode 100644 > index 00000000000..f2c7d7fec89 > --- /dev/null > +++ > b/RedfishPkg/Library/PlatformHostInterfaceBmcUsbNicLib/PlatformHostI > +++ nterfaceBmcUsbNicLib.inf > @@ -0,0 +1,48 @@ > +## @file > +# Module to provide the platform Redfish Host Interface information # > +of USB NIC Device exposed by BMC. > +# > +# Copyright (C) 2023 Advanced Micro Devices, Inc. All rights reserved. > +# > +# SPDX-License-Identifier: BSD-2-Clause-Patent # ## > + > +[Defines] > + INF_VERSION = 0x0001000b > + BASE_NAME = PlatformHostInterfaceBmcUsbNicLib > + FILE_GUID = C4837B58-225E-4352-8FDC-4C52A5D65891 > + MODULE_TYPE = DXE_DRIVER > + VERSION_STRING = 1.0 > + LIBRARY_CLASS = PlatformHostInterfaceBmcUsbNicLib > + > +[Sources] > + PlatformHostInterfaceBmcUsbNicLib.c > + PlatformHostInterfaceBmcUsbNicLib.h > + > +[Packages] > + MdePkg/MdePkg.dec > + MdeModulePkg/MdeModulePkg.dec > + NetworkPkg/NetworkPkg.dec > + RedfishPkg/RedfishPkg.dec > + > +[LibraryClasses] > + BaseMemoryLib > + DebugLib > + IpmiLib > + IpmiCommandLib > + MemoryAllocationLib > + UefiLib > + UefiBootServicesTableLib > + > +[Protocols] > + gEfiSimpleNetworkProtocolGuid ## CONSUMED > + gEfiUsbIoProtocolGuid ## CONSUMED > + gEfiDevicePathProtocolGuid ## CONSUMED > + > +[Pcd] > + gEfiRedfishPkgTokenSpaceGuid.PcdRedfishHostName ## CONSUMED > + gEfiRedfishPkgTokenSpaceGuid.PcdRedfishServiceUuid ## CONSUMED > + > +[Depex] > + gIpmiProtocolGuid > diff --git a/RedfishPkg/Include/Library/RedfishDebugLib.h > b/RedfishPkg/Include/Library/RedfishDebugLib.h > index 21f01353ede..913f2b2f358 100644 > --- a/RedfishPkg/Include/Library/RedfishDebugLib.h > +++ b/RedfishPkg/Include/Library/RedfishDebugLib.h > @@ -14,7 +14,8 @@ > #include <Library/JsonLib.h> > #include <Library/RedfishLib.h> > > -#define DEBUG_REDFISH_NETWORK DEBUG_INFO ///< Debug error level > for Redfish networking function > +#define DEBUG_REDFISH_NETWORK DEBUG_INFO ///< Debug error > level for Redfish networking function > +#define DEBUG_REDFISH_HOST_INTERFACE DEBUG_INFO ///< Debug > error level for Redfish networking function > > /** > > diff --git > a/RedfishPkg/Library/PlatformHostInterfaceBmcUsbNicLib/PlatformHostInte > rfaceBmcUsbNicLib.h > b/RedfishPkg/Library/PlatformHostInterfaceBmcUsbNicLib/PlatformHostInte > rfaceBmcUsbNicLib.h > new file mode 100644 > index 00000000000..669c304fc3d > --- /dev/null > +++ > b/RedfishPkg/Library/PlatformHostInterfaceBmcUsbNicLib/PlatformHostI > +++ nterfaceBmcUsbNicLib.h > @@ -0,0 +1,84 @@ > +/** @file > + Header file to provide the platform Redfish Host Interface > +information > + of USB NIC Device exposed by BMC. > + > + Copyright (C) 2023 Advanced Micro Devices, Inc. All rights reserved. > + > + SPDX-License-Identifier: BSD-2-Clause-Patent > + > +**/ > + > +#ifndef PLATFORM_HOST_INTERFACE_BMC_USB_NIC_LIB_H_ > +#define PLATFORM_HOST_INTERFACE_BMC_USB_NIC_LIB_H_ > + > +#include <Uefi.h> > +#include <IndustryStandard/Ipmi.h> > +#include <IndustryStandard/IpmiNetFnApp.h> #include > +<IndustryStandard/IpmiNetFnTransport.h> > +#include <IndustryStandard/RedfishHostInterfaceIpmi.h> > +#include <IndustryStandard/SmBios.h> > +#include <Library/BaseLib.h> > +#include <Library/BaseMemoryLib.h> > +#include <Library/DebugLib.h> > +#include <Library/DevicePathLib.h> > +#include <Library/IpmiLib.h> > +#include <Library/IpmiCommandLib.h> > +#include <Library/RedfishHostInterfaceLib.h> > +#include <Library/MemoryAllocationLib.h> #include > +<Library/UefiBootServicesTableLib.h> > +#include <Library/DevicePathLib.h> > +#include <Library/RedfishDebugLib.h> > + > +#include <Protocol/SimpleNetwork.h> > +#include <Protocol/UsbIo.h> > + > +#define BMC_USB_NIC_HOST_INTERFASCE_READINESS_GUID \ > + { \ > + 0xDD96F5D7, 0x4AE1, 0x4E6C, {0xA1, 0x30, 0xA5, 0xAC, 0x77, 0xDD, 0xE4, > 0xA5} \ > + } > + > +// > +// This is the structure for BMC exposed // USB NIC information. > +// > +typedef struct { > + LIST_ENTRY NextInstance; ///< Link to the > next instance. > + BOOLEAN IsExposedByBmc; ///< Flag > indicates this USB > NIC is > + ///< exposed by > BMC. > + BOOLEAN IsSuppportedHostInterface; ///< This BMC > USB NIC is > supported > + ///< as Redfish > host interface > + EFI_SIMPLE_NETWORK_PROTOCOL *ThisSnp; ///< The SNP > instance associated with > + ///< this USB > NIC. > + EFI_USB_IO_PROTOCOL *ThisUsbIo; ///< The USBIO > instance > associated with > + ///< this USB > NIC. > + UINT16 UsbVendorId; ///< USB Vendor > ID of this BMC > exposed USB NIC. > + UINT16 UsbProductId; ///< USB Product > ID of this BMC > exposed USB NIC. > + UINTN MacAddressSize; ///< HW address > size. > + UINT8 *MacAddress; ///< HW address. > + UINT8 IpmiLanChannelNumber; ///< BMC IPMI > Lan Channel > number. > + > + // > + // Below is the infortmation for building SMBIOS type 42. > + // > + UINT8 IpAssignedType; ///< Redfish > service IP assign type. > + UINT8 IpAddressFormat; ///< Redfish > service IP version. > + UINT8 HostIpAddressIpv4[4]; ///< Host IP > address. > + UINT8 RedfishIpAddressIpv4[4]; ///< Redfish > service IP > address. > + UINT8 SubnetMaskIpv4[4]; ///< Subnet mask. > + UINT8 GatewayIpv4[4]; ///< Gateway IP > address. > + UINT16 VLanId; ///< VLAN ID. > + BOOLEAN CredentialBootstrapping; ///< If Credential > bootstrapping is > + ///< supported. > +} HOST_INTERFACE_BMC_USB_NIC_INFO; > + > +// > +// This is the structure for caching > +// BMC IPMI LAN Channel > +// > +typedef struct { > + LIST_ENTRY NextInstance; ///< Link to the next IPMI LAN > Channel. > + UINT8 Channel; ///< IPMI Channel number. > + EFI_MAC_ADDRESS MacAddress; ///< IPMI LAN Channel MAC > address. > + UINT8 MacAddressSize; ///< MAC address size; > +} BMC_IPMI_LAN_CHANNEL_INFO; > +#endif > diff --git > a/RedfishPkg/Library/PlatformHostInterfaceBmcUsbNicLib/PlatformHostInte > rfaceBmcUsbNicLib.c > b/RedfishPkg/Library/PlatformHostInterfaceBmcUsbNicLib/PlatformHostInte > rfaceBmcUsbNicLib.c > new file mode 100644 > index 00000000000..1c530b692e8 > --- /dev/null > +++ > b/RedfishPkg/Library/PlatformHostInterfaceBmcUsbNicLib/PlatformHostI > +++ nterfaceBmcUsbNicLib.c > @@ -0,0 +1,1280 @@ > +/** @file > + Source file to provide the platform Redfish Host Interface > +information > + of USB NIC Device exposed by BMC. > + > + Copyright (C) 2023 Advanced Micro Devices, Inc. All rights reserved. > + > + SPDX-License-Identifier: BSD-2-Clause-Patent > + > +**/ > + > +#include "PlatformHostInterfaceBmcUsbNicLib.h" > + > +static EFI_GUID mPlatformHostInterfaceBmcUsbNicReadinessGuid = > + BMC_USB_NIC_HOST_INTERFASCE_READINESS_GUID; > +static EFI_EVENT mPlatformHostInterfaceSnpEvent = NULL; > +static VOID *mPlatformHostInterfaceSnpRegistration = NULL; > + > +static LIST_ENTRY mBmcUsbNic; > +static LIST_ENTRY mBmcIpmiLan; > + > +/** > + Probe if the system supports Redfish Host Interface Credentail > + Bootstrapping. > + > + @retval TRUE Yes, it is supported. > + TRUE No, it is not supported. > + > +**/ > +BOOLEAN > +ProbeRedfishCredentialBootstrap ( > + VOID > + ) > +{ > + EFI_STATUS Status; > + IPMI_BOOTSTRAP_CREDENTIALS_COMMAND_DATA CommandData; > + IPMI_BOOTSTRAP_CREDENTIALS_RESULT_RESPONSE ResponseData; > + UINT32 ResponseSize; > + BOOLEAN ReturnBool; > + > + DEBUG ((DEBUG_INFO, "%a: Entry\n", __FUNCTION__)); > + > + // > + // IPMI callout to NetFn 2C, command 02 > + // Request data: > + // Byte 1: REDFISH_IPMI_GROUP_EXTENSION > + // Byte 2: DisableBootstrapControl > + // > + CommandData.GroupExtensionId = > REDFISH_IPMI_GROUP_EXTENSION; > + CommandData.DisableBootstrapControl = > REDFISH_IPMI_BOOTSTRAP_CREDENTIAL_ENABLE; > + ResponseData.CompletionCode = IPMI_COMP_CODE_UNSPECIFIED; > + ResponseSize = sizeof (ResponseData); > + // > + // Response data: Ignored. > + // > + Status = IpmiSubmitCommand ( > + IPMI_NETFN_GROUP_EXT, > + REDFISH_IPMI_GET_BOOTSTRAP_CREDENTIALS_CMD, > + (UINT8 *)&CommandData, > + sizeof (CommandData), > + (UINT8 *)&ResponseData, > + &ResponseSize > + ); > + if (!EFI_ERROR (Status) && > + ((ResponseData.CompletionCode == IPMI_COMP_CODE_NORMAL) || > + (ResponseData.CompletionCode == > REDFISH_IPMI_COMP_CODE_BOOTSTRAP_CREDENTIAL_DISABLED) > + )) > + { > + DEBUG ((DEBUG_REDFISH_HOST_INTERFACE, " Redfish Credentail > Bootstrapping is supported\n", __FUNCTION__)); > + ReturnBool = TRUE; > + } else { > + DEBUG ((DEBUG_REDFISH_HOST_INTERFACE, " Redfish Credentail > Bootstrapping is not supported\n", __FUNCTION__)); > + ReturnBool = FALSE; > + } > + > + return ReturnBool; > +} > + > +/** > + Get platform Redfish host interface device descriptor. > + > + @param[in] DeviceType Pointer to retrieve device type. > + @param[out] DeviceDescriptor Pointer to retrieve > REDFISH_INTERFACE_DATA, caller has to free > + this memory using FreePool(). > + > + @retval EFI_NOT_FOUND No Redfish host interface descriptor provided > on this platform. > + > +**/ > +EFI_STATUS > +RedfishPlatformHostInterfaceDeviceDescriptor ( > + IN UINT8 *DeviceType, > + OUT REDFISH_INTERFACE_DATA **DeviceDescriptor > + ) > +{ > + HOST_INTERFACE_BMC_USB_NIC_INFO *ThisInstance; > + REDFISH_INTERFACE_DATA *InterfaceData; > + > + DEBUG ((DEBUG_INFO, "%a: Entry\n", __FUNCTION__)); > + > + if (IsListEmpty (&mBmcUsbNic)) { > + return EFI_NOT_FOUND; > + } > + > + // Check if BMC exposed USB NIC is found and ready for using. > + ThisInstance = (HOST_INTERFACE_BMC_USB_NIC_INFO *)GetFirstNode > + (&mBmcUsbNic); while (TRUE) { > + if (ThisInstance->IsExposedByBmc && ThisInstance- > >IsSuppportedHostInterface) { > + *DeviceType = REDFISH_HOST_INTERFACE_DEVICE_TYPE_USB_V2; > + > + // Fill up REDFISH_INTERFACE_DATA defined in Redfish host interface > spec v1.3 > + InterfaceData = (REDFISH_INTERFACE_DATA *)AllocateZeroPool > (USB_INTERFACE_DEVICE_DESCRIPTOR_V2_SIZE_1_3); > + if (InterfaceData == NULL) { > + DEBUG ((DEBUG_ERROR, "Failed to allocate memory for > REDFISH_INTERFACE_DATA\n")); > + return EFI_OUT_OF_RESOURCES; > + } > + > + InterfaceData->DeviceType = > REDFISH_HOST_INTERFACE_DEVICE_TYPE_USB_V2; > + InterfaceData->DeviceDescriptor.UsbDeviceV2.Length = > USB_INTERFACE_DEVICE_DESCRIPTOR_V2_SIZE_1_3; > + InterfaceData->DeviceDescriptor.UsbDeviceV2.IdVendor = > ThisInstance->UsbVendorId; > + InterfaceData->DeviceDescriptor.UsbDeviceV2.IdProduct = > ThisInstance->UsbProductId; > + InterfaceData->DeviceDescriptor.UsbDeviceV2.SerialNumberStr = 0; > + CopyMem ( > + (VOID *)&InterfaceData->DeviceDescriptor.UsbDeviceV2.MacAddress, > + (VOID *)&ThisInstance->MacAddress, > + sizeof (InterfaceData->DeviceDescriptor.UsbDeviceV2.MacAddress) > + ); > + InterfaceData->DeviceDescriptor.UsbDeviceV2.Characteristics > |= > (UINT16)ThisInstance->CredentialBootstrapping; > + InterfaceData- > >DeviceDescriptor.UsbDeviceV2.CredentialBootstrappingHandle = 0; > + *DeviceDescriptor > = InterfaceData; > + DEBUG ((DEBUG_REDFISH_HOST_INTERFACE, " > REDFISH_INTERFACE_DATA is returned successfully.\n")); > + return EFI_SUCCESS; > + } > + > + if (IsNodeAtEnd (&mBmcUsbNic, &ThisInstance->NextInstance)) { > + break; > + } > + > + ThisInstance = (HOST_INTERFACE_BMC_USB_NIC_INFO *) > + GetNextNode (&mBmcUsbNic, > + &ThisInstance->NextInstance); } > + > + return EFI_NOT_FOUND; > +} > + > +/** > + Get platform Redfish host interface protocol data. > + Caller should pass NULL in ProtocolRecord to retrive the first protocol > record. > + Then continuously pass previous ProtocolRecord for retrieving the next > ProtocolRecord. > + > + @param[in, out] ProtocolRecord Pointer to retrieve the first or the next > protocol record. > + caller has to free the new protocol record > returned from > + this function using FreePool(). > + @param[in] IndexOfProtocolData The index of protocol data. > + > + @retval EFI_NOT_FOUND No more protocol records. > + > +**/ > +EFI_STATUS > +RedfishPlatformHostInterfaceProtocolData ( > + IN OUT MC_HOST_INTERFACE_PROTOCOL_RECORD **ProtocolRecord, > + IN UINT8 IndexOfProtocolData > + ) > +{ > + HOST_INTERFACE_BMC_USB_NIC_INFO *ThisInstance; > + MC_HOST_INTERFACE_PROTOCOL_RECORD *ThisProtocolRecord; > + REDFISH_OVER_IP_PROTOCOL_DATA *RedfishOverIpData; > + UINT8 HostNameLength; > + CHAR8 *HostNameString; > + > + DEBUG ((DEBUG_INFO, "%a: Entry\n", __FUNCTION__)); > + > + if (IsListEmpty (&mBmcUsbNic) || (IndexOfProtocolData > 0)) { > + return EFI_NOT_FOUND; > + } > + > + ThisInstance = (HOST_INTERFACE_BMC_USB_NIC_INFO *)GetFirstNode > + (&mBmcUsbNic); while (TRUE) { > + if (ThisInstance->IsExposedByBmc && ThisInstance- > >IsSuppportedHostInterface) { > + // Get the host name before allocating memory. > + HostNameString = (CHAR8 *)PcdGetPtr (PcdRedfishHostName); > + HostNameLength = (UINT8)AsciiStrSize (HostNameString); > + ThisProtocolRecord = (MC_HOST_INTERFACE_PROTOCOL_RECORD > *)AllocateZeroPool ( > + sizeof > (MC_HOST_INTERFACE_PROTOCOL_RECORD) - 1 + > + sizeof > (REDFISH_OVER_IP_PROTOCOL_DATA) + > + > HostNameLength > + ); > + if (ThisProtocolRecord == NULL) { > + DEBUG ((DEBUG_ERROR, " Aloocate memory fail for > MC_HOST_INTERFACE_PROTOCOL_RECORD.\n")); > + return EFI_OUT_OF_RESOURCES; > + } > + > + ThisProtocolRecord->ProtocolType = > MCHostInterfaceProtocolTypeRedfishOverIP; > + ThisProtocolRecord->ProtocolTypeDataLen = sizeof > (REDFISH_OVER_IP_PROTOCOL_DATA) + HostNameLength; > + RedfishOverIpData = > (REDFISH_OVER_IP_PROTOCOL_DATA > *)&ThisProtocolRecord->ProtocolTypeData[0]; > + // > + // Fill up REDFISH_OVER_IP_PROTOCOL_DATA > + // > + > + // Service UUID > + ZeroMem ((VOID *)&RedfishOverIpData->ServiceUuid, sizeof > (EFI_GUID)); > + if (StrLen ((CONST CHAR16 *)PcdGetPtr (PcdRedfishServiceUuid)) != 0) { > + StrToGuid ((CONST CHAR16 *)PcdGetPtr (PcdRedfishServiceUuid), > &RedfishOverIpData->ServiceUuid); > + } > + > + // HostIpAddressFormat and RedfishServiceIpDiscoveryType > + RedfishOverIpData->HostIpAssignmentType = > RedfishHostIpAssignmentUnknown; > + RedfishOverIpData->RedfishServiceIpDiscoveryType = > RedfishHostIpAssignmentUnknown; > + if (ThisInstance->IpAssignedType == IpmiStaticAddrsss) { > + RedfishOverIpData->HostIpAssignmentType = > RedfishHostIpAssignmentStatic; > + RedfishOverIpData->RedfishServiceIpDiscoveryType = > RedfishHostIpAssignmentStatic; > + } else if (ThisInstance->IpAssignedType == > IpmiDynamicAddressBmcDhcp) { > + RedfishOverIpData->HostIpAssignmentType = > RedfishHostIpAssignmentDhcp; > + RedfishOverIpData->RedfishServiceIpDiscoveryType = > RedfishHostIpAssignmentDhcp; > + } > + > + // HostIpAddressFormat and RedfishServiceIpAddressFormat, only > support IPv4 for now. > + RedfishOverIpData->HostIpAddressFormat = > REDFISH_HOST_INTERFACE_HOST_IP_ADDRESS_FORMAT_IP4; > + RedfishOverIpData->RedfishServiceIpAddressFormat = > + REDFISH_HOST_INTERFACE_HOST_IP_ADDRESS_FORMAT_IP4; > + > + // HostIpAddress > + CopyMem ( > + (VOID *)RedfishOverIpData->HostIpAddress, > + (VOID *)ThisInstance->HostIpAddressIpv4, > + sizeof (ThisInstance->HostIpAddressIpv4) > + ); > + > + // HostIpMask and RedfishServiceIpMask > + CopyMem ( > + (VOID *)RedfishOverIpData->HostIpMask, > + (VOID *)ThisInstance->SubnetMaskIpv4, > + sizeof (ThisInstance->SubnetMaskIpv4) > + ); > + CopyMem ( > + (VOID *)RedfishOverIpData->RedfishServiceIpMask, > + (VOID *)ThisInstance->SubnetMaskIpv4, > + sizeof (ThisInstance->SubnetMaskIpv4) > + ); > + > + // RedfishServiceIpAddress > + CopyMem ( > + (VOID *)RedfishOverIpData->RedfishServiceIpAddress, > + (VOID *)ThisInstance->RedfishIpAddressIpv4, > + sizeof (ThisInstance->RedfishIpAddressIpv4) > + ); > + > + // RedfishServiceIpPort > + RedfishOverIpData->RedfishServiceIpPort = 0; > + > + // RedfishServiceVlanId > + RedfishOverIpData->RedfishServiceVlanId = ThisInstance->VLanId; > + > + // RedfishServiceHostnameLength > + RedfishOverIpData->RedfishServiceHostnameLength = > HostNameLength; > + > + // Redfish host name. > + CopyMem ( > + (VOID *)&RedfishOverIpData->RedfishServiceHostname, > + (VOID *)HostNameString, > + HostNameLength > + ); > + > + DEBUG ((DEBUG_REDFISH_HOST_INTERFACE, " > MC_HOST_INTERFACE_PROTOCOL_RECORD is returned successfully.\n")); > + *ProtocolRecord = ThisProtocolRecord; > + return EFI_SUCCESS; > + } > + > + if (IsNodeAtEnd (&mBmcUsbNic, &ThisInstance->NextInstance)) { > + break; > + } > + > + ThisInstance = (HOST_INTERFACE_BMC_USB_NIC_INFO *) > + GetNextNode (&mBmcUsbNic, > + &ThisInstance->NextInstance); } > + > + return EFI_NOT_FOUND; > +} > + > +/** > + This function retrieve the information of BMC USB NIC. > + > + @retval EFI_SUCCESS All necessary information is retrieved. > + @retval EFI_NOT_FOUND There is no BMC exposed USB NIC. > + @retval Others Other errors. > + > +**/ > +EFI_STATUS > +RetrievedBmcUsbNicInfo ( > + VOID > + ) > +{ > + EFI_STATUS Status; > + UINT32 ResponseDataSize; > + HOST_INTERFACE_BMC_USB_NIC_INFO *ThisInstance; > + IPMI_GET_LAN_CONFIGURATION_PARAMETERS_REQUEST > GetLanConfigReq; > + IPMI_GET_LAN_CONFIGURATION_PARAMETERS_RESPONSE > *GetLanConfigReps; > + IPMI_LAN_IP_ADDRESS_SRC *IpAddressSrc; > + IPMI_LAN_IP_ADDRESS *DestIpAddress; > + IPMI_LAN_SUBNET_MASK *SubnetMask; > + IPMI_LAN_DEFAULT_GATEWAY *DefaultGateway; > + IPMI_LAN_VLAN_ID *LanVlanId; > + EFI_USB_DEVICE_DESCRIPTOR UsbDeviceDescriptor; > + > + DEBUG ((DEBUG_INFO, "%a: Entry\n", __FUNCTION__)); > + > + if (IsListEmpty (&mBmcUsbNic)) { > + return EFI_NOT_FOUND; > + } > + > + ThisInstance = (HOST_INTERFACE_BMC_USB_NIC_INFO *)GetFirstNode > + (&mBmcUsbNic); while (TRUE) { > + if (ThisInstance->IsExposedByBmc) { > + ThisInstance->IsSuppportedHostInterface = FALSE; > + > + // Probe if Redfish Host Interface Credential Bootstrapping is > supported. > + ThisInstance->CredentialBootstrapping = > + ProbeRedfishCredentialBootstrap (); > + > + // Get IP address source > + GetLanConfigReq.SetSelector = 0; > + GetLanConfigReq.BlockSelector = 0; > + GetLanConfigReq.ChannelNumber.Bits.ChannelNo = ThisInstance- > >IpmiLanChannelNumber; > + GetLanConfigReq.ChannelNumber.Bits.GetParameter = 0; > + GetLanConfigReq.ChannelNumber.Bits.Reserved = 0; > + GetLanConfigReq.ParameterSelector = > IpmiLanIpAddressSource; > + ResponseDataSize = sizeof > (IPMI_GET_LAN_CONFIGURATION_PARAMETERS_RESPONSE) + sizeof > (IPMI_LAN_IP_ADDRESS_SRC); > + GetLanConfigReps = > (IPMI_GET_LAN_CONFIGURATION_PARAMETERS_RESPONSE > *)AllocateZeroPool (ResponseDataSize); > + GetLanConfigReps->CompletionCode = > IPMI_COMP_CODE_UNSPECIFIED; > + Status = > IpmiGetLanConfigurationParameters ( > + &GetLanConfigReq, > + GetLanConfigReps, > + &ResponseDataSize > + ); > + if (EFI_ERROR (Status) || (GetLanConfigReps->CompletionCode != > IPMI_COMP_CODE_NORMAL)) { > + DEBUG ((DEBUG_ERROR, " Failed to get IP address source at channel > %d: %r, 0x%02x.\n", ThisInstance->IpmiLanChannelNumber, Status, > GetLanConfigReps->CompletionCode)); > + FreePool (GetLanConfigReps); > + return Status; > + } > + > + IpAddressSrc = (IPMI_LAN_IP_ADDRESS_SRC *)(GetLanConfigReps + 1); > + DEBUG ((DEBUG_REDFISH_HOST_INTERFACE, " IP address source at > channel %d: %x\n", ThisInstance->IpmiLanChannelNumber, IpAddressSrc- > >Bits.AddressSrc)); > + ThisInstance->IpAssignedType = IpAddressSrc->Bits.AddressSrc; > + FreePool (GetLanConfigReps); > + > + // Get LAN IPv4 IP address > + GetLanConfigReq.ParameterSelector = IpmiLanIpAddress; > + ResponseDataSize = sizeof > (IPMI_GET_LAN_CONFIGURATION_PARAMETERS_RESPONSE) + sizeof > (IPMI_LAN_IP_ADDRESS); > + GetLanConfigReps = > (IPMI_GET_LAN_CONFIGURATION_PARAMETERS_RESPONSE > *)AllocateZeroPool (ResponseDataSize); > + GetLanConfigReps->CompletionCode = > IPMI_COMP_CODE_UNSPECIFIED; > + Status = IpmiGetLanConfigurationParameters ( > + &GetLanConfigReq, > + GetLanConfigReps, > + &ResponseDataSize > + ); > + if (EFI_ERROR (Status) || (GetLanConfigReps->CompletionCode != > IPMI_COMP_CODE_NORMAL)) { > + DEBUG ((DEBUG_ERROR, " Failed to get Dest IP address at channel > %d: > %r, 0x%02x.\n", ThisInstance->IpmiLanChannelNumber, Status, > GetLanConfigReps->CompletionCode)); > + FreePool (GetLanConfigReps); > + return Status; > + } > + > + DestIpAddress = (IPMI_LAN_IP_ADDRESS *)(GetLanConfigReps + 1); > + DEBUG (( > + DEBUG_REDFISH_HOST_INTERFACE, > + " Dest IP address at channel %d: %d.%d.%d.%d\n", > + ThisInstance->IpmiLanChannelNumber, > + DestIpAddress->IpAddress[0], > + DestIpAddress->IpAddress[1], > + DestIpAddress->IpAddress[2], > + DestIpAddress->IpAddress[3] > + )); > + CopyMem ((VOID *)&ThisInstance->RedfishIpAddressIpv4, (VOID > *)&DestIpAddress->IpAddress, sizeof (DestIpAddress->IpAddress)); > + // > + // According to UEFI spec, the IP address at BMC USB NIC host end is > the > IP address at BMC end minus 1. > + // > + CopyMem ((VOID *)&ThisInstance->HostIpAddressIpv4, (VOID > *)&DestIpAddress->IpAddress, sizeof (DestIpAddress->IpAddress)); > + ThisInstance->HostIpAddressIpv4[sizeof (ThisInstance- > >HostIpAddressIpv4) - 1] -= 1; > + FreePool (GetLanConfigReps); > + DEBUG (( > + DEBUG_REDFISH_HOST_INTERFACE, > + " Host IP address at channel %d: %d.%d.%d.%d\n", > + ThisInstance->IpmiLanChannelNumber, > + ThisInstance->HostIpAddressIpv4[0], > + ThisInstance->HostIpAddressIpv4[1], > + ThisInstance->HostIpAddressIpv4[2], > + ThisInstance->HostIpAddressIpv4[3] > + )); > + > + // Get IPv4 subnet mask > + GetLanConfigReq.ParameterSelector = IpmiLanSubnetMask; > + ResponseDataSize = sizeof > (IPMI_GET_LAN_CONFIGURATION_PARAMETERS_RESPONSE) + sizeof > (IPMI_LAN_SUBNET_MASK); > + GetLanConfigReps = > (IPMI_GET_LAN_CONFIGURATION_PARAMETERS_RESPONSE > *)AllocateZeroPool (ResponseDataSize); > + GetLanConfigReps->CompletionCode = > IPMI_COMP_CODE_UNSPECIFIED; > + Status = IpmiGetLanConfigurationParameters ( > + &GetLanConfigReq, > + GetLanConfigReps, > + &ResponseDataSize > + ); > + if ((EFI_ERROR (Status)) || (GetLanConfigReps->CompletionCode != > IPMI_COMP_CODE_NORMAL)) { > + DEBUG ((DEBUG_ERROR, " Failed to get subnet mask at channel %d: > %r, 0x%02x.\n", ThisInstance->IpmiLanChannelNumber, Status, > GetLanConfigReps->CompletionCode)); > + FreePool (GetLanConfigReps); > + return Status; > + } > + > + SubnetMask = (IPMI_LAN_SUBNET_MASK *)(GetLanConfigReps + 1); > + DEBUG (( > + DEBUG_REDFISH_HOST_INTERFACE, > + " Subnet mask at channel %d: %d.%d.%d.%d\n", > + ThisInstance->IpmiLanChannelNumber, > + SubnetMask->IpAddress[0], > + SubnetMask->IpAddress[1], > + SubnetMask->IpAddress[2], > + SubnetMask->IpAddress[3] > + )); > + CopyMem ((VOID *)&ThisInstance->SubnetMaskIpv4, (VOID > *)&SubnetMask->IpAddress, sizeof (SubnetMask->IpAddress)); > + FreePool (GetLanConfigReps); > + > + // Get Gateway IP address. > + GetLanConfigReq.ParameterSelector = IpmiLanDefaultGateway; > + ResponseDataSize = sizeof > (IPMI_GET_LAN_CONFIGURATION_PARAMETERS_RESPONSE) + sizeof > (IPMI_LAN_DEFAULT_GATEWAY); > + GetLanConfigReps = > (IPMI_GET_LAN_CONFIGURATION_PARAMETERS_RESPONSE > *)AllocateZeroPool (ResponseDataSize); > + GetLanConfigReps->CompletionCode = > IPMI_COMP_CODE_UNSPECIFIED; > + Status = IpmiGetLanConfigurationParameters ( > + &GetLanConfigReq, > + GetLanConfigReps, > + &ResponseDataSize > + ); > + if ((EFI_ERROR (Status)) || (GetLanConfigReps->CompletionCode != > IPMI_COMP_CODE_NORMAL)) { > + DEBUG ((DEBUG_ERROR, " Failed to get default gateway at channel > %d: %r, 0x%02x.\n", ThisInstance->IpmiLanChannelNumber, Status, > GetLanConfigReps->CompletionCode)); > + FreePool (GetLanConfigReps); > + return Status; > + } > + > + DefaultGateway = (IPMI_LAN_DEFAULT_GATEWAY > *)(GetLanConfigReps + 1); > + DEBUG (( > + DEBUG_REDFISH_HOST_INTERFACE, > + " Gateway at channel %d: %d.%d.%d.%d\n", > + ThisInstance->IpmiLanChannelNumber, > + DefaultGateway->IpAddress[0], > + DefaultGateway->IpAddress[1], > + DefaultGateway->IpAddress[2], > + DefaultGateway->IpAddress[3] > + )); > + CopyMem ((VOID *)&ThisInstance->GatewayIpv4, (VOID > *)&DefaultGateway->IpAddress, sizeof (DefaultGateway->IpAddress)); > + FreePool (GetLanConfigReps); > + > + // Get VLAN ID > + GetLanConfigReq.ParameterSelector = IpmiLanVlanId; > + ResponseDataSize = sizeof > (IPMI_GET_LAN_CONFIGURATION_PARAMETERS_RESPONSE) + sizeof > (IPMI_LAN_VLAN_ID); > + GetLanConfigReps = > (IPMI_GET_LAN_CONFIGURATION_PARAMETERS_RESPONSE > *)AllocateZeroPool (ResponseDataSize); > + GetLanConfigReps->CompletionCode = > IPMI_COMP_CODE_UNSPECIFIED; > + Status = IpmiGetLanConfigurationParameters ( > + &GetLanConfigReq, > + GetLanConfigReps, > + &ResponseDataSize > + ); > + if ((EFI_ERROR (Status)) || (GetLanConfigReps->CompletionCode != > IPMI_COMP_CODE_NORMAL)) { > + DEBUG ((DEBUG_ERROR, " Failed to get VLAN ID at channel %d: %r, > 0x%02x.\n", ThisInstance->IpmiLanChannelNumber, Status, > GetLanConfigReps->CompletionCode)); > + FreePool (GetLanConfigReps); > + return Status; > + } > + > + LanVlanId = (IPMI_LAN_VLAN_ID *)(GetLanConfigReps + 1); > + ThisInstance->VLanId = 0; > + if (LanVlanId->Data2.Bits.Enabled == 1) { > + ThisInstance->VLanId = LanVlanId->Data1.VanIdLowByte | (LanVlanId- > >Data2.Bits.VanIdHighByte << 8); > + } > + > + DEBUG ((DEBUG_REDFISH_HOST_INTERFACE, " VLAN ID %x\n", > ThisInstance->VLanId)); > + > + FreePool (GetLanConfigReps); > + > + // > + // Read USB device information. > + // > + if (ThisInstance->ThisUsbIo != NULL) { > + Status = ThisInstance->ThisUsbIo->UsbGetDeviceDescriptor > (ThisInstance->ThisUsbIo, &UsbDeviceDescriptor); > + if (!EFI_ERROR (Status)) { > + DEBUG ((DEBUG_REDFISH_HOST_INTERFACE, " USB NIC Vendor ID: > 0x%04x, Device ID: 0x%04x\n", UsbDeviceDescriptor.IdVendor, > UsbDeviceDescriptor.IdProduct)); > + ThisInstance->UsbVendorId = UsbDeviceDescriptor.IdVendor; > + ThisInstance->UsbProductId = UsbDeviceDescriptor.IdProduct; > + } else { > + DEBUG ((DEBUG_REDFISH_HOST_INTERFACE, " Fail to get USB device > descriptor.\n")); > + } > + } > + > + // All information is retrieved. > + ThisInstance->IsSuppportedHostInterface = TRUE; > + return EFI_SUCCESS; > + } > + > + if (IsNodeAtEnd (&mBmcUsbNic, &ThisInstance->NextInstance)) { > + break; > + } > + > + ThisInstance = (HOST_INTERFACE_BMC_USB_NIC_INFO *) > + GetNextNode (&mBmcUsbNic, > + &ThisInstance->NextInstance); } > + > + return EFI_NOT_FOUND; > +} > + > +/** > + This function caches the found IPMI LAN channel. So we > + don't have to sedn IPMI commands again if the USB NIC is > + connected later. > + > + @param[in] ChannelNum The IPMI channel number. > + @param[in] IpmiLanChannelMacAddress Pointer to EFI_MAC_ADDRESS. > + @param[in] IpmiLanMacAddressSize The MAC address size. > + > + @retval EFI_SUCCESS IPMI LAN channel is cached. > + @retval EFI_OUT_OF_RESOURCE Memory allocated failed. > + @retval Others Other errors. > + > +**/ > +EFI_STATUS > +CacheIpmiLanMac ( > + IN UINT8 ChannelNum, > + IN EFI_MAC_ADDRESS *IpmiLanChannelMacAddress, > + IN UINT8 IpmiLanMacAddressSize > + ) > +{ > + BMC_IPMI_LAN_CHANNEL_INFO *ChannelInfo; > + > + ChannelInfo = (BMC_IPMI_LAN_CHANNEL_INFO *)AllocateZeroPool > (sizeof > + (BMC_IPMI_LAN_CHANNEL_INFO)); if (ChannelInfo == NULL) { > + return EFI_OUT_OF_RESOURCES; > + } > + > + ChannelInfo->Channel = ChannelNum; > + CopyMem ((VOID *)&ChannelInfo->MacAddress.Addr, (VOID > +*)IpmiLanChannelMacAddress->Addr, IpmiLanMacAddressSize); > + ChannelInfo->MacAddressSize = IpmiLanMacAddressSize; > + InitializeListHead (&ChannelInfo->NextInstance); > + InsertTailList (&mBmcIpmiLan, &ChannelInfo->NextInstance); > + return EFI_SUCCESS; > +} > + > +/** > + This function checks if the IPMI channel already identified > + previously. > + > + @param[in] ChannelNum The IPMI channel number. > + @param[out] CachedIpmiLanChannel Pointer to retrieve the cached > + BMC_IPMI_LAN_CHANNEL_INFO. > + > + @retval EFI_SUCCESS IPMI LAN channel is found. > + @retval Others Other errors. > + > +**/ > +EFI_STATUS > +CheckCachedIpmiLanMac ( > + IN UINT8 ChannelNum, > + OUT BMC_IPMI_LAN_CHANNEL_INFO **CachedIpmiLanChannel > + ) > +{ > + BMC_IPMI_LAN_CHANNEL_INFO *ThisInstance; > + > + if (IsListEmpty (&mBmcIpmiLan)) { > + return EFI_NOT_FOUND; > + } > + > + ThisInstance = (BMC_IPMI_LAN_CHANNEL_INFO *)GetFirstNode > + (&mBmcIpmiLan); while (TRUE) { > + if (ThisInstance->Channel == ChannelNum) { > + *CachedIpmiLanChannel = ThisInstance; > + return EFI_SUCCESS; > + } > + > + if (IsNodeAtEnd (&mBmcIpmiLan, &ThisInstance->NextInstance)) { > + break; > + } > + > + ThisInstance = (BMC_IPMI_LAN_CHANNEL_INFO *) > + GetNextNode (&mBmcIpmiLan, > + &ThisInstance->NextInstance); } > + > + return EFI_NOT_FOUND; > +} > + > +/** > + This function goes through IPMI channels to find the > + mactched MAC addrss of BMC USB NIC endpoint. > + > + @param[in] UsbNicInfo The instance of > HOST_INTERFACE_BMC_USB_NIC_INFO. > + > + @retval EFI_SUCCESS Yes, USB NIC exposed by BMC is found. > + @retval EFI_NOT_FOUND No, USB NIC exposed by BMC is not found > + on the existing SNP handle. > + @retval Others Other errors. > + > +**/ > +EFI_STATUS > +HostInterfaceIpmiCheckMacAddress ( > + IN HOST_INTERFACE_BMC_USB_NIC_INFO *UsbNicInfo > + ) > +{ > + EFI_STATUS Status; > + EFI_STATUS ExitStatus; > + UINTN ChannelNum; > + UINT32 ResponseDataSize; > + IPMI_GET_CHANNEL_INFO_REQUEST GetChanelInfoRequest; > + IPMI_GET_CHANNEL_INFO_RESPONSE GetChanelInfoResponse; > + IPMI_GET_LAN_CONFIGURATION_PARAMETERS_REQUEST > GetLanConfigReq; > + IPMI_GET_LAN_CONFIGURATION_PARAMETERS_RESPONSE > *GetLanConfigReps; > + BMC_IPMI_LAN_CHANNEL_INFO *CachedIpmiLanChannel; > + UINT8 IpmiLanMacAddressSize; > + EFI_MAC_ADDRESS IpmiLanChannelMacAddress; > + BOOLEAN AlreadyCached; > + > + DEBUG ((DEBUG_INFO, "%a: Entry.\n", __FUNCTION__)); > + > + GetLanConfigReps = NULL; > + AlreadyCached = FALSE; > + if (!IsListEmpty (&mBmcIpmiLan)) { > + AlreadyCached = TRUE; > + } > + > + // Initial the get MAC address request. > + GetLanConfigReq.SetSelector = 0; > + GetLanConfigReq.BlockSelector = 0; > + GetLanConfigReq.ParameterSelector = IpmiLanMacAddress; > + > + ExitStatus = EFI_NOT_FOUND; > + for (ChannelNum = > IPMI_CHANNEL_NUMBER_IMPLEMENTATION_SPECIFIC_1; > + ChannelNum <= > IPMI_CHANNEL_NUMBER_IMPLEMENTATION_SPECIFIC_11; > + ChannelNum++) > + { > + IpmiLanMacAddressSize = 0; > + > + // Check if the IPMI channel information is already cached. > + Status = EFI_NOT_FOUND; > + if (AlreadyCached) { > + Status = CheckCachedIpmiLanMac ((UINT8)ChannelNum, > &CachedIpmiLanChannel); > + } > + > + if (Status == EFI_SUCCESS) { > + DEBUG ((DEBUG_REDFISH_HOST_INTERFACE, " Got cached IPMI LAN > info.\n")); > + IpmiLanMacAddressSize = sizeof (IPMI_LAN_MAC_ADDRESS); > + CopyMem ((VOID *)&IpmiLanChannelMacAddress.Addr, (VOID > *)&CachedIpmiLanChannel->MacAddress.Addr, IpmiLanMacAddressSize); > + } else { > + DEBUG ((DEBUG_REDFISH_HOST_INTERFACE, " No cached IPMI LAN > info\n")); > + DEBUG ((DEBUG_REDFISH_HOST_INTERFACE, " Send NetFn = App, > Command = 0x42 to channel %d\n", ChannelNum)); > + GetChanelInfoRequest.ChannelNumber.Bits.ChannelNo = > (UINT8)ChannelNum; > + Status = IpmiGetChannelInfo > ( > + > &GetChanelInfoRequest, > + > &GetChanelInfoResponse, > + &ResponseDataSize > + ); > + if (EFI_ERROR (Status)) { > + DEBUG ((DEBUG_ERROR, " - Fails to send command.\n", > ChannelNum)); > + continue; > + } > + > + DEBUG ((DEBUG_REDFISH_HOST_INTERFACE, " - Response data size = > 0x%x\n", ResponseDataSize)); > + if ((GetChanelInfoResponse.CompletionCode != > IPMI_COMP_CODE_NORMAL) || (ResponseDataSize == 0)) { > + DEBUG ((DEBUG_ERROR, " - Command returned fail: 0x%x.\n", > GetChanelInfoResponse.CompletionCode)); > + continue; > + } > + > + DEBUG (( > + DEBUG_REDFISH_HOST_INTERFACE, > + " - Channel protocol = 0x%x, Media = 0x%x\n", > + GetChanelInfoResponse.ProtocolType.Bits.ChannelProtocolType, > + GetChanelInfoResponse.MediumType.Bits.ChannelMediumType > + )); > + > + if (GetChanelInfoResponse.ChannelNumber.Bits.ChannelNo != > ChannelNum) { > + DEBUG (( > + DEBUG_ERROR, > + " - ChannelNumber = %d in the response which is not macthed to > the > request.\n", > + GetChanelInfoResponse.ChannelNumber.Bits.ChannelNo > + )); > + continue; > + } > + > + if ((GetChanelInfoResponse.MediumType.Bits.ChannelMediumType == > IPMI_CHANNEL_MEDIA_TYPE_802_3_LAN) && > + (GetChanelInfoResponse.ProtocolType.Bits.ChannelProtocolType == > IPMI_CHANNEL_PROTOCOL_TYPE_IPMB_1_0)) > + { > + DEBUG ((DEBUG_REDFISH_HOST_INTERFACE, " - Channel %d is a LAN > device!\n", ChannelNum)); > + > + ResponseDataSize = sizeof > (IPMI_GET_LAN_CONFIGURATION_PARAMETERS_RESPONSE) + > + sizeof (IPMI_LAN_MAC_ADDRESS); > + if (GetLanConfigReps == NULL) { > + GetLanConfigReps = > + (IPMI_GET_LAN_CONFIGURATION_PARAMETERS_RESPONSE > *)AllocateZeroPool (ResponseDataSize); > + if (GetLanConfigReps == NULL) { > + DEBUG ((DEBUG_ERROR, " Allocate memory failed for getting MAC > address.\n")); > + continue; > + } > + } > + > + GetLanConfigReq.ChannelNumber.Bits.ChannelNo = > (UINT8)ChannelNum; > + GetLanConfigReps->CompletionCode = > IPMI_COMP_CODE_UNSPECIFIED; > + Status = > IpmiGetLanConfigurationParameters ( > + &GetLanConfigReq, > + GetLanConfigReps, > + &ResponseDataSize > + ); > + if (EFI_ERROR (Status) || (GetLanConfigReps->CompletionCode != > IPMI_COMP_CODE_NORMAL)) { > + DEBUG (( > + DEBUG_ERROR, > + " Fails to get MAC address of channel %d, CompletionCode = > %02x.\n", > + ChannelNum, > + GetLanConfigReps->CompletionCode > + )); > + continue; > + } else { > + DEBUG ((DEBUG_REDFISH_HOST_INTERFACE, " The MAC address of > channel %d.\n", ChannelNum)); > + DEBUG (( > + DEBUG_REDFISH_HOST_INTERFACE, > + " %02x:%02x:%02x:%02x:%02x:%02x\n", > + *((UINT8 *)(GetLanConfigReps + 1) + 0), > + *((UINT8 *)(GetLanConfigReps + 1) + 1), > + *((UINT8 *)(GetLanConfigReps + 1) + 2), > + *((UINT8 *)(GetLanConfigReps + 1) + 3), > + *((UINT8 *)(GetLanConfigReps + 1) + 4), > + *((UINT8 *)(GetLanConfigReps + 1) + 5) > + )); > + IpmiLanMacAddressSize = sizeof (IPMI_LAN_MAC_ADDRESS); > + CopyMem ((VOID *)&IpmiLanChannelMacAddress.Addr, (VOID > *)(GetLanConfigReps + 1), IpmiLanMacAddressSize); > + } > + } > + } > + > + if (IpmiLanMacAddressSize != 0) { > + if (!AlreadyCached) { > + // Cache this IPMI LAN channel. > + DEBUG ((DEBUG_REDFISH_HOST_INTERFACE, " Cache this IPMI LAN > channel.\n")); > + CacheIpmiLanMac ((UINT8)ChannelNum, &IpmiLanChannelMacAddress, > IpmiLanMacAddressSize); > + } > + > + // > + // According to design spec in Readme file under RedfishPkg. > + // Compare the first five MAC address and > + // the 6th MAC address. > + // > + if ((IpmiLanMacAddressSize != UsbNicInfo->MacAddressSize) || > + (CompareMem ( > + (VOID *)UsbNicInfo->MacAddress, > + (VOID *)&IpmiLanChannelMacAddress.Addr, > + IpmiLanMacAddressSize - 1 > + ) != 0) || > + (IpmiLanChannelMacAddress.Addr[IpmiLanMacAddressSize - 1] != > + *(UsbNicInfo->MacAddress + IpmiLanMacAddressSize - 1) - 1) > + ) > + { > + DEBUG ((DEBUG_REDFISH_HOST_INTERFACE, " MAC address is not > matched.\n")); > + continue; > + } > + > + // This is the NIC exposed by BMC. > + UsbNicInfo->IpmiLanChannelNumber = (UINT8)ChannelNum; > + UsbNicInfo->IsExposedByBmc = TRUE; > + DEBUG ((DEBUG_REDFISH_HOST_INTERFACE, " MAC address is > matched.\n")); > + ExitStatus = EFI_SUCCESS; > + break; > + } > + } > + > + if (GetLanConfigReps != NULL) { > + FreePool (GetLanConfigReps); > + } > + > + return ExitStatus; > +} > + > +/** > + This function searches the next MSG_USB_DP device path node. > + > + @param[in] ThisDevicePath Device path to search. > + > + @retval NULL MSG_USB_DP is not found. > + Otherwise MSG_USB_DP is found. > + > +**/ > +EFI_DEVICE_PATH_PROTOCOL * > +UsbNicGetNextMsgUsbDp ( > + IN EFI_DEVICE_PATH_PROTOCOL *ThisDevicePath > + ) > +{ > + if (ThisDevicePath == NULL) { > + return NULL; > + } > + > + while (TRUE) { > + ThisDevicePath = NextDevicePathNode (ThisDevicePath); > + if (IsDevicePathEnd (ThisDevicePath)) { > + return NULL; > + } > + > + if ((ThisDevicePath->Type == MESSAGING_DEVICE_PATH) && > (ThisDevicePath->SubType == MSG_USB_DP)) { > + return ThisDevicePath; > + } > + } > + > + return NULL; > +} > + > +/** > + This function search the UsbIo handle that matches the UsbDevicePath. > + > + @param[in] UsbDevicePath Device path of this SNP handle. > + @param[out] UsbIo Return the UsbIo protocol. > + > + @retval EFI_SUCCESS Yes, UsbIo protocl is found. > + @retval EFI_NOT_FOUND No, UsbIo protocl is not found > + @retval Others Other errors. > + > +**/ > +EFI_STATUS > +UsbNicSearchUsbIo ( > + IN EFI_DEVICE_PATH_PROTOCOL *UsbDevicePath, > + OUT EFI_USB_IO_PROTOCOL **UsbIo > + ) > +{ > + EFI_STATUS Status; > + UINTN BufferSize; > + EFI_HANDLE *HandleBuffer; > + UINT16 Length; > + UINTN Index; > + CHAR16 *DevicePathStr; > + EFI_DEVICE_PATH_PROTOCOL *TempDevicePath; > + EFI_DEVICE_PATH_PROTOCOL *ThisDevicePath; > + EFI_DEVICE_PATH_PROTOCOL *ThisDevicePathEnd; > + EFI_DEVICE_PATH_PROTOCOL *ThisUsbDevicePath; > + EFI_DEVICE_PATH_PROTOCOL *ThisUsbDevicePathEnd; > + > + DEBUG ((DEBUG_INFO, "%a: Entry.\n", __FUNCTION__)); DEBUG > + ((DEBUG_REDFISH_HOST_INTERFACE, "Device path on the EFI handle > which > + has UsbIo and SNP instaleld on it.\n")); DevicePathStr = > + ConvertDevicePathToText (UsbDevicePath, FALSE, FALSE); DEBUG > + ((DEBUG_REDFISH_HOST_INTERFACE, "%s\n", DevicePathStr)); FreePool > + (DevicePathStr); > > It would be better to consider the case when ConvertDevicePathToText() > returns NULL pointer. > > + > + BufferSize = 0; > + HandleBuffer = NULL; > + *UsbIo = NULL; > + Status = gBS->LocateHandle ( > + ByProtocol, > + &gEfiUsbIoProtocolGuid, > + NULL, > + &BufferSize, > + NULL > + ); > + if (Status == EFI_BUFFER_TOO_SMALL) { > + DEBUG ((DEBUG_REDFISH_HOST_INTERFACE, " %d UsbIo protocol > instances.\n", BufferSize/sizeof (EFI_HANDLE))); > + HandleBuffer = AllocateZeroPool (BufferSize); > + if (HandleBuffer == NULL) { > + DEBUG ((DEBUG_ERROR, " Falied to allocate buffer for the > handles.\n")); > + return EFI_OUT_OF_RESOURCES; > + } > + > + Status = gBS->LocateHandle ( > + ByProtocol, > + &gEfiUsbIoProtocolGuid, > + NULL, > + &BufferSize, > + HandleBuffer > + ); > + if (EFI_ERROR (Status)) { > + DEBUG ((DEBUG_ERROR, " Falied to locate UsbIo protocol handles.\n")); > + FreePool (HandleBuffer); > + return Status; > + } > + } else { > + return Status; > + } > + > + for (Index = 0; Index < (BufferSize/sizeof (EFI_HANDLE)); Index++) { > + Status = gBS->HandleProtocol ( > + *(HandleBuffer + Index), > + &gEfiDevicePathProtocolGuid, > + (VOID **)&ThisDevicePath > + ); > + if (EFI_ERROR (Status)) { > + continue; > + } > + > + DEBUG ((DEBUG_REDFISH_HOST_INTERFACE, "Device path on #%d > instance of UsbIo.\n", Index)); > + DevicePathStr = ConvertDevicePathToText (ThisDevicePath, FALSE, > FALSE); > + DEBUG ((DEBUG_REDFISH_HOST_INTERFACE, "%s\n", DevicePathStr)); > + FreePool (DevicePathStr); > > It would be better to consider the case when ConvertDevicePathToText() > returns NULL pointer. > > Thanks, > Nickle > > + > + Status = EFI_NOT_FOUND; > + > + // Search for the starting MSG_USB_DP node. > + ThisUsbDevicePath = UsbDevicePath; > + if ((DevicePathType (ThisUsbDevicePath) != MESSAGING_DEVICE_PATH) > || > + (DevicePathSubType (ThisUsbDevicePath) != MSG_USB_DP)) > + { > + ThisUsbDevicePath = UsbNicGetNextMsgUsbDp (ThisUsbDevicePath); > + if (ThisUsbDevicePath == NULL) { > + continue; > + } > + } > + > + if ((DevicePathType (ThisDevicePath) != MESSAGING_DEVICE_PATH) || > + (DevicePathSubType (ThisDevicePath) != MSG_USB_DP)) > + { > + ThisDevicePath = UsbNicGetNextMsgUsbDp (ThisDevicePath); > + if (ThisDevicePath == NULL) { > + continue; > + } > + } > + > + // Search for the ending MSG_USB_DP node. > + ThisDevicePathEnd = ThisDevicePath; > + ThisUsbDevicePathEnd = ThisUsbDevicePath; > + while (TRUE) { > + TempDevicePath = UsbNicGetNextMsgUsbDp (ThisDevicePathEnd); > + if (TempDevicePath == NULL) { > + break; > + } > + > + ThisDevicePathEnd = TempDevicePath; > + } > + > + while (TRUE) { > + TempDevicePath = UsbNicGetNextMsgUsbDp (ThisUsbDevicePathEnd); > + if (TempDevicePath == NULL) { > + break; > + } > + > + ThisUsbDevicePathEnd = TempDevicePath; > + } > + > + // Compare these two device paths > + Length = (UINT16)((UINTN)(UINT8 *)ThisDevicePathEnd + > DevicePathNodeLength (ThisDevicePathEnd) - (UINTN)(UINT8 > *)ThisDevicePath); > + if (Length != ((UINTN)(UINT8 *)ThisUsbDevicePathEnd + > DevicePathNodeLength (ThisUsbDevicePathEnd) - (UINTN)(UINT8 > *)ThisUsbDevicePath)) { > + continue; > + } > + > + if (CompareMem ( > + (VOID *)ThisDevicePath, > + (VOID *)ThisUsbDevicePath, > + Length > + ) == 0) > + { > + Status = EFI_SUCCESS; > + DEBUG ((DEBUG_REDFISH_HOST_INTERFACE, "EFI handle with the > correct UsbIo is found at #%d instance of UsbIo.\n", Index)); > + break; > + } > + } > + > + if (Status == EFI_SUCCESS) { > + // Locate UsbIo from this handle. > + Status = gBS->HandleProtocol ( > + *(HandleBuffer + Index), > + &gEfiUsbIoProtocolGuid, > + (VOID **)UsbIo > + ); > + return Status; > + } > + > + return EFI_NOT_FOUND; > +} > + > +/** > + This function identifies if the USB NIC is exposed by BMC as > + the host-BMC channel. > + > + @param[in] Handle This is the EFI handle with SNP installed. > + @param[in] UsbDevicePath USB device path. > + > + @retval EFI_SUCCESS Yes, USB NIC exposed by BMC is found. > + @retval EFI_NOT_FOUND No, USB NIC exposed by BMC is not found > + on the existing SNP handle. > + @retval Others Other errors. > + > +**/ > +EFI_STATUS > +IdentifyUsbNicBmcChannel ( > + IN EFI_HANDLE Handle, > + IN EFI_DEVICE_PATH_PROTOCOL *UsbDevicePath > + ) > +{ > + UINTN Index; > + EFI_STATUS Status; > + EFI_SIMPLE_NETWORK_PROTOCOL *Snp; > + EFI_USB_IO_PROTOCOL *UsbIo; > + HOST_INTERFACE_BMC_USB_NIC_INFO *BmcUsbNic; > + > + DEBUG ((DEBUG_INFO, "%a: Entry.\n", __FUNCTION__)); Status = > + gBS->HandleProtocol ( > + Handle, > + &gEfiSimpleNetworkProtocolGuid, > + (VOID **)&Snp > + ); > + if (EFI_ERROR (Status)) { > + DEBUG ((DEBUG_ERROR, " Failed to locate SNP.\n")); > + return Status; > + } > + > + Status = UsbNicSearchUsbIo (UsbDevicePath, &UsbIo); if (EFI_ERROR > + (Status)) { > + DEBUG ((DEBUG_ERROR, " Failed to find USBIO.\n")); > + return Status; > + } > + > + // Get the MAC address of this SNP instance. > + BmcUsbNic = AllocateZeroPool (sizeof > + (HOST_INTERFACE_BMC_USB_NIC_INFO)); > + if (BmcUsbNic == NULL) { > + DEBUG ((DEBUG_ERROR, " Failed to allocate memory for > HOST_INTERFACE_BMC_USB_NIC_INFO.\n")); > + return EFI_OUT_OF_RESOURCES; > + } > + > + InitializeListHead (&BmcUsbNic->NextInstance); > + BmcUsbNic->MacAddressSize = Snp->Mode->HwAddressSize; > + BmcUsbNic->MacAddress = AllocateZeroPool (sizeof (BmcUsbNic- > >MacAddressSize)); > + if (BmcUsbNic->MacAddress == NULL) { > + DEBUG ((DEBUG_ERROR, " Failed to allocate memory for HW MAC > addresss.\n")); > + FreePool (BmcUsbNic); > + return EFI_OUT_OF_RESOURCES; > + } > + > + CopyMem ( > + (VOID *)BmcUsbNic->MacAddress, > + (VOID *)&Snp->Mode->CurrentAddress, > + BmcUsbNic->MacAddressSize > + ); > + DEBUG ((DEBUG_REDFISH_HOST_INTERFACE, " MAC address (in size %d) > for this SNP instance:\n ", BmcUsbNic->MacAddressSize)); > + for (Index = 0; Index < BmcUsbNic->MacAddressSize; Index++) { > + DEBUG ((DEBUG_REDFISH_HOST_INTERFACE, "%02x ", > + *(BmcUsbNic->MacAddress + Index))); } > + > + DEBUG ((DEBUG_REDFISH_HOST_INTERFACE, "\n")); > + BmcUsbNic->ThisSnp = Snp; > + BmcUsbNic->ThisUsbIo = UsbIo; > + > + Status = HostInterfaceIpmiCheckMacAddress (BmcUsbNic); if (Status == > + EFI_SUCCESS) { > + BmcUsbNic->IsExposedByBmc = TRUE; > + DEBUG ((DEBUG_REDFISH_HOST_INTERFACE, " BMC exposed USB NIC > is found.\n")); > + } else { > + DEBUG ((DEBUG_REDFISH_HOST_INTERFACE, " BMC exposed USB NIC > is not found.\n")); > + } > + > + InsertTailList (&mBmcUsbNic, &BmcUsbNic->NextInstance); > + return Status; > +} > + > +/** > + This function checks if the USB NIC exposed by BMC > + on each handle has SNP protocol installed on it. > + > + @param[in] HandleNumer Number of handles to check. > + @param[in] HandleBuffer Handles buffer. > + > + @retval EFI_SUCCESS Yes, USB NIC exposed by BMC is found. > + @retval EFI_NOT_FOUND No, USB NIC exposed by BMC is not found > + on the existing SNP handle. > + @retval Others Other errors. > + > +**/ > +EFI_STATUS > +CheckBmcUsbNicOnHandles ( > + IN UINTN HandleNumer, > + IN EFI_HANDLE *HandleBuffer > + ) > +{ > + UINTN Index; > + EFI_STATUS Status; > + EFI_DEVICE_PATH_PROTOCOL *DevicePath; > + BOOLEAN GotOneUsbNIc; > + > + if ((HandleNumer == 0) || (HandleBuffer == NULL)) { > + return EFI_INVALID_PARAMETER; > + } > + > + DEBUG ((DEBUG_INFO, "%a: Entry, #%d SNP handle\n", __FUNCTION__, > + HandleNumer)); > + > + GotOneUsbNIc = FALSE; > + for (Index = 0; Index < HandleNumer; Index++) { > + Status = gBS->HandleProtocol ( > + *(HandleBuffer + Index), > + &gEfiDevicePathProtocolGuid, > + (VOID **)&DevicePath > + ); > + if (EFI_ERROR (Status)) { > + DEBUG ((DEBUG_ERROR, " Failed to locate SNP on %d handle.\n", > __FUNCTION__, Index)); > + continue; > + } > + > + // Check if this is an BMC exposed USB NIC device. > + while (TRUE) { > + if ((DevicePath->Type == MESSAGING_DEVICE_PATH) && (DevicePath- > >SubType == MSG_USB_DP)) { > + Status = IdentifyUsbNicBmcChannel (*(HandleBuffer + Index), > DevicePath); > + if (!EFI_ERROR (Status)) { > + GotOneUsbNIc = TRUE; > + break; > + } > + } > + > + DevicePath = NextDevicePathNode (DevicePath); > + if (IsDevicePathEnd (DevicePath)) { > + break; > + } > + } > + } > + > + if (GotOneUsbNIc) { > + return EFI_SUCCESS; > + } > + > + return EFI_NOT_FOUND; > +} > + > +/** > + This function checks if the USB NIC exposed by BMC > + is already connected. > + > + @param[in] Registration Locate SNP protocol from the notification > + registeration key. > + NULL means locate SNP protocol from the > existing > + handles. > + > + @retval EFI_SUCCESS Yes, USB NIC exposed by BMC is found. > + @retval EFI_NOT_FOUND No, USB NIC exposed by BMC is not found > + on the existing SNP handle. > + @retval Others Other errors. > + > +**/ > +EFI_STATUS > +CheckBmcUsbNic ( > + VOID *Registration > + ) > +{ > + EFI_STATUS Status; > + EFI_HANDLE Handle; > + UINTN BufferSize; > + EFI_HANDLE *HandleBuffer; > + > + DEBUG ((DEBUG_INFO, "%a: Entry, the registration key - 0x%08x.\n", > + __FUNCTION__, Registration)); > + > + Handle = NULL; > + Status = EFI_SUCCESS; > + BufferSize = 0; > + > + Status = gBS->LocateHandle ( > + Registration == NULL ? ByProtocol : ByRegisterNotify, > + &gEfiSimpleNetworkProtocolGuid, > + Registration, > + &BufferSize, > + NULL > + ); > + if (Status == EFI_BUFFER_TOO_SMALL) { > + DEBUG ((DEBUG_REDFISH_HOST_INTERFACE, " %d SNP protocol > instances.\n", BufferSize/sizeof (EFI_HANDLE))); > + HandleBuffer = AllocateZeroPool (BufferSize); > + if (HandleBuffer == NULL) { > + DEBUG ((DEBUG_ERROR, " Falied to allocate buffer for the > handles.\n")); > + return EFI_OUT_OF_RESOURCES; > + } > + > + Status = gBS->LocateHandle ( > + Registration == NULL ? ByProtocol : ByRegisterNotify, > + &gEfiSimpleNetworkProtocolGuid, > + Registration, > + &BufferSize, > + HandleBuffer > + ); > + if (EFI_ERROR (Status)) { > + DEBUG ((DEBUG_ERROR, " Falied to locate SNP protocol handles.\n")); > + FreePool (HandleBuffer); > + return Status; > + } > + } else if (EFI_ERROR (Status)) { > + return Status; > + } > + > + // Check USB NIC on handles. > + Status = CheckBmcUsbNicOnHandles (BufferSize/sizeof (EFI_HANDLE), > + HandleBuffer); if (!EFI_ERROR (Status)) { > + // Retrieve the rest of BMC USB NIC information for Redfish over IP > information > + // and USB Network Interface V2. > + Status = RetrievedBmcUsbNicInfo (); > + if (!EFI_ERROR (Status)) { > + DEBUG ((DEBUG_REDFISH_HOST_INTERFACE, " Install protocol to > notify the platform Redfish Host Interface information is ready.\n")); > + Status = gBS->InstallProtocolInterface ( > + &Handle, > + &mPlatformHostInterfaceBmcUsbNicReadinessGuid, > + EFI_NATIVE_INTERFACE, > + NULL > + ); > + if (EFI_ERROR (Status)) { > + DEBUG ((DEBUG_ERROR, " Install protocol fail %r.\n", Status)); > + } > + } > + } > + > + FreePool (HandleBuffer); > + return Status; > +} > + > +/** > + Notification event of SNP readiness. > + > + @param[in] Event Event whose notification function is > being > invoked. > + @param[in] Context The pointer to the notification > function's > context, > + which is implementation-dependent. > + > +**/ > +VOID > +EFIAPI > +PlatformHostInterfaceSnpCallback ( > + IN EFI_EVENT Event, > + IN VOID *Context > + ) > +{ > + DEBUG ((DEBUG_INFO, "%a: Entry.\n", __FUNCTION__)); > + > + CheckBmcUsbNic (mPlatformHostInterfaceSnpRegistration); > + return; > +} > + > +/** > + Get the EFI protocol GUID installed by platform library which > + indicates the necessary information is ready for building > + SMBIOS 42h record. > + > + @param[out] InformationReadinessGuid Pointer to retrive the protocol > + GUID. > + > + @retval EFI_SUCCESS Notification is required for building up > + SMBIOS type 42h record. > + @retval EFI_UNSUPPORTED Notification is not required for building up > + SMBIOS type 42h record. > + @retval EFI_ALREADY_STARTED Platform host information is already ready. > + @retval Others Other errors. > +**/ > +EFI_STATUS > +RedfishPlatformHostInterfaceNotification ( > + OUT EFI_GUID **InformationReadinessGuid > + ) > +{ > + EFI_STATUS Status; > + > + DEBUG ((DEBUG_INFO, "%a: Entry\n", __FUNCTION__)); > + > + *InformationReadinessGuid = NULL; > + InitializeListHead (&mBmcUsbNic); > + InitializeListHead (&mBmcIpmiLan); > + > + // > + // Check if USB NIC exposed by BMC is already // connected. > + // > + Status = CheckBmcUsbNic (NULL); > + if (!EFI_ERROR (Status)) { > + return EFI_ALREADY_STARTED; > + } > + > + if (Status == EFI_NOT_FOUND) { > + DEBUG ((DEBUG_REDFISH_HOST_INTERFACE, "%a: BMC USB NIC is not > + found. Register the notification.\n", __FUNCTION__)); > + > + // Register the notification of SNP installation. > + Status = gBS->CreateEvent ( > + EVT_NOTIFY_SIGNAL, > + TPL_CALLBACK, > + PlatformHostInterfaceSnpCallback, > + NULL, > + &mPlatformHostInterfaceSnpEvent > + ); > + if (EFI_ERROR (Status)) { > + DEBUG ((DEBUG_ERROR, "%a: Fail to create event for the installation of > SNP protocol.", __FUNCTION__)); > + return Status; > + } > + > + Status = gBS->RegisterProtocolNotify ( > + &gEfiSimpleNetworkProtocolGuid, > + mPlatformHostInterfaceSnpEvent, > + &mPlatformHostInterfaceSnpRegistration > + ); > + if (EFI_ERROR (Status)) { > + DEBUG ((DEBUG_ERROR, "%a: Fail to register event for the installation > of > SNP protocol.", __FUNCTION__)); > + return Status; > + } > + > + *InformationReadinessGuid = > &mPlatformHostInterfaceBmcUsbNicReadinessGuid; > + return EFI_SUCCESS; > + } > + > + DEBUG ((DEBUG_ERROR, "%a: Something wrong when look for BMC USB > +NIC.\n", __FUNCTION__)); > + return Status; > +} > -- > 2.37.1.windows.1 -=-=-=-=-=-=-=-=-=-=-=- Groups.io Links: You receive all messages sent to this group. View/Reply Online (#101409): https://edk2.groups.io/g/devel/message/101409 Mute This Topic: https://groups.io/mt/97498499/21656 Group Owner: devel+ow...@edk2.groups.io Unsubscribe: https://edk2.groups.io/g/devel/unsub [arch...@mail-archive.com] -=-=-=-=-=-=-=-=-=-=-=-