From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from NAM11-CO1-obe.outbound.protection.outlook.com (NAM11-CO1-obe.outbound.protection.outlook.com [40.107.220.63]) by mx.groups.io with SMTP id smtpd.web10.6078.1679281990997896105 for ; Sun, 19 Mar 2023 20:13:11 -0700 Authentication-Results: mx.groups.io; dkim=pass header.i=@nvidia.com header.s=selector2 header.b=fv3XTHra; spf=permerror, err=parse error for token &{10 18 %{i}._ip.%{h}._ehlo.%{d}._spf.vali.email}: invalid domain name (domain: nvidia.com, ip: 40.107.220.63, mailfrom: nicklew@nvidia.com) ARC-Seal: i=1; a=rsa-sha256; s=arcselector9901; d=microsoft.com; cv=none; b=gW0ytAW3rycyHvEucgpYwFN0E1wBFod37TcwdldjQxKykIqgxAEpFJL0E7k2M4wtKup9pCPzrD2pFXcgC+qBv9dKYPwCSIxDPyaQF/iG5/HZlCijN63llji/EcDsPuGll/3F+mFscWqBsh1nODm+sLCisBC9+55meTCYpDhHHnP518x5HGSYcwhgLQripGIAyqVFDWcI0sBaqxpDpUvYJ6oh73fXqO9auAoGSIBChhQUJ9afcUb1Z0Re1pSonXtjwqGaFblPR2LH9qpIKqkrFqF3NP9ehhi31sEe4IwZodyIFbjxAxaHgxS5JYiRsH3WB/eN4BPqJlm0uPjEHd2DnA== 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=0f05Tc4fQlFyBBMFGFfcTRCWo7NRBHKH8P1YG/K1ZS0=; b=SAZvV/j7XZbw5XK+zafW1nBK+BB9NznBQyRj7KlHeBohwYF7UeSQurpNmfq711pX6O/5Qy5P9MsJpUw/UC2rzOiNHiXpN08fN5PAZck+Pyw60YJCA8RMhYOlXu5w/jx2a16liCzcAfd/hap3hsXh/qjWvnaUvnJQivG3TJ5ZDwZ7fjcmnt/0ta2zzPfav9OCglI82keB/DrnXfly2IdPShNHG5uHZe0AVKI3AZyaRDVcOEirS5ofiCj6sYnG5q7ORXUilgTnjAPeiabUxLTF54j9PwTXw7Pgp95+M5H1aGyP7wtVRgnQN56XLmRtU9BANO44zAaPn+gn2Ps4I5Xs5g== ARC-Authentication-Results: i=1; mx.microsoft.com 1; spf=pass smtp.mailfrom=nvidia.com; dmarc=pass action=none header.from=nvidia.com; dkim=pass header.d=nvidia.com; arc=none DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=Nvidia.com; s=selector2; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-SenderADCheck; bh=0f05Tc4fQlFyBBMFGFfcTRCWo7NRBHKH8P1YG/K1ZS0=; b=fv3XTHraUiAJH/Ev5moRweySX6pxTgvOmMhiXgXjACuwJ6i4ARsAijsp89smOKrzvUz43Hh+5dA982WrUdDUtONYf2EOgnMCUaYh+Qr8pzKjGt7Bol1b01xUcfLjqDNnNsxae9XjAkRqzr5+0z/SttZOU/Pni5mM5X1uQIwfxqdFjzcYebUjHLzNKx74VTrklmoJGPiFsRubglWF5hforStgNSwxixiwirBL+Zk2WUBzy6ERcoqb02poTtSZQVAj0fNx5KwwYIODqVizqwOtWGTRNavmg3r0GbXLFEmXNXXELwgOJKHW5r+IxkbQDCfeWg1sv9fvt9KOhW1FtYpg1Q== Received: from MW4PR12MB7031.namprd12.prod.outlook.com (2603:10b6:303:1ef::6) by MW4PR12MB6754.namprd12.prod.outlook.com (2603:10b6:303:1eb::7) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.6178.37; Mon, 20 Mar 2023 03:13:07 +0000 Received: from MW4PR12MB7031.namprd12.prod.outlook.com ([fe80::c27a:fa4b:66ea:d266]) by MW4PR12MB7031.namprd12.prod.outlook.com ([fe80::c27a:fa4b:66ea:d266%5]) with mapi id 15.20.6178.037; Mon, 20 Mar 2023 03:13:04 +0000 From: "Nickle Wang" To: "abner.chang@amd.com" , "devel@edk2.groups.io" CC: Igor Kulchytskyy Subject: Re: [PATCH 1/3] RedfishPkg/Library: Redfish BMC USBNIC Host Interface Thread-Topic: [PATCH 1/3] RedfishPkg/Library: Redfish BMC USBNIC Host Interface Thread-Index: AQHZUp2ZYNGQdwDcokG0hsNG1cusAa8DCh7A Date: Mon, 20 Mar 2023 03:13:03 +0000 Message-ID: References: <20230309154055.505-1-abner.chang@amd.com> <20230309154055.505-2-abner.chang@amd.com> In-Reply-To: <20230309154055.505-2-abner.chang@amd.com> Accept-Language: en-US X-MS-Has-Attach: X-MS-TNEF-Correlator: authentication-results: dkim=none (message not signed) header.d=none;dmarc=none action=none header.from=nvidia.com; x-ms-publictraffictype: Email x-ms-traffictypediagnostic: MW4PR12MB7031:EE_|MW4PR12MB6754:EE_ x-ms-office365-filtering-correlation-id: 14777fac-a82c-4156-ca07-08db28f10511 x-ms-exchange-senderadcheck: 1 x-ms-exchange-antispam-relay: 0 x-microsoft-antispam: BCL:0; x-microsoft-antispam-message-info: W6x2onmXGzFunjjRsrykFHRAqGx/M/Yp9eugfjYdXNKMR9lX8FQ+lfIijGmKzUQd0p7bKTQG2zS4u5yUUcWMEUYVqp1rpkqmI8uzLXEc2OCxt0nifa89ivqOpiQeGOTNpVb+MZTFsG/5c5I5zUYpT6WbVKtGnYXeLh2RFagQnUHA486lZnftqwVL6hqK6bt4H4Ra1hhTtNmwFd32l0rfyC23pRftQ5HAGzvXvgsSc9Z19eXVOQGlJtlX7GGKQ9pyL/GyCSKnJPPZ2dI2LcxNXaCrkJwkUHQtrJwduD7mEd34hT3SS4wRtmsvegVBMN9afG8o+t/Qz31TUmjR0jnUlPlwq3d2vIL320/xiSngk0cBS2hQH4cH0unhWeuAncRnuZlgsycVJelJDaRFmkkcvdCoZ/lnGMahuC2Eh9pmg88gqebO9a5WfCKdsIJAGUp8Ogw4nm4fWWfEdseLri4W/ETUJE8q3UP5xc6/VHFJDYUnKTzT+OwRIFQxDy2XI4cRF8sDUTFevLRHbTeiwOpkBkdwedERE3GiABo+SUQPkgkaAPGPWijc+i/odFF5rxugh57+dO4Z7bobf2JZrZ1Kh8D+7yRI0uqssVHfeTM5DTF2QCqNpmJ2Pe7CXS0DZaL6pwElYoT2zjzm6uGRIUpZqaC7uikRJD2h+72Y4G+lAS6k/kM1OvFJJ2MlivFE02LMks098h4AedbT4JG1mgxyQg== x-forefront-antispam-report: CIP:255.255.255.255;CTRY:;LANG:en;SCL:1;SRV:;IPV:NLI;SFV:NSPM;H:MW4PR12MB7031.namprd12.prod.outlook.com;PTR:;CAT:NONE;SFS:(13230025)(4636009)(396003)(136003)(366004)(376002)(346002)(39860400002)(451199018)(478600001)(71200400001)(7696005)(83380400001)(316002)(8676002)(66946007)(76116006)(66556008)(66476007)(66446008)(64756008)(186003)(9686003)(26005)(6506007)(110136005)(53546011)(4326008)(30864003)(8936002)(52536014)(5660300002)(41300700001)(122000001)(38100700002)(2906002)(55016003)(86362001)(38070700005)(33656002)(579004)(559001);DIR:OUT;SFP:1101; x-ms-exchange-antispam-messagedata-chunkcount: 1 x-ms-exchange-antispam-messagedata-0: =?us-ascii?Q?ym6jWIGba4fVTqGVijZRiS4WA+ZTsgOBDZFIKgv0f/gZzliNTlhncHRKJGxm?= =?us-ascii?Q?v8n7HLQNGMKhLzuG3XlvV4McwEtzOGen5ewXFz017T5Dga3z0D5JGKTpReai?= =?us-ascii?Q?6hitVLk7xR/HrCOc4elyMe7V7EhxLbncRt9bYKaxlL5zV89ofMF2hctFDXTN?= =?us-ascii?Q?kYnJXauFyOiQFXuwIvdZ03RFORwv0q0UD+Lpm0PQHEYf6GdG7C93CURNl2/x?= =?us-ascii?Q?5ql2YzRSAXJ5iT/AOMwMZqwbX1JAexL2q1YoEAXjMI91jZuVKCM1giLUS1hp?= =?us-ascii?Q?Fuwm0srftzW1+NenrL7QWSd64LCUgrWEX2m2kzvJ1aSwNuLYB5181pIVmxp3?= =?us-ascii?Q?k14dV5QP3bMpR/QFid1eWI7a1maDIcUpdgqnlCSlYBFjOwxfDp8A+l7wmoKH?= =?us-ascii?Q?U0NWIUdtoUYROV92MqvRgH0ZuIV9mva/nW2cUYkFBZh3BkRq7sUAYHxY5CX+?= =?us-ascii?Q?RYUjGH9b58PT2sUiF516oDxb1TaJ4ttjkElEPv9WmZYNzwlF27qSlBCoQBz4?= =?us-ascii?Q?3fmVZ5g46WOwNvUu7Ly8FTvqqDWWt1yy8nYARl1gaI46pjPTV+4jaiIvMs56?= =?us-ascii?Q?5GtT7qiX1SBXC0TuCSOZD/h0zSFW+ZKbV3Xba1Ve+8CDTzv4TxPdkVAp3h64?= =?us-ascii?Q?tOyqO1gXWPPW6Ri5N0I8zBgndd3EjRQoSQJqMVGQsXD0QlHhUXTtvQ/LeBDJ?= =?us-ascii?Q?XNZE4s2B/ATgQmkgUM9ZhearCcLrZebKoAG5Wf4VAP4qeCe+pMZ/+ZKYpDho?= =?us-ascii?Q?s2L03fTnBuAL4E8QYJlEvK2E523x+M44UQ39BCKufiz0bTAGzW6ufcQ8Kb1Z?= =?us-ascii?Q?gyQXZwDc3Xms+bljJoJvgTNqkshIq2gu0W6ejWNHfA2ftEFkBq73B95rJFrJ?= =?us-ascii?Q?P7Kn2K6Q+EcnXxbaTe447/8U6ZRIZY7MDAoHvGkff2SYi65O1gUzhfuzsZh3?= =?us-ascii?Q?QE7Kar0zzGJTLB4HS5fB/QKUd/PaWK7ONwf1qSKLCL3aj5xMlxLkJP/Ulutt?= =?us-ascii?Q?FPX5TIHPveUFpD5alWfGQfxLQNVEiFn9WYpXrPAXloYPVCT4Hf3q1jpKl1ir?= =?us-ascii?Q?ZPfuS1nyXXEbavD3+Au+s5kn+pRl1IsCsZo3Y5tEnIMoG6yrpT4qWuwG9Y5H?= =?us-ascii?Q?nNFk+0d/qZZtHU1ftEc902FOszxLWziC8Q4zWaotS8Yu0T0u/bhD/yYbmEHd?= =?us-ascii?Q?lhYUlwAj+sy20vxNdR+mgNgWwaVLUX51/fwZffdsp3mp9MbaqE8BCvBRarVH?= =?us-ascii?Q?jV1Gf4uqdeNg//6+DxtrRsvprOkzJLASdCMz+taetnC7V36KfmFXtIhTT4+e?= =?us-ascii?Q?0lno1/0V8nlZbP/OLg9XKzPy/U8joBNfPyX6dcY7iwmEZlJn63nlCS8MuGSN?= =?us-ascii?Q?klrZXSsSFxCCkvgT2qpb0pW+UoH/oV/OqHqqb5OS46wnJoCTjppdkMju6JIR?= =?us-ascii?Q?3o5COKOP6O9M5OaTu5Mprv1ezx+9Ii3bTR3N+O5lAVaPPKp4FOOC4iC5xYWL?= =?us-ascii?Q?E9zpRKJRd/kzKZwSNBgypDTm6VOXC3FABhfoz9qjyAAmqCjzdnz8tPiHYrTS?= =?us-ascii?Q?mQr3qS3cJ3VboEjoVDPTsI2Y4raYaZ74CClHWCQi?= MIME-Version: 1.0 X-OriginatorOrg: Nvidia.com X-MS-Exchange-CrossTenant-AuthAs: Internal X-MS-Exchange-CrossTenant-AuthSource: MW4PR12MB7031.namprd12.prod.outlook.com X-MS-Exchange-CrossTenant-Network-Message-Id: 14777fac-a82c-4156-ca07-08db28f10511 X-MS-Exchange-CrossTenant-originalarrivaltime: 20 Mar 2023 03:13:03.9713 (UTC) X-MS-Exchange-CrossTenant-fromentityheader: Hosted X-MS-Exchange-CrossTenant-id: 43083d15-7273-40c1-b7db-39efd9ccc17a X-MS-Exchange-CrossTenant-mailboxtype: HOSTED X-MS-Exchange-CrossTenant-userprincipalname: F8yiP0cNP2RjFUWpYI5JXUYIW66zWEKG8y6f+1f5nOZksObt6oGknO1mWu4/dw6ZNGfd58SrduShqDpDywT88A== X-MS-Exchange-Transport-CrossTenantHeadersStamped: MW4PR12MB6754 Content-Language: en-US Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: quoted-printable Please find my comment inline below, thanks! Regards, Nickle -----Original Message----- From: abner.chang@amd.com =20 Sent: Thursday, March 9, 2023 11:41 PM To: devel@edk2.groups.io Cc: Nickle Wang ; Igor Kulchytskyy Subject: [PATCH 1/3] RedfishPkg/Library: Redfish BMC USBNIC Host Interface External email: Use caution opening links or attachments From: Abner Chang BMC exposed USB NIC platform Redfish Host Interface library implementation. Signed-off-by: Abner Chang Cc: Nickle Wang Cc: Igor Kulchytskyy --- 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 Red= fishPkg/Library/PlatformHostInterfaceBmcUsbNicLib/PlatformHostInterfaceBmcU= sbNicLib.inf create mode 100644 RedfishPkg/Library/PlatformHostInterfaceBmcUsbNicLib/Pl= atformHostInterfaceBmcUsbNicLib.h create mode 100644 RedfishPkg/Library/PlatformHostInterfaceBmcUsbNicLib/Pl= atformHostInterfaceBmcUsbNicLib.c diff --git a/RedfishPkg/RedfishPkg.dec b/RedfishPkg/RedfishPkg.dec index 53= e52c2b008..251aa5e2b76 100644 --- a/RedfishPkg/RedfishPkg.dec +++ b/RedfishPkg/RedfishPkg.dec @@ -113,3 +113,13 @@ # Default is set to not add. # gEfiRedfishPkgTokenSpaceGuid.PcdRedfishRestExAddingExpect|FALSE|BOOLEAN|= 0x00001004 + # + # Use PCD to declare the Redfish host nmae becasue there is no #=20 + specification for that. + # + gEfiRedfishPkgTokenSpaceGuid.PcdRedfishHostName|""|VOID*|0x00001005 + # + # Use PCD to declare the Redfish service UUID becasue there is no #=20 + specification for that. + # + =20 + gEfiRedfishPkgTokenSpaceGuid.PcdRedfishServiceUuid|L""|VOID*|0x0000100 + 6 Would it be good to provide dummy string for above PCDs? For example: gEfiRedfishPkgTokenSpaceGuid.PcdRedfishHostName|"edk2_redfishpkg"|VOID*|0x0= 0001005 gEfiRedfishPkgTokenSpaceGuid.PcdRedfishServiceUuid|L"0000000000000000"|VOID= *|0x0000100 diff --git a/RedfishPkg/Library/PlatformHostInterfaceBmcUsbNicLib/PlatformH= ostInterfaceBmcUsbNicLib.inf b/RedfishPkg/Library/PlatformHostInterfaceBmcU= sbNicLib/PlatformHostInterfaceBmcUsbNicLib.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 # =20 +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 =3D 0x0001000b + BASE_NAME =3D PlatformHostInterfaceBmcUsbNicLib + FILE_GUID =3D C4837B58-225E-4352-8FDC-4C52A5D65891 + MODULE_TYPE =3D DXE_DRIVER + VERSION_STRING =3D 1.0 + LIBRARY_CLASS =3D 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/Incl= ude/Library/RedfishDebugLib.h index 21f01353ede..913f2b2f358 100644 --- a/RedfishPkg/Include/Library/RedfishDebugLib.h +++ b/RedfishPkg/Include/Library/RedfishDebugLib.h @@ -14,7 +14,8 @@ #include #include -#define DEBUG_REDFISH_NETWORK DEBUG_INFO ///< Debug error level for Red= fish 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/PlatformH= ostInterfaceBmcUsbNicLib.h b/RedfishPkg/Library/PlatformHostInterfaceBmcUsb= NicLib/PlatformHostInterfaceBmcUsbNicLib.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=20 +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 +#include +#include #include=20 + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include #include=20 + +#include +#include + +#include +#include + +#define BMC_USB_NIC_HOST_INTERFASCE_READINESS_GUID \ + { \ + 0xDD96F5D7, 0x4AE1, 0x4E6C, {0xA1, 0x30, 0xA5, 0xAC, 0x77, 0xDD, 0xE= 4, 0xA5} \ + } + +// +// This is the structure for BMC exposed // USB NIC information. +// +typedef struct { + LIST_ENTRY NextInstance; ///< Link to t= he next instance. + BOOLEAN IsExposedByBmc; ///< Flag indi= cates this USB NIC is + ///< exposed b= y BMC. + BOOLEAN IsSuppportedHostInterface; ///< This BMC = USB NIC is supported + ///< as Redfis= h host interface + EFI_SIMPLE_NETWORK_PROTOCOL *ThisSnp; ///< The SNP i= nstance associated with + ///< this USB = NIC. + EFI_USB_IO_PROTOCOL *ThisUsbIo; ///< The USBIO= instance associated with + ///< this USB = NIC. + UINT16 UsbVendorId; ///< USB Vendo= r ID of this BMC exposed USB NIC. + UINT16 UsbProductId; ///< USB Produ= ct ID of this BMC exposed USB NIC. + UINTN MacAddressSize; ///< HW addres= s size. + UINT8 *MacAddress; ///< HW addres= s. + UINT8 IpmiLanChannelNumber; ///< BMC IPMI = Lan Channel number. + + // + // Below is the infortmation for building SMBIOS type 42. + // + UINT8 IpAssignedType; ///< Redfish ser= vice IP assign type. + UINT8 IpAddressFormat; ///< Redfish ser= vice IP version. + UINT8 HostIpAddressIpv4[4]; ///< Host IP add= ress. + UINT8 RedfishIpAddressIpv4[4]; ///< Redfish ser= vice IP address. + UINT8 SubnetMaskIpv4[4]; ///< Subnet mask= . + UINT8 GatewayIpv4[4]; ///< Gateway IP = address. + UINT16 VLanId; ///< VLAN ID. + BOOLEAN CredentialBootstrapping; ///< If Credenti= al 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 L= AN Channel. + UINT8 Channel; ///< IPMI Channel number. + EFI_MAC_ADDRESS MacAddress; ///< IPMI LAN Channel MAC ad= dress. + UINT8 MacAddressSize; ///< MAC address size; +} BMC_IPMI_LAN_CHANNEL_INFO; +#endif diff --git a/RedfishPkg/Library/PlatformHostInterfaceBmcUsbNicLib/PlatformH= ostInterfaceBmcUsbNicLib.c b/RedfishPkg/Library/PlatformHostInterfaceBmcUsb= NicLib/PlatformHostInterfaceBmcUsbNicLib.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=20 +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 =3D + BMC_USB_NIC_HOST_INTERFASCE_READINESS_GUID; +static EFI_EVENT mPlatformHostInterfaceSnpEvent =3D NULL; +static VOID *mPlatformHostInterfaceSnpRegistration =3D 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 =3D REDFISH_IPMI_GROUP_EXTENSION; + CommandData.DisableBootstrapControl =3D REDFISH_IPMI_BOOTSTRAP_CREDENTIA= L_ENABLE; + ResponseData.CompletionCode =3D IPMI_COMP_CODE_UNSPECIFIED; + ResponseSize =3D sizeof (ResponseData); + // + // Response data: Ignored. + // + Status =3D IpmiSubmitCommand ( + IPMI_NETFN_GROUP_EXT, + REDFISH_IPMI_GET_BOOTSTRAP_CREDENTIALS_CMD, + (UINT8 *)&CommandData, + sizeof (CommandData), + (UINT8 *)&ResponseData, + &ResponseSize + ); + if (!EFI_ERROR (Status) && + ((ResponseData.CompletionCode =3D=3D IPMI_COMP_CODE_NORMAL) || + (ResponseData.CompletionCode =3D=3D REDFISH_IPMI_COMP_CODE_BOOTSTRA= P_CREDENTIAL_DISABLED) + )) + { + DEBUG ((DEBUG_REDFISH_HOST_INTERFACE, " Redfish Credentail Bootstra= pping is supported\n", __FUNCTION__)); + ReturnBool =3D TRUE; + } else { + DEBUG ((DEBUG_REDFISH_HOST_INTERFACE, " Redfish Credentail Bootstra= pping is not supported\n", __FUNCTION__)); + ReturnBool =3D 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 =3D (HOST_INTERFACE_BMC_USB_NIC_INFO *)GetFirstNode=20 + (&mBmcUsbNic); while (TRUE) { + if (ThisInstance->IsExposedByBmc && ThisInstance->IsSuppportedHostInte= rface) { + *DeviceType =3D REDFISH_HOST_INTERFACE_DEVICE_TYPE_USB_V2; + + // Fill up REDFISH_INTERFACE_DATA defined in Redfish host interface = spec v1.3 + InterfaceData =3D (REDFISH_INTERFACE_DATA *)AllocateZeroPool (USB_IN= TERFACE_DEVICE_DESCRIPTOR_V2_SIZE_1_3); + if (InterfaceData =3D=3D NULL) { + DEBUG ((DEBUG_ERROR, "Failed to allocate memory for REDFISH_INTERF= ACE_DATA\n")); + return EFI_OUT_OF_RESOURCES; + } + + InterfaceData->DeviceType =3D REDF= ISH_HOST_INTERFACE_DEVICE_TYPE_USB_V2; + InterfaceData->DeviceDescriptor.UsbDeviceV2.Length =3D USB_= INTERFACE_DEVICE_DESCRIPTOR_V2_SIZE_1_3; + InterfaceData->DeviceDescriptor.UsbDeviceV2.IdVendor =3D This= Instance->UsbVendorId; + InterfaceData->DeviceDescriptor.UsbDeviceV2.IdProduct =3D This= Instance->UsbProductId; + InterfaceData->DeviceDescriptor.UsbDeviceV2.SerialNumberStr =3D 0; + CopyMem ( + (VOID *)&InterfaceData->DeviceDescriptor.UsbDeviceV2.MacAddress, + (VOID *)&ThisInstance->MacAddress, + sizeof (InterfaceData->DeviceDescriptor.UsbDeviceV2.MacAddress) + ); + InterfaceData->DeviceDescriptor.UsbDeviceV2.Characteristics = |=3D (UINT16)ThisInstance->CredentialBootstrapping; + InterfaceData->DeviceDescriptor.UsbDeviceV2.CredentialBootstrappingH= andle =3D 0; + *DeviceDescriptor = =3D InterfaceData; + DEBUG ((DEBUG_REDFISH_HOST_INTERFACE, " REDFISH_INTERFACE_DATA is= returned successfully.\n")); + return EFI_SUCCESS; + } + + if (IsNodeAtEnd (&mBmcUsbNic, &ThisInstance->NextInstance)) { + break; + } + + ThisInstance =3D (HOST_INTERFACE_BMC_USB_NIC_INFO *) + GetNextNode (&mBmcUsbNic,=20 + &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 P= rotocolRecord. + + @param[in, out] ProtocolRecord Pointer to retrieve the first or the nex= t protocol record. + caller has to free the new protocol reco= rd 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 =3D (HOST_INTERFACE_BMC_USB_NIC_INFO *)GetFirstNode=20 + (&mBmcUsbNic); while (TRUE) { + if (ThisInstance->IsExposedByBmc && ThisInstance->IsSuppportedHostInt= erface) { + // Get the host name before allocating memory. + HostNameString =3D (CHAR8 *)PcdGetPtr (PcdRedfishHostName); + HostNameLength =3D (UINT8)AsciiStrSize (HostNameString); + ThisProtocolRecord =3D (MC_HOST_INTERFACE_PROTOCOL_RECORD *)Allocate= ZeroPool ( + sizeof (= MC_HOST_INTERFACE_PROTOCOL_RECORD) - 1 + + sizeof (= REDFISH_OVER_IP_PROTOCOL_DATA) + + HostName= Length + ); + if (ThisProtocolRecord =3D=3D NULL) { + DEBUG ((DEBUG_ERROR, " Aloocate memory fail for MC_HOST_INTERFA= CE_PROTOCOL_RECORD.\n")); + return EFI_OUT_OF_RESOURCES; + } + + ThisProtocolRecord->ProtocolType =3D MCHostInterfaceProtocolT= ypeRedfishOverIP; + ThisProtocolRecord->ProtocolTypeDataLen =3D sizeof (REDFISH_OVER_IP_= PROTOCOL_DATA) + HostNameLength; + RedfishOverIpData =3D (REDFISH_OVER_IP_PROTOCO= L_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)) !=3D = 0) { + StrToGuid ((CONST CHAR16 *)PcdGetPtr (PcdRedfishServiceUuid), &Red= fishOverIpData->ServiceUuid); + } + + // HostIpAddressFormat and RedfishServiceIpDiscoveryType + RedfishOverIpData->HostIpAssignmentType =3D RedfishHostIpAs= signmentUnknown; + RedfishOverIpData->RedfishServiceIpDiscoveryType =3D RedfishHostIpAs= signmentUnknown; + if (ThisInstance->IpAssignedType =3D=3D IpmiStaticAddrsss) { + RedfishOverIpData->HostIpAssignmentType =3D RedfishHostIp= AssignmentStatic; + RedfishOverIpData->RedfishServiceIpDiscoveryType =3D RedfishHostIp= AssignmentStatic; + } else if (ThisInstance->IpAssignedType =3D=3D IpmiDynamicAddressBmc= Dhcp) { + RedfishOverIpData->HostIpAssignmentType =3D RedfishHostIp= AssignmentDhcp; + RedfishOverIpData->RedfishServiceIpDiscoveryType =3D RedfishHostIp= AssignmentDhcp; + } + + // HostIpAddressFormat and RedfishServiceIpAddressFormat, only suppo= rt IPv4 for now. + RedfishOverIpData->HostIpAddressFormat =3D REDFISH_HOST_IN= TERFACE_HOST_IP_ADDRESS_FORMAT_IP4; + RedfishOverIpData->RedfishServiceIpAddressFormat =3D=20 + 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 =3D 0; + + // RedfishServiceVlanId + RedfishOverIpData->RedfishServiceVlanId =3D ThisInstance->VLanId; + + // RedfishServiceHostnameLength + RedfishOverIpData->RedfishServiceHostnameLength =3D HostNameLength; + + // Redfish host name. + CopyMem ( + (VOID *)&RedfishOverIpData->RedfishServiceHostname, + (VOID *)HostNameString, + HostNameLength + ); + + DEBUG ((DEBUG_REDFISH_HOST_INTERFACE, " MC_HOST_INTERFACE_PROTOCO= L_RECORD is returned successfully.\n")); + *ProtocolRecord =3D ThisProtocolRecord; + return EFI_SUCCESS; + } + + if (IsNodeAtEnd (&mBmcUsbNic, &ThisInstance->NextInstance)) { + break; + } + + ThisInstance =3D (HOST_INTERFACE_BMC_USB_NIC_INFO *) + GetNextNode (&mBmcUsbNic,=20 + &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 =3D (HOST_INTERFACE_BMC_USB_NIC_INFO *)GetFirstNode=20 + (&mBmcUsbNic); while (TRUE) { + if (ThisInstance->IsExposedByBmc) { + ThisInstance->IsSuppportedHostInterface =3D FALSE; + + // Probe if Redfish Host Interface Credential Bootstrapping is suppo= rted. + ThisInstance->CredentialBootstrapping =3D=20 + ProbeRedfishCredentialBootstrap (); + + // Get IP address source + GetLanConfigReq.SetSelector =3D 0; + GetLanConfigReq.BlockSelector =3D 0; + GetLanConfigReq.ChannelNumber.Bits.ChannelNo =3D ThisInstance->Ip= miLanChannelNumber; + GetLanConfigReq.ChannelNumber.Bits.GetParameter =3D 0; + GetLanConfigReq.ChannelNumber.Bits.Reserved =3D 0; + GetLanConfigReq.ParameterSelector =3D IpmiLanIpAddress= Source; + ResponseDataSize =3D sizeof (IPMI_GET= _LAN_CONFIGURATION_PARAMETERS_RESPONSE) + sizeof (IPMI_LAN_IP_ADDRESS_SRC); + GetLanConfigReps =3D (IPMI_GET_LAN_CO= NFIGURATION_PARAMETERS_RESPONSE *)AllocateZeroPool (ResponseDataSize); + GetLanConfigReps->CompletionCode =3D IPMI_COMP_CODE_U= NSPECIFIED; + Status =3D IpmiGetLanConfig= urationParameters ( + &GetLanConfigReq= , + GetLanConfigReps= , + &ResponseDataSiz= e + ); + if (EFI_ERROR (Status) || (GetLanConfigReps->CompletionCode !=3D IPM= I_COMP_CODE_NORMAL)) { + DEBUG ((DEBUG_ERROR, " Failed to get IP address source at chann= el %d: %r, 0x%02x.\n", ThisInstance->IpmiLanChannelNumber, Status, GetLanCo= nfigReps->CompletionCode)); + FreePool (GetLanConfigReps); + return Status; + } + + IpAddressSrc =3D (IPMI_LAN_IP_ADDRESS_SRC *)(GetLanConfigReps + 1); + DEBUG ((DEBUG_REDFISH_HOST_INTERFACE, " IP address source at chan= nel %d: %x\n", ThisInstance->IpmiLanChannelNumber, IpAddressSrc->Bits.Addre= ssSrc)); + ThisInstance->IpAssignedType =3D IpAddressSrc->Bits.AddressSrc; + FreePool (GetLanConfigReps); + + // Get LAN IPv4 IP address + GetLanConfigReq.ParameterSelector =3D IpmiLanIpAddress; + ResponseDataSize =3D sizeof (IPMI_GET_LAN_CONFIGURA= TION_PARAMETERS_RESPONSE) + sizeof (IPMI_LAN_IP_ADDRESS); + GetLanConfigReps =3D (IPMI_GET_LAN_CONFIGURATION_PA= RAMETERS_RESPONSE *)AllocateZeroPool (ResponseDataSize); + GetLanConfigReps->CompletionCode =3D IPMI_COMP_CODE_UNSPECIFIED; + Status =3D IpmiGetLanConfigurationParamet= ers ( + &GetLanConfigReq, + GetLanConfigReps, + &ResponseDataSize + ); + if (EFI_ERROR (Status) || (GetLanConfigReps->CompletionCode !=3D IPM= I_COMP_CODE_NORMAL)) { + DEBUG ((DEBUG_ERROR, " Failed to get Dest IP address at channel= %d: %r, 0x%02x.\n", ThisInstance->IpmiLanChannelNumber, Status, GetLanConf= igReps->CompletionCode)); + FreePool (GetLanConfigReps); + return Status; + } + + DestIpAddress =3D (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 *)&DestI= pAddress->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 *)&DestIpAd= dress->IpAddress, sizeof (DestIpAddress->IpAddress)); + ThisInstance->HostIpAddressIpv4[sizeof (ThisInstance->HostIpAddressI= pv4) - 1] -=3D 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 =3D IpmiLanSubnetMask; + ResponseDataSize =3D sizeof (IPMI_GET_LAN_CONFIGURA= TION_PARAMETERS_RESPONSE) + sizeof (IPMI_LAN_SUBNET_MASK); + GetLanConfigReps =3D (IPMI_GET_LAN_CONFIGURATION_PA= RAMETERS_RESPONSE *)AllocateZeroPool (ResponseDataSize); + GetLanConfigReps->CompletionCode =3D IPMI_COMP_CODE_UNSPECIFIED; + Status =3D IpmiGetLanConfigurationParamet= ers ( + &GetLanConfigReq, + GetLanConfigReps, + &ResponseDataSize + ); + if ((EFI_ERROR (Status)) || (GetLanConfigReps->CompletionCode !=3D I= PMI_COMP_CODE_NORMAL)) { + DEBUG ((DEBUG_ERROR, " Failed to get subnet mask at channel %d:= %r, 0x%02x.\n", ThisInstance->IpmiLanChannelNumber, Status, GetLanConfigRe= ps->CompletionCode)); + FreePool (GetLanConfigReps); + return Status; + } + + SubnetMask =3D (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 =3D IpmiLanDefaultGateway; + ResponseDataSize =3D sizeof (IPMI_GET_LAN_CONFIGURA= TION_PARAMETERS_RESPONSE) + sizeof (IPMI_LAN_DEFAULT_GATEWAY); + GetLanConfigReps =3D (IPMI_GET_LAN_CONFIGURATION_PA= RAMETERS_RESPONSE *)AllocateZeroPool (ResponseDataSize); + GetLanConfigReps->CompletionCode =3D IPMI_COMP_CODE_UNSPECIFIED; + Status =3D IpmiGetLanConfigurationParamet= ers ( + &GetLanConfigReq, + GetLanConfigReps, + &ResponseDataSize + ); + if ((EFI_ERROR (Status)) || (GetLanConfigReps->CompletionCode !=3D I= PMI_COMP_CODE_NORMAL)) { + DEBUG ((DEBUG_ERROR, " Failed to get default gateway at channel= %d: %r, 0x%02x.\n", ThisInstance->IpmiLanChannelNumber, Status, GetLanConf= igReps->CompletionCode)); + FreePool (GetLanConfigReps); + return Status; + } + + DefaultGateway =3D (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 =3D IpmiLanVlanId; + ResponseDataSize =3D sizeof (IPMI_GET_LAN_CONFIGURA= TION_PARAMETERS_RESPONSE) + sizeof (IPMI_LAN_VLAN_ID); + GetLanConfigReps =3D (IPMI_GET_LAN_CONFIGURATION_PA= RAMETERS_RESPONSE *)AllocateZeroPool (ResponseDataSize); + GetLanConfigReps->CompletionCode =3D IPMI_COMP_CODE_UNSPECIFIED; + Status =3D IpmiGetLanConfigurationParamet= ers ( + &GetLanConfigReq, + GetLanConfigReps, + &ResponseDataSize + ); + if ((EFI_ERROR (Status)) || (GetLanConfigReps->CompletionCode !=3D I= PMI_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 =3D (IPMI_LAN_VLAN_ID *)(GetLanConfigReps + 1); + ThisInstance->VLanId =3D 0; + if (LanVlanId->Data2.Bits.Enabled =3D=3D 1) { + ThisInstance->VLanId =3D LanVlanId->Data1.VanIdLowByte | (LanVlanI= d->Data2.Bits.VanIdHighByte << 8); + } + + DEBUG ((DEBUG_REDFISH_HOST_INTERFACE, " VLAN ID %x\n", ThisInstan= ce->VLanId)); + + FreePool (GetLanConfigReps); + + // + // Read USB device information. + // + if (ThisInstance->ThisUsbIo !=3D NULL) { + Status =3D ThisInstance->ThisUsbIo->UsbGetDeviceDescriptor (ThisIn= stance->ThisUsbIo, &UsbDeviceDescriptor); + if (!EFI_ERROR (Status)) { + DEBUG ((DEBUG_REDFISH_HOST_INTERFACE, " USB NIC Vendor ID: 0x= %04x, Device ID: 0x%04x\n", UsbDeviceDescriptor.IdVendor, UsbDeviceDescript= or.IdProduct)); + ThisInstance->UsbVendorId =3D UsbDeviceDescriptor.IdVendor; + ThisInstance->UsbProductId =3D UsbDeviceDescriptor.IdProduct; + } else { + DEBUG ((DEBUG_REDFISH_HOST_INTERFACE, " Fail to get USB devic= e descriptor.\n")); + } + } + + // All information is retrieved. + ThisInstance->IsSuppportedHostInterface =3D TRUE; + return EFI_SUCCESS; + } + + if (IsNodeAtEnd (&mBmcUsbNic, &ThisInstance->NextInstance)) { + break; + } + + ThisInstance =3D (HOST_INTERFACE_BMC_USB_NIC_INFO *) + GetNextNode (&mBmcUsbNic,=20 + &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 =3D (BMC_IPMI_LAN_CHANNEL_INFO *)AllocateZeroPool (sizeof=20 + (BMC_IPMI_LAN_CHANNEL_INFO)); if (ChannelInfo =3D=3D NULL) { + return EFI_OUT_OF_RESOURCES; + } + + ChannelInfo->Channel =3D ChannelNum; + CopyMem ((VOID *)&ChannelInfo->MacAddress.Addr, (VOID=20 +*)IpmiLanChannelMacAddress->Addr, IpmiLanMacAddressSize); + ChannelInfo->MacAddressSize =3D 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 =3D (BMC_IPMI_LAN_CHANNEL_INFO *)GetFirstNode=20 + (&mBmcIpmiLan); while (TRUE) { + if (ThisInstance->Channel =3D=3D ChannelNum) { + *CachedIpmiLanChannel =3D ThisInstance; + return EFI_SUCCESS; + } + + if (IsNodeAtEnd (&mBmcIpmiLan, &ThisInstance->NextInstance)) { + break; + } + + ThisInstance =3D (BMC_IPMI_LAN_CHANNEL_INFO *) + GetNextNode (&mBmcIpmiLan,=20 + &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 =3D NULL; + AlreadyCached =3D FALSE; + if (!IsListEmpty (&mBmcIpmiLan)) { + AlreadyCached =3D TRUE; + } + + // Initial the get MAC address request. + GetLanConfigReq.SetSelector =3D 0; + GetLanConfigReq.BlockSelector =3D 0; + GetLanConfigReq.ParameterSelector =3D IpmiLanMacAddress; + + ExitStatus =3D EFI_NOT_FOUND; + for (ChannelNum =3D IPMI_CHANNEL_NUMBER_IMPLEMENTATION_SPECIFIC_1; + ChannelNum <=3D IPMI_CHANNEL_NUMBER_IMPLEMENTATION_SPECIFIC_11; + ChannelNum++) + { + IpmiLanMacAddressSize =3D 0; + + // Check if the IPMI channel information is already cached. + Status =3D EFI_NOT_FOUND; + if (AlreadyCached) { + Status =3D CheckCachedIpmiLanMac ((UINT8)ChannelNum, &CachedIpmiLanC= hannel); + } + + if (Status =3D=3D EFI_SUCCESS) { + DEBUG ((DEBUG_REDFISH_HOST_INTERFACE, " Got cached IPMI LAN info.\n= ")); + IpmiLanMacAddressSize =3D sizeof (IPMI_LAN_MAC_ADDRESS); + CopyMem ((VOID *)&IpmiLanChannelMacAddress.Addr, (VOID *)&CachedIpmi= LanChannel->MacAddress.Addr, IpmiLanMacAddressSize); + } else { + DEBUG ((DEBUG_REDFISH_HOST_INTERFACE, " No cached IPMI LAN info\n")= ); + DEBUG ((DEBUG_REDFISH_HOST_INTERFACE, " Send NetFn =3D App, Command= =3D 0x42 to channel %d\n", ChannelNum)); + GetChanelInfoRequest.ChannelNumber.Bits.ChannelNo =3D (UINT8)Channel= Num; + Status =3D IpmiGetChannel= Info ( + &GetChanelInfo= Request, + &GetChanelInfo= Response, + &ResponseDataS= ize + ); + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_ERROR, " - Fails to send command.\n", ChannelNum)= ); + continue; + } + + DEBUG ((DEBUG_REDFISH_HOST_INTERFACE, " - Response data size =3D = 0x%x\n", ResponseDataSize)); + if ((GetChanelInfoResponse.CompletionCode !=3D IPMI_COMP_CODE_NORMAL= ) || (ResponseDataSize =3D=3D 0)) { + DEBUG ((DEBUG_ERROR, " - Command returned fail: 0x%x.\n", GetCh= anelInfoResponse.CompletionCode)); + continue; + } + + DEBUG (( + DEBUG_REDFISH_HOST_INTERFACE, + " - Channel protocol =3D 0x%x, Media =3D 0x%x\n", + GetChanelInfoResponse.ProtocolType.Bits.ChannelProtocolType, + GetChanelInfoResponse.MediumType.Bits.ChannelMediumType + )); + + if (GetChanelInfoResponse.ChannelNumber.Bits.ChannelNo !=3D ChannelN= um) { + DEBUG (( + DEBUG_ERROR, + " - ChannelNumber =3D %d in the response which is not macthed= to the request.\n", + GetChanelInfoResponse.ChannelNumber.Bits.ChannelNo + )); + continue; + } + + if ((GetChanelInfoResponse.MediumType.Bits.ChannelMediumType =3D=3D = IPMI_CHANNEL_MEDIA_TYPE_802_3_LAN) && + (GetChanelInfoResponse.ProtocolType.Bits.ChannelProtocolType =3D= =3D IPMI_CHANNEL_PROTOCOL_TYPE_IPMB_1_0)) + { + DEBUG ((DEBUG_REDFISH_HOST_INTERFACE, " - Channel %d is a LAN d= evice!\n", ChannelNum)); + + ResponseDataSize =3D sizeof (IPMI_GET_LAN_CONFIGURATION_PARAMETERS= _RESPONSE) + + sizeof (IPMI_LAN_MAC_ADDRESS); + if (GetLanConfigReps =3D=3D NULL) { + GetLanConfigReps =3D + (IPMI_GET_LAN_CONFIGURATION_PARAMETERS_RESPONSE *)AllocateZero= Pool (ResponseDataSize); + if (GetLanConfigReps =3D=3D NULL) { + DEBUG ((DEBUG_ERROR, " Allocate memory failed for getting M= AC address.\n")); + continue; + } + } + + GetLanConfigReq.ChannelNumber.Bits.ChannelNo =3D (UINT8)ChannelNum= ; + GetLanConfigReps->CompletionCode =3D IPMI_COMP_CODE_UN= SPECIFIED; + Status =3D IpmiGetLanConfigu= rationParameters ( + &GetLanConfigReq, + GetLanConfigReps, + &ResponseDataSize + ); + if (EFI_ERROR (Status) || (GetLanConfigReps->CompletionCode !=3D I= PMI_COMP_CODE_NORMAL)) { + DEBUG (( + DEBUG_ERROR, + " Fails to get MAC address of channel %d, CompletionCode = =3D %02x.\n", + ChannelNum, + GetLanConfigReps->CompletionCode + )); + continue; + } else { + DEBUG ((DEBUG_REDFISH_HOST_INTERFACE, " The MAC address of ch= annel %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 =3D sizeof (IPMI_LAN_MAC_ADDRESS); + CopyMem ((VOID *)&IpmiLanChannelMacAddress.Addr, (VOID *)(GetLan= ConfigReps + 1), IpmiLanMacAddressSize); + } + } + } + + if (IpmiLanMacAddressSize !=3D 0) { + if (!AlreadyCached) { + // Cache this IPMI LAN channel. + DEBUG ((DEBUG_REDFISH_HOST_INTERFACE, " Cache this IPMI LAN cha= nnel.\n")); + CacheIpmiLanMac ((UINT8)ChannelNum, &IpmiLanChannelMacAddress, Ipm= iLanMacAddressSize); + } + + // + // According to design spec in Readme file under RedfishPkg. + // Compare the first five MAC address and + // the 6th MAC address. + // + if ((IpmiLanMacAddressSize !=3D UsbNicInfo->MacAddressSize) || + (CompareMem ( + (VOID *)UsbNicInfo->MacAddress, + (VOID *)&IpmiLanChannelMacAddress.Addr, + IpmiLanMacAddressSize - 1 + ) !=3D 0) || + (IpmiLanChannelMacAddress.Addr[IpmiLanMacAddressSize - 1] !=3D + *(UsbNicInfo->MacAddress + IpmiLanMacAddressSize - 1) - 1) + ) + { + DEBUG ((DEBUG_REDFISH_HOST_INTERFACE, " MAC address is not matc= hed.\n")); + continue; + } + + // This is the NIC exposed by BMC. + UsbNicInfo->IpmiLanChannelNumber =3D (UINT8)ChannelNum; + UsbNicInfo->IsExposedByBmc =3D TRUE; + DEBUG ((DEBUG_REDFISH_HOST_INTERFACE, " MAC address is matched.\n= ")); + ExitStatus =3D EFI_SUCCESS; + break; + } + } + + if (GetLanConfigReps !=3D 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 =3D=3D NULL) { + return NULL; + } + + while (TRUE) { + ThisDevicePath =3D NextDevicePathNode (ThisDevicePath); + if (IsDevicePathEnd (ThisDevicePath)) { + return NULL; + } + + if ((ThisDevicePath->Type =3D=3D MESSAGING_DEVICE_PATH) && (ThisDevice= Path->SubType =3D=3D 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=20 + ((DEBUG_REDFISH_HOST_INTERFACE, "Device path on the EFI handle which=20 + has UsbIo and SNP instaleld on it.\n")); DevicePathStr =3D=20 + ConvertDevicePathToText (UsbDevicePath, FALSE, FALSE); DEBUG=20 + ((DEBUG_REDFISH_HOST_INTERFACE, "%s\n", DevicePathStr)); FreePool=20 + (DevicePathStr); It would be better to consider the case when ConvertDevicePathToText() retu= rns NULL pointer. + + BufferSize =3D 0; + HandleBuffer =3D NULL; + *UsbIo =3D NULL; + Status =3D gBS->LocateHandle ( + ByProtocol, + &gEfiUsbIoProtocolGuid, + NULL, + &BufferSize, + NULL + ); + if (Status =3D=3D EFI_BUFFER_TOO_SMALL) { + DEBUG ((DEBUG_REDFISH_HOST_INTERFACE, " %d UsbIo protocol instances.\= n", BufferSize/sizeof (EFI_HANDLE))); + HandleBuffer =3D AllocateZeroPool (BufferSize); + if (HandleBuffer =3D=3D NULL) { + DEBUG ((DEBUG_ERROR, " Falied to allocate buffer for the handles.= \n")); + return EFI_OUT_OF_RESOURCES; + } + + Status =3D 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 =3D 0; Index < (BufferSize/sizeof (EFI_HANDLE)); Index++) { + Status =3D 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 =3D ConvertDevicePathToText (ThisDevicePath, FALSE, FALS= E); + DEBUG ((DEBUG_REDFISH_HOST_INTERFACE, "%s\n", DevicePathStr)); + FreePool (DevicePathStr); It would be better to consider the case when ConvertDevicePathToText() retu= rns NULL pointer. Thanks, Nickle + + Status =3D EFI_NOT_FOUND; + + // Search for the starting MSG_USB_DP node. + ThisUsbDevicePath =3D UsbDevicePath; + if ((DevicePathType (ThisUsbDevicePath) !=3D MESSAGING_DEVICE_PATH) || + (DevicePathSubType (ThisUsbDevicePath) !=3D MSG_USB_DP)) + { + ThisUsbDevicePath =3D UsbNicGetNextMsgUsbDp (ThisUsbDevicePath); + if (ThisUsbDevicePath =3D=3D NULL) { + continue; + } + } + + if ((DevicePathType (ThisDevicePath) !=3D MESSAGING_DEVICE_PATH) || + (DevicePathSubType (ThisDevicePath) !=3D MSG_USB_DP)) + { + ThisDevicePath =3D UsbNicGetNextMsgUsbDp (ThisDevicePath); + if (ThisDevicePath =3D=3D NULL) { + continue; + } + } + + // Search for the ending MSG_USB_DP node. + ThisDevicePathEnd =3D ThisDevicePath; + ThisUsbDevicePathEnd =3D ThisUsbDevicePath; + while (TRUE) { + TempDevicePath =3D UsbNicGetNextMsgUsbDp (ThisDevicePathEnd); + if (TempDevicePath =3D=3D NULL) { + break; + } + + ThisDevicePathEnd =3D TempDevicePath; + } + + while (TRUE) { + TempDevicePath =3D UsbNicGetNextMsgUsbDp (ThisUsbDevicePathEnd); + if (TempDevicePath =3D=3D NULL) { + break; + } + + ThisUsbDevicePathEnd =3D TempDevicePath; + } + + // Compare these two device paths + Length =3D (UINT16)((UINTN)(UINT8 *)ThisDevicePathEnd + DevicePathNode= Length (ThisDevicePathEnd) - (UINTN)(UINT8 *)ThisDevicePath); + if (Length !=3D ((UINTN)(UINT8 *)ThisUsbDevicePathEnd + DevicePathNode= Length (ThisUsbDevicePathEnd) - (UINTN)(UINT8 *)ThisUsbDevicePath)) { + continue; + } + + if (CompareMem ( + (VOID *)ThisDevicePath, + (VOID *)ThisUsbDevicePath, + Length + ) =3D=3D 0) + { + Status =3D EFI_SUCCESS; + DEBUG ((DEBUG_REDFISH_HOST_INTERFACE, "EFI handle with the correct U= sbIo is found at #%d instance of UsbIo.\n", Index)); + break; + } + } + + if (Status =3D=3D EFI_SUCCESS) { + // Locate UsbIo from this handle. + Status =3D 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 =3D=20 + gBS->HandleProtocol ( + Handle, + &gEfiSimpleNetworkProtocolGuid, + (VOID **)&Snp + ); + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_ERROR, " Failed to locate SNP.\n")); + return Status; + } + + Status =3D UsbNicSearchUsbIo (UsbDevicePath, &UsbIo); if (EFI_ERROR=20 + (Status)) { + DEBUG ((DEBUG_ERROR, " Failed to find USBIO.\n")); + return Status; + } + + // Get the MAC address of this SNP instance. + BmcUsbNic =3D AllocateZeroPool (sizeof=20 + (HOST_INTERFACE_BMC_USB_NIC_INFO)); + if (BmcUsbNic =3D=3D NULL) { + DEBUG ((DEBUG_ERROR, " Failed to allocate memory for HOST_INTERFACE= _BMC_USB_NIC_INFO.\n")); + return EFI_OUT_OF_RESOURCES; + } + + InitializeListHead (&BmcUsbNic->NextInstance); =20 + BmcUsbNic->MacAddressSize =3D Snp->Mode->HwAddressSize; + BmcUsbNic->MacAddress =3D AllocateZeroPool (sizeof (BmcUsbNic->MacAd= dressSize)); + if (BmcUsbNic->MacAddress =3D=3D NULL) { + DEBUG ((DEBUG_ERROR, " Failed to allocate memory for HW MAC address= s.\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 =3D 0; Index < BmcUsbNic->MacAddressSize; Index++) { + DEBUG ((DEBUG_REDFISH_HOST_INTERFACE, "%02x ",=20 + *(BmcUsbNic->MacAddress + Index))); } + + DEBUG ((DEBUG_REDFISH_HOST_INTERFACE, "\n")); + BmcUsbNic->ThisSnp =3D Snp; + BmcUsbNic->ThisUsbIo =3D UsbIo; + + Status =3D HostInterfaceIpmiCheckMacAddress (BmcUsbNic); if (Status =3D= =3D=20 + EFI_SUCCESS) { + BmcUsbNic->IsExposedByBmc =3D TRUE; + DEBUG ((DEBUG_REDFISH_HOST_INTERFACE, " BMC exposed USB NIC is foun= d.\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 =3D=3D 0) || (HandleBuffer =3D=3D NULL)) { + return EFI_INVALID_PARAMETER; + } + + DEBUG ((DEBUG_INFO, "%a: Entry, #%d SNP handle\n", __FUNCTION__,=20 + HandleNumer)); + + GotOneUsbNIc =3D FALSE; + for (Index =3D 0; Index < HandleNumer; Index++) { + Status =3D gBS->HandleProtocol ( + *(HandleBuffer + Index), + &gEfiDevicePathProtocolGuid, + (VOID **)&DevicePath + ); + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_ERROR, " Failed to locate SNP on %d handle.\n", __F= UNCTION__, Index)); + continue; + } + + // Check if this is an BMC exposed USB NIC device. + while (TRUE) { + if ((DevicePath->Type =3D=3D MESSAGING_DEVICE_PATH) && (DevicePath->= SubType =3D=3D MSG_USB_DP)) { + Status =3D IdentifyUsbNicBmcChannel (*(HandleBuffer + Index), Devi= cePath); + if (!EFI_ERROR (Status)) { + GotOneUsbNIc =3D TRUE; + break; + } + } + + DevicePath =3D 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 exi= sting + 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",=20 + __FUNCTION__, Registration)); + + Handle =3D NULL; + Status =3D EFI_SUCCESS; + BufferSize =3D 0; + + Status =3D gBS->LocateHandle ( + Registration =3D=3D NULL ? ByProtocol : ByRegisterNotify= , + &gEfiSimpleNetworkProtocolGuid, + Registration, + &BufferSize, + NULL + ); + if (Status =3D=3D EFI_BUFFER_TOO_SMALL) { + DEBUG ((DEBUG_REDFISH_HOST_INTERFACE, " %d SNP protocol instances.\= n", BufferSize/sizeof (EFI_HANDLE))); + HandleBuffer =3D AllocateZeroPool (BufferSize); + if (HandleBuffer =3D=3D NULL) { + DEBUG ((DEBUG_ERROR, " Falied to allocate buffer for the handles.= \n")); + return EFI_OUT_OF_RESOURCES; + } + + Status =3D gBS->LocateHandle ( + Registration =3D=3D NULL ? ByProtocol : ByRegisterNoti= fy, + &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 =3D CheckBmcUsbNicOnHandles (BufferSize/sizeof (EFI_HANDLE),=20 + HandleBuffer); if (!EFI_ERROR (Status)) { + // Retrieve the rest of BMC USB NIC information for Redfish over IP in= formation + // and USB Network Interface V2. + Status =3D RetrievedBmcUsbNicInfo (); + if (!EFI_ERROR (Status)) { + DEBUG ((DEBUG_REDFISH_HOST_INTERFACE, " Install protocol to notif= y the platform Redfish Host Interface information is ready.\n")); + Status =3D 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 b= eing invoked. + @param[in] Context The pointer to the notification functi= on'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 u= p + 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 =3D NULL; + InitializeListHead (&mBmcUsbNic); + InitializeListHead (&mBmcIpmiLan); + + // + // Check if USB NIC exposed by BMC is already // connected. + // + Status =3D CheckBmcUsbNic (NULL); + if (!EFI_ERROR (Status)) { + return EFI_ALREADY_STARTED; + } + + if (Status =3D=3D EFI_NOT_FOUND) { + DEBUG ((DEBUG_REDFISH_HOST_INTERFACE, "%a: BMC USB NIC is not=20 + found. Register the notification.\n", __FUNCTION__)); + + // Register the notification of SNP installation. + Status =3D 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 =3D gBS->RegisterProtocolNotify ( + &gEfiSimpleNetworkProtocolGuid, + mPlatformHostInterfaceSnpEvent, + &mPlatformHostInterfaceSnpRegistration + ); + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_ERROR, "%a: Fail to register event for the installatio= n of SNP protocol.", __FUNCTION__)); + return Status; + } + + *InformationReadinessGuid =3D &mPlatformHostInterfaceBmcUsbNicReadines= sGuid; + return EFI_SUCCESS; + } + + DEBUG ((DEBUG_ERROR, "%a: Something wrong when look for BMC USB=20 +NIC.\n", __FUNCTION__)); + return Status; +} -- 2.37.1.windows.1